diff options
-rw-r--r-- | Changelog | 20 | ||||
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | bylabel.c | 6 | ||||
-rw-r--r-- | common.c | 11 | ||||
-rw-r--r-- | common.h | 6 | ||||
-rwxr-xr-x | configure | 111 | ||||
-rw-r--r-- | configure.in | 7 | ||||
-rw-r--r-- | convertquota.c | 43 | ||||
-rw-r--r-- | edquota.8 | 36 | ||||
-rw-r--r-- | edquota.c | 32 | ||||
-rw-r--r-- | mntopt.h | 2 | ||||
-rw-r--r-- | quot.8 | 3 | ||||
-rw-r--r-- | quot.c | 14 | ||||
-rw-r--r-- | quota.1 | 22 | ||||
-rw-r--r-- | quota.c | 38 | ||||
-rw-r--r-- | quotacheck.8 | 193 | ||||
-rw-r--r-- | quotacheck.c | 110 | ||||
-rw-r--r-- | quotacheck_v1.c | 8 | ||||
-rw-r--r-- | quotacheck_v2.c | 32 | ||||
-rw-r--r-- | quotactl.2 | 80 | ||||
-rw-r--r-- | quotaio.c | 44 | ||||
-rw-r--r-- | quotaio.h | 4 | ||||
-rw-r--r-- | quotaio_rpc.c | 7 | ||||
-rw-r--r-- | quotaio_v1.c | 72 | ||||
-rw-r--r-- | quotaio_v2.c | 31 | ||||
-rw-r--r-- | quotaon.8 | 20 | ||||
-rw-r--r-- | quotaon.c | 55 | ||||
-rw-r--r-- | quotaon_xfs.c | 20 | ||||
-rw-r--r-- | quotaops.c | 102 | ||||
-rw-r--r-- | quotastats.c | 4 | ||||
-rw-r--r-- | quotasys.c | 52 | ||||
-rw-r--r-- | quotasys.h | 8 | ||||
-rw-r--r-- | repquota.8 | 21 | ||||
-rw-r--r-- | repquota.c | 28 | ||||
-rw-r--r-- | rquota_server.c | 6 | ||||
-rw-r--r-- | rquota_svc.c | 44 | ||||
-rw-r--r-- | rquotad.8 | 8 | ||||
-rw-r--r-- | set_limits_example.c | 14 | ||||
-rw-r--r-- | setquota.8 | 18 | ||||
-rw-r--r-- | setquota.c | 19 | ||||
-rw-r--r-- | warnquota.c | 15 | ||||
-rw-r--r-- | xqmstats.c | 6 |
42 files changed, 921 insertions, 457 deletions
@@ -39,6 +39,26 @@ Changes in quota-package from 2.00 to 3.01 * Fix up numerous compiler warnings and all the minor problems that revealed - package now compiled with -Wall by default. (Jan Kara, Nathan Scott) +* Rewrote the error output handler (now uses errstr function) which also + displays the correct programname of the program issueing the error. + +* Additional configure option BSD_BEHAVIOUR for more the old BSD behaviour + as wanted by some people. + +* EOF -> -1, sprintf -> snprintf fixes + +* Don't turn quotas on on NFS + +* Fixed quota format detection, related bugs in quotaon + +* IO code now allows readonly access, doesn't open quotafile when not needed + +* Fixed bug in old quotaformat initialization + +* quota(1) now exits with nonzero exitcode when over quota + +* Manpage cleanup + Changes in quota-package from 1.70 to 2.00 * Added patches from Steven Walker <smw8923@cmsu2.cmsu.edu> for supporting diff --git a/Makefile.in b/Makefile.in index cecd989..d06bfae 100644 --- a/Makefile.in +++ b/Makefile.in @@ -42,7 +42,7 @@ IOOBJS = quotaio.o quotaio_v1.o quotaio_v2.o quotaio_rpc.o quotaio_xfs.o IOOBJS += $(RPCCLNTOBJS) LIBOBJS = bylabel.o common.o quotasys.o pot.o $(IOOBJS) LIBOBJS += @LIBMALLOC@ -INCLUDE = common.h quotasys.h bylabel.h +INCLUDE = common.h quotasys.h bylabel.h mntopt.h all: $(PROGS) @@ -110,8 +110,8 @@ warnquota: $(INCLUDE) common.h warnquota.o $(LIBOBJS) quotastats: quotastats.o pot.o $(CC) $(LDFLAGS) -o $@ quotastats.o pot.o -xqmstats: xqmstats.o pot.o - $(CC) $(LDFLAGS) -o $@ xqmstats.o pot.o +xqmstats: xqmstats.o common.o pot.o + $(CC) $(LDFLAGS) -o $@ xqmstats.o common.o pot.o edquota: $(INCLUDE) quotaops.h quotaio.h edquota.o quotaops.o $(LIBOBJS) $(CC) $(LDFLAGS) -o $@ edquota.o quotaops.o $(LIBOBJS) @@ -167,7 +167,7 @@ static void uuidcache_init(void) * (This is useful, if the cdrom on /dev/hdc must not * be accessed.) */ - sprintf(device, "%s/%s", DEVLABELDIR, ptname); + snprintf(device, sizeof(device), "%s/%s", DEVLABELDIR, ptname); if (!get_label_uuid(device, &label, uuid)) uuidcache_addentry(sstrdup(device), label, uuid); } @@ -231,7 +231,7 @@ static char *get_spec_by_uuid(const char *s) return get_spec_by_x(UUID, uuid); bad_uuid: - fprintf(stderr, _("Found an invalid UUID: %s\n"), s); + errstr(_("Found an invalid UUID: %s\n"), s); return NULL; } @@ -251,6 +251,6 @@ const char *get_device_name(const char *item) else rc = sstrdup(item); if (!rc) - fprintf(stderr, _("Error checking device name: %s\n"), item); + errstr(_("Error checking device name: %s\n"), item); return rc; } @@ -20,12 +20,23 @@ void die(int ret, char *fmtstr, ...) { va_list args; + fprintf(stderr, "%s: ", progname); va_start(args, fmtstr); vfprintf(stderr, fmtstr, args); va_end(args); exit(ret); } +void errstr(char *fmtstr, ...) +{ + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, fmtstr); + vfprintf(stderr, fmtstr, args); + va_end(args); +} + void *smalloc(size_t size) { void *ret = malloc(size); @@ -9,9 +9,15 @@ #define MY_EMAIL "mvw@planets.elm.net, jack@suse.cz" +/* Name of current program for error reporting */ +extern char *progname; + /* Finish programs being */ void die(int, char *, ...); +/* Print an error */ +void errstr(char *, ...); + /* malloc() with error check */ void *smalloc(size_t); @@ -20,6 +20,8 @@ ac_help="$ac_help ac_help="$ac_help --enable-rpcsetquota=[yes/no] Use RPC for setting quotas [default=yes]." ac_help="$ac_help + --enable-bsd_behaviour=[yes/no] Mimic BSD behaviour [default=yes]." +ac_help="$ac_help --enable-libefence=[yes/no] Use Electric Fence memory checks [default=no]." # Initialize some variables set by options. @@ -535,7 +537,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:539: checking for $ac_word" >&5 +echo "configure:541: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -565,7 +567,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:569: checking for $ac_word" >&5 +echo "configure:571: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -616,7 +618,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:620: checking for $ac_word" >&5 +echo "configure:622: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -648,7 +650,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:652: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:654: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -659,12 +661,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 663 "configure" +#line 665 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:668: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:670: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -690,12 +692,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:694: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:696: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:699: checking whether we are using GNU C" >&5 +echo "configure:701: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -704,7 +706,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:708: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:710: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -723,7 +725,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:727: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:729: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -755,7 +757,7 @@ else fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:759: checking how to run the C preprocessor" >&5 +echo "configure:761: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -770,13 +772,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 774 "configure" +#line 776 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:780: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -787,13 +789,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 791 "configure" +#line 793 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:797: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:799: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -804,13 +806,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 808 "configure" +#line 810 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:816: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -835,12 +837,12 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:839: checking for ANSI C header files" >&5 +echo "configure:841: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 844 "configure" +#line 846 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -848,7 +850,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:852: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:854: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -865,7 +867,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 869 "configure" +#line 871 "configure" #include "confdefs.h" #include <string.h> EOF @@ -883,7 +885,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 887 "configure" +#line 889 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -904,7 +906,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 908 "configure" +#line 910 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -915,7 +917,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -969,7 +971,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:973: checking for a BSD compatible install" >&5 +echo "configure:975: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1032,7 +1034,7 @@ fi if test "x$with_ext2direct" != "xno"; then echo $ac_n "checking for com_err in -lcom_err""... $ac_c" 1>&6 -echo "configure:1036: checking for com_err in -lcom_err" >&5 +echo "configure:1038: checking for com_err in -lcom_err" >&5 ac_lib_var=`echo com_err'_'com_err | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1040,7 +1042,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lcom_err $LIBS" cat > conftest.$ac_ext <<EOF -#line 1044 "configure" +#line 1046 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -1051,7 +1053,7 @@ int main() { com_err() ; return 0; } EOF -if { (eval echo configure:1055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1057: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1079,7 +1081,7 @@ else fi echo $ac_n "checking for ext2fs_initialize in -lext2fs""... $ac_c" 1>&6 -echo "configure:1083: checking for ext2fs_initialize in -lext2fs" >&5 +echo "configure:1085: checking for ext2fs_initialize in -lext2fs" >&5 ac_lib_var=`echo ext2fs'_'ext2fs_initialize | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1087,7 +1089,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lext2fs $LIBS" cat > conftest.$ac_ext <<EOF -#line 1091 "configure" +#line 1093 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -1098,7 +1100,7 @@ int main() { ext2fs_initialize() ; return 0; } EOF -if { (eval echo configure:1102: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1104: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1135,17 +1137,17 @@ fi else ac_safe=`echo "ext2fs/ext2fs.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ext2fs/ext2fs.h""... $ac_c" 1>&6 -echo "configure:1139: checking for ext2fs/ext2fs.h" >&5 +echo "configure:1141: checking for ext2fs/ext2fs.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1144 "configure" +#line 1146 "configure" #include "confdefs.h" #include <ext2fs/ext2fs.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1151: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1187,7 +1189,7 @@ EXT2LIBS=${LIBS} LIBS="" echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6 -echo "configure:1191: checking for main in -lnsl" >&5 +echo "configure:1193: checking for main in -lnsl" >&5 ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1195,14 +1197,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <<EOF -#line 1199 "configure" +#line 1201 "configure" #include "confdefs.h" int main() { main() ; return 0; } EOF -if { (eval echo configure:1206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1208: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1230,7 +1232,7 @@ else fi echo $ac_n "checking for main in -lwrap""... $ac_c" 1>&6 -echo "configure:1234: checking for main in -lwrap" >&5 +echo "configure:1236: checking for main in -lwrap" >&5 ac_lib_var=`echo wrap'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1238,14 +1240,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lwrap $LIBS" cat > conftest.$ac_ext <<EOF -#line 1242 "configure" +#line 1244 "configure" #include "confdefs.h" int main() { main() ; return 0; } EOF -if { (eval echo configure:1249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1251: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1276,17 +1278,17 @@ fi if test ${ac_cv_lib_wrap_main} = yes; then ac_safe=`echo "tcpd.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for tcpd.h""... $ac_c" 1>&6 -echo "configure:1280: checking for tcpd.h" >&5 +echo "configure:1282: checking for tcpd.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1285 "configure" +#line 1287 "configure" #include "confdefs.h" #include <tcpd.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1290: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1292: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1316,12 +1318,12 @@ fi fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:1320: checking for working const" >&5 +echo "configure:1322: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1325 "configure" +#line 1327 "configure" #include "confdefs.h" int main() { @@ -1370,7 +1372,7 @@ ccp = (char const *const *) p; ; return 0; } EOF -if { (eval echo configure:1374: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1376: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -1391,21 +1393,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:1395: checking for inline" >&5 +echo "configure:1397: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <<EOF -#line 1402 "configure" +#line 1404 "configure" #include "confdefs.h" int main() { } $ac_kw foo() { ; return 0; } EOF -if { (eval echo configure:1409: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1411: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -1455,6 +1457,14 @@ else enable_rpcsetquota="yes" fi +# Check whether --enable-bsd_behaviour or --disable-bsd_behaviour was given. +if test "${enable_bsd_behaviour+set}" = set; then + enableval="$enable_bsd_behaviour" + : +else + enable_bsd_behaviour="yes" +fi + # Check whether --enable-libefence or --disable-libefence was given. if test "${enable_libefence+set}" = set; then enableval="$enable_libefence" @@ -1473,6 +1483,9 @@ fi if test "$enable_rpcsetquota" = "yes" ; then CFLAGS="-DRPC_SETQUOTA $CFLAGS" fi +if test "$enable_bsd_behaviour" = "yes" ; then + CFLAGS="-DBSD_BEHAVIOUR $CFLAGS" +fi if test "$enable_libefence" = "yes" ; then LIBMALLOC="/usr/lib/libefence.a" fi diff --git a/configure.in b/configure.in index 84606f3..4775238 100644 --- a/configure.in +++ b/configure.in @@ -71,6 +71,10 @@ AC_ARG_ENABLE(rpcsetquota, [ --enable-rpcsetquota=[yes/no] Use RPC for setting quotas [default=yes].], , enable_rpcsetquota="yes") +AC_ARG_ENABLE(bsd_behaviour, + [ --enable-bsd_behaviour=[yes/no] Mimic BSD behaviour [default=yes].], + , + enable_bsd_behaviour="yes") AC_ARG_ENABLE(libefence, [ --enable-libefence=[yes/no] Use Electric Fence memory checks [default=no].], , @@ -85,6 +89,9 @@ fi if test "$enable_rpcsetquota" = "yes" ; then CFLAGS="-DRPC_SETQUOTA $CFLAGS" fi +if test "$enable_bsd_behaviour" = "yes" ; then + CFLAGS="-DBSD_BEHAVIOUR $CFLAGS" +fi if test "$enable_libefence" = "yes" ; then LIBMALLOC="/usr/lib/libefence.a" fi diff --git a/convertquota.c b/convertquota.c index c061459..6d3afbf 100644 --- a/convertquota.c +++ b/convertquota.c @@ -22,9 +22,17 @@ #include "bylabel.h" char *mntpoint; +char *progname; int ucv, gcv; struct quota_handle *qn; /* Handle of new file */ +static void usage(void) +{ + errstr(_("Utility for converting quota files.\nUsage:\n\t%s [-u] [-g] mountpoint\n"), progname); + errstr(_("Bugs to %s\n"), MY_EMAIL); + exit(1); +} + void parse_options(int argcnt, char **argstr) { int ret; @@ -34,15 +42,13 @@ void parse_options(int argcnt, char **argstr) slash = argstr[0]; else slash++; + sstrncpy(cmdname, slash, sizeof(cmdname)); while ((ret = getopt(argcnt, argstr, "Vugh:")) != -1) { switch (ret) { case '?': case 'h': -usage: - printf(_("Utility for converting quota files.\nUsage:\n\t%s [-u] [-g] mountpoint\n"), cmdname); - printf(_("Bugs to %s\n"), MY_EMAIL); - exit(1); + usage(); case 'V': version(); exit(0); @@ -54,12 +60,15 @@ usage: break; } } + if (optind + 1 != argcnt) { puts(_("Bad number of arguments.")); - goto usage; + usage(); } + if (!(ucv | gcv)) ucv = 1; + mntpoint = argstr[optind]; } @@ -79,7 +88,8 @@ int convert_dquot(struct dquot *dquot) newdquot.dq_dqb.dqb_btime = dquot->dq_dqb.dqb_btime; newdquot.dq_dqb.dqb_itime = dquot->dq_dqb.dqb_itime; if (qn->qh_ops->commit_dquot(&newdquot) < 0) { - fprintf(stderr, _("Can't commit dquot for id %u: %s\n"), (uint)dquot->dq_id, strerror(errno)); + errstr(_("Can't commit dquot for id %u: %s\n"), + (uint)dquot->dq_id, strerror(errno)); return -1; } return 0; @@ -103,12 +113,14 @@ void convert_file(int type) } if (!mnt) die(1, _("Can't find given mountpoint %s\n"), mntpoint); - if (!(qo = init_io(mnt, type, QF_VFSOLD))) { - fprintf(stderr, _("Can't open old format file for %ss on %s\n"), type2name(type), mntpoint); + if (!(qo = init_io(mnt, type, QF_VFSOLD, 1))) { + errstr(_("Can't open old format file for %ss on %s\n"), + type2name(type), mntpoint); return; } if (!(qn = new_io(mnt, type, QF_VFSV0))) { - fprintf(stderr, _("Can't create file for %ss for new format on %s: %s\n"), type2name(type), mntpoint, strerror(errno)); + errstr(_("Can't create file for %ss for new format on %s: %s\n"), + type2name(type), mntpoint, strerror(errno)); end_io(qo); return; } @@ -117,7 +129,8 @@ void convert_file(int type) strcpy(namebuf, qfname); sstrncat(namebuf, ".new", sizeof(namebuf)); if (rename(namebuf, qfname) < 0) - fprintf(stderr, _("Can't rename new quotafile %s to name %s: %s\n"), namebuf, qfname, strerror(errno)); + errstr(_("Can't rename new quotafile %s to name %s: %s\n"), + namebuf, qfname, strerror(errno)); free(qfname); } endmntent(mntf); @@ -125,13 +138,19 @@ void convert_file(int type) end_io(qn); } -int main(int argcnt, char **argstr) +int main(int argc, char **argv) { - parse_options(argcnt, argstr); + gettexton(); + progname = basename(argv[0]); + + parse_options(argc, argv); + if (ucv) convert_file(USRQUOTA); + if (ucv) convert_file(GRPQUOTA); + return 0; } @@ -5,18 +5,23 @@ edquota \- edit user quotas .B edquota [ .B \-p -.I proto-username +.I protoname ] [ .B \-ug +] [ +.B \-r +] [ +.B \-F +.I format-name ] .IR username .\|.\|. .LP .B edquota [ -.B \-r -] -[ .B \-ug +] [ +.B \-F +.I format-name ] .B \-t .SH DESCRIPTION @@ -70,19 +75,30 @@ Edit the user quota. This is the default. .B \-g Edit the group quota. .TP -.B \-p +.B \-p \f2protoname\f1 Duplicate the quotas of the prototypical user specified for each user specified. This is the normal mechanism used to initialize quotas for groups of users. .TP +.B \-F \f2format-name\f1 +Edit quota for specified format (ie. don't perform format autodetection). +Possible format names are: +.B vfsold +(version 1 quota), +.B vfsv0 +(version 2 quota), +.B rpc +(quota over NFS), +.B xfs +(quota on XFS filesystem) +.TP .B \-t Edit the soft time limits for each filesystem. -If the time limits are zero, the default time limits in +In old quota format if the time limits are zero, the default time limits in .B <linux/quota.h> -are used. -Time units of seconds, minutes, hours, days, weeks, and months -are understood. -Time limits are printed in the greatest possible time unit such that +are used. In new quota format time limits must be specified (there is no default +value set in kernel). Time units of seconds, minutes, hours, days, weeks, and months +are understood. Time limits are printed in the greatest possible time unit such that the value is greater than or equal to one. .SH FILES .PD 0 @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: edquota.c,v 1.3 2001/04/26 09:36:08 jkar8572 Exp $" +#ident "$Id: edquota.c,v 1.4 2001/05/02 09:32:22 jkar8572 Exp $" /* * Disk quota editor. @@ -58,22 +58,22 @@ #include "quotaio.h" #include "common.h" -static char tmpfil[] = _PATH_TMP "EdP.aXXXXXX"; +char *progname; void usage(void) { #if defined(RPC_SETQUOTA) - fprintf(stderr, "%s%s%s%s", + errstr("%s%s%s%s", _("Usage:\tedquota [-r] [-u] [-F formatname] [-p username] username ...\n"), - _("\tedquota [-r] -g [-p groupname] groupname ...\n"), - _("\tedquota [-r] [-u] -t\n"), _("\tedquota [-r] -g -t\n")); + _("\tedquota [-r] -g [-F formatname] [-p groupname] groupname ...\n"), + _("\tedquota [-r] [-u] [-F formatname] -t\n"), _("\tedquota [-r] -g [-F formatname] -t\n")); #else - fprintf(stderr, "%s%s%s%s", + errstr("%s%s%s%s", _("Usage:\tedquota [-u] [-F formatname] [-p username] username ...\n"), - _("\tedquota -g [-p groupname] groupname ...\n"), - _("\tedquota [-u] -t\n"), _("\tedquota -g -t\n")); + _("\tedquota -g [-F formatname] [-p groupname] groupname ...\n"), + _("\tedquota [-u] [-F formatname] -t\n"), _("\tedquota -g [-F formatname] -t\n")); #endif - fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL); + errstr(_("Bugs to: %s\n"), MY_EMAIL); exit(1); } @@ -85,8 +85,10 @@ int main(int argc, char **argv) char *protoname = NULL; int tflag = 0, pflag = 0, rflag = 0, fmt = -1; struct quota_handle **handles; + char *tmpfil, *tmpdir = NULL; gettexton(); + progname = basename(argv[0]); if (argc < 2) usage(); @@ -134,7 +136,7 @@ int main(int argc, char **argv) if (tflag && argc != 0) usage(); - handles = create_handle_list(0, NULL, quotatype, fmt, (rflag == 0)); + handles = create_handle_list(0, NULL, quotatype, fmt, rflag ? 0 : IOI_LOCALONLY); if (!handles[0]) { dispose_handle_list(handles); fputs(_("No filesystems with quota detected.\n"), stderr); @@ -154,7 +156,7 @@ int main(int argc, char **argv) for (pprivs = protoprivs, cprivs = curprivs; pprivs && cprivs; pprivs = pprivs->dq_next, cprivs = cprivs->dq_next) { if (!devcmp_handles(pprivs->dq_h, cprivs->dq_h)) - fprintf(stderr, _("fsname mismatch\n")); + errstr(_("fsname mismatch\n")); else { cprivs->dq_dqb.dqb_bsoftlimit = pprivs->dq_dqb.dqb_bsoftlimit; @@ -174,6 +176,13 @@ int main(int argc, char **argv) } umask(077); + if (getuid() == geteuid() && getgid() == getegid()) + tmpdir = getenv("TMPDIR"); + if (!tmpdir) + tmpdir = _PATH_TMP; + tmpfil = smalloc(strlen(tmpdir) + strlen("/EdP.aXXXXXX") + 1); + strcpy(tmpfil, tmpdir); + strcat(tmpfil, "/EdP.aXXXXXX"); tmpfd = mkstemp(tmpfil); fchown(tmpfd, getuid(), getgid()); if (tflag) { @@ -196,5 +205,6 @@ int main(int argc, char **argv) close(tmpfd); unlink(tmpfil); + free(tmpfil); return 0; } @@ -9,7 +9,7 @@ #define MNTTYPE_MINIX "minix" /* MINIX file system */ #define MNTTYPE_UFS "ufs" /* UNIX file system */ #define MNTTYPE_UDF "udf" /* OSTA UDF file system */ -#define MNTTYPE_REISER "reiser" /* Reiser file system */ +#define MNTTYPE_REISER "reiserfs" /* Reiser file system */ #define MNTTYPE_XFS "xfs" /* SGI XFS file system */ /* mount options */ @@ -9,7 +9,8 @@ quot \- summarize filesystem ownership .IR quot displays the number of kilobytes in the named .I filesystem -currently owned by each user or group. +currently owned by each user or group. Note that this utility +currently works only for XFS. .SH OPTIONS .TP .B \-a @@ -66,8 +66,8 @@ static int fflag; static int gflag; static int uflag; static int vflag; -static char *progname; static time_t now; +char *progname; static void mounttable(char *); static char *idname(__uint32_t, int); @@ -76,7 +76,7 @@ static void creport(const char *, char *); static void usage(void) { - fprintf(stderr, _("Usage: %s [-acfugvV] [filesystem...]\n"), progname); + errstr(_("Usage: %s [-acfugvV] [filesystem...]\n")); exit(1); } @@ -135,7 +135,7 @@ static void mounttable(char *entry) int doit; if ((mtab = setmntent(MOUNTED, "r")) == NULL) { - fprintf(stderr, _("%s: no " MOUNTED " file\n"), progname); + errstr(_("no " MOUNTED " file\n")); exit(1); } while ((mntp = getmntent(mtab)) != NULL) { @@ -165,7 +165,7 @@ static void mounttable(char *entry) } } if (entry != NULL) - fprintf(stderr, _("%s: cannot locate block device for %s\n"), progname, entry); + errstr(_("cannot locate block device for %s\n"), entry); endmntent(mtab); } @@ -361,7 +361,7 @@ static void checkXFS(const char *file, char *fsdir) fsfd = open(fsdir, O_RDONLY); if (fsfd < 0) { - fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, fsdir, strerror(errno)); + errstr(_("cannot open %s: %s\n"), fsdir, strerror(errno)); exit(1); } sync(); @@ -381,8 +381,8 @@ static void checkXFS(const char *file, char *fsdir) acctXFS(&buf[i]); } if (sts < 0) { - fprintf(stderr, _("%s: XFS_IOC_FSBULKSTAT ioctl failed: %s\n"), - progname, strerror(errno)); + errstr(_("XFS_IOC_FSBULKSTAT ioctl failed: %s\n"), + strerror(errno)); exit(1); } free(buf); @@ -3,19 +3,22 @@ quota \- display disk usage and limits .SH SYNOPSIS quota [ -.B -n +.B -F +.I format-name ] [ .B -guv | q ] .br quota [ -.B -n +.B -F +.I format-name ] [ .B -uv | q ] user .br quota [ -.B -n +.B -F +.I format-name ] [ .B -gv | q ] group @@ -31,8 +34,17 @@ For filesystems that are NFS-mounted a call to the rpc.rquotad on the server machine is performed to get the information. .SH OPTIONS .TP -.B \-n -Print info on numeric arguments e.g. uids and gids instead of users and groups +.B \-F \f2format-name\f1 +Show quota for specified format (ie. don't perform format autodetection). +Possible format names are: +.B vfsold +(version 1 quota), +.B vfsv0 +(version 2 quota), +.B rpc +(quota over NFS), +.B xfs +(quota on XFS filesystem) .TP .B \-g Print group quotas for the group @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: quota.c,v 1.4 2001/04/26 09:36:08 jkar8572 Exp $" +#ident "$Id: quota.c,v 1.5 2001/05/02 09:32:22 jkar8572 Exp $" /* * Disk quota reporting program. @@ -61,9 +61,10 @@ #include "common.h" int qflag, vflag, fmt = -1; +char *progname; void usage(void); -void showquotas(int type, qid_t id); +int showquotas(int type, qid_t id); void heading(int type, qid_t id, char *name, char *tag); int main(int argc, char **argv) @@ -73,6 +74,7 @@ int main(int argc, char **argv) int i, ret, gflag = 0, uflag = 0; gettexton(); + progname = basename(argv[0]); while ((ret = getopt(argc, argv, "guqvVF:")) != -1) { switch (ret) { @@ -122,38 +124,39 @@ int main(int argc, char **argv) if (uflag && gflag) usage(); + ret = 0; if (uflag) for (; argc > 0; argc--, argv++) - showquotas(USRQUOTA, user2uid(*argv)); + ret |= showquotas(USRQUOTA, user2uid(*argv)); else if (gflag) for (; argc > 0; argc--, argv++) - showquotas(GRPQUOTA, group2gid(*argv)); - return 0; + ret |= showquotas(GRPQUOTA, group2gid(*argv)); + return ret; } void usage(void) { - fprintf(stderr, "%s\n%s\n%s\n", - _("Usage: quota [-guqvV] [-F quotaformat]"), - _("\tquota [-qv] [-F quotaformat] -u username ..."), - _("\tquota [-qv] [-F quotaformat] -g groupname ...")); - fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL); + errstr( "%s%s%s", + _("Usage: quota [-guqv] [-F quotaformat]\n"), + _("\tquota [-qv] [-F quotaformat] -u username ...\n"), + _("\tquota [-qv] [-F quotaformat] -g groupname ...\n")); + errstr(_("Bugs to: %s\n"), MY_EMAIL); exit(1); } -void showquotas(int type, qid_t id) +int showquotas(int type, qid_t id) { struct dquot *qlist, *q; char *msgi, *msgb; char timebuf[MAXTIMELEN]; char name[MAXNAMELEN]; struct quota_handle **handles; - int lines = 0; + int lines = 0, over = 0; time_t now; time(&now); id2name(id, type, name); - handles = create_handle_list(0, NULL, type, fmt, 0); + handles = create_handle_list(0, NULL, type, fmt, IOI_READONLY); qlist = getprivs(id, handles); for (q = qlist; q; q = q->dq_next) { if (!vflag && !q->dq_dqb.dqb_isoftlimit && !q->dq_dqb.dqb_ihardlimit @@ -166,8 +169,10 @@ void showquotas(int type, qid_t id) && q->dq_dqb.dqb_curinodes >= q->dq_dqb.dqb_isoftlimit) { if (q->dq_dqb.dqb_itime > now) msgi = _("In file grace period on"); - else + else { msgi = _("Over file quota on"); + over = 1; + } } msgb = NULL; if (q->dq_dqb.dqb_bhardlimit @@ -177,8 +182,10 @@ void showquotas(int type, qid_t id) && toqb(q->dq_dqb.dqb_curspace) >= q->dq_dqb.dqb_bsoftlimit) { if (q->dq_dqb.dqb_btime > now) msgb = _("In block grace period on"); - else + else { msgb = _("Over block quota on"); + over = 1; + } } if (qflag) { if ((msgi || msgb) && !lines++) @@ -213,6 +220,7 @@ void showquotas(int type, qid_t id) heading(type, id, name, _("none")); freeprivs(qlist); dispose_handle_list(handles); + return over; } void heading(int type, qid_t id, char *name, char *tag) diff --git a/quotacheck.8 b/quotacheck.8 index 7270040..2a7489a 100644 --- a/quotacheck.8 +++ b/quotacheck.8 @@ -1,51 +1,90 @@ -.TH QUOTACHECK 8 +.TH quotacheck 8 "Mon Jul 17 2000" .SH NAME -quotacheck \- scan a filesystem for disk usages +quotacheck \- scan a file system for disk usages, create, check and repair quota files .SH SYNOPSIS .B quotacheck -[-g] [-u] [-v] -a +[ +.B \-gucfinvdMmR +] [ +.B \-F +.I quota-format +] +.B \-a +| +.I filesystem .br -.B quotacheck -[-g] [-u] [-v] filesys ... .SH DESCRIPTION -.I Quotacheck -performs a filesystems scan for usage of files and directories, used -by either user or group. -XFS filesystems are ignored by -.IR quotacheck , -since the XFS quota system is journaled and therefore inherently consistent. -.PP -The output is the quota file for the corresponding filesystem. -By default the names for these files are: +.B Quotacheck +first checks old quota files for given filesystem and reads user / group limits +from them (if it is creating new files -- see option +.B -c +-- this step is ommited, of course). Then performs a filesystem scan for usage +of files and directories, used by either user or group. The output are new quota +files for the corresponding filesystem. The names of these files are: .br \- A user scan: -.I quota.user +.B aquota.user +or +.B quota.user +(depending on quota format) .br \- A group scan: -.I quota.group +.B aquota.group +or +.B quota.group +.PP +Old files are stored as +.B aquota.user~ +/ +.B quota.user~ +and +.B aquota.group~ +/ +.BR quota.group~ . .PP -The resulting file consists of a -.I struct dqblk -for each possible id up to the highest existing uid or gid and contains the -values for the disk file and block usage and possibly excess time for these -values. ( for definitions of -.I struct dqblk -see -.I \<linux/quota.h\> -) +Old quota format (version 1) has no way of detecting quotafile corruption and so +following text is meaningful only for version 2 quota format. When quota file is corrupted, +.B quotacheck +tries to save as many data as possible (which can sometimes result in bogus entries +being created). Rescuing data might need user intervention. With no special options +.B quotacheck +will simply exit in that situation. When in interactive mode (option +.BR -i ) +user is asked for an advice. Advices can be also provided from command line (see option +.BR -n ) +which is handful when +.B quotacheck +is run automatically (ie. from script) and you can't +afford +.B quotacheck +to fail. .PP -.I Quotacheck -should be run each time the system boots and mounts non-valid filesystems. +.B Quotacheck +should be run each time the system boots and mounts non-valid file systems. This is most likely to happen after a system crash. .PP -The speed of the scan decreases with the number of directories increasing. -The time needed doubles when disk usage is doubled as well. A 100 MB partition -used for 94% is scanned in 1 minute, the same partition used for 50% is -done in 25 seconds. +It is strongly recommended to run +.B quotacheck +with quotas turned off on concerned file system. Otherwise you can loose or damage some +data in quota files. Also it is wise not to run +.B quotacheck +on live filesystem as directory scan might count bogus usage in that case. To prevent this +.B quotacheck +tries to remount filesystem read-only before starting the scan of filesystem and after +the scan is done it remounts filesystem read-write. You can turn off this feature by +option +.BR \-m . +You can also make +.B quotacheck +ignore that it didn't succeed when remounting filesystem read-only by option +.BR \-M . +.PP +The speed of the scan decrease with the amount of directories increasing. +The time needed doubles when disk usage is doubled as well. .SH OPTIONS .TP .B \-v -This way the program will give some useful information about what it is +This way the program will give some usefull information about what it is doing, plus some fancy stuff. .TP .B \-d @@ -58,37 +97,93 @@ This flag tells the program to scan the disk and to count the files and directories used by a certain uid. This is the default action. .TP .B \-g -This flag forces the program to count the files and directories +This flag forces the program to count the the files and directories used by a certain gid. .TP +.B \-c +Don't read old quota files. Just perform directory scan and dump usage. +.TP +.B \-f +This flags forces checking of filesystem with quotas enabled. Note that doing +this is not recomended as created quota files might be damaged or out of date. +.TP +.B \-M +This flag forces checking of filesystem in read-write mode if remount fails. Do this only when +you are sure no process will write to a filesystem while scanning. +.TP +.B \-m +Don't try to remount filesystem read-only. See comment at option +.BR \-M . +.TP +.B \-i +Interactive mode. By default +.B quotacheck +exits when it finds some error. In interactive mode user is asked for an advice instead. +See also option +.BR \-n . +.TP +.B \-n +Sometimes it may happen that more entries for the same id are found. Normally +.B quotacheck +exits or asks user. When this option is set first entry found is always used (this option +works in interactive mode too). +.TP +.B \-F \f2format-name\f1 +Check quota quota for specified format (ie. don't perform format autodetection). This is +recommended as detection might not work well on corrupted quotafiles. +Possible format names are: +.B vfsold +(version 1 quota), +.B vfsv0 +(version 2 quota), +.B rpc +(quota over NFS), +.B xfs +(quota on XFS filesystem) +.TP .B \-a -Check all of the quotas for the filesystems mentioned in /etc/mtab. Both -user and group quotas are checked as indicated by the /etc/mtab options. +Check all filesystems in +.B /etc/mtab .TP .B \-R -When used in conjunction with \fP\-a\fR, all filesystems except the root -filesystem are checked for quotas. +When used together with +.B \-a +option, all filesystems except root filesystem are checked for quotas. .SH NOTE -.I Quotacheck -should only be run as Super User. Non-privilidged users are presumably not allowed +.B Quotacheck +should only be run by super-user. Non-priviledged users are presumably not allowed to read all the directories on the given filesystem. .SH "SEE ALSO" -quota(1), quotactl(2), fstab(5), quotaon(8), quotaoff(8), edquota(8), -repquota(8), fsck(8) +.BR quota (1), +.BR quotactl (2), +.BR fstab (5), +.BR quotaon (8), +.BR repquota (8), +.BR convertquota (8), +.BR setquota (8), +.BR edquota (8), +.BR fsck (8), +.BR efsck (8), +.BR e2fsck (8), +.BR xfsck (8) .SH FILES .PD 0 -.TP 20 +.TP 15 .B aquota.user or aquota.group -quota file at the filesystem root (version 2 quota, non-XFS filesystems) -.TP 20 +located at filesystem root with user quotas (version 2 quota, non-XFS filesystems) +.TP 15 .B quota.user or quota.group -quota file at the filesystem root (version 1 quota, non-XFS filesystems) +located at filesystem root with user quotas (version 1 quota, non-XFS filesystems) .TP .B /etc/mtab -default filesystems -.PD -.SH "AUTHOR" +names and locations of mounted filesystems +.SH AUTHOR +Jan Kara \<jack@suse.cz\> +.br +Based on old +.B quotacheck +by: +.br Edvard Tuinder \<ed@elm.net\> .br Marco van Wieringen \<mvw@planets.elm.net\> - diff --git a/quotacheck.c b/quotacheck.c index f1f02a8..6c01ffd 100644 --- a/quotacheck.c +++ b/quotacheck.c @@ -8,7 +8,7 @@ * New quota format implementation - Jan Kara <jack@suse.cz> - Sponsored by SuSE CR */ -#ident "$Id: quotacheck.c,v 1.7 2001/04/26 09:36:08 jkar8572 Exp $" +#ident "$Id: quotacheck.c,v 1.8 2001/05/02 09:32:22 jkar8572 Exp $" #include <dirent.h> #include <stdio.h> @@ -60,6 +60,7 @@ int files_done, dirs_done; int flags, fmt = -1, cfmt; /* Options from command line; Quota format to use spec. by user; Actual format to check */ int uwant, gwant, ucheck, gcheck; /* Does user want to check user/group quota; Do we check user/group quota? */ char *mntpoint; /* Mountpoint to check */ +char *progname; struct util_dqinfo old_info[MAXQUOTAS]; /* Loaded infos */ char extensions[MAXQUOTAS + 2][20] = INITQFNAMES; /* Extensions depending on quota type */ @@ -96,6 +97,8 @@ void debug(int df, char *fmtstr, ...) if (!(flags & df)) return; + + fprintf(stderr, "%s: ", progname); va_start(args, fmtstr); vfprintf(stderr, fmtstr, args); va_end(args); @@ -271,15 +274,16 @@ static inline void blit(void) bitc %= BITS_SIZE; } +static void usage(void) +{ + printf(_("Utility for checking and repairing quota files.\n%s [-gucfinvdmMR] [-F <quota-format>] filesystem|-a\n"), progname); + printf(_("Bugs to %s\n"), MY_EMAIL); + exit(1); +} + static void parse_options(int argcnt, char **argstr) { int ret; - char *slash = strrchr(argstr[0], '/'); - - if (slash) - slash++; - else - slash = argstr[0]; while ((ret = getopt(argcnt, argstr, "VhcvugidnfF:mMRa")) != -1) { switch (ret) { @@ -328,17 +332,14 @@ static void parse_options(int argcnt, char **argstr) exit(1); break; default: - usage: - printf(_("Utility for checking and repairing quota files.\n%s [-gucfinvdmMR] [-F <quota-format>] filesystem|-a\n"), slash); - printf(_("Bugs to %s\n"), MY_EMAIL); - exit(1); + usage(); } } if (!(uwant | gwant)) uwant = 1; if (argcnt == optind && !(flags & FL_ALL)) { fputs(_("Bad number of arguments.\n"), stderr); - goto usage; + usage(); } if (fmt == QF_XFS) { fputs(_("XFS quota format needs no checking.\n"), stderr); @@ -365,30 +366,27 @@ static int ext2_direct_scan(char *device) ext2fs_inode_bitmap inode_dir_map; if ((error = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs))) { - fprintf(stderr, _("quotacheck: error (%d) while opening %s\n"), (int)error, device); + errstr(_("error (%d) while opening %s\n"), (int)error, device); return -1; } if ((error = ext2fs_allocate_inode_bitmap(fs, "in-use inode map", &inode_used_map))) { - fprintf(stderr, _("quotacheck: error (%d) while allocating inode file bitmap\n"), - (int)error); + errstr(_("error (%d) while allocating inode file bitmap\n"), (int)error); return -1; } if ((error = ext2fs_allocate_inode_bitmap(fs, "directory inode map", &inode_dir_map))) { - fprintf(stderr, - _("quotacheck: error (%d) while allocating inode directory bitmap\n"), - (int)error); + errstr(_("errstr (%d) while allocating inode directory bitmap\n"), (int)error); return -1; } if ((error = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan))) { - fprintf(stderr, _("quotacheck: error (%d) while opening inode scan\n"), (int)error); + errstr(_("error (%d) while opening inode scan\n"), (int)error); return -1; } if ((error = ext2fs_get_next_inode(scan, &i_num, &inode))) { - fprintf(stderr, _("quotacheck: error (%d) while starting inode scan\n"), (int)error); + errstr(_("error (%d) while starting inode scan\n"), (int)error); return -1; } @@ -412,8 +410,7 @@ static int ext2_direct_scan(char *device) } if ((error = ext2fs_get_next_inode(scan, &i_num, &inode))) { - fprintf(stderr, _("Something weird happened while scanning. Error %d\n"), - (int)error); + errstr(_("Something weird happened while scanning. Error %d\n"), (int)error); return -1; } } @@ -447,9 +444,7 @@ static int scan_dir(char *pathname) blit(); if ((lstat(de->d_name, &st)) == -1) { - fprintf(stderr, - _ - ("lstat Cannot stat `%s/%s': %s\nGuess you'd better run fsck first !\nexiting...\n"), + errstr(_("lstat Cannot stat `%s/%s': %s\nGuess you'd better run fsck first !\nexiting...\n"), pathname, de->d_name, strerror(errno)); goto out; } @@ -556,25 +551,25 @@ static int process_file(char *mnt_fsname, struct mntent *mnt, int type) } } else - die(6, - _ - ("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n\ + die(6, _("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n\ Please turn quotas off or use -f to force checking.\n"), type2name(type), mnt->mnt_dir); } /* At least sync quotas so damage will be smaller */ if (quotactl(QCMD(Q_SYNC, type), mnt_fsname, 0, NULL) < 0) - die(4, _("Error while syncing quotas: %s\n"), strerror(errno)); + die(4, _("Error while syncing quotas on %s: %s\n"), mnt_fsname, strerror(errno)); } if (!(flags & FL_NEWFILE)) { /* Need to really buffer file? */ qfname = get_qf_name(mnt, type, cfmt); if (!qfname) { - fprintf(stderr, _("Cannot get quotafile name for %s\n"), mnt_fsname); + errstr(_("Cannot get quotafile name for %s\n"), + mnt_fsname); return -1; } if ((fd = open(qfname, O_RDONLY)) < 0) { - fprintf(stderr, _("Cannot open quotafile %s: %s\n"), qfname, strerror(errno)); + errstr(_("Cannot open quotafile %s: %s\n"), + qfname, strerror(errno)); free(qfname); return -1; } @@ -584,7 +579,8 @@ Please turn quotas off or use -f to force checking.\n"), memset(old_info + type, 0, sizeof(old_info[type])); switch (cfmt) { case QF_TOONEW: - fprintf(stderr, _("Too new quotafile format on %s\n"), mnt_fsname); + errstr(_("Too new quotafile format on %s\n"), + mnt_fsname); ret = -1; break; case QF_VFSOLD: @@ -606,6 +602,7 @@ static int rename_files(struct mntent *mnt, int type) { char *filename, newfilename[PATH_MAX]; struct stat st; + mode_t mode = S_IRUSR | S_IWUSR; if (!(filename = get_qf_name(mnt, type, cfmt))) die(2, _("Cannot get name of old quotafile on %s.\n"), mnt->mnt_dir); @@ -615,11 +612,12 @@ static int rename_files(struct mntent *mnt, int type) debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n")); goto rename_new; } - fprintf(stderr, _("Error while searching for old quota file %s: %s\n"), filename, - strerror(errno)); + errstr(_("Error while searching for old quota file %s: %s\n"), + filename, strerror(errno)); free(filename); return -1; } + mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); /* Backup old file */ strcpy(newfilename, filename); /* Make backingup safe */ @@ -627,8 +625,8 @@ static int rename_files(struct mntent *mnt, int type) if (newfilename[strlen(newfilename) - 1] != '~') die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL); if (rename(filename, newfilename) < 0) { - fprintf(stderr, _("Cannot rename old quotafile %s to %s: %s\n"), filename, - newfilename, strerror(errno)); + errstr(_("Cannot rename old quotafile %s to %s: %s\n"), + filename, newfilename, strerror(errno)); free(filename); return -1; } @@ -638,8 +636,13 @@ static int rename_files(struct mntent *mnt, int type) strcpy(newfilename, filename); sstrncat(newfilename, ".new", PATH_MAX); if (rename(newfilename, filename) < 0) { - fprintf(stderr, _("Cannot rename new quotafile %s to name %s: %s\n"), newfilename, - filename, strerror(errno)); + errstr(_("Cannot rename new quotafile %s to name %s: %s\n"), + newfilename, filename, strerror(errno)); + free(filename); + return -1; + } + if (chmod(filename, mode) < 0) { + errstr(_("Cannot change permission of %s: %s\n"), filename, strerror(errno)); free(filename); return -1; } @@ -660,7 +663,8 @@ static int dump_to_file(char *mnt_fsname, struct mntent *mnt, int type) debug(FL_DEBUG | FL_VERBOSE, _("Dumping gathered data for %ss.\n"), type2name(type)); if (!(h = new_io(mnt, type, cfmt))) { - fprintf(stderr, _("Cannot initialize IO on new quotafile: %s\n"), strerror(errno)); + errstr(_("Cannot initialize IO on new quotafile: %s\n"), + strerror(errno)); return -1; } memcpy(&h->qh_info, old_info + type, sizeof(h->qh_info)); @@ -676,7 +680,8 @@ static int dump_to_file(char *mnt_fsname, struct mntent *mnt, int type) h->qh_ops->commit_dquot(dquot); } if (end_io(h) < 0) { - fprintf(stderr, _("Cannot finish IO on new quotafile: %s\n"), strerror(errno)); + errstr(_("Cannot finish IO on new quotafile: %s\n"), + strerror(errno)); return -1; } if (rename_files(mnt, type) < 0) @@ -687,9 +692,8 @@ static int dump_to_file(char *mnt_fsname, struct mntent *mnt, int type) filename = get_qf_name(mnt, type, cfmt); if (quotactl(QCMD(Q_QUOTAOFF, type), mnt_fsname, 0, NULL) || quotactl(QCMD(Q_QUOTAON, type), mnt_fsname, 0, filename)) - fprintf(stderr, - _ - ("Cannot turn %s quotas on %s off and on: %s\nKernel won't know about changes quotacheck did.\n"), + errstr( + _("Cannot turn %s quotas on %s off and on: %s\nKernel won't know about changes quotacheck did.\n"), type2name(type), mnt_fsname, strerror(errno)); free(filename); } @@ -741,9 +745,8 @@ mnt->mnt_dir); } } else { - fprintf(stderr, - _ - ("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\ + errstr( + _("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\ Please stop all programs writing to filesystem or use -m flag to force checking.\n"), mnt->mnt_dir); goto out; @@ -790,12 +793,12 @@ static int detect_filename_format(struct mntent *mnt, int type) struct stat statbuf; char namebuf[PATH_MAX]; - sprintf(namebuf, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSV0], extensions[type]); + snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSV0], extensions[type]); if (!stat(namebuf, &statbuf)) return QF_VFSV0; if (errno != ENOENT) return -1; - sprintf(namebuf, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSOLD], extensions[type]); + snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSOLD], extensions[type]); if (!stat(namebuf, &statbuf)) return QF_VFSOLD; return -1; @@ -845,7 +848,8 @@ static void check_all(void) continue; if (cfmt == -1) { if ((cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : GRPQUOTA)) == -1) { - fprintf(stderr, _("Cannot guess format from filename on %s. Please specify format on commandline.\n"), mnt_fslabel); + errstr(_("Cannot guess format from filename on %s. Please specify format on commandline.\n"), + mnt_fslabel); continue; } debug(FL_DEBUG | FL_VERBOSE, _("Detected quota format %s\n"), fmt2name(cfmt)); @@ -860,15 +864,17 @@ static void check_all(void) free(devlist[i]); } -int main(int argcnt, char **argstr) +int main(int argc, char **argv) { gettexton(); - parse_options(argcnt, argstr); + progname = basename(argv[0]); + + parse_options(argc, argv); warn_new_kernel(fmt); check_all(); #ifdef DEBUG_MALLOC - fprintf(stderr, _("Allocated %d bytes memory\nFree'd %d bytes\nLost %d bytes\n"), + errstr(_("Allocated %d bytes memory\nFree'd %d bytes\nLost %d bytes\n"), malloc_mem, free_mem, malloc_mem - free_mem); #endif return 0; diff --git a/quotacheck_v1.c b/quotacheck_v1.c index db21c94..7fe8012 100644 --- a/quotacheck_v1.c +++ b/quotacheck_v1.c @@ -30,7 +30,8 @@ static void load_dquots(char *filename, int fd, int type) die(1, _("Can't read entry for id %u from quotafile %s: %s\n"), (uint) id, filename, strerror(errno)); if (err != sizeof(ddqblk)) { - fprintf(stderr, _("Entry for id %u is truncated.\n"), (uint) id); + errstr(_("Entry for id %u is truncated.\n"), + (uint) id); break; } dquot = add_dquot(id, type); @@ -58,9 +59,8 @@ static int check_info(char *filename, int fd, int type) die(1, _("Can't read first entry from quotafile %s: %s\n"), filename, strerror(errno)); if (err != sizeof(ddqblk)) { - fprintf(stderr, - _ - ("WARNING: Quotafile %s was probably truncated. Can't save quota settings...\n"), + errstr( + _("WARNING - Quotafile %s was probably truncated. Can't save quota settings...\n"), filename); return -1; } diff --git a/quotacheck_v2.c b/quotacheck_v2.c index 31a558f..da3ede3 100644 --- a/quotacheck_v2.c +++ b/quotacheck_v2.c @@ -53,11 +53,12 @@ static int check_info(char *filename, int fd, int type) err = read(fd, &dinfo, sizeof(struct v2_disk_dqinfo)); if (err < 0) { - fprintf(stderr, _("Can't read info from quota file %s: %s\n"), filename, strerror(errno)); + errstr(_("Can't read info from quota file %s: %s\n"), + filename, strerror(errno)); return -1; } if (err != sizeof(struct v2_disk_dqinfo)) { - fprintf(stderr, _("WARNING: Quota file %s was probably truncated. Can't save quota settings...\n"), + errstr(_("WARNING - Quota file %s was probably truncated. Can't save quota settings...\n"), filename); return -1; } @@ -69,7 +70,7 @@ static int check_info(char *filename, int fd, int type) filesize = lseek(fd, 0, SEEK_END); if (check_blkref(freeblk, blocks) < 0 || dflags & ~V2_DQF_MASK || check_blkref(freeent, blocks) < 0 || (filesize + V2_DQBLKSIZE - 1) >> V2_DQBLKSIZE_BITS != blocks) { - fprintf(stderr, _("WARNING: Quota file info was corrupted.\n")); + errstr(_("WARNING - Quota file info was corrupted.\n")); debug(FL_DEBUG, _("Size of file: %lu\nBlocks: %u Free block: %u Block with free entry: %u Flags: %x\n"), (unsigned long)filesize, blocks, freeblk, freeent, dflags); old_info[type].dqi_bgrace = MAX_DQ_TIME; @@ -91,27 +92,27 @@ static int check_info(char *filename, int fd, int type) return 0; } -/* Print error message */ +/* Print errstr message */ static void blk_corrupted(int *corrupted, uint * lblk, uint blk, char *fmtstr, ...) { va_list args; if (!*corrupted) { if (!(flags & (FL_VERBOSE | FL_DEBUG))) - fprintf(stderr, _("Corrupted blocks: ")); + errstr(_("Corrupted blocks: ")); } if (flags & (FL_VERBOSE | FL_DEBUG)) { va_start(args, fmtstr); - fprintf(stderr, _("Block %u: "), blk); + errstr(_("Block %u: "), blk); vfprintf(stderr, fmtstr, args); fputc('\n', stderr); va_end(args); } else if (*lblk != blk) { if (!*corrupted) - fprintf(stderr, "%u", blk); + errstr( "%u", blk); else - fprintf(stderr, ", %u", blk); + errstr( ", %u", blk); } *corrupted = 1; *lblk = blk; @@ -157,13 +158,13 @@ static int buffer_entry(dqbuf_t buf, uint blk, int *corrupted, uint * lblk, int if (flags & FL_GUESSDQ) { if (!(flags & (FL_DEBUG | FL_VERBOSE))) fputc('\n', stderr); - fprintf(stderr, _("Found more structures for ID %u. Using values: BHARD: %Ld BSOFT: %Ld IHARD: %Ld ISOFT: %Ld\n"), + errstr(_("Found more structures for ID %u. Using values: BHARD: %Ld BSOFT: %Ld IHARD: %Ld ISOFT: %Ld\n"), (uint) id, (long long)fdq->dqb_bhardlimit, (long long)fdq->dqb_bsoftlimit, (long long)fdq->dqb_ihardlimit, (long long)fdq->dqb_isoftlimit); return 0; } else if (flags & FL_INTERACTIVE) { - fprintf(stderr, _("\nFound more structures for ID %u. Values: BHARD: %Ld/%Ld BSOFT: %Ld/%Ld IHARD: %Ld/%Ld ISOFT: %Ld/%Ld\n"), + errstr(_("\nFound more structures for ID %u. Values: BHARD: %Ld/%Ld BSOFT: %Ld/%Ld IHARD: %Ld/%Ld ISOFT: %Ld/%Ld\n"), (uint) id, (long long)fdq->dqb_bhardlimit, (long long)mdq.dqb_bhardlimit, (long long)fdq->dqb_bsoftlimit, (long long)mdq.dqb_bsoftlimit, (long long)fdq->dqb_ihardlimit, (long long)mdq.dqb_ihardlimit, @@ -178,7 +179,7 @@ static int buffer_entry(dqbuf_t buf, uint blk, int *corrupted, uint * lblk, int } } else { - fprintf(stderr, _("ID %u has more structures. User intervention needed (use -i for interactive mode or -n for automatic answer).\n"), + errstr(_("ID %u has more structures. User intervention needed (use -i for interactive mode or -n for automatic answer).\n"), (uint) id); return -1; } @@ -296,12 +297,13 @@ static int check_header(char *filename, int fd, int type) if (err < 0) die(1, _("Can't read header from quotafile %s: %s\n"), filename, strerror(errno)); if (err != sizeof(head)) { - fprintf(stderr, _("WARNING: Quotafile %s was probably truncated. Can't save quota settings...\n"), + errstr(_("WARNING - Quotafile %s was probably truncated. Can't save quota settings...\n"), filename); return -1; } if (__le32_to_cpu(head.dqh_magic) != magics[type] || __le32_to_cpu(head.dqh_version) > known_versions[type]) - fprintf(stderr, _("WARNING: Quota file %s has corrupted headers\n"), filename); + errstr(_("WARNING - Quota file %s has corrupted headers\n"), + filename); debug(FL_DEBUG, _("Headers checked.\n")); return 0; } @@ -328,7 +330,7 @@ int v2_buffer_file(char *filename, int fd, int type) if (check_tree_ref(0, V2_DQTREEOFF, blocks, 1, &corrupted, &lastblk) >= 0) ret = check_tree_blk(fd, V2_DQTREEOFF, 0, type, blocks, &corrupted, &lastblk); else - fprintf(stderr, _("Can't gather quota data. Tree root node corrupted.\n")); + errstr(_("Can't gather quota data. Tree root node corrupted.\n")); #ifdef DEBUG_MALLOC free_mem += (blocks + 7) >> 3; #endif @@ -336,7 +338,7 @@ int v2_buffer_file(char *filename, int fd, int type) if (corrupted) { if (!(flags & (FL_VERBOSE | FL_DEBUG))) fputc('\n', stderr); - fprintf(stderr, _("WARNING: Some data might be changed due to corruption.\n")); + errstr(_("WARNING - Some data might be changed due to corruption.\n")); } else debug(FL_DEBUG | FL_VERBOSE, _("Not found any corrupted blocks. Congratulations.\n")); @@ -6,7 +6,7 @@ quotactl \- manipulate disk quotas .B #include <linux/quota.h> .B #include <linux/xqm.h> .LP -.B int quotactl(int cmd, char \(**special, int uid, caddr_t addr) +.B long quotactl(int cmd, char \(**special, qid_t id, caddr_t addr) .fi .SH DESCRIPTION .LP @@ -48,7 +48,7 @@ program. This call is restricted to the super-user. Turn off quotas for a filesystem. .I addr and -.I uid +.I id are ignored. This call is restricted to the super-user. .TP @@ -57,7 +57,7 @@ Get disk quota limits and current usage for user or group .IR id . .I addr is a pointer to a -.B dqblk +.B mem_dqblk structure (defined in .BR <linux/quota.h> ). Only the super-user may get the quotas of a user other than himself. @@ -67,7 +67,7 @@ Set disk quota limits and current usage for user or group .IR id . .I addr is a pointer to a -.B dqblk +.B mem_dqblk structure (defined in .BR <linux/quota.h> ). This call is restricted to the super-user. @@ -77,7 +77,17 @@ Set disk quota limits for user or group .IR id . .I addr is a pointer to a -.B dqblk +.B mem_dqblk +structure (defined in +.BR <linux/quota.h> ). +This call is restricted to the super-user. +.TP +.SB Q_SETUSE +Set current usage for user or group +.IR id . +.I addr +is a pointer to a +.B mem_dqblk structure (defined in .BR <linux/quota.h> ). This call is restricted to the super-user. @@ -89,9 +99,63 @@ If is null then all filesystems with active quotas are sync'ed. .I addr and -.I uid +.I id +are ignored. +.TP +.SB Q_GETSTATS +Get statistics and other generic information about quota subsystem. +.I addr +should be a pointer to +.B dqstats +structure (defined in +.BR <linux/quota.h> ) +in which data should be stored. +.I special +and +.I id are ignored. .PP +New quota format also allows following additional calls: +.TP 15 +.SB Q_GETINFO +Get information (like grace times) about quotafile. +.I addr +should be a pointer to +.B mem_dqinfo +structure (defined in +.IR <linux/quota.h> ). +.I id +is ignored. +.TP +.SB Q_SETINFO +Set information about quotafile. +.I addr should be a pointer to +.B mem_dqinfo +structure (defined in +.IR <linux/quota.h> ). +.I id +is ignored. This operation is restricted to super-user. +.TP +.SB Q_SETGRACE +Set grace times in information about quotafile. +.I addr should be a pointer to +.B mem_dqinfo +structure (defined in +.IR <linux/quota.h> ). +.I id +is ignored. This operation is restricted to super-user. +.TP +.SB Q_SETFLAGS +Set flags in information about quotafile. These flags are defined in +.IR <linux/quota.h> . +Note that there are currently no defined flags. +.I addr should be a pointer to +.B mem_dqinfo +structure (defined in +.IR <linux/quota.h> ). +.I id +is ignored. This operation is restricted to super-user. +.TP For XFS filesystems making use of the XFS Quota Manager (XQM), the above commands are bypassed and the following commands are used: .TP 15 @@ -115,7 +179,7 @@ This call is restricted to the superuser. .TP .SB Q_XGETQUOTA Get disk quota limits and current usage for user -.IR uid . +.IR id . .I addr is a pointer to a .B fs_disk_quota @@ -125,7 +189,7 @@ Only the superuser may get the quotas of a user other than himself. .TP .SB Q_XSETQLIM Set disk quota limits for user -.IR uid . +.IR id . .I addr is a pointer to a .B fs_disk_quota @@ -54,7 +54,7 @@ int detect_qf_format(int fd, int type) /* * Detect quota format and initialize quota IO */ -struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) +struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags) { char *qfname = NULL; int fd = -1, kernfmt; @@ -68,12 +68,14 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) if (stat(mnt_fsname, &h->qh_stat) < 0) memset(&h->qh_stat, 0, sizeof(struct stat)); h->qh_io_flags = 0; + if (flags & IOI_READONLY) + h->qh_io_flags |= IOFL_RO; h->qh_type = type; sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev)); free((char *)mnt_fsname); if (!strcmp(mnt->mnt_type, MNTTYPE_NFS)) { /* NFS filesystem? */ if (fmt != -1 && fmt != QF_RPC) { /* User wanted some other format? */ - fprintf(stderr, _("Only RPC quota format is allowed on NFS filesystem.\n")); + errstr(_("Only RPC quota format is allowed on NFS filesystem.\n")); goto out_handle; } #ifdef RPC @@ -82,14 +84,14 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) h->qh_ops = "afile_ops_rpc; return h; #else - fprintf(stderr, _("RPC quota format not compiled.\n")); + errstr(_("RPC quota format not compiled.\n")); goto out_handle; #endif } if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) { /* XFS filesystem? */ if (fmt != -1 && fmt != QF_XFS) { /* User wanted some other format? */ - fprintf(stderr, _("Only XFS quota format is allowed on XFS filesystem.\n")); + errstr(_("Only XFS quota format is allowed on XFS filesystem.\n")); goto out_handle; } h->qh_fd = -1; @@ -107,14 +109,14 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) fmt = kernfmt; /* Default is kernel used format */ } if (!(qfname = get_qf_name(mnt, type, fmt))) { - fprintf(stderr, _("Can't get quotafile name.\n")); + errstr(_("Can't get quotafile name.\n")); goto out_handle; } - if (qfname[0]) { /* Has format any quotafile to open? */ + if (qfname[0] && (!QIO_ENABLED(h) || flags & IOI_OPENFILE)) { /* Need to open file? */ /* We still need to open file for operations like 'repquota' */ - if ((fd = open(qfname, O_RDWR)) < 0) { - fprintf(stderr, _("Can't open quotafile %s: %s\n"), qfname, - strerror(errno)); + if ((fd = open(qfname, QIO_RO(h) ? O_RDONLY : O_RDWR)) < 0) { + errstr(_("Can't open quotafile %s: %s\n"), + qfname, strerror(errno)); goto out_handle; } flock(fd, LOCK_EX); @@ -124,11 +126,12 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) /* Check file format */ h->qh_fmt = detect_qf_format(fd, type); if (h->qh_fmt == -2) { - fprintf(stderr, _("Quotafile format too new in %s\n"), qfname); + errstr(_("Quotafile format too new in %s\n"), + qfname); goto out_lock; } if (fmt != -1 && h->qh_fmt != fmt) { - fprintf(stderr, _("Quotafile format detected differs from the specified one (or the one kernel uses on the file).\n")); + errstr(_("Quotafile format detected differs from the specified one (or the one kernel uses on the file).\n")); goto out_handle; } } @@ -143,8 +146,10 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) h->qh_ops = "afile_ops_2; memset(&h->qh_info, 0, sizeof(h->qh_info)); - if (h->qh_ops->init_io && h->qh_ops->init_io(h) < 0) + if (h->qh_ops->init_io && h->qh_ops->init_io(h) < 0) { + errstr(_("Can't initialize quota on %s: %s\n"), h->qh_quotadev, strerror(errno)); goto out_lock; + } return h; out_lock: if (fd != -1) @@ -170,7 +175,7 @@ struct quota_handle *new_io(struct mntent *mnt, int type, int fmt) if (fmt == -1) fmt = QF_VFSV0; /* Use the newest format */ else if (fmt == QF_RPC || fmt == QF_XFS) { - fprintf(stderr, _("Creation of %s quota format is not supported.\n"), + errstr(_("Creation of %s quota format is not supported.\n"), fmt == QF_RPC ? "RPC" : "XFS"); return NULL; } @@ -180,7 +185,8 @@ struct quota_handle *new_io(struct mntent *mnt, int type, int fmt) sstrncat(namebuf, ".new", PATH_MAX); free(qfname); if ((fd = open(namebuf, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0) { - fprintf(stderr, _("Can't create new quotafile %s: %s\n"), namebuf, strerror(errno)); + errstr(_("Can't create new quotafile %s: %s\n"), + namebuf, strerror(errno)); return NULL; } if (!(mnt_fsname = get_device_name(mnt->mnt_fsname))) @@ -215,15 +221,13 @@ struct quota_handle *new_io(struct mntent *mnt, int type, int fmt) */ int end_io(struct quota_handle *h) { - int ret; - if (h->qh_io_flags & IOFL_INFODIRTY) { - if (h->qh_ops->write_info && (ret = h->qh_ops->write_info(h)) >= 0) - return ret; + if (h->qh_ops->write_info && h->qh_ops->write_info(h) < 0) + return -1; h->qh_io_flags &= ~IOFL_INFODIRTY; } - if (h->qh_ops->end_io && (ret = h->qh_ops->end_io(h)) >= 0) - return ret; + if (h->qh_ops->end_io && h->qh_ops->end_io(h) < 0) + return -1; flock(h->qh_fd, LOCK_UN); close(h->qh_fd); free(h); @@ -62,6 +62,7 @@ #define IOFL_QUOTAON 0x01 /* Is quota enabled in kernel? */ #define IOFL_INFODIRTY 0x02 /* Did info change? */ +#define IOFL_RO 0x04 /* Just RO access? */ struct quotafile_ops; @@ -131,12 +132,13 @@ static inline void mark_quotafile_info_dirty(struct quota_handle *h) } #define QIO_ENABLED(h) ((h)->qh_io_flags & IOFL_QUOTAON) +#define QIO_RO(h) ((h)->qh_io_flags & IOFL_RO) /* Detect format of given quotafile */ int detect_qf_format(int fd, int type); /* Check quota format used on specified medium and initialize it */ -struct quota_handle *init_io(struct mntent *mnt, int type, int fmt); +struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags); /* Create new quotafile of specified format on given filesystem */ struct quota_handle *new_io(struct mntent *mnt, int type, int fmt); diff --git a/quotaio_rpc.c b/quotaio_rpc.c index cbdfe8b..3482de8 100644 --- a/quotaio_rpc.c +++ b/quotaio_rpc.c @@ -6,9 +6,11 @@ #include <errno.h> #include <sys/types.h> +#include "common.h" #include "quotaio.h" #include "dqblk_rpc.h" #include "rquota_client.h" +#include "pot.h" static struct dquot *rpc_read_dquot(struct quota_handle *h, qid_t id); static int rpc_commit_dquot(struct dquot *dquot); @@ -47,6 +49,11 @@ static struct dquot *rpc_read_dquot(struct quota_handle *h, qid_t id) static int rpc_commit_dquot(struct dquot *dquot) { #ifdef RPC + if (QIO_RO(dquot->dq_h)) { + errstr(_("Trying to write quota to readonly quotafile on %s\n"), dquot->dq_h->qh_quotadev); + errno = EPERM; + return -1; + } rpc_rquota_set(QCMD(Q_RPC_SETQUOTA, dquot->dq_h->qh_type), dquot); return 0; #else diff --git a/quotaio_v1.c b/quotaio_v1.c index 31b47e9..405479e 100644 --- a/quotaio_v1.c +++ b/quotaio_v1.c @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: quotaio_v1.c,v 1.3 2001/04/04 17:47:50 jkar8572 Exp $" +#ident "$Id: quotaio_v1.c,v 1.4 2001/05/02 09:32:22 jkar8572 Exp $" #include <unistd.h> #include <errno.h> @@ -127,10 +127,17 @@ static int v1_init_io(struct quota_handle *h) if (QIO_ENABLED(h)) { struct v1_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < - 0) return -1; - h->qh_info.dqi_bgrace = kdqblk.dqb_btime; - h->qh_info.dqi_igrace = kdqblk.dqb_itime; + if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) { + if (errno == EPERM) { /* We have no permission to get this information? */ + h->qh_info.dqi_bgrace = h->qh_info.dqi_igrace = 0; /* It hopefully won't be needed */ + } + else + return -1; + } + else { + h->qh_info.dqi_bgrace = kdqblk.dqb_btime; + h->qh_info.dqi_igrace = kdqblk.dqb_itime; + } } else { struct v1_disk_dqblk ddqblk; @@ -168,15 +175,20 @@ static int v1_new_io(struct quota_handle *h) */ static int v1_write_info(struct quota_handle *h) { + if (QIO_RO(h)) { + errstr(_("Trying to write info to readonly quotafile on %s.\n"), h->qh_quotadev); + errno = EPERM; + return -1; + } if (QIO_ENABLED(h)) { struct v1_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < - 0) return -1; + if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) + return -1; kdqblk.dqb_btime = h->qh_info.dqi_bgrace; kdqblk.dqb_itime = h->qh_info.dqi_igrace; - if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < - 0) return -1; + if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) + return -1; } else { struct v1_disk_dqblk ddqblk; @@ -195,7 +207,7 @@ static int v1_write_info(struct quota_handle *h) /* * Read a dqblk struct from the quotafile. - * User can use 'errno' to detect error. + * User can use 'errno' to detect errstr. */ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) { @@ -217,21 +229,19 @@ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) else { lseek(h->qh_fd, (long)V1_DQOFF(id), SEEK_SET); switch (read(h->qh_fd, &ddqblk, sizeof(ddqblk))) { - case 0: /* EOF */ - /* - * Convert implicit 0 quota (EOF) into an - * explicit one (zero'ed dqblk) - */ - memset(&dquot->dq_dqb, 0, sizeof(struct util_dqblk)); - - break; - case sizeof(struct v1_disk_dqblk): /* OK */ - v1_disk2memdqblk(&dquot->dq_dqb, &ddqblk); - - break; - default: /* ERROR */ - free(dquot); - return NULL; + case 0: /* EOF */ + /* + * Convert implicit 0 quota (EOF) into an + * explicit one (zero'ed dqblk) + */ + memset(&dquot->dq_dqb, 0, sizeof(struct util_dqblk)); + break; + case sizeof(struct v1_disk_dqblk): /* OK */ + v1_disk2memdqblk(&dquot->dq_dqb, &ddqblk); + break; + default: /* ERROR */ + free(dquot); + return NULL; } } return dquot; @@ -239,19 +249,23 @@ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) /* * Write a dqblk struct to the quotafile. - * User can process use 'errno' to detect error + * User can process use 'errno' to detect errstr */ static int v1_commit_dquot(struct dquot *dquot) { struct v1_disk_dqblk ddqblk; struct quota_handle *h = dquot->dq_h; + if (QIO_RO(h)) { + errstr(_("Trying to write quota to readonly quotafile on %s\n"), h->qh_quotadev); + errno = EPERM; + return -1; + } if (QIO_ENABLED(h)) { /* Kernel uses same file? */ struct v1_kern_dqblk kdqblk; v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb); - if (quotactl - (QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, dquot->dq_id, + if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) return -1; } @@ -296,5 +310,5 @@ static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct d } if (!rd) /* EOF? */ return 0; - return -1; /* Some read error... */ + return -1; /* Some read errstr... */ } diff --git a/quotaio_v2.c b/quotaio_v2.c index ecbce1d..f256b3c 100644 --- a/quotaio_v2.c +++ b/quotaio_v2.c @@ -139,8 +139,8 @@ static int v2_init_io(struct quota_handle *h) if (QIO_ENABLED(h)) { struct v2_kern_dqinfo kdqinfo; - if (quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < - 0) return -1; + if (quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) + return -1; h->qh_info.dqi_bgrace = kdqinfo.dqi_bgrace; h->qh_info.dqi_igrace = kdqinfo.dqi_igrace; h->qh_info.u.v2_mdqi.dqi_flags = kdqinfo.dqi_flags; @@ -194,6 +194,11 @@ static int v2_new_io(struct quota_handle *h) */ static int v2_write_info(struct quota_handle *h) { + if (QIO_RO(h)) { + errstr(_("Trying to write info to readonly quotafile on %s\n"), h->qh_quotadev); + errno = EPERM; + return -1; + } if (QIO_ENABLED(h)) { struct v2_kern_dqinfo kdqinfo; @@ -203,8 +208,8 @@ static int v2_write_info(struct quota_handle *h) kdqinfo.dqi_blocks = h->qh_info.u.v2_mdqi.dqi_blocks; kdqinfo.dqi_free_blk = h->qh_info.u.v2_mdqi.dqi_free_blk; kdqinfo.dqi_free_entry = h->qh_info.u.v2_mdqi.dqi_free_entry; - if (quotactl(QCMD(Q_V2_SETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < - 0) return -1; + if (quotactl(QCMD(Q_V2_SETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) + return -1; } else { struct v2_disk_dqinfo ddqinfo; @@ -261,7 +266,7 @@ static int get_free_dqblk(struct quota_handle *h) memset(buf, 0, V2_DQBLKSIZE); if (write_blk(h, info->dqi_blocks, buf) < 0) { /* Assure block allocation... */ freedqbuf(buf); - fprintf(stderr, "Can't allocate new quota block (out of disk space).\n"); + errstr(_("Can't allocate new quota block (out of disk space).\n")); return -ENOSPC; } blk = info->dqi_blocks++; @@ -570,7 +575,7 @@ static inline loff_t find_dqentry(struct quota_handle *h, struct dquot *dquot) /* * Read dquot (either from disk or from kernel) - * User can use errno to detect error when NULL is returned + * User can use errno to detect errstr when NULL is returned */ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) { @@ -587,8 +592,7 @@ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) if (QIO_ENABLED(h)) { struct v2_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < - 0) { + if (quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { free(dquot); return NULL; } @@ -613,20 +617,25 @@ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) /* * Commit changes of dquot to disk - it might also mean deleting it when quota became fake one and user has no blocks... - * User can process use 'errno' to detect error + * User can process use 'errno' to detect errstr */ static int v2_commit_dquot(struct dquot *dquot) { struct util_dqblk *b = &dquot->dq_dqb; + if (QIO_RO(dquot->dq_h)) { + errstr(_("Trying to write quota to readonly quotafile on %s\n"), dquot->dq_h->qh_quotadev); + errno = EPERM; + return -1; + } if (QIO_ENABLED(dquot->dq_h)) { struct v2_kern_dqblk kdqblk; v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb); - if (quotactl - (QCMD(Q_V2_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, + if (quotactl(QCMD(Q_V2_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) return -1; + return 0; } if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit && !b->dqb_isoftlimit && !b->dqb_bhardlimit && !b->dqb_ihardlimit) @@ -5,18 +5,18 @@ quotaon, quotaoff \- turn filesystem quotas on and off .SH SYNOPSIS .B /usr/sbin/quotaon [ -.B \-vug +.B \-vugf ] .IR filesystem .\|.\|. .br .B /usr/sbin/quotaon [ -.B \-avug +.B \-avugf ] .LP .B /usr/sbin/quotaoff [ -.B \-vugdo +.B \-vug ] [ .B \-x @@ -26,7 +26,7 @@ quotaon, quotaoff \- turn filesystem quotas on and off .br .B /usr/sbin/quotaoff [ -.B \-avugdo +.B \-avug ] .SH DESCRIPTION .SS quotaon @@ -76,9 +76,11 @@ have any disk quotas turned off. .SS quotaon .TP .B \-a -All filesystems in +All automatically mounted (no +.B noauto +option) non-NFS filesystems in .B /etc/fstab -marked read-write with quotas will have their quotas turned on. +with quotas will have their quotas turned on. This is normally used at boot time to enable quotas. .TP .B \-v @@ -89,6 +91,12 @@ Manipulate user quotas. This is the default. .TP .B \-g Manipulate group quotas. +.TP +.B \-f +Make +.B quotaon +behave like being called as +.BR quotaoff . .SS quotaoff .TP .B \-a @@ -34,12 +34,13 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: quotaon.c,v 1.3 2001/04/26 09:36:08 jkar8572 Exp $" +#ident "$Id: quotaon.c,v 1.4 2001/05/02 09:32:22 jkar8572 Exp $" /* * Turn quota on/off for a filesystem. */ #include <stdio.h> +#include <errno.h> #include <getopt.h> #include <string.h> #include <stdlib.h> @@ -51,11 +52,12 @@ int gflag; /* operate on group quotas */ int uflag; /* operate on user quotas */ int vflag; /* verbose */ int kqf; /* kernel quota format */ +char *progname; -static void usage(char *whoami) +static void usage(void) { - fprintf(stderr, _("Usage:\n\t%s [-guv] [-x state] -a\n"), whoami); - fprintf(stderr, _("\t%s [-guv] [-x state] filesys ...\n"), whoami); + errstr(_("Usage:\n\t%s [-guv] [-x state] -a\n")); + errstr(_("\t%s [-guv] [-x state] filesys ...\n")); exit(1); } @@ -99,8 +101,8 @@ static int newstate(struct mntent *mnt, int offmode, int type, char *extra) || (!offmode && kern_quota_on(mnt_fsname, type, 1 << QF_XFS)))) ret = xfs_newstate(mnt, type, extra, flags); else { - extra = get_qf_name(mnt, type, kqf); - statefunc = (kqf & (1 << QF_VFSV0)) ? v1_newstate : v2_newstate; + extra = get_qf_name(mnt, type, (kqf & (1 << QF_VFSV0)) ? QF_VFSV0 : QF_VFSOLD); + statefunc = (kqf & (1 << QF_VFSV0)) ? v2_newstate : v1_newstate; ret = statefunc(mnt, type, extra, flags); free(extra); } @@ -112,16 +114,16 @@ int main(int argc, char **argv) FILE *fp; struct mntent *mnt; long argnum, done = 0; - char *whoami, *xarg = NULL; + char *xarg = NULL; int c, offmode = 0, errs = 0; gettexton(); - whoami = basename(argv[0]); - if (strcmp(whoami, "quotaoff") == 0) + progname = basename(argv[0]); + if (strcmp(progname, "quotaoff") == 0) offmode++; - else if (strcmp(whoami, "quotaon") != 0) - die(1, _("Name must be quotaon or quotaoff not %s\n"), whoami); + else if (strcmp(progname, "quotaon") != 0) + die(1, _("Name must be quotaon or quotaoff not %s\n"), progname); while ((c = getopt(argc, argv, "afvugx:V")) != -1) { switch (c) { @@ -147,14 +149,14 @@ int main(int argc, char **argv) version(); exit(0); default: - usage(whoami); + usage(); } } argc -= optind; argv += optind; if (argc <= 0 && !aflag) - usage(whoami); + usage(); if (!gflag && !uflag) { gflag++; uflag++; @@ -165,7 +167,7 @@ int main(int argc, char **argv) fp = setmntent(MNTTAB, "r"); while ((mnt = getmntent(fp))) { if (aflag) { - if (hasmntopt(mnt, MNTOPT_NOAUTO)) + if (hasmntopt(mnt, MNTOPT_NOAUTO) || !strcmp(mnt->mnt_type, MNTTYPE_NFS)) continue; } else { @@ -174,6 +176,10 @@ int main(int argc, char **argv) else continue; } + if (!strcmp(mnt->mnt_type, MNTTYPE_NFS)) { + fprintf(stderr, "%s: Quota can't be turned on on NFS filesystem\n", mnt->mnt_fsname); + continue; + } if (gflag) errs += newstate(mnt, offmode, GRPQUOTA, xarg); @@ -184,7 +190,7 @@ int main(int argc, char **argv) for (c = 0; c < argc; c++) if ((done & (1 << c)) == 0) - fprintf(stderr, _("%s not found in fstab\n"), argv[c]); + errstr(_("%s not found in fstab\n"), argv[c]); return errs; } @@ -197,9 +203,8 @@ static int quotaonoff(char *quotadev, char *quotafile, int type, int flags) if (flags & STATEFLAG_OFF) { qcmd = QCMD(Q_QUOTAOFF, type); - if (quotactl(qcmd, quotadev, 0, (void *)0) < 0) { - fprintf(stderr, "quotaoff: "); - perror(quotadev); + if (quotactl(qcmd, quotadev, 0, NULL) < 0) { + errstr(_("quotactl on %s: %s\n"), quotadev, strerror(errno)); return 1; } if (flags & STATEFLAG_VERBOSE) @@ -208,8 +213,7 @@ static int quotaonoff(char *quotadev, char *quotafile, int type, int flags) } qcmd = QCMD(Q_QUOTAON, type); if (quotactl(qcmd, quotadev, 0, (void *)quotafile) < 0) { - fprintf(stderr, _("quotaon: using %s on "), quotafile); - perror(quotadev); + errstr(_("using %s on %s: %s\n"), quotafile, quotadev, strerror(errno)); return 1; } if (flags & STATEFLAG_VERBOSE) @@ -227,8 +231,7 @@ static int quotarsquashonoff(const char *quotadev, int type, int flags) int qcmd = QCMD(Q_V1_RSQUASH, type); if (quotactl(qcmd, quotadev, 0, (void *)&mode) < 0) { - fprintf(stderr, _("quotaon: set root_squash on")); - perror(quotadev); + errstr(_("set root_squash on %s: %s\n"), quotadev, strerror(errno)); return 1; } if ((flags & STATEFLAG_VERBOSE) && (flags & STATEFLAG_OFF)) @@ -265,12 +268,12 @@ int v1_newstate(struct mntent *mnt, int type, char *file, int flags) int v2_newstate(struct mntent *mnt, int type, char *file, int flags) { const char *dev = get_device_name(mnt->mnt_fsname); - int err = 1; + int errs = 0; if (!dev) - return err; + return 1; if (hasquota(mnt, type)) - err = quotaonoff((char *)dev, file, type, flags); + errs = quotaonoff((char *)dev, file, type, flags); free((char *)dev); - return err; + return errs; } diff --git a/quotaon_xfs.c b/quotaon_xfs.c index 4252fcf..f9d1918 100644 --- a/quotaon_xfs.c +++ b/quotaon_xfs.c @@ -31,8 +31,7 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int root, i return 0; /* noop */ if (quotactl(QCMD(Q_XFS_GETQSTAT, 0), dev, 0, (void *)&info) < 0) { - fprintf(stderr, flags & STATEFLAG_ON ? "quotaon: " : "quotaoff: "); - perror(dev); + errstr(_("quotactl() on %s: %s\n"), dev, strerror(errno)); return -1; } @@ -64,7 +63,7 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int root, i " (reboot to take effect)\n"), type2name(type)); return 1; } - fprintf(stderr, _("Enable XFS %s quota during mount\n"), + errstr(_("Enable XFS %s quota during mount\n"), type2name(type)); return -1; case Q_XFS_QUOTAOFF: @@ -74,7 +73,7 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int root, i case ACCT: switch (qcmd) { case Q_XFS_QUOTARM: - fprintf(stderr, _("Cannot delete %s quota on %s - " + errstr(_("Cannot delete %s quota on %s - " "switch quota accounting off first\n"), type2name(type), dev); return -1; @@ -100,12 +99,12 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int root, i case ENFD: switch (qcmd) { case Q_XFS_QUOTARM: - fprintf(stderr, _("Cannot delete %s quota on %s - " + errstr(_("Cannot delete %s quota on %s - " "switch quota enforcement off first\n"), type2name(type), dev); return -1; case Q_XFS_QUOTAON: - fprintf(stderr, _("Enforcing %s quota already on %s\n"), + errstr(_("Enforcing %s quota already on %s\n"), type2name(type), dev); return -1; case Q_XFS_QUOTAOFF: @@ -116,7 +115,7 @@ static int xfs_state_check(int qcmd, int type, int flags, char *dev, int root, i } break; } - fprintf(stderr, _("Unexpected XFS quota state sought on %s\n"), dev); + errstr(_("Unexpected XFS quota state sought on %s\n"), dev); return -1; } @@ -131,8 +130,7 @@ static int xfs_onoff(char *dev, int type, int flags, int rootfs, int *xopts) return (check < 0); if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) { - fprintf(stderr, qoff ? "quotaoff: " : "quotaon: "); - perror(dev); + errstr(_("quotactl on %s: %s\n"), dev, strerror(errno)); return 1; } if ((flags & STATEFLAG_VERBOSE) && qoff) @@ -152,8 +150,8 @@ static int xfs_delete(char *dev, int type, int flags, int rootfs, int *xopts) return (check < 0); if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) { - fprintf(stderr, _("Failed to delete quota: ")); - perror(dev); + errstr(_("Failed to delete quota: %s"), + strerror(errno)); return 1; } @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: quotaops.c,v 1.3 2001/04/12 05:56:53 jkar8572 Exp $" +#ident "$Id: quotaops.c,v 1.4 2001/05/02 09:32:22 jkar8572 Exp $" #include <rpc/rpc.h> #include <sys/types.h> @@ -76,7 +76,7 @@ static int cvtatos(time_t time, char *units, time_t * seconds) else if (memcmp(units, "day", 3) == 0) *seconds = time * 24 * 60 * 60; else { - fprintf(stderr, _("%s: bad units, specify:\n %s, %s, %s, or %s"), units, + errstr(_("bad units, specify:\n %s, %s, %s, or %s"), units, "days", "hours", "minutes", "seconds"); return -1; } @@ -90,10 +90,48 @@ struct dquot *getprivs(qid_t id, struct quota_handle **handles) { struct dquot *q, *qtail = NULL, *qhead = NULL; int i; +#if defined(BSD_BEHAVIOUR) + int j, ngroups; + uid_t euid; + gid_t gidset[NGROUPS]; + char name[MAXNAMELEN]; +#endif for (i = 0; handles[i]; i++) { +#if defined(BSD_BEHAVIOUR) + switch (handles[i]->qh_type) { + case USRQUOTA: + euid = geteuid(); + if (euid != id && euid != 0) { + uid2user(id, name); + die(1, _("%s (uid %d): permission denied\n"), name, id); + } + break; + case GRPQUOTA: + ngroups = getgroups(NGROUPS, gidset); + if (ngroups < 0) { + die(1, _("Error while trying getgroups(): %s\n"), strerror(errno)); + continue; + } + + for (j = 0; j < ngroups; j++) + if (id == gidset[j]) + break; + + if (j >= ngroups && geteuid() != 0) { + gid2group(id, name); + errstr(_("%s (gid %d): permission denied\n"), + name, id); + return (struct dquot *)NULL; + } + break; + default: + break; + } +#endif + if (!(q = handles[i]->qh_ops->read_dquot(handles[i], id))) { - fprintf(stderr, _("Error while getting quota from %s for %u: %s\n"), + errstr(_("Error while getting quota from %s for %u: %s\n"), handles[i]->qh_quotadev, id, strerror(errno)); continue; } @@ -116,8 +154,8 @@ int putprivs(struct dquot *qlist) for (q = qlist; q; q = q->dq_next) { if (q->dq_h->qh_ops->commit_dquot(q) == -1) { - fprintf(stderr, _("Can't write quota for %u on %s: %s\n"), q->dq_id, - q->dq_h->qh_quotadev, strerror(errno)); + errstr(_("Can't write quota for %u on %s: %s\n"), + q->dq_id, q->dq_h->qh_quotadev, strerror(errno)); continue; } } @@ -129,10 +167,15 @@ int putprivs(struct dquot *qlist) */ int editprivs(char *tmpfile) { - long omask; - int pid, stat; - - omask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP)); + sigset_t omask, nmask; + pid_t pid; + int stat; + + sigemptyset(&nmask); + sigaddset(&nmask, SIGINT); + sigaddset(&nmask, SIGQUIT); + sigaddset(&nmask, SIGHUP); + sigprocmask(SIG_SETMASK, &nmask, &omask); if ((pid = fork()) < 0) { perror("fork"); return -1; @@ -140,7 +183,7 @@ int editprivs(char *tmpfile) if (pid == 0) { char *ed; - sigsetmask(omask); + sigprocmask(SIG_SETMASK, &omask, NULL); setgid(getgid()); setuid(getuid()); if ((ed = getenv("VISUAL")) == (char *)0) @@ -150,7 +193,7 @@ int editprivs(char *tmpfile) die(1, _("Can't exec %s\n"), ed); } waitpid(pid, &stat, 0); - sigsetmask(omask); + sigprocmask(SIG_SETMASK, &omask, NULL); return 0; } @@ -188,7 +231,7 @@ int writeprivs(struct dquot *qlist, int outfd, char *name, int quotatype) #else fprintf(fd, _("Quotas for %s %s:\n"), type2name(quotatype), name); for (q = qlist; q; q = q->dq_next) { - fprintf(fd, _("%s: %s %d, limits (soft = %d, hard = %d)\n"), + fprintf(fd, _("%s %d, limits (soft = %d, hard = %d)\n"), q->dq_h->qh_quotadev, _("blocks in use:"), (int)toqb(q->dq_dqb.dqb_curspace), q->dq_dqb.dqb_bsoftlimit, q->dq_dqb.dqb_bhardlimit); @@ -233,10 +276,10 @@ static void merge_to_list(struct dquot *qlist, char *dev, u_int64_t blocks, u_in q->dq_flags |= DQ_FOUND; if (blocks != toqb(q->dq_dqb.dqb_curspace)) - fprintf(stderr, _("WARNING: %s: cannot change current block allocation\n"), + errstr(_("WARNING - %s: cannot change current block allocation\n"), q->dq_h->qh_quotadev); if (inodes != q->dq_dqb.dqb_curinodes) - fprintf(stderr, _("WARNING: %s: cannot change current inode allocation\n"), + errstr(_("WARNING - %s: cannot change current inode allocation\n"), q->dq_h->qh_quotadev); } } @@ -273,7 +316,7 @@ int readprivs(struct dquot *qlist, int infd) fsp, &blocks, &bsoft, &bhard, &inodes, &isoft, &ihard); if (cnt != 7) { - fprintf(stderr, _("Bad format:\n%s\n"), line); + errstr(_("Bad format:\n%s\n"), line); return -1; } @@ -286,30 +329,34 @@ int readprivs(struct dquot *qlist, int infd) fgets(line1, sizeof(line1), fd); while (fgets(line1, sizeof(line1), fd) && fgets(line2, sizeof(line2), fd)) { if (!(fsp = strtok(line1, " \t:"))) { - fprintf(stderr, _("%s: bad format\n"), line1); + errstr(_("%s - bad format\n"), line1); return -1; } if (!(cp = strtok(NULL, "\n"))) { - fprintf(stderr, _("%s: %s: bad format\n"), fsp, &fsp[strlen(fsp) + 1]); + errstr(_("%s - %s -- bad format\n"), + fsp, &fsp[strlen(fsp) + 1]); return -1; } cnt = sscanf(cp, _(" blocks in use: %Lu, limits (soft = %Lu, hard = %Lu)"), &blocks, &bsoft, &bhard); if (cnt != 3) { - fprintf(stderr, _("%s:%s: bad format\n"), fsp, cp); + errstr(_("%s - %s -- bad format\n"), + fsp, cp); return -1; } if (!(cp = strtok(line2, "\n"))) { - fprintf(stderr, _("%s: %s: bad format\n"), fsp, line2); + errstr(_("%s - %s -- bad format\n"), + fsp, line2); return -1; } cnt = sscanf(cp, _("\tinodes in use: %Lu, limits (soft = %Lu, hard = %Lu)"), &inodes, &isoft, &ihard); if (cnt != 3) { - fprintf(stderr, _("%s: %s: bad format\n"), fsp, line2); + errstr(_("%s - %s -- bad format\n"), + fsp, line2); return -1; } @@ -369,7 +416,7 @@ int writetimes(struct quota_handle **handles, int outfd) for (i = 0; handles[i]; i++) { time2str(handles[i]->qh_info.dqi_bgrace, btimebuf, 0); time2str(handles[i]->qh_info.dqi_igrace, itimebuf, 0); - fprintf(fd, _("%s: block grace period: %s, file grace period: %s\n"), + fprintf(fd, _("block grace period: %s, file grace period: %s\n"), handles[i]->qh_quotadev, btimebuf, itimebuf); } #endif @@ -397,7 +444,8 @@ int readtimes(struct quota_handle **handles, int infd) return 0; lseek(infd, 0, SEEK_SET); if (!(fd = fdopen(dup(infd), "r"))) { - fprintf(stderr, _("Can't reopen temp file: %s\n"), strerror(errno)); + errstr(_("Can't reopen temp file: %s\n"), + strerror(errno)); return -1; } @@ -418,7 +466,7 @@ int readtimes(struct quota_handle **handles, int infd) while (fgets(line, sizeof(line), fd)) { cnt = sscanf(line, "%s %d %s %d %s", fsp, &btime, bunits, &itime, iunits); if (cnt != 5) { - fprintf(stderr, _("bad format:\n%s\n"), line); + errstr(_("bad format:\n%s\n"), line); return -1; } #else @@ -430,17 +478,19 @@ int readtimes(struct quota_handle **handles, int infd) while (fgets(line1, sizeof(line1), fd)) { if (!(fsp = strtok(line1, " \t:"))) { - fprintf(stderr, _("%s: bad format\n"), line1); + errstr(_("%s - bad format\n"), line1); return -1; } if (!(cp = strtok(NULL, "\n"))) { - fprintf(stderr, _("%s: %s: bad format\n"), fsp, &fsp[strlen(fsp) + 1]); + errstr(_("%s - %s -- bad format\n"), + fsp, &fsp[strlen(fsp) + 1]); return -1; } cnt = sscanf(cp, _(" block grace period: %d %s file grace period: %d %s"), &btime, bunits, &itime, iunits); if (cnt != 4) { - fprintf(stderr, _("%s:%s: bad format\n"), fsp, cp); + errstr(_("%s - %s -- bad format\n"), + fsp, cp); return -1; } #endif diff --git a/quotastats.c b/quotastats.c index 6b67222..522f6a6 100644 --- a/quotastats.c +++ b/quotastats.c @@ -10,7 +10,7 @@ * * Author: Marco van Wieringen <mvw@planets.elm.net> * - * Version: $Id: quotastats.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $ + * Version: $Id: quotastats.c,v 1.2 2001/05/02 09:32:22 jkar8572 Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -27,7 +27,7 @@ static inline int get_stats(struct dqstats *dqstats) { - return quotactl(QCMD(Q_GETSTATS, 0), (char *)NULL, 0, (caddr_t) dqstats); + return quotactl(QCMD(Q_GETSTATS, 0), (char *)NULL, 0, (caddr_t)dqstats); } static inline int print_stats(struct dqstats *dqstats) @@ -62,7 +62,7 @@ uid_t user2uid(char *name) if (!*errch) /* Is name number - we got directly uid? */ return ret; if (!(entry = getpwnam(name))) { - fprintf(stderr, _("User %s doesn't exist.\n"), name); + errstr(_("User %s doesn't exist.\n"), name); exit(1); } return entry->pw_uid; @@ -81,7 +81,7 @@ gid_t group2gid(char *name) if (!*errch) /* Is name number - we got directly gid? */ return ret; if (!(entry = getgrnam(name))) { - fprintf(stderr, _("Group %s doesn't exist.\n"), name); + errstr(_("Group %s doesn't exist.\n"), name); exit(1); } return entry->gr_gid; @@ -106,7 +106,7 @@ void uid2user(uid_t id, char *buf) struct passwd *entry; if (!(entry = getpwuid(id))) - sprintf(buf, "#%u", (uint) id); + snprintf(buf, MAXNAMELEN, "#%u", (uint) id); else sstrncpy(buf, entry->pw_name, MAXNAMELEN); } @@ -119,7 +119,7 @@ void gid2group(gid_t id, char *buf) struct group *entry; if (!(entry = getgrgid(id))) - sprintf(buf, "#%u", (uint) id); + snprintf(buf, MAXNAMELEN, "#%u", (uint) id); else sstrncpy(buf, entry->gr_name, MAXNAMELEN); } @@ -145,7 +145,7 @@ int name2fmt(char *str) for (fmt = 0; fmt < QUOTAFORMATS; fmt++) if (!strcmp(str, fmtnames[fmt])) return fmt; - fprintf(stderr, _("Unknown quota format: %s\nSupported formats are:\n\ + errstr(_("Unknown quota format: %s\nSupported formats are:\n\ vfsold - original quota format\n\ vfsv0 - new quota format\n\ rpc - use RPC calls\n\ @@ -196,17 +196,17 @@ void time2str(time_t seconds, char *buf, int flags) hours %= 24; if (flags & TF_ROUND) { if (days >= 2) - sprintf(buf, _("%ddays"), days); + snprintf(buf, MAXTIMELEN, _("%ddays"), days); else - sprintf(buf, _("%02d:%02d"), hours + days * 24, minutes); + snprintf(buf, MAXTIMELEN, _("%02d:%02d"), hours + days * 24, minutes); } else { if (minutes || (!minutes && !hours && !days)) - sprintf(buf, _("%uminutes"), (uint) (seconds + 30) / 60); + snprintf(buf, MAXTIMELEN, _("%uminutes"), (uint) (seconds + 30) / 60); else if (hours) - sprintf(buf, _("%uhours"), hours + days * 24); + snprintf(buf, MAXTIMELEN, _("%uhours"), hours + days * 24); else - sprintf(buf, _("%udays"), days); + snprintf(buf, MAXTIMELEN, _("%udays"), days); } } @@ -271,11 +271,12 @@ static int check_fmtfile_exists(struct mntent *mnt, int type, int fmt, char *nam { struct stat buf; - sprintf(namebuf, "%s/%s.%s", mnt->mnt_dir, basenames[fmt], extensions[type]); + snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[fmt], extensions[type]); if (!stat(namebuf, &buf)) return 1; if (errno != ENOENT) { - fprintf(stderr, _("Can't stat quotafile %s: %s\n"), namebuf, strerror(errno)); + errstr(_("Can't stat quotafile %s: %s\n"), + namebuf, strerror(errno)); return -1; } return 0; @@ -328,7 +329,7 @@ char *get_qf_name(struct mntent *mnt, int type, int fmt) return NULL; } else if (basenames[fmt][0]) /* Any name specified? */ - sprintf(qfullname, "%s/%s.%s", mnt->mnt_dir, basenames[fmt], extensions[type]); + snprintf(qfullname, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[fmt], extensions[type]); return sstrdup(qfullname); } @@ -338,7 +339,7 @@ char *get_qf_name(struct mntent *mnt, int type, int fmt) * List of zero length means scan all entries in /etc/mtab */ struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt, - char local_only) + int flags) { FILE *mntf; struct mntent *mnt; @@ -365,16 +366,16 @@ struct quota_handle **create_handle_list(int count, char **mntpoints, int type, if (gotmnt == MAXMNTPOINTS) die(3, _("Too many mountpoints. Please report to: %s\n"), MY_EMAIL); - if (!(hlist[gotmnt] = init_io(mnt, type, fmt))) + if (!(hlist[gotmnt] = init_io(mnt, type, fmt, flags))) continue; gotmnt++; } - else if (!local_only && (fmt == -1 || fmt == QF_RPC)) { /* Use NFS? */ + else if (!(flags & IOI_LOCALONLY) && (fmt == -1 || fmt == QF_RPC)) { /* Use NFS? */ #ifdef RPC if (gotmnt == MAXMNTPOINTS) die(3, _("Too many mountpoints. Please report to: %s\n"), MY_EMAIL); - if (!(hlist[gotmnt] = init_io(mnt, type, fmt))) + if (!(hlist[gotmnt] = init_io(mnt, type, fmt, flags))) continue; gotmnt++; #endif @@ -393,11 +394,11 @@ struct quota_handle **create_handle_list(int count, char **mntpoints, int type, */ int dispose_handle_list(struct quota_handle **hlist) { - int i, ret; + int i; for (i = 0; hlist[i]; i++) - if ((ret = end_io(hlist[i]))) - fprintf(stderr, _("Error while releasing file on %s\n"), + if (end_io(hlist[i]) < 0) + errstr(_("Error while releasing file on %s\n"), hlist[i]->qh_quotadev); return 0; } @@ -463,17 +464,17 @@ int kern_quota_format(void) void warn_new_kernel(int fmt) { if (fmt == -1 && kern_quota_format() == QF_TOONEW) - fprintf(stderr, - _ - ("Warning: Kernel quota is newer than supported. Quotafile used by utils need not be the one used by kernel.\n")); + errstr( + _("WARNING - Kernel quota is newer than supported. Quotafile used by utils need not be the one used by kernel.\n")); } /* Check whether old quota is turned on on given device */ static int v1_kern_quota_on(const char *dev, int type) { char tmp[1024]; /* Just temporary buffer */ + qid_t id = (type == USRQUOTA) ? getuid() : getgid(); - if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, 0, tmp)) /* OK? */ + if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, id, tmp)) /* OK? */ return 1; return 0; } @@ -482,8 +483,9 @@ static int v1_kern_quota_on(const char *dev, int type) static int v2_kern_quota_on(const char *dev, int type) { char tmp[1024]; /* Just temporary buffer */ + qid_t id = (type == USRQUOTA) ? getuid() : getgid(); - if (!quotactl(QCMD(Q_V2_GETINFO, type), dev, 0, tmp)) /* OK? */ + if (!quotactl(QCMD(Q_V2_GETQUOTA, type), dev, id, tmp)) /* OK? */ return 1; return 0; } @@ -17,6 +17,11 @@ /* Flags for formatting time */ #define TF_ROUND 0x1 /* Should be printed time rounded? */ +/* Flags for IO initialization */ +#define IOI_LOCALONLY 0x1 /* Operate only on local quota */ +#define IOI_READONLY 0x2 /* Only readonly access */ +#define IOI_OPENFILE 0x4 /* Open file even if kernel has quotas turned on */ + /* * Exported functions */ @@ -61,8 +66,7 @@ char *get_qf_name(struct mntent *mnt, int type, int fmt); /* Create NULL-terminated list of handles for quotafiles for given mountpoints */ struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt, - - char local_only); + int flags); /* Dispose given list of handles */ int dispose_handle_list(struct quota_handle **hlist); @@ -6,12 +6,18 @@ repquota \- summarize quotas for a filesystem .B /usr/etc/repquota [ .B \-vug +] [ +.B \-F +.I format-name ] .IR filesystem .\|.\|. .LP .B /usr/etc/repquota [ .B \-avug +] [ +.B \-F +.I format-name ] .SH DESCRIPTION .IX "repquota command" "" "\fLrepquota\fP \(em summarize quotas" @@ -36,7 +42,20 @@ Report on all filesystems indicated in to be read-write with quotas. .TP .B \-v -Report all quotas, even if there is no usage. +Report all quotas, even if there is no usage. Be also more verbose about quotafile +information. +.TP +.B \-F \f2format-name\f1 +Report quota for specified format (ie. don't perform format autodetection). +Possible format names are: +.B vfsold +(version 1 quota), +.B vfsv0 +(version 2 quota), +.B rpc +(quota over NFS), +.B xfs +(quota on XFS filesystem) .TP .B \-g Report quotas for groups. @@ -27,6 +27,14 @@ int flags, fmt = -1; char **mnt; int mntcnt; +char *progname; + +static void usage() +{ + errstr(_("Utility for reporting quotas.\nUsage:\n%s [-vug] [-F quotaformat] (-a | mntpoint)\n"), progname); + errstr(_("Bugs to %s\n"), MY_EMAIL); + exit(1); +} static void parse_options(int argcnt, char **argstr) { @@ -42,10 +50,7 @@ static void parse_options(int argcnt, char **argstr) switch (ret) { case '?': case 'h': - usage: - fprintf(stderr, _("Utility for reporting quotas.\nUsage:\n%s [-vug] [-F quotaformat] (-a | mntpoint)\n"), slash); - fprintf(stderr, _("Bugs to %s\n"), MY_EMAIL); - exit(1); + usage(); case 'V': version(); exit(0); @@ -71,7 +76,7 @@ static void parse_options(int argcnt, char **argstr) if ((flags & FL_ALL && optind != argcnt) || (!(flags & FL_ALL) && optind == argcnt)) { fputs(_("Bad number of arguments.\n"), stderr); - goto usage; + usage(); } if (fmt == QF_RPC) { fputs(_("Repquota can't report through RPC calls.\n"), stderr); @@ -142,22 +147,27 @@ static void report(int type) int i; if (flags & FL_ALL) - handles = create_handle_list(0, NULL, type, fmt, 1); + handles = create_handle_list(0, NULL, type, fmt, IOI_LOCALONLY | IOI_READONLY | IOI_OPENFILE); else - handles = create_handle_list(mntcnt, mnt, type, fmt, 1); + handles = create_handle_list(mntcnt, mnt, type, fmt, IOI_LOCALONLY | IOI_READONLY | IOI_OPENFILE); for (i = 0; handles[i]; i++) report_it(handles[i], type); dispose_handle_list(handles); } -int main(int argcnt, char **argstr) +int main(int argc, char **argv) { gettexton(); - parse_options(argcnt, argstr); + progname = basename(argv[0]); + + parse_options(argc, argv); warn_new_kernel(fmt); + if (flags & FL_USER) report(USRQUOTA); + if (flags & FL_GROUP) report(GRPQUOTA); + return 0; } diff --git a/rquota_server.c b/rquota_server.c index 7468661..caa1327 100644 --- a/rquota_server.c +++ b/rquota_server.c @@ -9,7 +9,7 @@ * * This part does the lookup of the info. * - * Version: $Id: rquota_server.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $ + * Version: $Id: rquota_server.c,v 1.2 2001/05/02 09:32:22 jkar8572 Exp $ * * Author: Marco van Wieringen <mvw@planets.elm.net> * @@ -177,7 +177,7 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp) continue; if (st.st_dev != device) continue; - if (!(handles[0] = init_io(mnt, type, -1))) + if (!(handles[0] = init_io(mnt, type, -1, 0))) continue; break; } @@ -281,7 +281,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp) continue; if (st.st_dev != device) continue; - if (!(handles[0] = init_io(mnt, type, -1))) + if (!(handles[0] = init_io(mnt, type, -1, IOI_READONLY))) continue; break; } diff --git a/rquota_svc.c b/rquota_svc.c index 368d212..6baf0a3 100644 --- a/rquota_svc.c +++ b/rquota_svc.c @@ -1,8 +1,23 @@ /* - * Please do not edit this file. - * It was generated using rpcgen. + * QUOTA An implementation of the diskquota system for the LINUX operating + * system. QUOTA is implemented using the BSD systemcall interface + * as the means of communication with the user level. Should work for + * all filesystems because of integration into the VFS layer of the + * operating system. This is based on the Melbourne quota system wich + * uses both user and group quota files. + * + * Rquota service handlers. + * + * Author: Marco van Wieringen <mvw@planets.elm.net> + * + * Version: $Id: rquota_svc.c,v 1.2 2001/05/02 09:32:22 jkar8572 Exp $ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. */ - + #include <rpc/rpc.h> #include <sys/socket.h> #include <netinet/in.h> @@ -18,9 +33,12 @@ #endif #include "pot.h" +#include "common.h" #include "rquota.h" #include "quotasys.h" +char *progname; + /* * Global authentication credentials. */ @@ -100,7 +118,7 @@ static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT * transp) svcerr_systemerr(transp); } if (!svc_freeargs(transp, xdr_argument, (caddr_t) & argument)) { - fprintf(stderr, _("unable to free arguments")); + errstr(_("unable to free arguments")); exit(1); } return; @@ -178,7 +196,7 @@ static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT * transp) svcerr_systemerr(transp); } if (!svc_freeargs(transp, xdr_argument, (caddr_t) & argument)) { - fprintf(stderr, _("unable to free arguments")); + errstr(_("unable to free arguments")); exit(1); } return; @@ -192,6 +210,8 @@ int main(int argc, char **argv) argvargs = argv; gettexton(); + progname = basename(argv[0]); + warn_new_kernel(-1); (void)pmap_unset(RQUOTAPROG, RQUOTAVERS); @@ -199,35 +219,35 @@ int main(int argc, char **argv) transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL) { - fprintf(stderr, _("cannot create udp service.")); + errstr(_("cannot create udp service.")); exit(1); } if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_UDP)) { - fprintf(stderr, _("unable to register (RQUOTAPROG, RQUOTAVERS, udp).")); + errstr(_("unable to register (RQUOTAPROG, RQUOTAVERS, udp).")); exit(1); } if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_UDP)) { - fprintf(stderr, _("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp).")); + errstr(_("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp).")); exit(1); } transp = svctcp_create(RPC_ANYSOCK, 0, 0); if (transp == NULL) { - fprintf(stderr, _("cannot create tcp service.")); + errstr(_("cannot create tcp service.")); exit(1); } if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_TCP)) { - fprintf(stderr, _("unable to register (RQUOTAPROG, RQUOTAVERS, tcp).")); + errstr(_("unable to register (RQUOTAPROG, RQUOTAVERS, tcp).")); exit(1); } if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_TCP)) { - fprintf(stderr, _("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, tcp).")); + errstr(_("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, tcp).")); exit(1); } daemon(1, 1); svc_run(); - fprintf(stderr, _("svc_run returned")); + errstr(_("svc_run returned")); exit(1); /* NOTREACHED */ } @@ -18,9 +18,13 @@ is an server which returns quotas for a user of a local filesystem which is mounted by a remote machine over the .SM NFS\s0. -The results are used by +It also allows setting of quotas on +.SM NFS +mounted filesystem. The results are used by .BR quota (1) -to display user quotas for remote filesystems. +to display user quotas for remote filesystems and by +.BR edquota (8) +to set quotas on remote filesystems. The .B rquotad daemon is normally started at boot time from the diff --git a/set_limits_example.c b/set_limits_example.c index 52af20c..d437604 100644 --- a/set_limits_example.c +++ b/set_limits_example.c @@ -14,15 +14,14 @@ int copy_user_quota_limits(const char *block_device, uid_t from, uid_t to) return (0); } else { - fprintf(stderr, - _ - ("copy_user_quota_limits: Failed to set userquota for uid %ld : %s\n"), + errstr( + _("copy_user_quota_limits: Failed to set userquota for uid %ld : %s\n"), to, strerror(errno)); return (1); } } else { - fprintf(stderr, + errstr( _("copy_user_quota_limits: Failed to get userquota for uid %ld : %s\n"), from, strerror(errno)); return (1); @@ -38,15 +37,14 @@ int copy_group_quota_limits(const char *block_device, gid_t from, gid_t to) return (0); } else { - fprintf(stderr, - _ - ("copy_group_quota_limits: Failed to set groupquota for uid %ld : %s\n"), + errstr( + _("copy_group_quota_limits: Failed to set groupquota for uid %ld : %s\n"), to, strerror(errno)); return (1); } } else { - fprintf(stderr, + errstr( _("copy_group_quota_limits: Failed to get groupquota for uid %ld : %s\n"), from, strerror(errno)); return (1); @@ -22,7 +22,7 @@ setquota \- set disk quotas .I inode-hardlimit .B \-a | -.I filesystem +.I filesystem... .LP .B /usr/sbin/setquota [ @@ -44,7 +44,7 @@ setquota \- set disk quotas .I name .B \-a | -.I filesystem +.I filesystem... .LP .B /usr/sbin/setquota .B \-t @@ -61,7 +61,7 @@ setquota \- set disk quotas .I inode-grace .B \-a | -.I filesystem +.I filesystem... .SH DESCRIPTION .IX "setquota command" "" "\fLsetquota\fP \(em set disk quotas" .IX set "disk quotas \(em \fLsetquota\fP" @@ -78,8 +78,16 @@ filesystem can be specified on the command line. Edit also remote quota use rpc.rquotad on remote server to set quota. .TP .B -F \f2quotaformat\f1 -Perform setting for specified quota format. If this option isn't specified -newest option found is used. +Perform setting for specified format (ie. don't perform format autodetection). +Possible format names are: +.B vfsold +(version 1 quota), +.B vfsv0 +(version 2 quota), +.B rpc +(quota over NFS), +.B xfs +(quota on XFS filesystem) .TP .B -u Set user quotas for named user. This is the default. @@ -29,6 +29,7 @@ int flags, fmt = -1; char **mnt; +char *progname; int mntcnt; qid_t protoid, id; struct util_dqblk toset; @@ -37,30 +38,30 @@ struct util_dqblk toset; static void usage(void) { #if defined(RPC_SETQUOTA) - fprintf(stderr, _("Usage:\n" + errstr(_("Usage:\n" " setquota [-u|-g] [-r] [-F quotaformat] <user|group>\n" "\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> -a|<filesystem>...\n" " setquota [-u|-g] [-r] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n" " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n")); #else - fprintf(stderr, _("Usage:\n" + errstr(_("Usage:\n" " setquota [-u|-g] [-F quotaformat] <user|group>\n" "\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> -a|<filesystem>...\n" " setquota [-u|-g] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n" " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n")); #endif - fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL); + errstr(_("Bugs to: %s\n"), MY_EMAIL); exit(1); } -/* Convert string to number - print error message in case of failure */ +/* Convert string to number - print errstr message in case of failure */ static long parse_num(char *str, char *msg) { char *errch; long ret = strtol(str, &errch, 0); if (*errch) { - fprintf(stderr, _("Bad %s: %s\n"), msg, str); + errstr(_("Bad %s: %s\n"), msg, str); usage(); } return ret; @@ -216,18 +217,22 @@ int main(int argc, char **argv) struct quota_handle **handles; gettexton(); + progname = basename(argv[0]); + parse_options(argc, argv); warn_new_kernel(fmt); if (flags & FL_ALL) - handles = create_handle_list(0, NULL, flag2type(flags), fmt, !(flags & FL_RPC)); + handles = create_handle_list(0, NULL, flag2type(flags), fmt, (flags & FL_RPC) ? 0 : IOI_LOCALONLY); else - handles = create_handle_list(mntcnt, mnt, flag2type(flags), fmt, !(flags & FL_RPC)); + handles = create_handle_list(mntcnt, mnt, flag2type(flags), fmt, (flags & FL_RPC) ? 0 : IOI_LOCALONLY); if (flags & FL_GRACE) setgraces(handles); else setlimits(handles); + dispose_handle_list(handles); + return 0; } diff --git a/warnquota.c b/warnquota.c index a4516d5..8c0a4de 100644 --- a/warnquota.c +++ b/warnquota.c @@ -10,7 +10,7 @@ * * Author: Marco van Wieringen <mvw@planets.elm.net> * - * Version: $Id: warnquota.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $ + * Version: $Id: warnquota.c,v 1.2 2001/05/02 09:32:22 jkar8572 Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -84,6 +84,7 @@ typedef struct quotatable { } quotatable_t; int qtab_i = 0; +char *progname; quotatable_t *quotatable = (quotatable_t *) NULL; /* @@ -273,7 +274,7 @@ void stripstring(char **buff) /* * Reads config parameters from configfile - * uses default values if error occurs + * uses default values if errstr occurs */ void readconfigfile(const char *filename, struct configparams *config) { @@ -335,11 +336,12 @@ void readconfigfile(const char *filename, struct configparams *config) strncpy(config->phone, value, CNF_BUFFER); } else { /* not matched at all */ - fprintf(stderr, "Error in config file (line %d), ignoring\n", line); + errstr( "Error in config file (line %d), ignoring\n", + line); } } else { /* no '=' char in this line */ - fprintf(stderr, "Possible error in config file (line %d), ignoring\n", + errstr( "Possible error in config file (line %d), ignoring\n", line); } } @@ -358,7 +360,7 @@ void warn_quota(void) readconfigfile(WARNQUOTA_CONF, &config); - handles = create_handle_list(0, NULL, USRQUOTA, -1, 1); + handles = create_handle_list(0, NULL, USRQUOTA, -1, IOI_LOCALONLY | IOI_READONLY | IOI_OPENFILE); for (i = 0; handles[i]; i++) handles[i]->qh_ops->scan_dquots(handles[i], check_offence); get_quotatable(); @@ -368,7 +370,10 @@ void warn_quota(void) int main(int argc, char **argv) { gettexton(); + progname = basename(argv[0]); + warn_new_kernel(-1); warn_quota(); + return 0; } @@ -7,11 +7,14 @@ #include <stdio.h> #include <unistd.h> #include <string.h> +#include "common.h" #include "pot.h" #define XQMFILE "/proc/fs/xfs/xqm" #define STATFILE "/proc/fs/xfs/stat" +char *progname; + int main(int argc, char **argv) { FILE *stats, *xqm; @@ -19,11 +22,12 @@ int main(int argc, char **argv) unsigned values[8]; gettexton(); + progname = basename(argv[0]); memset(values, 0, sizeof(unsigned) * 8); if ((stats = fopen(STATFILE, "r")) == NULL || (xqm = fopen(XQMFILE, "r")) == NULL) { - fprintf(stderr, _("The running kernel does not support XFS\n")); + errstr(_("The running kernel does not support XFS\n")); return 1; } while (!feof(stats)) { |