From a2c2a8e32303a7aebaa88689fd9ade430dfd7f66 Mon Sep 17 00:00:00 2001 From: James Youngman Date: Mon, 6 Dec 2004 00:44:50 +0000 Subject: [PATCH] Use gnulib's mountlist module instead of grokking it ourselves. --- find/fstype.c | 552 ++++++++--------------------------------------- import-gnulib.sh | 2 +- 2 files changed, 92 insertions(+), 462 deletions(-) diff --git a/find/fstype.c b/find/fstype.c index 3ca91096..d07ea94f 100644 --- a/find/fstype.c +++ b/find/fstype.c @@ -1,5 +1,5 @@ /* fstype.c -- determine type of filesystems that files are on - Copyright (C) 1990, 91, 92, 93, 94, 2000 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94, 2000, 2004 Free Software Foundation, Inc. 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 @@ -17,11 +17,17 @@ USA. */ -/* Written by David MacKenzie . */ +/* Written by David MacKenzie . + * + * Converted to use gnulib's read_file_system_list() + * by James Youngman (which saves a lot + * of manual hacking of configure.in). + */ #include #include #include +#include #ifdef HAVE_SYS_TYPES_H #include @@ -41,13 +47,6 @@ #include #endif -#if defined(MNTIOC_NMNTS) && defined(MNTIOC_GETDEVLIST) -#define USE_MNTIOC_GETDEVLIST 1 -#else -#undef USE_MNTIOC_GETDEVLIST -#endif - - #ifdef STDC_HEADERS #include #else @@ -63,6 +62,8 @@ extern int errno; #include "../gnulib/lib/xstrtol.h" #include "extendbuf.h" +#include "mountlist.h" + #if ENABLE_NLS @@ -80,160 +81,40 @@ extern int errno; static char *filesystem_type_uncached PARAMS((const char *path, const char *relpath, const struct stat *statp)); -#if defined(FSTYPE_MNTENT) || defined(HAVE_GETMNTENT) || defined(HAVE_SYS_MNTTAB_H) /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ +/* Get MNTTYPE_IGNORE if it is available. */ #if HAVE_MNTENT_H # include #endif - #if HAVE_SYS_MNTTAB_H # include # include #endif -#if HAVE_STRUCT_MNTTAB_MNT_MOUNTP -#define mnt_dir mnt_mountp -#endif -#if !defined(MOUNTED) -# if defined(MNT_MNTTAB) /* HP-UX. */ -# define MOUNTED MNT_MNTTAB -# endif -# if defined(MNTTABNAME) /* Dynix. */ -# define MOUNTED MNTTABNAME -# endif -# if defined(MNTTAB) /* Solaris. */ -# define MOUNTED MNTTAB -# endif -#endif - -#if !defined(MOUNTED) /* last resort. */ -# define MOUNTED "/etc/mtab" -#endif -#if HAVE_SETMNTENT -#define SETMNTENT(name,mode) setmntent(name,mode) -#else -#define SETMNTENT(name,mode) fopen(name,mode) -#endif - -#if HAVE_ENDMNTENT -#define ENDMNTENT(fp) (0 != endmntent(fp)) -#else -#define ENDMNTENT(fp) (0 == fclose(fp)) -#endif -#endif - -#ifdef FSTYPE_GETMNT /* Ultrix. */ -#include -#include -#include -#endif - -#ifdef FSTYPE_USG_STATFS /* SVR3. */ -#include -#include -#endif - -#ifdef FSTYPE_STATVFS /* SVR4. */ -#include -#include -#endif - -#ifdef FSTYPE_STATFS /* 4.4BSD. */ -#include /* NetBSD needs this. */ -#include - - -#include "xstrtol.h" /* for xstrtoumax(). */ - - -#ifndef HAVE_F_FSTYPENAME_IN_STATFS -#ifndef MFSNAMELEN /* NetBSD defines this. */ -static char * -fstype_to_string (t) - short t; +static void +free_file_system_list(struct mount_entry *p) { -#ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */ - static char *mn[] = INITMOUNTNAMES; - if (t >= 0 && t <= MOUNT_MAXTYPE) - return mn[t]; - else - return "?"; -#else /* !INITMOUNTNAMES */ - switch (t) + while (p) { - case MOUNT_UFS: - return "ufs"; - case MOUNT_NFS: - return "nfs"; -#ifdef MOUNT_PC - case MOUNT_PC: - return "pc"; -#endif -#ifdef MOUNT_MFS - case MOUNT_MFS: - return "mfs"; -#endif -#ifdef MOUNT_LO - case MOUNT_LO: - return "lofs"; -#endif -#ifdef MOUNT_TFS - case MOUNT_TFS: - return "tfs"; -#endif -#ifdef MOUNT_TMP - case MOUNT_TMP: - return "tmp"; -#endif -#ifdef MOUNT_MSDOS - case MOUNT_MSDOS: - return "msdos"; -#endif -#ifdef MOUNT_ISO9660 - case MOUNT_ISO9660: - return "iso9660fs"; -#endif - default: - return "?"; - } -#endif /* !INITMOUNTNAMES */ -} -#endif /* !MFSNAMELEN */ -#endif /* !HAVE_F_FSTYPENAME_IN_STATFS */ -#endif /* FSTYPE_STATFS */ - -#ifdef FSTYPE_AIX_STATFS /* AIX. */ -#include -#include - -#define FSTYPE_STATFS /* Otherwise like 4.4BSD. */ -#define f_type f_vfstype - -static char * -fstype_to_string (t) - short t; -{ - switch (t) - { - case MNT_AIX: -#if 0 /* NFS filesystems are actually MNT_AIX. */ - return "aix"; -#endif - case MNT_NFS: - return "nfs"; - case MNT_JFS: - return "jfs"; - case MNT_CDROM: - return "cdrom"; - default: - return "?"; + struct mount_entry *pnext = p->me_next; + + free(p->me_devname); + free(p->me_mountdir); + + if(p->me_type_malloced) + free(p->me_type); + p->me_next = NULL; + free(p); + p = pnext; } } -#endif /* FSTYPE_AIX_STATFS */ + + + #ifdef AFS #include @@ -249,8 +130,7 @@ fstype_to_string (t) #endif static int -in_afs (path) - char *path; +in_afs (char *path) { static char space[2048]; struct ViceIoctl vi; @@ -291,6 +171,27 @@ filesystem_type (const char *path, const char *relpath, const struct stat *statp return current_fstype; } +static int +set_fstype_devno(struct mount_entry *p) +{ + struct stat stbuf; + + if (p->me_dev == (dev_t)-1) + { + if (0 == stat(p->me_mountdir, &stbuf)) + { + p->me_dev = stbuf.st_dev; + return 0; + } + else + { + return -1; + } + } + return 0; /* not needed */ +} + + /* Return a newly allocated string naming the type of filesystem that the file PATH, described by STATP, is on. RELPATH is the file name relative to the current directory. @@ -299,359 +200,88 @@ filesystem_type (const char *path, const char *relpath, const struct stat *statp static char * filesystem_type_uncached (const char *path, const char *relpath, const struct stat *statp) { - char *type = NULL; - -#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ - char *table = MOUNTED; - FILE *mfp; - struct mntent *mnt; - - (void) &path; - (void) &relpath; - - mfp = SETMNTENT (table, "r"); - if (mfp == NULL) - error (1, errno, "%s", table); - - /* Find the entry with the same device number as STATP, and return - that entry's fstype. */ - while (type == NULL && (mnt = getmntent (mfp))) - { - char *devopt; - dev_t dev; - struct stat disk_stats; - -#ifdef MNTTYPE_IGNORE - if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE)) - continue; -#endif - - /* Newer systems like SunOS 4.1 keep the dev number in the mtab, - in the options string. For older systems, we need to stat the - directory that the filesystem is mounted on to get it. - - Unfortunately, the HPUX 9.x mnttab entries created by automountq - contain a dev= option but the option value does not match the - st_dev value of the file (maybe the lower 16 bits match?). */ - -#if !defined(hpux) && !defined(__hpux__) - devopt = strstr (mnt->mnt_opts, "dev="); - if (devopt) - { - uintmax_t u = 0; - devopt += 4; - if (devopt[0] == '0' && (devopt[1] == 'x' || devopt[1] == 'X')) - devopt += 2; - xstrtoumax (devopt, NULL, 16, &u, NULL); - dev = u; - } - else -#endif /* not hpux */ - { - if (stat (mnt-> mnt_dir, &disk_stats) == -1) { - if (errno == EACCES) - continue; - else - error (1, errno, _("error in %s: %s"), table, mnt-> mnt_dir); - } - dev = disk_stats.st_dev; - } - - if (dev == statp->st_dev) - type = mnt->mnt_type; - } - - if (ENDMNTENT (mfp) == 0) - error (0, errno, "%s", table); -#endif - -#ifdef FSTYPE_GETMNT /* Ultrix. */ - int offset = 0; - struct fs_data fsd; - - while (type == NULL - && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0) - { - if (fsd.fd_req.dev == statp->st_dev) - type = gt_names[fsd.fd_req.fstype]; - } -#endif - -#ifdef FSTYPE_USG_STATFS /* SVR3. */ - struct statfs fss; - char typebuf[FSTYPSZ]; - - if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1) - { - /* Don't die if a file was just removed. */ - if (errno != ENOENT) - error (1, errno, "%s", path); - } - else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf)) - type = typebuf; -#endif - -#ifdef FSTYPE_STATVFS /* SVR4. */ - struct statvfs fss; - - if (statvfs (relpath, &fss) == -1) - { - /* Don't die if a file was just removed. */ - if (errno != ENOENT) - error (1, errno, "%s", path); - } - else - type = fss.f_basetype; -#endif - -#ifdef FSTYPE_STATFS /* 4.4BSD. */ - struct statfs fss; - char *p; - - if (S_ISLNK (statp->st_mode)) - p = dir_name (relpath); - else - p = relpath; - - if (statfs (p, &fss) == -1) - { - /* Don't die if symlink to nonexisting file, or a file that was - just removed. */ - if (errno != ENOENT) - error (1, errno, "%s", path); - } - else - { -#ifdef HAVE_F_FSTYPENAME_IN_STATFS - type = xstrdup (fss.f_fstypename); -#else - type = fstype_to_string (fss.f_type); -#endif - } - if (p != relpath) - free (p); -#endif + struct mount_entry *entries, *entry; + char *type; #ifdef AFS - if ((!type || !strcmp (type, "xx")) && in_afs (relpath)) - type = "afs"; + if (in_afs(path)) + { + fstype_known = 1; + return xstrdup("afs"); + } +#endif + + entries = read_file_system_list(true); + for (type=NULL, entry=entries; entry; entry=entry->me_next) + { +#ifdef MNTTYPE_IGNORE + if (!strcmp (entry->me_type, MNTTYPE_IGNORE)) + continue; #endif + set_fstype_devno(entry); + if (entry->me_dev == statp->st_dev) + type = xstrdup(entry->me_type); + } + free_file_system_list(entries); - /* An unknown value can be caused by an ENOENT error condition. - Don't cache those values. */ + /* Don't cache unknown values. */ fstype_known = (type != NULL); - - return xstrdup (type ? type : _("unknown")); -} - - - - - -#ifdef HAVE_GETMNTENT - -#if HAVE_STRUCT_MNTTAB - typedef struct mnttab MountPointEntry; -#elif HAVE_STRUCT_MNTENT - typedef struct mntent MountPointEntry; -#endif - -#if GETMNTENT_RETURNS_STRUCT -static MountPointEntry* -next_mount_point(FILE *fp) -{ - return getmntent(fp); -} -#elif GETMNTENT_RETURNS_INT && GETMNTENT_REQUIRES_STRUCT_PTR -static MountPointEntry current_mount_point; - -static MountPointEntry* -next_mount_point(FILE *fp) -{ - int rv = getmntent(fp, ¤t_mount_point); - - switch (rv) - { - case 0: - return ¤t_mount_point; /* success */ - - case -1: /* EOF - this is normal.*/ - return NULL; - - case MNT_TOOLONG: - error(0, 0, _("Line too long in `%s'"), MOUNTED); - return NULL; - - case MNT_TOOMANY: - error(0, 0, - _("One of the lines in `%s' has too many fields"), - MOUNTED); - return NULL; - - case MNT_TOOFEW: - error(0, 0, - _("One of the lines in `%s' has too few fields"), - MOUNTED); - return NULL; - - default: - error(0, 0, - _("Failed to parse an entry in `%s'"), - MOUNTED); - return NULL; - } -} -#else -static MountPointEntry* -next_mount_point(FILE *fp) -{ - if (warnings) - { - error(0, 0, _("Don't know how to use getmntent() to read `%s'. This is a bug.")); - } - return NULL; + return type ? type : xstrdup(_("unknown")); } -#endif char * get_mounted_filesystems (void) { - char *table = MOUNTED; - FILE *mfp; -#if HAVE_STRUCT_MNTTAB - struct mnttab *mnt; -#elif HAVE_STRUCT_MNTENT - struct mntent *mnt; -#endif char *result = NULL; size_t alloc_size = 0u; size_t used = 0u; + struct mount_entry *entries, *entry; - mfp = SETMNTENT(table, "r"); - if (mfp == NULL) - error (1, errno, "%s", table); - - while (NULL != (mnt = next_mount_point (mfp))) + entries = read_file_system_list(false); + for (entry=entries; entry; entry=entry->me_next) { size_t len; #ifdef MNTTYPE_IGNORE - if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE)) + if (!strcmp (entry->me_type, MNTTYPE_IGNORE)) continue; #endif + set_fstype_devno(entry); - len = strlen(mnt-> mnt_dir) + 1; + len = strlen(entry->me_mountdir) + 1; result = extendbuf(result, used+len, &alloc_size); - strcpy(&result[used], mnt->mnt_dir); + strcpy(&result[used], entry->me_mountdir); used += len; /* len already includes one for the \0 */ } - if (ENDMNTENT(mfp) == 0) - error (0, errno, "%s", table); - if (used) - { - /* Add the extra terminating \0 */ - result = extendbuf(result, used+1, &alloc_size); - result[used] = 0; - } - else - { - assert(NULL == result); /* Postcondition. */ - } + free_file_system_list(entries); return result; } -#else -char * -get_mounted_filesystems (void) -{ - return NULL; /* No getmntent(). */ -} -#endif -#ifdef USE_MNTIOC_GETDEVLIST -dev_t* -get_mounted_devices (size_t *n) -{ - dev_t *result = NULL; - int i, fd; - - /* Yes, we really are issuing an ioctl() against a vanilla file in order to - * find out what's in it. - */ - if ( (fd = open(MOUNTED, O_RDONLY)) >= 0) - { - int nmnts = -1; - if (0 == ioctl(fd, MNTIOC_NMNTS, &nmnts)) - { - uint32_t * devlist = (uint32_t*) xcalloc(2 * nmnts, sizeof(uint32_t)); - result = xcalloc(nmnts, sizeof(dev_t)); - - if (0 == ioctl(fd, MNTIOC_GETDEVLIST, devlist)) - { - for (i = 0; i < nmnts; ++i) - { - result[i] = makedev(devlist[2*i], devlist[2*i+1]); - } - free(devlist); - *n = nmnts; - return result; - } - } - close(fd); - } - error (1, errno, "%s", MOUNTED); - /*NOTREAHED*/ - return 0; -} - -#else dev_t * get_mounted_devices (size_t *n) { - char *mountpoints = get_mounted_filesystems(); - dev_t *result; size_t alloc_size = 0u; - size_t used; + size_t used = 0u; + struct mount_entry *entries, *entry; + dev_t *result = NULL; - used = 0u; - result = NULL; - if (mountpoints) + for (entry = entries = read_file_system_list(false); + entry; + entry = entry->me_next) { - const char *mountpoint = mountpoints; - while (*mountpoint) - { - struct stat st; - if (0 == lstat(mountpoint, &st)) - { - result = extendbuf(result, sizeof(dev_t)*(used+1), &alloc_size); - result[used] = st.st_dev; - ++used; - } - else - { - if (errno == ENOENT || errno == EACCES) - { - /* ignore, carry on with the next. */ - } - else - { - error (1, errno, "%s", mountpoint); - } - } - mountpoint += strlen(mountpoint); - ++mountpoint; /* skip the terminating NUL to find next entry. */ - } - - if (NULL != result) - result = xrealloc(result, sizeof(dev_t)*used); + result = extendbuf(result, sizeof(dev_t)*(used+1), &alloc_size); + set_fstype_devno(entry); + result[used] = entry->me_dev; + ++used; } - + free_file_system_list(entries); *n = used; return result; } -#endif + diff --git a/import-gnulib.sh b/import-gnulib.sh index 5c75cd07..995b478c 100755 --- a/import-gnulib.sh +++ b/import-gnulib.sh @@ -40,7 +40,7 @@ getline getopt human idcache lstat malloc memcmp memset mktime \ modechange pathmax quotearg realloc regex rpmatch savedir stat \ stpcpy strdup strftime strstr strtol strtoul strtoull strtoumax \ xalloc xalloc-die xgetcwd xstrtol xstrtoumax yesno human filemode \ -getline stpcpy canonicalize" +getline stpcpy canonicalize mountlist" # Modules needed for the "intl" subdirectory. #intl_modules="regex"