Code

made getmountopt and checkmountopt public as quota_mnt_getmountopt and quota_mnt_chec...
[collectd.git] / src / quota_mnt.c
1 /**
2  * collectd - src/quota_mnt.c
3  * Copyright (C) 2005  Niki W. Waibel
4  *
5  * This program is free software; you can redistribute it and/
6  * or modify it under the terms of the GNU General Public Li-
7  * cence as published by the Free Software Foundation; either
8  * version 2 of the Licence, or any later version.
9  *
10  * This program is distributed in the hope that it will be use-
11  * ful, but WITHOUT ANY WARRANTY; without even the implied war-
12  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public Licence for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * Licence along with this program; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
18  * USA.
19  *
20  * Author:
21  *   Niki W. Waibel <niki.waibel@gmx.net>
22 **/
24 #include "common.h"
25 #include "quota_debug.h"
26 #include "quota_common.h"
27 #include "quota_fs.h"
28 #include "quota_mnt.h"
31 /* if sthg is changed here also change it in configure.in!!! */
32 #if HAVE_MNTENT_H   /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
33 # include <mntent.h>
34 #endif
35 #if HAVE_MNTTAB_H   /* SVR2, SVR3. */
36 # include <mnttab.h>
37 #endif
38 #if HAVE_PATHS_H
39 # include <paths.h>
40 #endif
41 #if HAVE_SYS_FS_TYPES_H   /* Ultrix. */
42 # include <sys/fs_types.h>
43 #endif
44 #if HAVE_SYS_MNTENT_H
45 # include <sys/mntent.h>
46 #endif
47 #if HAVE_SYS_MNTTAB_H   /* SVR4. */
48 # include <sys/mnttab.h>
49 #endif
50 #if HAVE_SYS_MOUNT_H   /* 4.4BSD, Ultrix. */
51 # include <sys/mount.h>
52 #endif
53 #if HAVE_SYS_VFSTAB_H
54 # include <sys/vfstab.h>
55 #endif
56 #if HAVE_SYS_QUOTA_H
57 # include <sys/quota.h>
58 #endif
59 #if HAVE_SYS_VFS_H
60 # include <sys/vfs.h>
61 #endif
62 /* END if sthg is changed here also change it in configure.in!!! */
63 #if HAVE_XFS_XQM_H
64 # include <xfs/xqm.h>
65 #define xfs_mem_dqinfo  fs_quota_stat
66 #define Q_XFS_GETQSTAT  Q_XGETQSTAT
67 #define XFS_SUPER_MAGIC_STR "XFSB"
68 #define XFS_SUPER_MAGIC2_STR "BSFX"
69 #endif
71 #include "quota_mntopt.h"
75 /* *** *** ***   local functions   *** *** *** */
79 /* stolen from quota-3.13 (quota-tools) */
81 #define PROC_PARTITIONS "/proc/partitions"
82 #define DEVLABELDIR     "/dev"
83 #define UUID   1
84 #define VOL    2
86 #define AUTOFS_DIR_MAX 64       /* Maximum number of autofs directories */
88 static struct uuidCache_s {
89         struct uuidCache_s *next;
90         char uuid[16];
91         char *label;
92         char *device;
93 } *uuidCache = NULL;
95 #define EXT2_SUPER_MAGIC 0xEF53
96 struct ext2_super_block {
97         unsigned char s_dummy1[56];
98         unsigned char s_magic[2];
99         unsigned char s_dummy2[46];
100         unsigned char s_uuid[16];
101         char s_volume_name[16];
102 };
103 #define ext2magic(s) ((unsigned int)s.s_magic[0] \
104         + (((unsigned int)s.s_magic[1]) << 8))
106 #if HAVE_XFS_XQM_H
107 struct xfs_super_block {
108         unsigned char s_magic[4];
109         unsigned char s_dummy[28];
110         unsigned char s_uuid[16];
111         unsigned char s_dummy2[60];
112         char s_fsname[12];
113 };
114 #endif /* HAVE_XFS_XQM_H */
116 #define REISER_SUPER_MAGIC "ReIsEr2Fs"
117 struct reiserfs_super_block {
118         unsigned char s_dummy1[52];
119         unsigned char s_magic[10];
120         unsigned char s_dummy2[22];
121         unsigned char s_uuid[16];
122         char s_volume_name[16];
123 };
125 /* for now, only ext2 and xfs are supported */
126 static int
127 get_label_uuid(const char *device, char **label, char *uuid)
129         /* start with ext2 and xfs tests, taken from mount_guess_fstype */
130         /* should merge these later */
131         int fd, rv = 1;
132         size_t namesize;
133         struct ext2_super_block e2sb;
134 #if HAVE_XFS_XQM_H
135         struct xfs_super_block xfsb;
136 #endif
137         struct reiserfs_super_block reisersb;
139         fd = open(device, O_RDONLY);
140         if(fd == -1) {
141                 return rv;
142         }
144         if(lseek(fd, 1024, SEEK_SET) == 1024
145         && read(fd, (char *)&e2sb, sizeof(e2sb)) == sizeof(e2sb)
146         && ext2magic(e2sb) == EXT2_SUPER_MAGIC) {
147                 memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
148                 namesize = sizeof(e2sb.s_volume_name);
149                 *label = smalloc(namesize + 1);
150                 sstrncpy(*label, e2sb.s_volume_name, namesize);
151                 rv = 0;
152 #if HAVE_XFS_XQM_H
153         } else if(lseek(fd, 0, SEEK_SET) == 0
154         && read(fd, (char *)&xfsb, sizeof(xfsb)) == sizeof(xfsb)
155         && (strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC_STR, 4) == 0 ||
156         strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC2_STR, 4) == 0)) {
157                 memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
158                 namesize = sizeof(xfsb.s_fsname);
159                 *label = smalloc(namesize + 1);
160                 sstrncpy(*label, xfsb.s_fsname, namesize);
161                 rv = 0;
162 #endif /* HAVE_XFS_XQM_H */
163         } else if(lseek(fd, 65536, SEEK_SET) == 65536
164         && read(fd, (char *)&reisersb, sizeof(reisersb)) == sizeof(reisersb)
165         && !strncmp((char *)&reisersb.s_magic, REISER_SUPER_MAGIC, 9)) {
166                 memcpy(uuid, reisersb.s_uuid, sizeof(reisersb.s_uuid));
167                 namesize = sizeof(reisersb.s_volume_name);
168                 *label = smalloc(namesize + 1);
169                 sstrncpy(*label, reisersb.s_volume_name, namesize);
170                 rv = 0;
171         }
172         close(fd);
173         return rv;
176 static void
177 uuidcache_addentry(char *device, char *label, char *uuid)
179         struct uuidCache_s *last;
181         if(!uuidCache) {
182                 last = uuidCache = smalloc(sizeof(*uuidCache));
183         } else {
184                 for(last = uuidCache; last->next; last = last->next);
185                 last->next = smalloc(sizeof(*uuidCache));
186                 last = last->next;
187         }
188         last->next = NULL;
189         last->device = device;
190         last->label = label;
191         memcpy(last->uuid, uuid, sizeof(last->uuid));
194 static void
195 uuidcache_init(void)
197         char line[100];
198         char *s;
199         int ma, mi, sz;
200         static char ptname[100];
201         FILE *procpt;
202         char uuid[16], *label = NULL;
203         char device[110];
204         int firstPass;
205         int handleOnFirst;
207         if(uuidCache) {
208                 return;
209         }
211         procpt = fopen(PROC_PARTITIONS, "r");
212         if(procpt == NULL) {
213                 return;
214         }
216         for(firstPass = 1; firstPass >= 0; firstPass--) {
217                 fseek(procpt, 0, SEEK_SET);
218                 while(fgets(line, sizeof(line), procpt)) {
219                         if(sscanf(line, " %d %d %d %[^\n ]",
220                                 &ma, &mi, &sz, ptname) != 4)
221                         {
222                                 continue;
223                         }
225                         /* skip extended partitions (heuristic: size 1) */
226                         if(sz == 1) {
227                                 continue;
228                         }
230                         /* look only at md devices on first pass */
231                         handleOnFirst = !strncmp(ptname, "md", 2);
232                         if(firstPass != handleOnFirst) {
233                                 continue;
234                         }
236                         /* skip entire disk (minor 0, 64, ... on ide;
237                         0, 16, ... on sd) */
238                         /* heuristic: partition name ends in a digit */
240                         for(s = ptname; *s; s++);
242                         if(isdigit((int)s[-1])) {
243                         /*
244                         * Note: this is a heuristic only - there is no reason
245                         * why these devices should live in /dev.
246                         * Perhaps this directory should be specifiable by option.
247                         * One might for example have /devlabel with links to /dev
248                         * for the devices that may be accessed in this way.
249                         * (This is useful, if the cdrom on /dev/hdc must not
250                         * be accessed.)
251                         */
252                                 snprintf(device, sizeof(device), "%s/%s",
253                                         DEVLABELDIR, ptname);
254                                 if(!get_label_uuid(device, &label, uuid)) {
255                                         uuidcache_addentry(sstrdup(device),
256                                                 label, uuid);
257                                 }
258                         }
259                 }
260         }
261         fclose(procpt);
264 static unsigned char
265 fromhex(char c)
267         if(isdigit((int)c)) {
268                 return (c - '0');
269         } else if(islower((int)c)) {
270                 return (c - 'a' + 10);
271         } else {
272                 return (c - 'A' + 10);
273         }
276 static char *
277 get_spec_by_x(int n, const char *t)
279         struct uuidCache_s *uc;
281         uuidcache_init();
282         uc = uuidCache;
284         while(uc) {
285                 switch(n) {
286                 case UUID:
287                         if(!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
288                                 return sstrdup(uc->device);
289                         }
290                         break;
291                 case VOL:
292                         if(!strcmp(t, uc->label)) {
293                                 return sstrdup(uc->device);
294                         }
295                         break;
296                 }
297                 uc = uc->next;
298         }
299         return NULL;
302 static char *
303 get_spec_by_uuid(const char *s)
305         char uuid[16];
306         int i;
308         if(strlen(s) != 36
309         || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') {
310                 goto bad_uuid;
311         }
313         for(i=0; i<16; i++) {
314                 if(*s == '-') {
315                         s++;
316                 }
317                 if(!isxdigit((int)s[0]) || !isxdigit((int)s[1])) {
318                         goto bad_uuid;
319                 }
320                 uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
321                 s += 2;
322         }
323         return get_spec_by_x(UUID, uuid);
325         bad_uuid:
326                 DBG("Found an invalid UUID: %s", s);
327         return NULL;
330 static char *
331 get_spec_by_volume_label(const char *s)
333         return get_spec_by_x(VOL, s);
336 static char *
337 get_device_name(const char *item)
339         char *rc;
341         if(!strncmp(item, "UUID=", 5)) {
342                 DBG("TODO: check UUID= code!");
343                 rc = get_spec_by_uuid(item + 5);
344         } else if(!strncmp(item, "LABEL=", 6)) {
345                 DBG("TODO: check LABEL= code!");
346                 rc = get_spec_by_volume_label(item + 6);
347         } else {
348                 rc = sstrdup(item);
349         }
350         if(!rc) {
351                 DBG("Error checking device name: %s", item);
352         }
353         return rc;
356 /*
357  *      Check for various kinds of NFS filesystem
358  */
359 int
360 nfs_fstype(char *type)
362         return !strcmp(type, MNTTYPE_NFS) || !strcmp(type, MNTTYPE_NFS4);
365 #if HAVE_XFS_XQM_H
366 /*
367  *      Check for XFS filesystem with quota accounting enabled
368  */
369 static int
370 hasxfsquota(struct mntent *mnt, int type)
372         int ret = 0;
373         u_int16_t sbflags;
374         struct xfs_mem_dqinfo info;
375         const char *dev = get_device_name(mnt->mnt_fsname);
377         if(!dev) {
378                 return ret;
379         }
381         memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
382         if(!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
383                 sbflags = (info.qs_flags & 0xff00) >> 8;
384                 if(type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT)) {
385                         ret = 1;
386                 } else if(type == GRPQUOTA && (info.qs_flags & XFS_QUOTA_GDQ_ACCT)) {
387                         ret = 1;
388                 }
389                 #ifdef XFS_ROOTHACK
390                 /*
391                 * Old XFS filesystems (up to XFS 1.2 / Linux 2.5.47) had a
392                 * hack to allow enabling quota on the root filesystem without
393                 * having to specify it at mount time.
394                 */
395                 else if(strcmp(mnt->mnt_dir, "/")) {
396                         ret = 0;
397                 } else if(type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT)) {
398                         ret = 1;
399                 } else if(type == GRPQUOTA && (sbflags & XFS_QUOTA_GDQ_ACCT)) {
400                         ret = 1;
401                 #endif /* XFS_ROOTHACK */
402         }
403         sfree((char *)dev);
404         return ret;
406 #endif /* HAVE_XFS_XQM_H */
409 #if HAVE_LISTMNTENT
410 static void
411 quota_mnt_listmntent(struct tabmntent *mntlist, quota_mnt_t **list)
413         struct *p;
414         struct mntent *mnt;
416         for(p = mntlist; p; p = p->next) {
417                 mnt = p->ment;
418                 *list = smalloc(sizeof(quota_mnt_t));
419                 list->device = strdup(mnt->mnt_fsname);
420                 list->name = strdup(mnt->mnt_dir);
421                 list->type = strdup(mnt->mnt_type);
422                 list->next = NULL;
423                 list = &(ist->next);
424         }
425         freemntlist(mntlist);
427 #endif /* HAVE_LISTMNTENT */
431 #if HAVE_GETVFSENT
432 static void
433 quota_mnt_getvfsmnt(FILE *mntf, quota_mnt_t **list)
435         DBG("TODO: getvfsmnt");
436         *list = NULL;
438 #endif /* HAVE_GETVFSENT */
440 char *
441 quota_mnt_checkmountopt(char *line, char *keyword, int full)
443         char *line2, *l2;
444         int l = strlen(keyword);
445         char *p1, *p2;
447         if(line == NULL || keyword == NULL) {
448                 return NULL;
449         }
450         if(full != 0) {
451                 full = 1;
452         }
454         line2 = sstrdup(line);
455         l2 = line2;
456         while(*l2 != '\0') {
457                 if(*l2 == ',') {
458                         *l2 = '\0';
459                 }
460                 l2++;
461         }
463         p1 = line - 1;
464         p2 = strchr(line, ',');
465         do {
466                 if(strncmp(line2+(p1-line)+1, keyword, l+full) == 0) {
467                         free(line2);
468                         return p1+1;
469                 }
470                 p1 = p2;
471                 if(p1 != NULL) {
472                         p2 = strchr(p1+1, ',');
473                 }
474         } while(p1 != NULL);
476         free(line2);
477         return NULL;
478 } /* char *quota_mnt_checkmountopt(char *line, char *keyword, int full) */
480 char *
481 quota_mnt_getmountopt(char *line, char *keyword)
483         char *r;
485         r = quota_mnt_checkmountopt(line, keyword, 0);
486         if(r != NULL) {
487                 char *p;
488                 r += strlen(keyword);
489                 p = strchr(r, ',');
490                 if(p == NULL) {
491                         if(strlen(r) == 0) {
492                                 return NULL;
493                         }
494                         return sstrdup(r);
495                 } else {
496                         char *m;
497                         if((p-r) == 1) {
498                                 return NULL;
499                         }
500                         m = (char *)smalloc(p-r+1);
501                         sstrncpy(m, r, p-r+1);
502                         return m;
503                 }
504         }
505         return r;
506 } /* char *quota_mnt_getmountopt(char *line, char *keyword) */
508 #if HAVE_GETMNTENT
509 static void
510 quota_mnt_getmntent(FILE *mntf, quota_mnt_t **list)
512         struct mntent *mnt;
514         while((mnt = getmntent(mntf)) != NULL) {
515                 char *loop = NULL, *device = NULL;
516                 char *usrjquota = NULL;
517                 char *grpjquota = NULL;
518                 char *jqfmt = NULL;
520 #if 0
521                 DBG("------------------");
522                 DBG("mnt->mnt_fsname %s", mnt->mnt_fsname);
523                 DBG("mnt->mnt_dir    %s", mnt->mnt_dir);
524                 DBG("mnt->mnt_type   %s", mnt->mnt_type);
525                 DBG("mnt->mnt_opts   %s", mnt->mnt_opts);
526                 DBG("mnt->mnt_freq   %d", mnt->mnt_freq);
527                 DBG("mnt->mnt_passno %d", mnt->mnt_passno);
528 #endif
530                 if(quota_fs_issupported(mnt->mnt_type) == EXIT_FAILURE)
531                 {
532                         DBG("unsupportet fs (%s) %s (%s): ignored",
533                                 mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
534                         continue;
535                 }
537                 if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_NOQUOTA, 1) != NULL) {
538                         DBG("noquota option on fs (%s) %s (%s): ignored",
539                                 mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
540                         continue;
541                 }
543                 if(quota_mnt_checkmountopt(mnt->mnt_opts, "bind", 1) != NULL) {
544                         DBG("bind mount on fs (%s) %s (%s): ignored",
545                                 mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
546                         continue;
547                 }
549                 loop = quota_mnt_getmountopt(mnt->mnt_opts, "loop=");
550                 if(loop == NULL) {   /* no loop= mount */
551                         device = get_device_name(mnt->mnt_fsname);
552                         if(device == NULL) {
553                                 DBG("can't get devicename for fs (%s) %s (%s)"
554                                         ": ignored", mnt->mnt_type,
555                                         mnt->mnt_dir, mnt->mnt_fsname);
556                                 continue;
557                         }
558                 } else {
559                         device = loop;
560                 }
562                 usrjquota = quota_mnt_getmountopt(mnt->mnt_opts, "usrjquota=");
563                 grpjquota = quota_mnt_getmountopt(mnt->mnt_opts, "grpjquota=");
564                 jqfmt = quota_mnt_getmountopt(mnt->mnt_opts, "jqfmt=");
566 #if HAVE_XFS_XQM_H
567                 if(!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
568                         if(hasxfsquota(mnt, USRQUOTA) == 0
569                         && hasxfsquota(mnt, GRPQUOTA) == 0)
570                         {
571                                 DBG("no quota on fs (%s) %s (%s): ignored",
572                                         mnt->mnt_type, mnt->mnt_dir,
573                                         mnt->mnt_fsname);
574                                 sfree(loop);
575                                 sfree(usrjquota);
576                                 sfree(grpjquota);
577                                 sfree(jqfmt);
578                                 continue;
579                         }
580                 } else {
581 #endif /* HAVE_XFS_XQM_H */
582                         if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_QUOTA, 1)
583                                 == NULL
584                         && quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_USRQUOTA, 1)
585                                 == NULL
586                         && quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_GRPQUOTA, 1)
587                                 == NULL
588                         && quota_fs_isnfs(mnt->mnt_type) == EXIT_FAILURE)
589                         {
590                                 DBG("neither quota/usrquota/grpquota option"
591                                         " nor nfs fs (%s) %s (%s): ignored",
592                                         mnt->mnt_type, mnt->mnt_dir, mnt->mnt_fsname);
593                                 sfree(loop);
594                                 sfree(usrjquota);
595                                 sfree(grpjquota);
596                                 sfree(jqfmt);
597                                 continue;
598                         }
599 #if HAVE_XFS_XQM_H
600                 }
601 #endif /* HAVE_XFS_XQM_H */
602 #if 0
603                 DBG("------------------ OK");
604 #endif
605                 *list = (quota_mnt_t *)smalloc(sizeof(quota_mnt_t));
606                 (*list)->dir = sstrdup(mnt->mnt_dir);
607                 (*list)->device = device;
608                 (*list)->usrjquota = usrjquota;
609                 (*list)->grpjquota = grpjquota;
610                 (*list)->jqfmt = jqfmt;
611                 (*list)->type = sstrdup(mnt->mnt_type);
612                 (*list)->opts = QMO_NONE;
613 /* TODO: this is not sufficient for XFS! */
614 /* TODO: maybe we should anyway NOT rely on the option in the mountfile...
615    ... maybe the fs should be asked direktly all time! */
616                 if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_QUOTA, 1) != NULL
617                 || quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_USRQUOTA, 1) != NULL) {
618                         (*list)->opts |= QMO_USRQUOTA;
619                 }
620                 if(quota_mnt_checkmountopt(mnt->mnt_opts, MNTOPT_GRPQUOTA, 1) != NULL) {
621                         (*list)->opts |= QMO_GRPQUOTA;
622                 }
623                 (*list)->next = NULL;
624                 list = &((*list)->next);
625         } /* while((mnt = getmntent(mntf)) != NULL) */
627 #endif /* HAVE_GETMNTENT */
631 quota_mnt_t *
632 quota_mnt_getlist(quota_mnt_t **list)
634         /* yes, i know that the indentation is wrong.
635            but show me a better way to do this... */
636         /* see lib/mountlist.c of coreutils for all
637            gory details! */
638 #if HAVE_GETMNTENT && defined(_PATH_MOUNTED)
639         {
640         FILE *mntf = NULL;
641         if((mntf = setmntent(_PATH_MOUNTED, "r")) == NULL) {
642                 DBG("opening %s failed: %s", _PATH_MOUNTED, strerror(errno));
643 #endif
644 #if HAVE_GETMNTENT && defined(MNT_MNTTAB)
645         {
646         FILE *mntf = NULL;
647         if((mntf = setmntent(MNT_MNTTAB, "r")) == NULL) {
648                 DBG("opening %s failed: %s", MNT_MNTTAB, strerror(errno));
649 #endif
650 #if HAVE_GETMNTENT && defined(MNTTABNAME)
651         {
652         FILE *mntf = NULL;
653         if((mntf = setmntent(MNTTABNAME, "r")) == NULL) {
654                 DBG("opening %s failed: %s", MNTTABNAME, strerror(errno));
655 #endif
656 #if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
657         {
658         FILE *mntf = NULL;
659         if((mntf = setmntent(_PATH_MNTTAB, "r")) == NULL) {
660                 DBG("opening %s failed: %s", _PATH_MNTTAB, strerror(errno));
661 #endif
662 #if HAVE_GETVFSENT && defined(VFSTAB)
663         {
664         FILE *mntf = NULL;
665         if((mntf = fopen(VFSTAB, "r")) == NULL) {
666                 DBG("opening %s failed: %s", VFSTAB, strerror(errno));
667 #endif
668 #if HAVE_LISTMNTENT
669         {
670         struct tabmntent *mntlist;
672         if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) {
673                 DBG("calling listmntent() failed: %s", strerror(errno));
674 #endif
675                 /* give up */
676                 DBG("failed get local mountpoints");
677                 *list = NULL;
678                 return(NULL);
680 #if HAVE_LISTMNTENT
681         } else { quota_mnt_listmntent(mntlist, list); }
682         freemntlist(mntlist);
683         }
684 #endif
685 #if HAVE_GETVFSENT && defined(VFSTAB)
686         } else { quota_mnt_getvfsmnt(mntf, list); }
687         (void)fclose(mntf);
688         }
689 #endif
690 #if HAVE_GETMNTENT && defined(_PATH_MNTTAB)
691         } else { quota_mnt_getmntent(mntf, list); }
692         (void)endmntent(mntf);
693         }
694 #endif
695 #if HAVE_GETMNTENT && defined(MNTTABNAME)
696         } else { quota_mnt_getmntent(mntf, list); }
697         (void)endmntent(mntf);
698         }
699 #endif
700 #if HAVE_GETMNTENT && defined(MNT_MNTTAB)
701         } else { quota_mnt_getmntent(mntf, list); }
702         (void)endmntent(mntf);
703         }
704 #endif
705 #if HAVE_GETMNTENT && defined(_PATH_MOUNTED)
706         } else { quota_mnt_getmntent(mntf, list); }
707         (void)endmntent(mntf);
708         }
709 #endif
710         return(*list);
713 void
714 quota_mnt_freelist(quota_mnt_t *list)
716         quota_mnt_t *l = list, *p = NULL;
718         while(l != NULL) {
719                 while(l->next != NULL) {
720                         p = l;
721                         l = l->next;
722                 }
723                 if(p != NULL) {
724                         p->next = NULL;
725                 }
726                 sfree(l->dir);
727                 sfree(l->device);
728                 sfree(l->type);
729                 sfree(l->usrjquota);
730                 sfree(l->grpjquota);
731                 sfree(l->jqfmt);
732                 sfree(l);
733                 p = NULL;
734                 if(l != list) {
735                         l = list;
736                 } else {
737                         l = NULL;
738                 }
739         } /* while(l != NULL) */
740 } /* void quota_mnt_freelist(quota_mnt_t *list) */
742 int
743 quota_mnt_type(const char *type)
745         if(strcmp(type, "ext3") == 0) return QMT_EXT3;
746         if(strcmp(type, "ext2") == 0) return QMT_EXT2;
747         if(strcmp(type, "ufs")  == 0) return QMT_UFS;
748         if(strcmp(type, "vxfs") == 0) return QMT_VXFS;
749         if(strcmp(type, "zfs")  == 0) return QMT_ZFS;
750         return QMT_UNKNOWN;
751 } /* int quota_mnt_type(const char *type) */