diff options
| -rw-r--r-- | src/options.c | 4 | ||||
| -rw-r--r-- | src/output.c | 94 |
2 files changed, 97 insertions, 1 deletions
diff --git a/src/options.c b/src/options.c index fc53396..16d6cf5 100644 --- a/src/options.c +++ b/src/options.c @@ -71,13 +71,15 @@ void usage(char *executable) { fprintf(stderr, "\n--format-string: Characters unlike the following are ignored\n"); fprintf(stderr, " A - access time\n"); fprintf(stderr, " C - change time\n"); + fprintf(stderr, " G - group name\n"); fprintf(stderr, " g - group id\n"); fprintf(stderr, " M - modification time\n"); - fprintf(stderr, " n - name\n"); + fprintf(stderr, " n - file name\n"); fprintf(stderr, " p - permissions\n"); fprintf(stderr, " s - size\n"); fprintf(stderr, " T - type\n"); fprintf(stderr, " t - time defined by --time-field (default: modification time)\n"); + fprintf(stderr, " U - user name\n"); fprintf(stderr, " u - user id\n"); } diff --git a/src/output.c b/src/output.c index 35500b0..04cafe7 100644 --- a/src/output.c +++ b/src/output.c @@ -11,6 +11,10 @@ #include <time.h> #include <sys/ioctl.h> #include <sys/stat.h> +#include <sys/types.h> +#include <pwd.h> +#include <grp.h> +#include <stdint.h> #include <errno.h> #include "output.h" @@ -28,11 +32,13 @@ #define out_print_uid(x) printf(" %4u ", x->ln_stat.st_gid) #define out_print_gid(x) printf(" %4u ", x->ln_stat.st_uid) +void out_print_group_name(struct list_node *ptr); void out_print_permissions(struct list_node *ptr); void out_print_size(struct list_node *ptr); void out_print_time(time_t tv); void out_print_time_by_option(struct list_node *ptr); void out_print_type(struct list_node *ptr); +void out_print_user_name(struct list_node *ptr); /* === IMPLEMENTATION === */ @@ -79,6 +85,83 @@ inline int fputc_width_x(char c, size_t x, FILE *fdout) { /* === FORMATTING RELATED FUNCTIONS === */ +/* Be aware: getting the name via uid takes a lot of time depending on the + * systems setup. local, NIS, LDAP ... + * Caching happens outside the executable, minimal here for skipping funcion calls. */ +inline void out_print_group_name(struct list_node *ptr) { + struct group *group = NULL; + static gid_t prev_gid = UINT32_MAX; + static char prev_group_name[64] = ""; + size_t group_name_length = 0; + + /* For the unlikely case of multi threading this program: lock required here... */ + if (prev_gid == ptr->ln_stat.st_gid) { + if (prev_group_name[0] == '\0') { /* first call of function and GID UINT32_MAX ? */ + if ((group = getgrgid(prev_gid)) == NULL) { + LOGERR("ERROR: Failed to resolve information for gid %u: %s (errno %d)\n", + prev_gid, strerror(errno), errno); + return; + } + group_name_length = strlen(group->gr_name); + group_name_length = (group_name_length > 63) ? 63 : group_name_length; + explicit_bzero(prev_group_name, 64); + memcpy(prev_group_name, group->gr_name, group_name_length); + } + printf(" %-10s ", prev_group_name); + return; + } + + prev_gid = ptr->ln_stat.st_gid; + if ((group = getgrgid(prev_gid)) == NULL) { + LOGERR("ERROR: Failed to resolve information for gid %u: %s (errno %d)\n", + prev_gid, strerror(errno), errno); + return; + } + group_name_length = strlen(group->gr_name); + group_name_length = (group_name_length > 63) ? 63 : group_name_length; + explicit_bzero(prev_group_name, 64); + memcpy(prev_group_name, group->gr_name, group_name_length); + printf(" %-10s ", prev_group_name); +} + +/* Reminder: resolving may take some time even with cache in libraries, + * minimal cache here to prevent function call */ +inline void out_print_user_name(struct list_node *ptr) { + struct passwd *pwd = NULL; + static uid_t prev_uid = UINT32_MAX; + static char prev_user_name[64] = ""; + size_t user_name_length = 0; + + /* For the unlikely case of multi threading this program: lock required here... */ + if (prev_uid == ptr->ln_stat.st_uid) { + if (prev_user_name[0] == '\0') { /* first call of function and UID UINT32_MAX ? */ + if ((pwd = getpwuid(prev_uid)) == NULL) { + LOGERR("ERROR: Failed to resolve information for uid %u: %s (errno %d)\n", + prev_uid, strerror(errno), errno); + return; + } + user_name_length = strlen(pwd->pw_name); + user_name_length = (user_name_length > 63) ? 63 : user_name_length; + explicit_bzero(prev_user_name, 64); + memcpy(prev_user_name, pwd->pw_name, user_name_length); + } + printf(" %-10s ", prev_user_name); + return; + } + + prev_uid = ptr->ln_stat.st_uid; + if ((pwd = getpwuid(prev_uid)) == NULL) { + LOGERR("ERROR: Failed to resolve information for uid %u: %s (errno %d)\n", + prev_uid, strerror(errno), errno); + return; + } + user_name_length = strlen(pwd->pw_name); + user_name_length = (user_name_length > 63) ? 63 : user_name_length; + explicit_bzero(prev_user_name, 64); + memcpy(prev_user_name, pwd->pw_name, user_name_length); + printf(" %-10s ", prev_user_name); +} + inline void out_print_size(struct list_node *ptr) { printf(" %8ld %2s ", ((ptr->ln_stat.st_size>=1024) ? (ptr->ln_stat.st_size/1024) : ptr->ln_stat.st_size), ((ptr->ln_stat.st_size >= 1024) ? "kB" : "")); @@ -250,6 +333,11 @@ void print_list(struct list_head *list) { * n - name * s - file size * T - type + * U - user name + * u - user id + * G - group name + * g - group id + * p - permissions and special bits * * Time related * t - timestamp set by option_time_field @@ -315,6 +403,12 @@ void print_list_formatted(const char *format, struct list_head *list) { case 'g': out_print_gid(ptr); break; + case 'U': + out_print_user_name(ptr); + break; + case 'G': + out_print_group_name(ptr); + break; case 'p': out_print_permissions(ptr); break; |
