logo

utils-std

Collection of commonly available Unix tools
commit: 7d963c3fe6e89216f169bbf81b7d4e5f6329754b
parent 9698dc42e958be417bec48032a0b16932fb46446
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun, 31 Mar 2024 08:14:51 +0200

cmd/df: Add support for arguments

Diffstat:

Mcmd/df.111+++++++++--
Mcmd/df.c91++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mtest-cmd/df6++++++
3 files changed, 75 insertions(+), 33 deletions(-)

diff --git a/cmd/df.1 b/cmd/df.1 @@ -1,7 +1,7 @@ .\" utils-std: Collection of commonly available Unix tools .\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> .\" SPDX-License-Identifier: MPL-2.0 -.Dd 2024-03-09 +.Dd 2024-03-31 .Dt DF 1 .Os .Sh NAME @@ -12,10 +12,17 @@ .Op Fl ahlPkT .Op Fl t Ar mnt_type .Op Fl x Ar mnt_type +.Op Ar file... .Sh DESCRIPTION .Nm displays the current usage and mountpoints of mounted filesystems in a space-separated list containing: Filesystem, Total, Used, Available, Use percentage, Mountpoint. +If +.Ar file +is given +.Nm +filters to the first filesystem containing each +.Ar file . .Pp Unlike some implementations the table formatting isn't perfect, you might want to use .Xr column 1 @@ -58,7 +65,7 @@ Option can be passed multiple times to exclude multiple types. .Xr statvfs 3 .Sh STANDARDS .Nm -lacks getting a list of filesystems as argument to be compliant with the +should be compliant with the .St -p1003.1-2008 specification. .Pp diff --git a/cmd/df.c b/cmd/df.c @@ -101,6 +101,21 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; + int args_left = argc != 0 ? argc : 1; + + dev_t arg_devs[argc]; + for(int i = 0; i < argc; i++) + { + struct stat file_stats; + if(stat(argv[i], &file_stats) != 0) + { + fprintf(stderr, "df: Error stat(\"%s\", _): %s\n", argv[i], strerror(errno)); + return 1; + } + + arg_devs[i] = file_stats.st_dev; + } + // Begin: Print header printf("%-*s ", fs_col_width, "Filesystem"); @@ -132,7 +147,8 @@ main(int argc, char *argv[]) dev_t devices[4096]; size_t devices_found = 0; - while(1) + // Even with argc>0 we still need to go over mntent for the filesystem mountpoint and type + while(args_left > 0) { struct mntent *mntent = getmntent(mounted); if(mntent == NULL) break; @@ -179,6 +195,47 @@ main(int argc, char *argv[]) if(remote) continue; } + struct stat file_stats; + if(!opt_a || argc > 0) + { + if(stat(mntent->mnt_dir, &file_stats) != 0) + fprintf(stderr, "df: Warning stat(\"%s\", _): %s\n", mntent->mnt_dir, strerror(errno)); + } + + if(argc > 0) + { + bool found = false; + for(size_t i = 0; i < argc; i++) + if(arg_devs[i] == file_stats.st_dev) + { + found = true; + break; + } + + if(!found) continue; + + args_left--; + } + + if(!opt_a) + { + bool dupe = false; + for(size_t i = 0; i < devices_found; i++) + if(devices[i] == file_stats.st_dev) + { + dupe = true; + break; + } + + if(dupe) continue; + + if(devices_found >= 4096) + fprintf(stderr, + "df: Warning: Reached maximum amount of devices which can be deduplicated\n"); + + devices[devices_found++] = file_stats.st_dev; + } + // Note: musl prior to 1.2.5 has broken getmntent when octal sequences and carriage return is used // https://git.musl-libc.org/cgit/musl/commit/src/misc/mntent.c?id=f314e133929b6379eccc632bef32eaebb66a7335 // https://git.musl-libc.org/cgit/musl/commit/src/misc/mntent.c?id=ee1d39bc1573c1ae49ee6b658938b56bbef95a6c @@ -202,36 +259,8 @@ main(int argc, char *argv[]) continue; } - if(!opt_a) - { - // Skip null filesystems - if(stats.f_blocks == 0) continue; - - struct stat file_stats; - bool dupe = false; - - if(stat(mntent->mnt_dir, &file_stats) != 0) - { - fprintf(stderr, "df: Warning stat(\"%s\", _): %s\n", mntent->mnt_dir, strerror(errno)); - } - else - { - for(size_t i = 0; i < devices_found; i++) - if(devices[i] == file_stats.st_dev) - { - dupe = true; - break; - } - - if(dupe) continue; - - if(devices_found >= 4096) - fprintf(stderr, - "df: Warning: Reached maximum amount of devices which can be deduplicated\n"); - - devices[devices_found++] = file_stats.st_dev; - } - } + // Skip null filesystems + if(!opt_a && stats.f_blocks == 0) continue; // Needs to be done after calling statvfs(3) and stat(3) static_escape(mntent->mnt_fsname); diff --git a/test-cmd/df b/test-cmd/df @@ -17,8 +17,14 @@ posix_body() { atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% [^ ]$' sh -c '../cmd/df -Pak | sed -n 2,\$p' } +atf_test_case args +args_body() { + atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% /$' sh -c '../cmd/df -P / | sed -n 2,\$p' +} + atf_init_test_cases() { cd "$(atf_get_srcdir)" || exit 1 atf_add_test_case posix + atf_add_test_case args }