diff options
| author | Thorsten Töpper <atsutane@freethoughts.de> | 2025-07-06 02:49:46 +0200 |
|---|---|---|
| committer | Thorsten Töpper <atsutane@freethoughts.de> | 2025-07-06 02:49:46 +0200 |
| commit | 3dc5a650b3d2d58606d7080f6e4fdacb2c0832a0 (patch) | |
| tree | 1fddee3229cc5fe97b70732eb9c7379b4be7d912 /src/output.c | |
| parent | 1154e2aacf1539936ca2d45a14f923b63d288d36 (diff) | |
| download | dir_monitor-3dc5a650b3d2d58606d7080f6e4fdacb2c0832a0.tar.gz dir_monitor-3dc5a650b3d2d58606d7080f6e4fdacb2c0832a0.tar.bz2 | |
output: format string: user and group name
Depending on the OS setup the function calls may be extremely time
consuming if it's not local and not in the kernel cache.
static fields for minimal local caching to circumvent function calls.
Diffstat (limited to 'src/output.c')
| -rw-r--r-- | src/output.c | 94 |
1 files changed, 94 insertions, 0 deletions
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; |
