From phil@hercules.centerline.com Fri Nov 22 19:57:17 2002 Date: Fri, 22 Nov 2002 19:57:15 -0500 (EST) From: Phil Budne Message-Id: <200211230057.TAA46809@hercules.centerline.com> To: phil@ultimate.com Subject: diff *** tar-1.13.25/src/incremen.c.orig Wed Aug 29 14:20:19 2001 --- tar-1.13.25/src/incremen.c Fri Nov 22 19:56:17 2002 *************** *** 1,3 **** --- 1,10 ---- + /* should be set by autoconf */ + #define HAVE_STATVFS 0 + #define HAVE_LINUX_STATFS 0 + #define HAVE_BSD_STATFS 1 + #define HAVE_SUNOS4_STATFS 0 + #define HAVE_ST_VFSTYPE 0 + /* GNU dump extensions to tar. Copyright 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001 Free *************** *** 97,109 **** static Hash_table *directory_table; #if HAVE_ST_FSTYPE_STRING ! static char const nfs_string[] = "nfs"; ! # define NFS_FILE_STAT(st) (strcmp ((st).st_fstype, nfs_string) == 0) #else ! # define ST_DEV_MSB(st) (~ (dev_t) 0 << (sizeof (st).st_dev * CHAR_BIT - 1)) ! # define NFS_FILE_STAT(st) (((st).st_dev & ST_DEV_MSB (st)) != 0) #endif /* Calculate the hash of a directory. */ static unsigned hash_directory (void const *entry, unsigned n_buckets) --- 104,227 ---- static Hash_table *directory_table; #if HAVE_ST_FSTYPE_STRING ! static const char nfs[] = "nfs"; ! # define ISNFS(path,stp) (strcmp ((stp)->st_fstype, nfs) == 0) ! #elif HAVE_ST_VFSTYPE ! /* AIX */ ! #include ! #include ! #ifdef MNT_NFS3 ! # define ISNFS(path,stp) \ ! ((stp)->st_vfstype == MNT_NFS || (stp)->st_vfstype == MNT_NFS3) #else ! # define ISNFS(path,stp) ((stp)->st_vfstype == MNT_NFS) #endif + #elif HAVE_STATVFS + /* works on SunOS5, HP-UX 10.20, HP-UX 11.0, IRIX 6.5, AIX 4.3 */ + + #include + #include + #define NEED_CACHE + + static int + isnfs(char *path, struct stat *stp) + { + struct statvfs f; + + if (statvfs(path, &f) < 0) + return 0; + + return strcmp(f.f_basetype, "nfs3") == 0 || strcmp(f.f_basetype, "nfs") == 0; + } + #elif HAVE_BSD_STATFS + /* BSD4.4 */ + #include + #include + #define NEED_CACHE + + static int + isnfs(char *path, struct stat *stp) + { + struct statfs f; + + if (statfs(path, &f) < 0) + return 0; + return strcmp(f.f_fstypename, "nfs") == 0; + } + #elif HAVE_LINUX_STATFS + #include + + /* it's in linux/nfs_fs.h, but can't include it?! */ + #define NFS_SUPER_MAGIC 0x6969 + #define NEED_CACHE + + static int + isnfs(char *path, struct stat *stp) + { + struct statfs f; + + if (statfs(path, &f) < 0) + return 0; + + return f.f_type == NFS_SUPER_MAGIC; + } + #elif HAVE_SUNOS4_STATFS + #include + #include + #define NEED_CACHE + + static int + isnfs(path) + char *path; + { + struct statfs f; + + if (statfs(path, &f) < 0) + return 0; + + /* SunOS4 only supports NFSv2 which doesn't return inode info */ + return f.f_files == -1 && f.f_ffree == -1; + } + #else + /* try ustat call, check for f_tinode == -1??? */ + + /* fall back to the old and unreliable way.... */ + # define ST_DEV_MSB(stp) (~ (dev_t) 0 << (sizeof (stp)->st_dev * CHAR_BIT - 1)) + # define ISNFS(path,stp) (((stp)->st_dev & ST_DEV_MSB (stp)) != 0) + /* check minor(dev) == 0xff?? */ + #endif + + #ifdef NEED_CACHE + # define ISNFS(path,stp) check_nfs_cache(path,stp) + + #define ISNFS_CACHE_LOG2 0 /* log2 of number of cache entries */ + #define ISNFS_CACHE_ENTRIES (1<<(ISNFS_CACHE_LOG2)) /* must be power of 2 */ + #define ISNFS_CACHE_MASK (ISNFS_CACHE_ENTRIES-1) + + struct isnfs_cache_line { + dev_t dev; + char flags; + } isnfs_cache[ISNFS_CACHE_ENTRIES]; + + #define NC_VALID 01 + #define NC_ISNFS 02 + + static int + check_nfs_cache(char *path, struct stat *stp) + { + struct isnfs_cache_line *cp = isnfs_cache + (stp->st_dev & ISNFS_CACHE_MASK); + if (!(cp->flags & NC_VALID) || cp->dev != stp->st_dev) { + /* here with mismatched cache entry, or invalid cache entry */ + cp->dev = stp->st_dev; + cp->flags = NC_VALID; + if (isnfs(path, stp)) + cp->flags |= NC_ISNFS; + } + return (cp->flags & NC_ISNFS) != 0; + } + #endif /* NEED_CACHE */ + /* Calculate the hash of a directory. */ static unsigned hash_directory (void const *entry, unsigned n_buckets) *************** *** 233,239 **** if (S_ISDIR (stat_data.st_mode)) { ! bool nfs = NFS_FILE_STAT (stat_data); if (directory = find_directory (name_buffer), directory) { --- 351,357 ---- if (S_ISDIR (stat_data.st_mode)) { ! bool nfs = ISNFS (name_buffer, &stat_data); if (directory = find_directory (name_buffer), directory) { *************** *** 244,250 **** directories, consider all NFS devices as equal, relying on the i-node to establish differences. */ ! if (! (((directory->nfs & nfs) || directory->device_number == stat_data.st_dev) && directory->inode_number == stat_data.st_ino)) { --- 362,368 ---- directories, consider all NFS devices as equal, relying on the i-node to establish differences. */ ! if (! (((directory->nfs && nfs) || directory->device_number == stat_data.st_dev) && directory->inode_number == stat_data.st_ino)) {