Whamcloud - gitweb
LU-15837 utils: added lfs find --printf functions 41/55441/20
authorMaximilian Dilger <mdilger@whamcloud.com>
Wed, 12 Jun 2024 17:04:31 +0000 (13:04 -0400)
committerOleg Drokin <green@whamcloud.com>
Thu, 8 Aug 2024 00:05:49 +0000 (00:05 +0000)
adding functionality for:  %i (inode number)
     %M (symbolic file access mode)
     %g (groupname)
     %u (username)

Test-Parameters: trivial
Signed-off-by: Maximilian Dilger <mdilger@whamcloud.com>
Change-Id: I2a577c1c9869bfcda9aa20f60db65c7dc888204d
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55441
Tested-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/doc/lfs-find.1
lustre/tests/sanity.sh
lustre/utils/liblustreapi.c

index 09a1bbc..2ee8aec 100644 (file)
@@ -352,12 +352,21 @@ File\'s last status change time in the format returned by the C \`ctime\' functi
 .B %C@
 File\'s last status change time in seconds since Jan. 1, 1970, 00:00 GMT.
 .TP
+.B %g
+File\'s groupname.
+.TP
 .B %G
 File\'s numeric group ID.
 .TP
+.B %i
+Inode number.
+.TP
 .B %m
 File permission bits (in octal).
 .TP
+.B %M
+File permissions (rwx format)
+.TP
 .B %n
 Number of hard links to file.
 .TP
@@ -373,6 +382,9 @@ File\'s last modification time in the format returned by the C \`ctime\' functio
 .B %T@
 File\'s last modification time in seconds since Jan. 1, 1970, 00:00 GMT.
 .TP
+.B %u
+File's username.
+.TP
 .B %U
 File's numeric user ID.
 .TP
@@ -513,6 +525,10 @@ the OST object attributes for that file.
 Efficiently lists all files in a given directory and its subdirectories,
 without fetching any file attributes.
 .TP
+.B $ lfs find /mnt/lustre -printf "%u %M %i \n"
+Prints a formatted find string, listing the username, access mode and inode
+number.
+.TP
 .B $ lfs find /mnt/lustre -mtime +30 -type f -print
 Recursively list all regular files in given directory more than 30 days old.
 .TP
index 3fd123f..7d57de4 100755 (executable)
@@ -9173,6 +9173,22 @@ test_56ea() { #LU-10378
 }
 run_test 56ea "test lfs find -printf option"
 
+test_56eaa() {
+       local lfs_find=($($LFS find $DIR -printf "%i %u %g %M %p\n" | sort -n))
+       local normal_find=($(find $DIR -printf "%i %u %g %M %p\n" | sort -n))
+
+       echo "comparing ${#normal_find[@]} elements starting with:"
+       echo "lfs: ${lfs_find[0]} ${lfs_find[1]} ${lfs_find[2]} ${lfs_find[3]} ${lfs_find[4]}"
+       echo "find: ${normal_find[0]} ${normal_find[1]} ${normal_find[2]} ${normal_find[3]} ${normal_find[4]}"
+
+       for ((i = 0; i < ${#normal_find[@]}; i++)); do
+               if [[ "${lfs_find[i]}" != "${normal_find[i]}" ]]; then
+                       error "expected '${normal_find[i]}' but got '${lfs_find[i]}' from file ${lfs_find[$((i - (i % 5) + 4))]}"
+               fi
+       done
+}
+run_test 56eaa "test lfs find -printf added functions"
+
 test_56eb() {
        local dir=$DIR/$tdir
        local subdir_1=$dir/subdir_1
index 3930a3a..99c9cf0 100644 (file)
 #endif
 
 #include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
 #include <mntent.h>
+#include <pwd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stddef.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
 #include <stdarg.h>
 #include <sys/stat.h>
 #include <sys/statfs.h>
@@ -5401,6 +5403,62 @@ format_done:
 }
 
 /*
+ * Create a formated access mode string
+ *
+ * @param[in] param->fp_lmd->lmd_stx.stx_mode
+ *
+ */
+
+static int snprintf_access_mode(char *buffer, size_t size, __u16 mode)
+{
+       char access_string[16];
+       char *p = access_string;
+
+       switch (mode & S_IFMT) {
+       case S_IFREG:
+               *p++ = '-';
+               break;
+       case S_IFDIR:
+               *p++ = 'd';
+               break;
+       case S_IFLNK:
+               *p++ = 'l';
+               break;
+       case S_IFIFO:
+               *p++ = 'p';
+               break;
+       case S_IFSOCK:
+               *p++ = 's';
+               break;
+       case S_IFBLK:
+               *p++ = 'b';
+               break;
+       case S_IFCHR:
+               *p++ = 'c';
+               break;
+       default:
+               *p++ = '?';
+               break;
+       }
+
+       *p++ = (mode & S_IRUSR) ? 'r' : '-';
+       *p++ = (mode & S_IWUSR) ? 'w' : '-';
+       *p++ = (mode & S_IXUSR) ? ((mode & S_ISUID) ? 's' : 'x') :
+                                 ((mode & S_ISUID) ? 'S' : '-');
+       *p++ = (mode & S_IRGRP) ? 'r' : '-';
+       *p++ = (mode & S_IWGRP) ? 'w' : '-';
+       *p++ = (mode & S_IXGRP) ? ((mode & S_ISGID) ? 's' : 'x') :
+                                 ((mode & S_ISGID) ? 'S' : '-');
+       *p++ = (mode & S_IROTH) ? 'r' : '-';
+       *p++ = (mode & S_IWOTH) ? 'w' : '-';
+       *p++ = (mode & S_IXOTH) ? ((mode & S_ISVTX) ? 't' : 'x') :
+                                 ((mode & S_ISVTX) ? 'T' : '-');
+       *p = '\0';
+
+       return snprintf(buffer, size, "%s", access_string);
+}
+
+/*
  * Interpret format specifiers beginning with '%'.
  *
  * @param[in]  seq     String being parsed for format specifier.  The leading
@@ -5436,10 +5494,34 @@ static int printf_format_directive(char *seq, char *buffer, size_t size,
        case 'b':       /* file size (in 512B blocks) */
                *wrote = snprintf(buffer, size, "%"PRIu64, blocks);
                break;
+       case 'g': { /* groupname of owner*/
+               static char save_gr_name[LOGIN_NAME_MAX + 1];
+               static gid_t save_gid = -1;
+
+               if (save_gid != param->fp_lmd->lmd_stx.stx_gid) {
+                       struct group *gr;
+
+                       gr = getgrgid(param->fp_lmd->lmd_stx.stx_gid);
+                       if (gr) {
+                               save_gid = param->fp_lmd->lmd_stx.stx_gid;
+                               strncpy(save_gr_name, gr->gr_name,
+                                       sizeof(save_gr_name) - 1);
+                       }
+               }
+               if (save_gr_name[0]) {
+                       *wrote = snprintf(buffer, size, "%s", save_gr_name);
+                       break;
+               }
+               fallthrough;
+       }
        case 'G':       /* GID of owner */
                *wrote = snprintf(buffer, size, "%u",
                                   param->fp_lmd->lmd_stx.stx_gid);
                break;
+       case 'i':       /* inode number */
+               *wrote = snprintf(buffer, size, "%llu",
+                                 param->fp_lmd->lmd_stx.stx_ino);
+               break;
        case 'k':       /* file size (in 1K blocks) */
                *wrote = snprintf(buffer, size, "%"PRIu64, (blocks + 1)/2);
                break;
@@ -5450,6 +5532,9 @@ static int printf_format_directive(char *seq, char *buffer, size_t size,
        case 'm':       /* file mode in octal */
                *wrote = snprintf(buffer, size, "%#o", (mode & (~S_IFMT)));
                break;
+       case 'M':       /* file access mode */
+               *wrote = snprintf_access_mode(buffer, size, mode);
+               break;
        case 'n':       /* number of links */
                *wrote = snprintf(buffer, size, "%u",
                                  param->fp_lmd->lmd_stx.stx_nlink);
@@ -5461,6 +5546,26 @@ static int printf_format_directive(char *seq, char *buffer, size_t size,
                *wrote = snprintf(buffer, size, "%"PRIu64,
                                   (uint64_t) param->fp_lmd->lmd_stx.stx_size);
                break;
+       case 'u': {/* username of owner */
+               static char save_username[LOGIN_NAME_MAX + 1];
+               static uid_t save_uid = -1;
+
+               if (save_uid != param->fp_lmd->lmd_stx.stx_uid) {
+                       struct passwd *pw;
+
+                       pw = getpwuid(param->fp_lmd->lmd_stx.stx_uid);
+                       if (pw) {
+                               save_uid = param->fp_lmd->lmd_stx.stx_uid;
+                               strncpy(save_username, pw->pw_name,
+                                       sizeof(save_username) - 1);
+                       }
+               }
+               if (save_username[0]) {
+                       *wrote = snprintf(buffer, size, "%s", save_username);
+                       break;
+               }
+               fallthrough;
+       }
        case 'U':       /* UID of owner */
                *wrote = snprintf(buffer, size, "%u",
                                   param->fp_lmd->lmd_stx.stx_uid);
@@ -6460,7 +6565,7 @@ static int validate_printf_esc(char *c)
  */
 static int validate_printf_fmt(char *c)
 {
-       char *valid_fmt_single = "abcGkmnpstUwy%";
+       char *valid_fmt_single = "abcigGkmMnpstuUwy%";
        char *valid_fmt_double = "ACTW";
        char *valid_fmt_lustre = "aAcFhioPpS";
        char curr = *c, next;