From: Maximilian Dilger Date: Wed, 12 Jun 2024 17:04:31 +0000 (-0400) Subject: LU-15837 utils: added lfs find --printf functions X-Git-Tag: 2.15.65~20 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=08a3e19a0455867467f4ea42ebf3ce4a1aa8fef7;p=fs%2Flustre-release.git LU-15837 utils: added lfs find --printf functions adding functionality for: %i (inode number) %M (symbolic file access mode) %g (groupname) %u (username) Test-Parameters: trivial Signed-off-by: Maximilian Dilger Change-Id: I2a577c1c9869bfcda9aa20f60db65c7dc888204d Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55441 Tested-by: Oleg Drokin Reviewed-by: Oleg Drokin --- diff --git a/lustre/doc/lfs-find.1 b/lustre/doc/lfs-find.1 index 09a1bbc..2ee8aec 100644 --- a/lustre/doc/lfs-find.1 +++ b/lustre/doc/lfs-find.1 @@ -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 diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 3fd123f..7d57de4 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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 diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 3930a3a..99c9cf0 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -41,16 +41,18 @@ #endif #include +#include +#include +#include +#include #include +#include #include #include #include #include #include #include -#include -#include -#include #include #include #include @@ -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;