3 * Utility to check disk quotas
5 * Some parts of this utility are copied from old quotacheck by
6 * Marco van Wieringen <mvw@planets.elm.net> and Edvard Tuinder <ed@elm.net>
8 * New quota format implementation - Jan Kara <jack@suse.cz> - Sponsored by SuSE CR
24 #include <sys/types.h>
26 #include <sys/statfs.h>
27 #include <sys/ioctl.h>
28 #include <sys/mount.h>
29 #include <sys/utsname.h>
31 #if defined(HAVE_EXT2_INCLUDE)
32 #include <linux/types.h>
33 #include <ext2fs/ext2fs.h>
42 #include "quotacheck.h"
45 #ifndef HAVE_EXT2_INO_T
46 typedef ino_t ext2_ino_t;
49 #define LINKSHASHSIZE 16384 /* Size of hashtable for hardlinked inodes */
50 #define DQUOTHASHSIZE 32768 /* Size of hashtable for dquots from file */
62 #define BITS_SIZE 4 /* sizeof(bits) == 5 */
63 #define BLIT_RATIO 10 /* Blit in just 1/10 of blit() calls */
65 dev_t cur_dev; /* Device we are working on */
66 int files_done, dirs_done;
67 int flags, fmt = -1, cfmt; /* Options from command line; Quota format to use spec. by user; Actual format to check */
68 int uwant, gwant, ucheck, gcheck; /* Does user want to check user/group quota; Do we check user/group quota? */
69 char *mntpoint; /* Mountpoint to check */
71 struct util_dqinfo old_info[MAXQUOTAS]; /* Loaded infos */
73 char extensions[MAXQUOTAS + 2][20] = INITQFNAMES; /* Extensions depending on quota type */
74 char *basenames[] = INITQFBASENAMES; /* Names of quota files */
77 size_t malloc_mem = 0;
81 struct dquot *dquot_hash[MAXQUOTAS][DQUOTHASHSIZE];
82 struct dlinks *links_hash[MAXQUOTAS][DQUOTHASHSIZE];
85 * Ok check each memory allocation.
87 void *xmalloc(size_t size)
96 die(3, _("Not enough memory.\n"));
101 void debug(int df, char *fmtstr, ...)
108 fprintf(stderr, "%s: ", progname);
109 va_start(args, fmtstr);
110 vfprintf(stderr, fmtstr, args);
114 /* Compute hashvalue for given inode number */
115 static inline uint hash_ino(uint i_num)
117 return ((i_num ^ (i_num << 16)) * 997) & (LINKSHASHSIZE - 1);
121 * Store a hardlinked inode as we don't want to count it more then once.
123 static int store_dlinks(int type, ino_t i_num)
126 uint hash = hash_ino(i_num);
128 debug(FL_DEBUG, _("Adding hardlink for ino %llu\n"), (unsigned long long)i_num);
130 for (lptr = links_hash[type][hash]; lptr; lptr = lptr->next)
131 if (lptr->i_num == i_num)
134 lptr = (struct dlinks *)xmalloc(sizeof(struct dlinks));
137 lptr->next = links_hash[type][hash];
138 links_hash[type][hash] = lptr;
143 static inline uint hash_dquot(uint id)
145 return ((id ^ (id << 16)) * 997) & (DQUOTHASHSIZE - 1);
149 * Do a lookup of a type of quota for a specific id. Use short cut with
150 * most recently used dquot struct pointer.
152 struct dquot *lookup_dquot(qid_t id, int type)
155 uint hash = hash_dquot(id);
157 for (lptr = dquot_hash[type][hash]; lptr != NODQUOT; lptr = lptr->dq_next)
158 if (lptr->dq_id == id)
164 * Add a new dquot for a new id to the list.
166 struct dquot *add_dquot(qid_t id, int type)
169 uint hash = hash_dquot(id);
171 debug(FL_DEBUG, _("Adding dquot structure type %s for %d\n"), type2name(type), (int)id);
173 lptr = (struct dquot *)xmalloc(sizeof(struct dquot));
176 lptr->dq_next = dquot_hash[type][hash];
177 dquot_hash[type][hash] = lptr;
178 lptr->dq_dqb.dqb_btime = lptr->dq_dqb.dqb_itime = (time_t) 0;
184 * Add a number of blocks and inodes to a quota.
186 static void add_to_quota(int type, ino_t i_num, uid_t i_uid, gid_t i_gid, mode_t i_mode,
187 nlink_t i_nlink, loff_t i_space, int need_remember)
192 if (type == USRQUOTA)
197 if ((lptr = lookup_dquot(wanted, type)) == NODQUOT)
198 lptr = add_dquot(wanted, type);
200 if (i_nlink != 1 && need_remember)
201 if (store_dlinks(type, i_num)) /* Did we already count this inode? */
203 lptr->dq_dqb.dqb_curinodes++;
204 lptr->dq_dqb.dqb_curspace += i_space;;
208 * Clean up all list from a previous run.
210 static void remove_list(void)
214 struct dquot *dquot, *dquot_free;
215 struct dlinks *dlink, *dlink_free;
217 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
218 for (i = 0; i < DQUOTHASHSIZE; i++) {
219 dquot = dquot_hash[cnt][i];
220 while (dquot != NODQUOT) {
222 dquot = dquot->dq_next;
224 free_mem += sizeof(struct dquot);
228 dquot_hash[cnt][i] = NODQUOT;
230 for (i = 0; i < LINKSHASHSIZE; i++) {
231 dlink = links_hash[cnt][i];
236 free_mem += sizeof(struct dlinks);
240 links_hash[cnt][i] = NULL;
245 /* Get size used by file */
246 static loff_t getqsize(char *fname, struct stat *st)
248 static char ioctl_fail_warn;
252 if (S_ISLNK(st->st_mode)) /* There's no way to do ioctl() on links... */
253 return st->st_blocks << 9;
254 if (!S_ISDIR(st->st_mode) && !S_ISREG(st->st_mode))
255 return st->st_blocks << 9;
256 if ((fd = open(fname, O_RDONLY)) == -1)
257 die(2, _("Cannot open file %s: %s\n"), fname, strerror(errno));
258 if (ioctl(fd, FIOQSIZE, &size) == -1) {
259 size = st->st_blocks << 9;
260 if (!ioctl_fail_warn) {
262 fputs(_("Cannot get exact used space... Results might be inaccurate.\n"), stderr);
270 * Show a blitting cursor as means of visual progress indicator.
272 static inline void blit(char *msg)
275 static const char bits[] = "|/-\\";
276 static int slow_down;
278 if (flags & FL_VERYVERBOSE && msg) {
279 int len = strlen(msg);
282 printf("%.70s", msg);
284 fputs("...", stdout);
286 printf("%*s",73-len, "");
288 if (flags & FL_VERYVERBOSE || ++slow_down >= BLIT_RATIO) {
298 static void usage(void)
300 printf(_("Utility for checking and repairing quota files.\n%s [-gucbfinvdmMR] [-F <quota-format>] filesystem|-a\n\n\
301 -u, --user check user files\n\
302 -g, --group check group files\n\
303 -c, --create-files create new quota files\n\
304 -b, --backup create backups of old quota files\n\
305 -f, --force force check even if quotas are enabled\n\
306 -i, --interactive interactive mode\n\
307 -n, --use-first-dquot use the first copy of duplicated structure\n\
308 -v, --verbose print more information\n\
309 -d, --debug print even more messages\n\
310 -m, --no-remount do not remount filesystem read-only\n\
311 -M, --try-remount try remounting filesystem read-only,\n\
312 continue even if it fails\n\
313 -R, --exclude-root exclude root when checking all filesystems\n\
314 -F, --format=formatname check quota files of specific format\n\
315 -a, --all check all filesystems\n\
316 -h, --help display this message and exit\n\
317 -V, --version display version information and exit\n\n"), progname);
318 printf(_("Bugs to %s\n"), MY_EMAIL);
322 static void parse_options(int argcnt, char **argstr)
325 struct option long_opts[] = {
326 { "version", 0, NULL, 'V' },
327 { "help", 0, NULL, 'h' },
328 { "backup", 0, NULL, 'b' },
329 { "create-files", 0, NULL, 'c' },
330 { "verbose", 0, NULL, 'v' },
331 { "debug", 0, NULL, 'd' },
332 { "user", 0, NULL, 'u' },
333 { "group", 0, NULL, 'g' },
334 { "interactive", 0, NULL, 'i' },
335 { "use-first-dquot", 0, NULL, 'n' },
336 { "force", 0, NULL, 'f' },
337 { "format", 1, NULL, 'F' },
338 { "no-remount", 0, NULL, 'm' },
339 { "try-remount", 0, NULL, 'M' },
340 { "exclude-root", 0, NULL, 'R' },
341 { "all", 0, NULL, 'a' },
345 while ((ret = getopt_long(argcnt, argstr, "VhbcvugidnfF:mMRa", long_opts, NULL)) != -1) {
361 if (flags & FL_VERBOSE)
362 flags |= FL_VERYVERBOSE;
370 flags |= FL_INTERACTIVE;
382 flags |= FL_FORCEREMOUNT;
385 flags |= FL_NOREMOUNT;
394 if ((fmt = name2fmt(optarg)) == QF_ERROR)
401 if (!(uwant | gwant))
403 if ((argcnt == optind && !(flags & FL_ALL)) || (argcnt > optind && flags & FL_ALL)) {
404 fputs(_("Bad number of arguments.\n"), stderr);
408 fputs(_("XFS quota format needs no checking.\n"), stderr);
411 if (flags & FL_VERBOSE && flags & FL_DEBUG)
412 flags &= ~FL_VERBOSE;
413 if (!(flags & FL_ALL))
414 mntpoint = argstr[optind];
419 #if defined(EXT2_DIRECT)
420 static int ext2_direct_scan(char *device)
425 ext2_inode_scan scan;
426 struct ext2_inode inode;
427 int inode_buffer_blocks = 0;
428 ext2fs_inode_bitmap inode_used_map;
429 ext2fs_inode_bitmap inode_dir_map;
433 if ((error = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs))) {
434 errstr(_("error (%d) while opening %s\n"), (int)error, device);
438 if ((error = ext2fs_allocate_inode_bitmap(fs, "in-use inode map", &inode_used_map))) {
439 errstr(_("error (%d) while allocating inode file bitmap\n"), (int)error);
443 if ((error = ext2fs_allocate_inode_bitmap(fs, "directory inode map", &inode_dir_map))) {
444 errstr(_("errstr (%d) while allocating inode directory bitmap\n"), (int)error);
448 if ((error = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan))) {
449 errstr(_("error (%d) while opening inode scan\n"), (int)error);
453 if ((error = ext2fs_get_next_inode(scan, &i_num, &inode))) {
454 errstr(_("error (%d) while starting inode scan\n"), (int)error);
458 while ((long)i_num) {
459 if (inode.i_links_count) {
460 debug(FL_DEBUG, _("Found i_num %ld, blocks %ld\n"), (long)i_num, (long)inode.i_blocks);
461 if (flags & FL_VERBOSE)
463 uid = inode.i_uid | (inode.i_uid_high << 16);
464 gid = inode.i_gid | (inode.i_gid_high << 16);
465 if (inode.i_uid_high | inode.i_gid_high)
466 debug(FL_DEBUG, _("High uid detected.\n"));
468 add_to_quota(USRQUOTA, i_num, uid, gid,
469 inode.i_mode, inode.i_links_count,
470 ((loff_t)inode.i_blocks) << 9, 0);
472 add_to_quota(GRPQUOTA, i_num, uid, gid,
473 inode.i_mode, inode.i_links_count,
474 ((loff_t)inode.i_blocks) << 9, 0);
475 if (S_ISDIR(inode.i_mode))
481 if ((error = ext2fs_get_next_inode(scan, &i_num, &inode))) {
482 errstr(_("Something weird happened while scanning. Error %d\n"), (int)error);
491 * Scan a directory with the readdir systemcall. Stat the files and add the sizes
492 * of the files to the appropriate quotas. When we find a dir we recursivly call
493 * ourself to scan that dir.
495 static int scan_dir(char *pathname)
497 struct dirs *dir_stack = NULL;
498 struct dirs *new_dir;
505 if (lstat(pathname, &st) == -1) {
506 errstr(_("Cannot stat directory %s: %s\n"), pathname, strerror(errno));
509 qspace = getqsize(pathname, &st);
511 add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
512 st.st_nlink, qspace, 0);
514 add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
515 st.st_nlink, qspace, 0);
517 if ((dp = opendir(pathname)) == (DIR *) NULL)
518 die(2, _("\nCan open directory %s: %s\n"), pathname, strerror(errno));
521 if (flags & FL_VERYVERBOSE)
523 while ((de = readdir(dp)) != (struct dirent *)NULL) {
524 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
526 if (flags & FL_VERBOSE)
529 if ((lstat(de->d_name, &st)) == -1) {
530 errstr(_("lstat Cannot stat `%s/%s': %s\nGuess you'd better run fsck first !\nexiting...\n"),
531 pathname, de->d_name, strerror(errno));
535 if (S_ISDIR(st.st_mode)) {
536 if (st.st_dev != cur_dev)
539 * Add this to the directory stack and check this later on.
541 debug(FL_DEBUG, _("pushd %s/%s\n"), pathname, de->d_name);
542 new_dir = xmalloc(sizeof(struct dirs));
544 new_dir->dir_name = xmalloc(strlen(pathname) + strlen(de->d_name) + 2);
545 sprintf(new_dir->dir_name, "%s/%s", pathname, de->d_name);
546 new_dir->next = dir_stack;
550 qspace = getqsize(de->d_name, &st);
552 add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
553 st.st_nlink, qspace, 1);
555 add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
556 st.st_nlink, qspace, 1);
557 debug(FL_DEBUG, _("\tAdding %s size %lld ino %d links %d uid %u gid %u\n"), de->d_name,
558 (long long)st.st_size, (int)st.st_ino, (int)st.st_nlink, (int)st.st_uid, (int)st.st_gid);
565 * Traverse the directory stack, and check it.
567 debug(FL_DEBUG, _("Scanning stored directories from directory stack\n"));
568 while (dir_stack != (struct dirs *)NULL) {
570 dir_stack = dir_stack->next;
571 debug(FL_DEBUG, _("popd %s\nEntering directory %s\n"), new_dir->dir_name,
573 ret = scan_dir(new_dir->dir_name);
576 free_mem += sizeof(struct dirs) + strlen(new_dir->dir_name) + 1;
578 free(new_dir->dir_name);
580 if (ret < 0) /* Error while scanning? */
583 debug(FL_DEBUG, _("Leaving %s\n"), pathname);
586 for (new_dir = dir_stack; new_dir; new_dir = dir_stack) {
587 dir_stack = dir_stack->next;
589 free_mem += sizeof(struct dirs) + strlen(new_dir->dir_name) + 1;
591 free(new_dir->dir_name);
597 /* Ask user y/n question */
598 int ask_yn(char *q, int def)
600 char a[10]; /* Users answer */
602 printf("%s [%c]: ", q, def ? 'y' : 'n');
605 fgets(a, sizeof(a)-1, stdin);
608 if (!strcasecmp(a, "y\n"))
610 if (!strcasecmp(a, "n\n"))
612 printf("Illegal answer. Please answer y/n: ");
617 /* Do checks and buffer quota file into memory */
618 static int process_file(struct mntent *mnt, int type)
623 debug(FL_DEBUG, _("Going to check %s quota file of %s\n"), type2name(type),
626 if (kern_quota_on(mnt->mnt_fsname, type, cfmt) >= 0) { /* Is quota enabled? */
627 if (!(flags & FL_FORCE)) {
628 if (flags & FL_INTERACTIVE) {
629 printf(_("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n"), type2name(type), mnt->mnt_dir);
630 if (!ask_yn(_("Should I continue"), 0)) {
631 printf(_("As you wish... Canceling check of this file.\n"));
636 die(6, _("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n\
637 Please turn quotas off or use -f to force checking.\n"),
638 type2name(type), mnt->mnt_dir);
640 /* At least sync quotas so damage will be smaller */
641 if (quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type),
642 mnt->mnt_fsname, 0, NULL) < 0)
643 die(4, _("Error while syncing quotas on %s: %s\n"), mnt->mnt_fsname, strerror(errno));
646 if (!(flags & FL_NEWFILE)) { /* Need to buffer file? */
647 if (get_qf_name(mnt, type, cfmt, 0, &qfname) < 0) {
648 errstr(_("Cannot get quotafile name for %s\n"), mnt->mnt_fsname);
651 if ((fd = open(qfname, O_RDONLY)) < 0) {
652 if (errno != ENOENT) {
653 errstr(_("Cannot open quotafile %s: %s\n"),
654 qfname, strerror(errno));
658 /* When file was not found, just skip it */
666 memset(old_info + type, 0, sizeof(old_info[type]));
667 if (is_tree_qfmt(cfmt))
668 ret = v2_buffer_file(qfname, fd, type, cfmt);
670 ret = v1_buffer_file(qfname, fd, type);
672 if (!(flags & FL_NEWFILE)) {
679 /* Backup old quotafile and rename new one to right name */
680 static int rename_files(struct mntent *mnt, int type)
682 char *filename, newfilename[PATH_MAX];
684 mode_t mode = S_IRUSR | S_IWUSR;
685 #ifdef HAVE_EXT2_INCLUDE
686 long ext2_flags = -1;
690 debug(FL_DEBUG, _("Renaming new files to proper names.\n"));
691 if (get_qf_name(mnt, type, cfmt, 0, &filename) < 0)
692 die(2, _("Cannot get name of old quotafile on %s.\n"), mnt->mnt_dir);
693 if (stat(filename, &st) < 0) { /* File doesn't exist? */
694 if (errno == ENOENT) {
695 debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n"));
698 errstr(_("Error while searching for old quota file %s: %s\n"),
699 filename, strerror(errno));
703 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
704 #ifdef HAVE_EXT2_INCLUDE
705 if ((fd = open(filename, O_RDONLY)) < 0) {
706 if (errno == ENOENT) {
707 debug(FL_DEBUG | FL_VERBOSE, _("Old file found removed during check!\n"));
710 errstr(_("Error while opening old quota file %s: %s\n"),
711 filename, strerror(errno));
715 if (ioctl(fd, EXT2_IOC_GETFLAGS, &ext2_flags) < 0)
716 debug(FL_DEBUG, _("EXT2_IOC_GETFLAGS failed: %s\n"), strerror(errno));
717 else if (ext2_flags & EXT2_IMMUTABLE_FL) {
718 /* IMMUTABLE flag set probably because system crashed and quota
719 * was not properly turned off */
720 debug(FL_DEBUG | FL_VERBOSE, _("Quota file %s has IMMUTABLE flag set. Clearing.\n"), filename);
721 ext2_flags &= ~EXT2_IMMUTABLE_FL;
722 if (ioctl(fd, EXT2_IOC_SETFLAGS, &ext2_flags) < 0) {
723 errstr(_("Failed to remove IMMUTABLE flag from quota file %s: %s\n"), filename, strerror(errno));
731 if (flags & FL_BACKUPS) {
732 debug(FL_DEBUG, _("Renaming old quotafile to %s~\n"), filename);
733 /* Backup old file */
734 strcpy(newfilename, filename);
735 /* Make backingup safe */
736 sstrncat(newfilename, "~", PATH_MAX);
737 if (newfilename[strlen(newfilename) - 1] != '~')
738 die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL);
739 if (rename(filename, newfilename) < 0) {
740 errstr(_("Cannot rename old quotafile %s to %s: %s\n"),
741 filename, newfilename, strerror(errno));
746 debug(FL_DEBUG, _("Renaming new quotafile\n"));
748 /* Rename new file to right name */
749 strcpy(newfilename, filename);
750 sstrncat(newfilename, ".new", PATH_MAX);
751 if (rename(newfilename, filename) < 0) {
752 errstr(_("Cannot rename new quotafile %s to name %s: %s\n"),
753 newfilename, filename, strerror(errno));
757 if (chmod(filename, mode) < 0) {
758 errstr(_("Cannot change permission of %s: %s\n"), filename, strerror(errno));
762 #ifdef HAVE_EXT2_INCLUDE
763 if (ext2_flags != -1) {
764 if ((fd = open(filename, O_RDONLY)) < 0) {
765 errstr(_("Cannot open new quota file %s: %s\n"), filename, strerror(errno));
769 if (ioctl(fd, EXT2_IOC_SETFLAGS, &ext2_flags) < 0)
770 errstr(_("Warning: Cannot set EXT2 flags on %s: %s\n"), filename, strerror(errno));
779 * Dump the quota info that we have in memory now to the appropriate
780 * quota file. As quotafiles doesn't account to quotas we don't have to
781 * bother about accounting new blocks for quota file
783 static int dump_to_file(struct mntent *mnt, int type)
787 struct quota_handle *h;
789 debug(FL_DEBUG, _("Dumping gathered data for %ss.\n"), type2name(type));
790 if (!(h = new_io(mnt, type, cfmt))) {
791 errstr(_("Cannot initialize IO on new quotafile: %s\n"),
795 if (!(flags & FL_NEWFILE)) {
796 h->qh_info.dqi_bgrace = old_info[type].dqi_bgrace;
797 h->qh_info.dqi_igrace = old_info[type].dqi_igrace;
798 if (is_tree_qfmt(cfmt))
799 v2_merge_info(&h->qh_info, old_info + type);
800 mark_quotafile_info_dirty(h);
802 for (i = 0; i < DQUOTHASHSIZE; i++)
803 for (dquot = dquot_hash[type][i]; dquot; dquot = dquot->dq_next) {
805 update_grace_times(dquot);
806 h->qh_ops->commit_dquot(dquot, COMMIT_ALL);
809 errstr(_("Cannot finish IO on new quotafile: %s\n"), strerror(errno));
812 debug(FL_DEBUG, _("Data dumped.\n"));
813 if (kern_quota_on(mnt->mnt_fsname, type, cfmt) >= 0) { /* Quota turned on? */
816 if (get_qf_name(mnt, type, cfmt, NF_FORMAT, &filename) < 0)
817 errstr(_("Cannot find checked quota file for %ss on %s!\n"), type2name(type), mnt->mnt_fsname);
819 if (quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type),
820 mnt->mnt_fsname, 0, NULL) < 0)
821 errstr(_("Cannot turn %s quotas off on %s: %s\nKernel won't know about changes quotacheck did.\n"),
822 type2name(type), mnt->mnt_fsname, strerror(errno));
826 /* Rename files - if it fails we cannot do anything better than just turn on quotas again */
827 rename_files(mnt, type);
829 if (kernel_iface == IFACE_GENERIC)
830 ret = quotactl(QCMD(Q_QUOTAON, type), mnt->mnt_fsname, util2kernfmt(cfmt), filename);
832 ret = quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->mnt_fsname, 0, filename);
834 errstr(_("Cannot turn %s quotas on on %s: %s\nKernel won't know about changes quotacheck did.\n"),
835 type2name(type), mnt->mnt_fsname, strerror(errno));
841 if (rename_files(mnt, type) < 0)
846 /* Substract space used by old quota file from usage */
847 static void sub_quota_file(struct mntent *mnt, int qtype, int ftype)
855 debug(FL_DEBUG, _("Substracting space used by old %s quota file.\n"), type2name(ftype));
856 if (get_qf_name(mnt, ftype, cfmt, 0, &filename) < 0) {
857 debug(FL_VERBOSE, _("Old %s file not found. Usage will not be substracted.\n"), type2name(ftype));
861 if (stat(filename, &st) < 0) {
862 debug(FL_VERBOSE, _("Cannot stat old %s quota file: %s\n"), type2name(ftype), strerror(errno));
866 qspace = getqsize(filename, &st);
869 if (qtype == USRQUOTA)
873 if ((d = lookup_dquot(id, qtype)) == NODQUOT) {
874 errstr(_("Quota structure for %s owning quota file not present! Something is really wrong...\n"), type2name(qtype));
877 d->dq_dqb.dqb_curinodes--;
878 d->dq_dqb.dqb_curspace -= qspace;
879 debug(FL_DEBUG, _("Substracted %lu bytes.\n"), (unsigned long)qspace);
882 /* Buffer quotafile, run filesystem scan, dump quotafiles */
883 static void check_dir(struct mntent *mnt)
888 if (lstat(mnt->mnt_dir, &st) < 0)
889 die(2, _("Cannot stat mountpoint %s: %s\n"), mnt->mnt_dir, strerror(errno));
890 if (!S_ISDIR(st.st_mode))
891 die(2, _("Mountpoint %s is not a directory?!\n"), mnt->mnt_dir);
893 files_done = dirs_done = 0;
895 if (process_file(mnt, USRQUOTA) < 0)
898 if (process_file(mnt, GRPQUOTA) < 0)
900 if (!ucheck && !gcheck) /* Nothing to check? */
902 if (!(flags & FL_NOREMOUNT)) {
903 /* Now we try to remount fs read-only to prevent races when scanning filesystem */
905 (NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY,
906 NULL) < 0 && !(flags & FL_FORCEREMOUNT)) {
907 if (flags & FL_INTERACTIVE) {
908 printf(_("Cannot remount filesystem mounted on %s read-only. Counted values might not be right.\n"), mnt->mnt_dir);
909 if (!ask_yn(_("Should I continue"), 0)) {
910 printf(_("As you wish... Canceling check of this file.\n"));
915 errstr(_("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\
916 Please stop all programs writing to filesystem or use -m flag to force checking.\n"), mnt->mnt_dir);
922 debug(FL_DEBUG, _("Filesystem remounted read-only\n"));
924 debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt->mnt_fsname, mnt->mnt_dir);
925 #if defined(EXT2_DIRECT)
926 if (!strcmp(mnt->mnt_type, MNTTYPE_EXT2) || !strcmp(mnt->mnt_type, MNTTYPE_EXT3)) {
927 if (ext2_direct_scan(mnt->mnt_fsname) < 0)
934 if (flags & FL_VERYVERBOSE)
936 if (scan_dir(mnt->mnt_dir) < 0)
940 if (flags & FL_VERBOSE || flags & FL_VERYVERBOSE)
941 fputs(_("done\n"), stdout);
943 sub_quota_file(mnt, USRQUOTA, USRQUOTA);
944 sub_quota_file(mnt, USRQUOTA, GRPQUOTA);
947 sub_quota_file(mnt, GRPQUOTA, USRQUOTA);
948 sub_quota_file(mnt, GRPQUOTA, GRPQUOTA);
950 debug(FL_DEBUG | FL_VERBOSE, _("Checked %d directories and %d files\n"), dirs_done,
953 if (mount(NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT, NULL) < 0)
954 die(4, _("Cannot remount filesystem %s read-write. cannot write new quota files.\n"), mnt->mnt_dir);
955 debug(FL_DEBUG, _("Filesystem remounted RW.\n"));
958 dump_to_file(mnt, USRQUOTA);
960 dump_to_file(mnt, GRPQUOTA);
965 /* Detect quota format from filename of present files */
966 static int detect_filename_format(struct mntent *mnt, int type)
970 char namebuf[PATH_MAX];
974 if (type == USRQUOTA) {
975 if ((option = hasmntopt(mnt, MNTOPT_USRQUOTA)))
976 option += strlen(MNTOPT_USRQUOTA);
977 else if (hasmntopt(mnt, MNTOPT_USRJQUOTA)) {
979 option += strlen(MNTOPT_USRJQUOTA);
981 else if ((option = hasmntopt(mnt, MNTOPT_QUOTA)))
982 option += strlen(MNTOPT_QUOTA);
985 if ((option = hasmntopt(mnt, MNTOPT_GRPQUOTA)))
986 option += strlen(MNTOPT_GRPQUOTA);
987 else if (hasmntopt(mnt, MNTOPT_GRPJQUOTA)) {
989 option += strlen(MNTOPT_GRPJQUOTA);
993 die(2, _("Cannot find quota option on filesystem %s with quotas!\n"), mnt->mnt_dir);
995 char fmtbuf[64], *space;
997 if (!(option = hasmntopt(mnt, MNTOPT_JQFMT))) {
999 errstr(_("Cannot detect quota format for journalled quota on %s\n"), mnt->mnt_dir);
1002 option += strlen(MNTOPT_JQFMT);
1005 space = strchr(option, ',');
1007 space = option + strlen(option);
1008 if (space-option > sizeof(fmtbuf))
1010 sstrncpy(fmtbuf, option+1, space-option);
1011 fmt = name2fmt(fmtbuf);
1012 if (fmt == QF_ERROR)
1016 else if (*option == '=') /* If the file name is specified we can't detect quota format from it... */
1018 snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSV0], extensions[type]);
1019 if (!stat(namebuf, &statbuf)) {
1020 int fd = open(namebuf, O_RDONLY);
1023 fmt = v2_detect_version(namebuf, fd, type);
1028 if (errno != ENOENT)
1030 snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSOLD], extensions[type]);
1031 if (!stat(namebuf, &statbuf))
1033 /* Old quota files don't exist, just create VFSv0 format if available */
1034 if (kern_qfmt_supp(QF_VFSV0))
1036 if (kern_qfmt_supp(QF_VFSOLD))
1041 static void check_all(void)
1047 if (init_mounts_scan((flags & FL_ALL) ? 0 : 1, &mntpoint, 0) < 0)
1048 die(2, _("Cannot initialize mountpoint scan.\n"));
1049 while ((mnt = get_next_mount())) {
1050 if (flags & FL_ALL && flags & FL_NOROOT && !strcmp(mnt->mnt_dir, "/"))
1052 if (!strcmp(mnt->mnt_type, MNTTYPE_XFS) || nfs_fstype(mnt->mnt_type) ||
1053 meta_qf_fstype(mnt->mnt_type)) {
1054 debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt->mnt_fsname, mnt->mnt_dir);
1058 if (uwant && hasquota(mnt, USRQUOTA, 0))
1062 if (gwant && hasquota(mnt, GRPQUOTA, 0))
1066 if (!ucheck && !gcheck)
1069 cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : GRPQUOTA);
1071 errstr(_("Cannot guess format from filename on %s. Please specify format on commandline.\n"),
1075 debug(FL_DEBUG, _("Detected quota format %s\n"), fmt2name(cfmt));
1078 if (flags & FL_VERBOSE && !hasmntopt(mnt, MNTOPT_USRJQUOTA) &&
1079 !hasmntopt(mnt, MNTOPT_GRPJQUOTA) && !warned &&
1080 (!strcmp(mnt->mnt_type, MNTTYPE_EXT3) ||
1081 !strcmp(mnt->mnt_type, MNTTYPE_EXT4) ||
1082 !strcmp(mnt->mnt_type, MNTTYPE_EXT4DEV) ||
1083 !strcmp(mnt->mnt_type, MNTTYPE_REISER))) {
1084 struct utsname stats;
1086 /* Parse Linux kernel version and issue warning if not using
1087 * journaled quotas. */
1089 if (uname(&stats) < 0)
1090 errstr(_("Cannot get system info: %s\n"),
1092 else if (!strcmp(stats.sysname, "Linux")) {
1096 v = strtol(stats.release, &errch, 10);
1097 if (*errch == '.' && v >= 2) {
1098 v = strtol(errch + 1, &errch, 10);
1099 if (*errch == '.' && v >= 6) {
1100 v = strtol(errch + 1, &errch, 10);
1102 errstr(_("Your kernel probably supports journaled quota but you are not using it. Consider switching to journaled quota to avoid running quotacheck after an unclean shutdown.\n"));
1112 if (!checked && (!(flags & FL_ALL) || flags & (FL_VERBOSE | FL_DEBUG)))
1113 errstr(_("Cannot find filesystem to check or filesystem not mounted with quota option.\n"));
1116 int main(int argc, char **argv)
1119 progname = basename(argv[0]);
1121 parse_options(argc, argv);
1122 init_kernel_interface();
1126 errstr(_("Allocated %d bytes memory\nFree'd %d bytes\nLost %d bytes\n"),
1127 malloc_mem, free_mem, malloc_mem - free_mem);