3 * Interactions of quota with system - filenames, fstab and so on...
5 * Jan Kara <jack@suse.cz> - sponsored by SuSE CR
23 #include <sys/types.h>
34 #include "dqblk_xfs.h"
35 #include "quotaio_v2.h"
37 #define min(x,y) (((x) < (y)) ? (x) : (y))
41 static char extensions[MAXQUOTAS + 2][20] = INITQFNAMES;
42 static char *basenames[] = INITQFBASENAMES;
43 static char *fmtnames[] = { "vfsold",
51 * Check for various kinds of NFS filesystem
53 int nfs_fstype(char *type)
55 return !strcmp(type, MNTTYPE_NFS) || !strcmp(type, MNTTYPE_NFS4) ||
56 !strcmp(type, MNTTYPE_MPFS);
60 * Check whether filesystem has hidden quota files which is handles
61 * as metadata (and thus always tracks usage).
63 int meta_qf_fstype(char *type)
65 return !strcmp(type, MNTTYPE_OCFS2);
69 * Check whether give filesystem type is supported
72 static int correct_fstype(char *type)
74 char *mtype = sstrdup(type), *next;
78 next = strchr(type, ',');
81 if (!strcmp(type, MNTTYPE_EXT2) ||
82 !strcmp(type, MNTTYPE_EXT3) ||
83 !strcmp(type, MNTTYPE_EXT4) ||
84 !strcmp(type, MNTTYPE_EXT4DEV) ||
85 !strcmp(type, MNTTYPE_JFS) ||
86 !strcmp(type, MNTTYPE_MINIX) ||
87 !strcmp(type, MNTTYPE_UFS) ||
88 !strcmp(type, MNTTYPE_UDF) ||
89 !strcmp(type, MNTTYPE_REISER) ||
90 !strcmp(type, MNTTYPE_XFS) ||
91 !strcmp(type, MNTTYPE_NFS) ||
92 !strcmp(type, MNTTYPE_NFS4) ||
93 !strcmp(type, MNTTYPE_OCFS2) ||
94 !strcmp(type, MNTTYPE_MPFS)) {
105 * Convert type of quota to written representation
107 char *type2name(int type)
109 return extensions[type];
113 * Convert name to uid
115 uid_t user2uid(char *name, int flag, int *err)
117 struct passwd *entry;
124 ret = strtoul(name, &errch, 0);
125 if (!*errch) /* Is name number - we got directly uid? */
128 if (!(entry = getpwnam(name))) {
130 errstr(_("user %s does not exist.\n"), name);
138 return entry->pw_uid;
142 * Convert group name to gid
144 gid_t group2gid(char *name, int flag, int *err)
153 ret = strtoul(name, &errch, 0);
154 if (!*errch) /* Is name number - we got directly gid? */
157 if (!(entry = getgrnam(name))) {
159 errstr(_("group %s does not exist.\n"), name);
167 return entry->gr_gid;
173 int name2id(char *name, int qtype, int flag, int *err)
175 if (qtype == USRQUOTA)
176 return user2uid(name, flag, err);
178 return group2gid(name, flag, err);
182 * Convert uid to name
184 int uid2user(uid_t id, char *buf)
186 struct passwd *entry;
188 if (!(entry = getpwuid(id))) {
189 snprintf(buf, MAXNAMELEN, "#%u", (uint) id);
193 sstrncpy(buf, entry->pw_name, MAXNAMELEN);
198 * Convert gid to name
200 int gid2group(gid_t id, char *buf)
204 if (!(entry = getgrgid(id))) {
205 snprintf(buf, MAXNAMELEN, "#%u", (uint) id);
209 sstrncpy(buf, entry->gr_name, MAXNAMELEN);
214 * Convert id to user/groupname
216 int id2name(int id, int qtype, char *buf)
218 if (qtype == USRQUOTA)
219 return uid2user(id, buf);
221 return gid2group(id, buf);
225 * Parse /etc/nsswitch.conf and return type of default passwd handling
227 int passwd_handling(void)
230 char buf[1024], *colpos, *spcpos;
231 int ret = PASSWD_FILES;
233 if (!(f = fopen("/etc/nsswitch.conf", "r")))
234 return PASSWD_FILES; /* Can't open nsswitch.conf - fallback on compatible mode */
235 while (fgets(buf, sizeof(buf), f)) {
236 if (strncmp(buf, "passwd:", 7)) /* Not passwd entry? */
238 for (colpos = buf+7; isspace(*colpos); colpos++);
239 if (!*colpos) /* Not found any type of handling? */
241 for (spcpos = colpos; !isspace(*spcpos) && *spcpos; spcpos++);
243 if (!strcmp(colpos, "db") || !strcmp(colpos, "nis") || !strcmp(colpos, "nis+"))
252 * Convert quota format name to number
254 int name2fmt(char *str)
258 for (fmt = 0; fmt < QFMT_NAMES; fmt++)
259 if (!strcmp(str, fmtnames[fmt]))
261 errstr(_("Unknown quota format: %s\nSupported formats are:\n\
262 vfsold - original quota format\n\
263 vfsv0 - standard quota format\n\
264 vfsv1 - quota format with 64-bit limits\n\
265 rpc - use RPC calls\n\
266 xfs - XFS quota format\n"), str);
271 * Convert quota format number to name
273 char *fmt2name(int fmt)
275 return fmtnames[fmt];
279 * Convert kernel to utility quota format number
281 int kern2utilfmt(int kernfmt)
297 * Convert utility to kernel quota format number
299 int util2kernfmt(int fmt)
313 * Convert time difference of seconds and current time
315 void difftime2str(time_t seconds, char *buf)
323 if (seconds <= now) {
324 strcpy(buf, _("none"));
327 time2str(seconds - now, buf, TF_ROUND);
331 * Convert time to printable form
333 void time2str(time_t seconds, char *buf, int flags)
335 uint minutes, hours, days;
337 if (flags & TF_ROUND) {
338 minutes = (seconds + 30) / 60; /* Rounding */
339 hours = minutes / 60;
344 snprintf(buf, MAXTIMELEN, _("%ddays"), days);
346 snprintf(buf, MAXTIMELEN, _("%02d:%02d"), hours + days * 24, minutes);
349 minutes = seconds / 60;
351 hours = minutes / 60;
355 if (seconds || (!minutes && !hours && !days))
356 snprintf(buf, MAXTIMELEN, _("%useconds"), (uint)(seconds+minutes*60+hours*3600+days*3600*24));
358 snprintf(buf, MAXTIMELEN, _("%uminutes"), (uint)(minutes+hours*60+days*60*24));
360 snprintf(buf, MAXTIMELEN, _("%uhours"), (uint)(hours+days*24));
362 snprintf(buf, MAXTIMELEN, _("%udays"), days);
367 * Convert number with unit to time in seconds
369 int str2timeunits(time_t num, char *unit, time_t *res)
371 if (memcmp(unit, "second", 6) == 0)
373 else if (memcmp(unit, "minute", 6) == 0)
375 else if (memcmp(unit, "hour", 4) == 0)
376 *res = num * 60 * 60;
377 else if (memcmp(unit, "day", 3) == 0)
378 *res = num * 24 * 60 * 60;
385 * Convert number in quota blocks to some nice short form for printing
387 void space2str(qsize_t space, char *buf, int format)
390 char suffix[8] = " MGT";
392 space = qb2kb(space);
394 for (i = 3; i > 0; i--)
395 if (space >= (1LL << (QUOTABLOCK_BITS*i))*100) {
396 sprintf(buf, "%llu%c", (unsigned long long)(space+(1 << (QUOTABLOCK_BITS*i))-1) >> (QUOTABLOCK_BITS*i), suffix[i]);
399 sprintf(buf, "%lluK", (unsigned long long)space);
402 sprintf(buf, "%llu", (unsigned long long)space);
406 * Convert number to some nice short form for printing
408 void number2str(unsigned long long num, char *buf, int format)
411 unsigned long long div;
412 char suffix[8] = " kmgt";
415 for (i = 4, div = 1000000000000LL; i > 0; i--, div /= 1000)
416 if (num >= 100*div) {
417 sprintf(buf, "%llu%c", (num+div-1) / div, suffix[i]);
420 sprintf(buf, "%llu", num);
424 * Check for XFS filesystem with quota accounting enabled
426 static int hasxfsquota(struct mntent *mnt, int type, int flags)
430 struct xfs_mem_dqinfo info;
434 if (flags & MS_XFS_DISABLED)
437 dev = get_device_name(mnt->mnt_fsname);
440 /* Loopback mounted device with a loopback device in the arguments? */
441 if ((opt = hasmntopt(mnt, MNTOPT_LOOP)) && (opt = strchr(opt, '='))) {
443 endopt = strchr(opt+1, ',');
447 dev = strndup(opt+1, endopt-opt-1);
452 memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
453 if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
454 sbflags = (info.qs_flags & 0xff00) >> 8;
455 if (type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT))
457 else if (type == GRPQUOTA && (info.qs_flags & XFS_QUOTA_GDQ_ACCT))
461 * Old XFS filesystems (up to XFS 1.2 / Linux 2.5.47) had a
462 * hack to allow enabling quota on the root filesystem without
463 * having to specify it at mount time.
465 else if (strcmp(mnt->mnt_dir, "/"))
467 else if (type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT))
469 else if (type == GRPQUOTA && (sbflags & XFS_QUOTA_GDQ_ACCT))
471 #endif /* XFS_ROOTHACK */
477 /* Return if given option has nonempty argument */
478 char *hasmntoptarg(struct mntent *mnt, char *opt)
480 char *p = hasmntopt(mnt, opt);
485 if (*p == '=' && p[1] != ',')
491 * Check to see if a particular quota is to be enabled (filesystem mounted with proper option)
493 int hasquota(struct mntent *mnt, int type, int flags)
495 if (!correct_fstype(mnt->mnt_type) || hasmntopt(mnt, MNTOPT_NOQUOTA))
498 if (!strcmp(mnt->mnt_type, MNTTYPE_XFS))
499 return hasxfsquota(mnt, type, flags);
500 if (nfs_fstype(mnt->mnt_type)) /* NFS always has quota or better there is no good way how to detect it */
503 if ((type == USRQUOTA) && (hasmntopt(mnt, MNTOPT_USRQUOTA) || hasmntoptarg(mnt, MNTOPT_USRJQUOTA)))
505 if ((type == GRPQUOTA) && (hasmntopt(mnt, MNTOPT_GRPQUOTA) || hasmntoptarg(mnt, MNTOPT_GRPJQUOTA)))
507 if ((type == USRQUOTA) && hasmntopt(mnt, MNTOPT_QUOTA))
512 /* Check whether quotafile for given format exists - return its name in namebuf */
513 static int check_fmtfile_ok(char *name, int type, int fmt, int flags)
517 if (flags & NF_EXIST) {
520 if (stat(name, &st) < 0) {
522 errstr(_("Cannot stat quota file %s: %s\n"), name, strerror(errno));
526 if (flags & NF_FORMAT) {
529 if ((fd = open(name, O_RDONLY)) >= 0) {
530 if (is_tree_qfmt(fmt))
531 ret = quotafile_ops_2.check_file(fd, type, fmt);
533 ret = quotafile_ops_1.check_file(fd, type, fmt);
538 else if (errno != ENOENT && errno != EPERM) {
539 errstr(_("Cannot open quotafile %s: %s\n"), name, strerror(errno));
547 * Get quotafile name for given entry. Return 0 in case format check succeeded,
548 * otherwise return -1.
549 * Note that formats without quotafile *must* be detected prior to calling this function
551 int get_qf_name(struct mntent *mnt, int type, int fmt, int flags, char **filename)
553 char *option, *pathname, has_quota_file_definition = 0;
554 char qfullname[PATH_MAX];
557 if (type == USRQUOTA && (option = hasmntopt(mnt, MNTOPT_USRQUOTA))) {
558 if (*(pathname = option + strlen(MNTOPT_USRQUOTA)) == '=')
559 has_quota_file_definition = 1;
561 else if (type == USRQUOTA && (option = hasmntoptarg(mnt, MNTOPT_USRJQUOTA))) {
563 has_quota_file_definition = 1;
564 sstrncpy(qfullname, mnt->mnt_dir, sizeof(qfullname));
565 sstrncat(qfullname, "/", sizeof(qfullname));
567 else if (type == GRPQUOTA && (option = hasmntopt(mnt, MNTOPT_GRPQUOTA))) {
568 pathname = option + strlen(MNTOPT_GRPQUOTA);
569 if (*pathname == '=') {
570 has_quota_file_definition = 1;
574 else if (type == GRPQUOTA && (option = hasmntoptarg(mnt, MNTOPT_GRPJQUOTA))) {
576 has_quota_file_definition = 1;
577 sstrncpy(qfullname, mnt->mnt_dir, sizeof(qfullname));
578 sstrncat(qfullname, "/", sizeof(qfullname));
580 else if (type == USRQUOTA && (option = hasmntopt(mnt, MNTOPT_QUOTA))) {
581 pathname = option + strlen(MNTOPT_QUOTA);
582 if (*pathname == '=') {
583 has_quota_file_definition = 1;
590 if (has_quota_file_definition) {
591 if ((option = strchr(pathname, ','))) {
592 int tocopy = min(option - pathname + 1,
593 sizeof(qfullname) - strlen(qfullname));
594 sstrncpy(qfullname + strlen(qfullname), pathname, tocopy);
596 sstrncat(qfullname, pathname, sizeof(qfullname));
598 snprintf(qfullname, PATH_MAX, "%s/%s.%s", mnt->mnt_dir,
599 basenames[fmt], extensions[type]);
601 if (check_fmtfile_ok(qfullname, type, fmt, flags)) {
602 *filename = sstrdup(qfullname);
608 #define START_MNT_POINTS 256 /* The number of mount points we start with... */
611 * Create NULL terminated list of quotafile handles from given list of mountpoints
612 * List of zero length means scan all entries in /etc/mtab
614 struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt,
615 int ioflags, int mntflags)
619 static int hlist_allocated = 0;
620 static struct quota_handle **hlist = NULL;
622 if (!hlist_allocated) {
623 hlist = smalloc(START_MNT_POINTS * sizeof(struct quota_handle *));
624 hlist_allocated = START_MNT_POINTS;
627 /* If directories are specified, cache all NFS mountpoints */
628 if (count && !(mntflags & MS_LOCALONLY))
629 mntflags |= MS_NFS_ALL;
631 if (init_mounts_scan(count, mntpoints, mntflags) < 0)
632 die(2, _("Cannot initialize mountpoint scan.\n"));
633 while ((mnt = get_next_mount())) {
635 if (nfs_fstype(mnt->mnt_type))
638 if (fmt == -1 || count) {
640 if (gotmnt+1 >= hlist_allocated) {
641 hlist_allocated += START_MNT_POINTS;
642 hlist = srealloc(hlist, hlist_allocated * sizeof(struct quota_handle *));
644 if (!(hlist[gotmnt] = init_io(mnt, type, fmt, ioflags)))
651 if (nfs_fstype(mnt->mnt_type))
655 if (!strcmp(mnt->mnt_type, MNTTYPE_XFS))
659 if (strcmp(mnt->mnt_type, MNTTYPE_XFS) && !nfs_fstype(mnt->mnt_type))
666 hlist[gotmnt] = NULL;
667 if (count && gotmnt != count)
668 die(1, _("Not all specified mountpoints are using quota.\n"));
673 * Free given list of handles
675 int dispose_handle_list(struct quota_handle **hlist)
680 for (i = 0; hlist[i]; i++)
681 if (end_io(hlist[i]) < 0) {
682 errstr(_("Error while releasing file on %s\n"),
683 hlist[i]->qh_quotadev);
690 * Check whether given device name matches this quota handle
692 int devcmp_handle(const char *dev, struct quota_handle *h)
696 if (stat(dev, &sbuf) < 0)
697 return (strcmp(dev, h->qh_quotadev) == 0);
698 if (!S_ISBLK(sbuf.st_mode))
699 return (strcmp(dev, h->qh_quotadev) == 0);
700 if (sbuf.st_rdev != h->qh_stat.st_rdev)
706 * Check whether two quota handles are for the same device
708 int devcmp_handles(struct quota_handle *a, struct quota_handle *b)
710 if (!S_ISBLK(a->qh_stat.st_mode) || !S_ISBLK(b->qh_stat.st_mode))
711 return (strcmp(a->qh_quotadev, b->qh_quotadev) == 0);
712 if (a->qh_stat.st_rdev != b->qh_stat.st_rdev)
718 * Check kernel quota version
721 int kernel_iface; /* Kernel interface type */
722 static int kernel_qfmt_num; /* Number of different supported formats */
723 static int kernel_qfmt[QUOTAFORMATS]; /* Formats supported by kernel */
726 #define FS_DQSTATS 16
729 #define FS_DQ_SYNCS 8
732 void init_kernel_interface(void)
735 struct sigaction sig, oldsig;
737 /* This signal handling is needed because old kernels send us SIGSEGV as they try to resolve the device */
738 sig.sa_handler = SIG_IGN;
739 sig.sa_sigaction = NULL;
740 if (sigemptyset(&sig.sa_mask) < 0)
741 die(2, _("Cannot create set for sigaction(): %s\n"), strerror(errno));
743 if (sigaction(SIGSEGV, &sig, &oldsig) < 0)
744 die(2, _("Cannot set signal handler: %s\n"), strerror(errno));
747 if (!stat("/proc/fs/xfs/stat", &st))
748 kernel_qfmt[kernel_qfmt_num++] = QF_XFS;
750 if (!quotactl(QCMD(Q_XGETQSTAT, 0), NULL, 0, NULL) || (errno != EINVAL && errno != ENOSYS))
751 kernel_qfmt[kernel_qfmt_num++] = QF_XFS;
752 /* Detect new kernel interface; Assume generic interface unless we can prove there is not one... */
753 if (!stat("/proc/sys/fs/quota", &st) || errno != ENOENT) {
754 kernel_iface = IFACE_GENERIC;
755 kernel_qfmt[kernel_qfmt_num++] = QF_META;
756 kernel_qfmt[kernel_qfmt_num++] = QF_VFSOLD;
757 kernel_qfmt[kernel_qfmt_num++] = QF_VFSV0;
758 kernel_qfmt[kernel_qfmt_num++] = QF_VFSV1;
761 struct v2_dqstats v2_stats;
763 if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (void *)&v2_stats) >= 0) {
764 kernel_qfmt[kernel_qfmt_num++] = QF_VFSV0;
765 kernel_iface = IFACE_VFSV0;
767 else if (errno != ENOSYS && errno != ENOTSUP) {
768 /* RedHat 7.1 (2.4.2-2) newquota check
769 * Q_V2_GETSTATS in it's old place, Q_GETQUOTA in the new place
770 * (they haven't moved Q_GETSTATS to its new value) */
773 char tmp[1024]; /* Just temporary buffer */
775 if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, tmp))
777 if (quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", 0, tmp))
780 /* On a RedHat 2.4.2-2 we expect 0, EINVAL
781 * On a 2.4.x we expect 0, ENOENT
782 * On a 2.4.x-ac we wont get here */
783 if (err_stat == 0 && err_quota == EINVAL) {
784 kernel_qfmt[kernel_qfmt_num++] = QF_VFSV0;
785 kernel_iface = IFACE_VFSV0;
788 kernel_qfmt[kernel_qfmt_num++] = QF_VFSOLD;
789 kernel_iface = IFACE_VFSOLD;
793 if (sigaction(SIGSEGV, &oldsig, NULL) < 0)
794 die(2, _("Cannot reset signal handler: %s\n"), strerror(errno));
797 /* Return whether kernel is able to handle given format */
798 int kern_qfmt_supp(int fmt)
803 return kernel_qfmt_num > 0;
805 for (i = 0; i < kernel_qfmt_num; i++)
806 if (fmt == kernel_qfmt[i])
811 /* Check whether old quota is turned on on given device */
812 static int v1_kern_quota_on(const char *dev, int type)
814 char tmp[1024]; /* Just temporary buffer */
815 qid_t id = (type == USRQUOTA) ? getuid() : getgid();
817 if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, id, tmp)) /* OK? */
822 /* Check whether new quota is turned on on given device */
823 static int v2_kern_quota_on(const char *dev, int type)
825 char tmp[1024]; /* Just temporary buffer */
826 qid_t id = (type == USRQUOTA) ? getuid() : getgid();
828 if (!quotactl(QCMD(Q_V2_GETQUOTA, type), dev, id, tmp)) /* OK? */
833 /* Check whether XFS quota is turned on on given device */
834 static int xfs_kern_quota_on(const char *dev, int type)
836 struct xfs_mem_dqinfo info;
838 if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
839 if (type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT))
841 if (type == GRPQUOTA && (info.qs_flags & XFS_QUOTA_GDQ_ACCT))
848 * Check whether is quota turned on on given device for given type
850 int kern_quota_on(const char *dev, int type, int fmt)
852 /* Check whether quota is turned on... */
853 if (kernel_iface == IFACE_GENERIC) {
856 if (quotactl(QCMD(Q_GETFMT, type), dev, 0, (void *)&actfmt) < 0)
858 actfmt = kern2utilfmt(actfmt);
863 if ((fmt == -1 || fmt == QF_VFSV0) &&
864 v2_kern_quota_on(dev, type)) /* VFSv0 quota format */
866 if ((fmt == -1 || fmt == QF_XFS) &&
867 xfs_kern_quota_on(dev, type)) /* XFS quota format */
869 if ((fmt == -1 || fmt == QF_VFSOLD) &&
870 v1_kern_quota_on(dev, type)) /* Old quota format */
877 * mtab/fstab handling routines
882 char *me_type; /* Type of filesystem for given entry */
883 char *me_opts; /* Options of filesystem */
884 dev_t me_dev; /* Device filesystem is mounted on */
885 ino_t me_ino; /* Inode number of root of filesystem */
886 const char *me_devname; /* Name of device (after pass through get_device_name()) */
887 const char *me_dir; /* One of mountpoints of filesystem */
890 struct searched_dir {
891 int sd_dir; /* Is searched dir mountpoint or in fact device? */
892 dev_t sd_dev; /* Device mountpoint lies on */
893 ino_t sd_ino; /* Inode number of mountpoint */
894 const char *sd_name; /* Name of given dir/device */
897 #define ALLOC_ENTRIES_NUM 16 /* Allocate entries by this number */
898 #define AUTOFS_DIR_MAX 64 /* Maximum number of autofs directories */
900 static int mnt_entries_cnt; /* Number of cached mountpoint entries */
901 static struct mount_entry *mnt_entries; /* Cached mounted filesystems */
902 static int check_dirs_cnt, act_checked; /* Number of dirs to check; Actual checked dir/(mountpoint in case of -a) */
903 static struct searched_dir *check_dirs; /* Directories to check */
905 /* Cache mtab/fstab */
906 static int cache_mnt_table(int flags)
911 struct statfs fsstat;
912 int allocated = 0, i = 0;
914 char mntpointbuf[PATH_MAX];
915 int autofsdircnt = 0;
916 char autofsdir[AUTOFS_DIR_MAX][PATH_MAX];
919 mntf = setmntent(ALT_MTAB, "r");
923 mntf = setmntent(_PATH_MOUNTED, "r");
926 /* Fallback to fstab when mtab not available */
927 if (!(mntf = setmntent(_PATH_MNTTAB, "r"))) {
928 errstr(_("Cannot open any file with mount points.\n"));
932 mnt_entries = smalloc(sizeof(struct mount_entry) * ALLOC_ENTRIES_NUM);
934 allocated += ALLOC_ENTRIES_NUM;
935 while ((mnt = getmntent(mntf))) {
938 if (!(devname = get_device_name(mnt->mnt_fsname))) {
939 errstr(_("Cannot get device name for %s\n"), mnt->mnt_fsname);
943 /* Check for mountpoints under autofs and skip them*/
944 for (i = 0; i < autofsdircnt; i++) {
945 int slen = strlen(autofsdir[i]);
947 if (slen <= strlen(mnt->mnt_dir) && !strncmp(autofsdir[i], mnt->mnt_dir, slen))
950 if (i < autofsdircnt) {
951 free((char *)devname);
955 if (flags & MS_NO_AUTOFS && !strcmp(mnt->mnt_type, MNTTYPE_AUTOFS)) { /* Autofs dir to remember? */
956 if (autofsdircnt == AUTOFS_DIR_MAX)
957 die(3, "Too many autofs mountpoints. Please contact <jack@suse.cz>\n");
958 snprintf(autofsdir[autofsdircnt++], PATH_MAX, "%s/", mnt->mnt_dir);
959 free((char *)devname);
963 if (flags & MS_LOCALONLY && nfs_fstype(mnt->mnt_type)) {
964 free((char *)devname);
968 /* Further we are not interested in mountpoints without quotas and
969 we don't want to touch them */
970 if (!hasquota(mnt, USRQUOTA, flags) && !hasquota(mnt, GRPQUOTA, flags)) {
971 free((char *)devname);
975 if (!realpath(mnt->mnt_dir, mntpointbuf)) {
976 errstr(_("Cannot resolve mountpoint path %s: %s\n"), mnt->mnt_dir, strerror(errno));
977 free((char *)devname);
981 if (statfs(mntpointbuf, &fsstat) != 0) {
982 errstr(_("Cannot statfs() %s: %s\n"), mntpointbuf, strerror(errno));
983 free((char *)devname);
986 /* Do not scan quotas on "magic" automount points */
987 if (fsstat.f_blocks == 0 && fsstat.f_bfree == 0 && fsstat.f_bavail == 0) {
988 free((char *)devname);
992 if (!nfs_fstype(mnt->mnt_type)) {
993 if (stat(devname, &st) < 0) { /* Can't stat mounted device? */
994 errstr(_("Cannot stat() mounted device %s: %s\n"), devname, strerror(errno));
995 free((char *)devname);
998 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
1000 errstr(_("Device (%s) filesystem is mounted on unsupported device type. Skipping.\n"), devname);
1001 free((char *)devname);
1006 if (hasmntopt(mnt, MNTOPT_BIND)) {
1007 free((char *)devname);
1008 continue; /* We just ignore bind mounts... */
1010 else if ((opt = hasmntopt(mnt, MNTOPT_LOOP))) {
1011 char loopdev[PATH_MAX];
1014 if (!(opt = strchr(opt, '='))) {
1015 errstr(_("Cannot find device of loopback mount in options for %s. Skipping.\n"), devname);
1016 free((char *)devname);
1019 /* Copy the device name */
1020 for (opt++, i = 0; *opt && i < sizeof(loopdev)-1 && *opt != ','; opt++, i++)
1023 if (stat(loopdev, &st) < 0) { /* Can't stat loopback device? */
1024 errstr(_("Cannot stat() loopback device %s: %s\n"), opt, strerror(errno));
1025 free((char *)devname);
1028 if (!S_ISBLK(st.st_mode)) {
1029 errstr(_("Loopback device %s is not block device!\n"), opt);
1030 free((char *)devname);
1034 free((char *)devname);
1035 devname = sstrdup(loopdev);
1037 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
1038 goto unsupporteddev;
1042 for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
1044 /* Cope with network filesystems or new mountpoint */
1045 if (nfs_fstype(mnt->mnt_type) || i == mnt_entries_cnt) {
1046 if (stat(mnt->mnt_dir, &st) < 0) { /* Can't stat mountpoint? We have better ignore it... */
1047 errstr(_("Cannot stat() mountpoint %s: %s\n"), mnt->mnt_dir, strerror(errno));
1048 free((char *)devname);
1051 if (nfs_fstype(mnt->mnt_type)) {
1052 /* For network filesystems we must get device from root */
1054 if (!(flags & MS_NFS_ALL)) {
1055 for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
1057 else /* Always behave as if the device was unique */
1058 i = mnt_entries_cnt;
1061 if (i == mnt_entries_cnt) { /* New mounted device? */
1062 if (allocated == mnt_entries_cnt) {
1063 allocated += ALLOC_ENTRIES_NUM;
1064 mnt_entries = srealloc(mnt_entries, allocated * sizeof(struct mount_entry));
1066 mnt_entries[i].me_type = sstrdup(mnt->mnt_type);
1067 mnt_entries[i].me_opts = sstrdup(mnt->mnt_opts);
1068 mnt_entries[i].me_dev = dev;
1069 mnt_entries[i].me_ino = st.st_ino;
1070 mnt_entries[i].me_devname = devname;
1071 mnt_entries[i].me_dir = sstrdup(mntpointbuf);
1075 free((char *)devname); /* We don't need it any more */
1082 /* Find mountpoint of filesystem hosting dir in 'st'; Store it in 'st' */
1083 static const char *find_dir_mntpoint(struct stat *st)
1087 for (i = 0; i < mnt_entries_cnt; i++)
1088 if (mnt_entries[i].me_dev == st->st_dev) {
1089 st->st_ino = mnt_entries[i].me_ino;
1090 return mnt_entries[i].me_dir;
1095 /* Process and store given paths */
1096 static int process_dirs(int dcnt, char **dirs, int flags)
1100 char mntpointbuf[PATH_MAX];
1105 check_dirs = smalloc(sizeof(struct searched_dir) * dcnt);
1106 for (i = 0; i < dcnt; i++) {
1107 if (!strncmp(dirs[i], "UUID=", 5) || !strncmp(dirs[i], "LABEL=", 6)) {
1108 char *devname = (char *)get_device_name(dirs[i]);
1111 errstr(_("Cannot find a device with %s.\nSkipping...\n"), dirs[i]);
1114 if (stat(devname, &st) < 0) {
1115 errstr(_("Cannot stat() a mountpoint with %s: %s\nSkipping...\n"), dirs[i], strerror(errno));
1122 if (stat(dirs[i], &st) < 0) {
1123 errstr(_("Cannot stat() given mountpoint %s: %s\nSkipping...\n"), dirs[i], strerror(errno));
1126 check_dirs[check_dirs_cnt].sd_dir = S_ISDIR(st.st_mode);
1127 if (S_ISDIR(st.st_mode)) {
1128 const char *realmnt = dirs[i];
1130 /* Return st of mountpoint of dir in st.. */
1131 if (flags & MS_NO_MNTPOINT && !(realmnt = find_dir_mntpoint(&st))) {
1132 if (!(flags & MS_QUIET))
1133 errstr(_("Cannot find a filesystem mountpoint for directory %s\n"), dirs[i]);
1136 check_dirs[check_dirs_cnt].sd_dev = st.st_dev;
1137 check_dirs[check_dirs_cnt].sd_ino = st.st_ino;
1138 if (!realpath(realmnt, mntpointbuf)) {
1139 errstr(_("Cannot resolve path %s: %s\n"), realmnt, strerror(errno));
1143 else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
1146 check_dirs[check_dirs_cnt].sd_dev = st.st_rdev;
1147 for (mentry = 0; mentry < mnt_entries_cnt && mnt_entries[mentry].me_dev != st.st_rdev; mentry++);
1148 if (mentry == mnt_entries_cnt) {
1149 if (!(flags & MS_QUIET))
1150 errstr(_("Cannot find mountpoint for device %s\n"), dirs[i]);
1153 sstrncpy(mntpointbuf, mnt_entries[mentry].me_dir, PATH_MAX-1);
1156 errstr(_("Specified path %s is not directory nor device.\n"), dirs[i]);
1159 check_dirs[check_dirs_cnt].sd_name = sstrdup(mntpointbuf);
1162 if (!check_dirs_cnt) {
1163 if (!(flags & MS_QUIET))
1164 errstr(_("No correct mountpoint specified.\n"));
1173 * Initialize mountpoint scan
1175 int init_mounts_scan(int dcnt, char **dirs, int flags)
1177 if (cache_mnt_table(flags) < 0)
1179 if (process_dirs(dcnt, dirs, flags) < 0) {
1186 /* Find next usable mountpoint when scanning all mountpoints */
1187 static int find_next_entry_all(int *pos)
1191 while (++act_checked < mnt_entries_cnt) {
1192 mnt.mnt_fsname = (char *)mnt_entries[act_checked].me_devname;
1193 mnt.mnt_type = mnt_entries[act_checked].me_type;
1194 mnt.mnt_opts = mnt_entries[act_checked].me_opts;
1195 mnt.mnt_dir = (char *)mnt_entries[act_checked].me_dir;
1196 if (!hasmntopt(&mnt, MNTOPT_NOAUTO))
1199 if (act_checked >= mnt_entries_cnt)
1205 /* Find next usable mountpoint when scanning selected mountpoints */
1206 static int find_next_entry_sel(int *pos)
1209 struct searched_dir *sd;
1212 if (++act_checked == check_dirs_cnt)
1214 sd = check_dirs + act_checked;
1215 for (i = 0; i < mnt_entries_cnt; i++) {
1217 if (sd->sd_dev == mnt_entries[i].me_dev && sd->sd_ino == mnt_entries[i].me_ino)
1221 if (sd->sd_dev == mnt_entries[i].me_dev)
1224 if (i == mnt_entries_cnt) {
1225 errstr(_("Mountpoint (or device) %s not found or has no quota enabled.\n"), sd->sd_name);
1233 * Return next directory from the list
1235 struct mntent *get_next_mount(void)
1237 static struct mntent mnt;
1240 if (!check_dirs_cnt) { /* Scan all mountpoints? */
1241 if (!find_next_entry_all(&mntpos))
1243 mnt.mnt_dir = (char *)mnt_entries[mntpos].me_dir;
1246 if (!find_next_entry_sel(&mntpos))
1248 mnt.mnt_dir = (char *)check_dirs[act_checked].sd_name;
1250 mnt.mnt_fsname = (char *)mnt_entries[mntpos].me_devname;
1251 mnt.mnt_type = mnt_entries[mntpos].me_type;
1252 mnt.mnt_opts = mnt_entries[mntpos].me_opts;
1257 * Free all structures allocated for mountpoint scan
1259 void end_mounts_scan(void)
1263 for (i = 0; i < mnt_entries_cnt; i++) {
1264 free(mnt_entries[i].me_type);
1265 free(mnt_entries[i].me_opts);
1266 free((char *)mnt_entries[i].me_devname);
1267 free((char *)mnt_entries[i].me_dir);
1271 mnt_entries_cnt = 0;
1272 if (check_dirs_cnt) {
1273 for (i = 0; i < check_dirs_cnt; i++)
1274 free((char *)check_dirs[i].sd_name);