aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/options.c4
-rw-r--r--src/output.c94
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;