I have a backlog of mail that I thought I'd put onto a DOS floppy, so
that I can easily read it on a Solaris desktop box or on a Linux
notebook.  But it turned out that "folders -recurse" didn't work on
the Solaris box.  This is because DOS floppies don't support hard
links, and the Solaris pcfs code doesn't emulate the link count for
directories.

Here's a patch against nmh 1.0.3 to make "folders -recurse" and "flist
-recurse" work on a DOS floppy under Solaris.

Mike Kupfer                             [EMAIL PROTECTED]
Solaris File Sharing                    Speaking for myself, not for Sun.

--- ChangeLog~  Sun Feb 20 05:15:22 2000
+++ ChangeLog   Sun Dec 24 22:22:04 2000
@@ -1,3 +1,19 @@
+2000-12-24  Mike Kupfer  <[EMAIL PROTECTED]>
+
+       * sbr/Makefile.in: added nlink_valid.[co].
+
+       * sbr/nlink_valid.c (nlink_valid): new file and function to
+       determine if the filesystem supports hard links.
+
+       * uip/folder.c (addir): Fixed to work with filesystems that don't
+       support hard links (e.g., Solaris pcfs).
+
+       * uip/flist.c (BuildFolderList, BuildFolderListRecurse): Fixed to
+       work with filesystems that don't support hard links (e.g., Solaris
+       pcfs).
+
+       * h/prototypes.h: Added prototype for nlink_valid().
+
 Sun Feb 20 12:17:15 2000 Ruud de Rooij <[EMAIL PROTECTED]>
 
        * Fix security hole in mhshowsbr.c which allowed untrusted shell

--- sbr/Makefile.in.old Tue Dec 26 15:48:27 2000
+++ sbr/Makefile.in     Sun Dec 24 22:20:08 2000
@@ -2,6 +2,7 @@
 # Makefile for sbr subdirectory
 #
 # $Id: Makefile.in,v 1.4 1999/10/27 05:21:12 doug Exp $
+# @(#)Makefile.in      1.2     00/12/24 22:20:08
 #
 
 SHELL = /bin/sh
@@ -46,6 +47,7 @@
        fmt_compile.c fmt_new.c fmt_rfc2047.c fmt_scan.c lock_file.c \
        m_atoi.c m_backup.c m_convert.c m_draft.c m_getfld.c m_gmprot.c \
        m_maildir.c m_name.c m_scratch.c m_tmpfil.c makedir.c \
+       nlink_valid.c \
        path.c peekc.c pidwait.c pidstatus.c print_help.c \
        print_sw.c print_version.c push.c putenv.c pwd.c refile.c \
        remdir.c r1bindex.c readconfig.c seq_add.c seq_bits.c seq_del.c \
@@ -67,6 +69,7 @@
        fmt_compile.o fmt_new.o fmt_rfc2047.o fmt_scan.o lock_file.o \
        m_atoi.o m_backup.o m_convert.o m_draft.o m_getfld.o m_gmprot.o \
        m_maildir.o m_name.o m_scratch.o m_tmpfil.o makedir.o \
+       nlink_valid.o \
        path.o peekc.o pidwait.o pidstatus.o print_help.o \
        print_sw.o print_version.o push.o putenv.o pwd.o refile.o \
        remdir.o r1bindex.o readconfig.o seq_add.o seq_bits.o seq_del.o \
@@ -99,7 +102,7 @@
        else \
          ar cr libmh.a `$(LORDER) $(OBJS) | $(TSORT)`  ; \
          $(RANLIB) libmh.a  ; \
-       fi 
+       fi 
 
 install:
 
--- /dev/null   Tue Dec 26 15:56:55 2000
+++ sbr/nlink_valid.c   Sun Dec 24 22:20:42 2000
@@ -0,0 +1,34 @@
+
+/*
+ * nlink_valid.c -- Is the nlink count useful?
+ *
+ * @(#)nlink_valid.c   1.1     00/12/24 22:20:40
+ */
+
+#include <h/mh.h>
+#include <errno.h>
+
+/*
+ * Return non-zero if the given object supports hard links. 
+ */
+
+int
+nlink_valid (char *name)
+{
+    int maxlink;
+
+    /* clear errno so that we can if pathconf set it */
+    errno = 0;
+
+    maxlink = pathconf (name, _PC_LINK_MAX);
+    if (maxlink < 0) {
+       /*
+        * If errno is unchanged, it means there is no limit.  Otherwise,
+        * there was an unexpected error, in which case it's probably safer 
+        * to assume that hard links are not supported.
+        */
+       return (errno == 0);
+    } else {
+       return (maxlink > 1);
+    }
+}

--- uip/folder.c.old    Tue Dec 26 15:54:07 2000
+++ uip/folder.c        Sun Dec 24 22:21:02 2000
@@ -5,6 +5,7 @@
  *             -- list the folder stack
  *
  * $Id: folder.c,v 1.3 2000/02/04 20:28:23 danh Exp $
+ * @(#)folder.c        1.2     00/12/24 22:21:01
  */
 
 #include <h/mh.h>
@@ -710,6 +711,7 @@
     struct stat st;
     struct dirent *dp;
     DIR * dd;
+    int check_nlink;
 
     cp = name + strlen (name);
     *cp++ = '/';
@@ -722,7 +724,8 @@
     base = strcmp (name, "./") ? name : name + 2;
 
    /* short-cut to see if directory has any sub-directories */
-    if (stat (name, &st) != -1 && st.st_nlink == 2)
+    check_nlink = nlink_valid (name);
+    if (stat (name, &st) != -1 && check_nlink && st.st_nlink == 2)
         return;
  
     if (!(dd = opendir (name))) {
@@ -734,11 +737,15 @@
      * Keep track of the number of directories we've seen
      * so we can quit stat'ing early, if we've seen them all.
      */
-    nlink = st.st_nlink;
+    if (check_nlink)
+       nlink = st.st_nlink;
+    else
+       nlink = 1;
 
     while (nlink && (dp = readdir (dd))) {
        if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) {
-           nlink--;
+           if (check_nlink)
+               nlink--;
            continue;
        }
        if (cp + NLENGTH(dp) + 2 >= name + BUFSIZ)
@@ -749,7 +756,7 @@
             * Check if this was really a symbolic link pointing at
             * a directory.  If not, then decrement link count.
             */
-           if (lstat (name, &st) == -1)
+           if (lstat (name, &st) == -1 && check_nlink)
                nlink--;
            addfold (base);
        }

--- uip/flist.c.old     Tue Dec 26 15:54:15 2000
+++ uip/flist.c Sun Dec 24 22:21:15 2000
@@ -14,6 +14,7 @@
  * any specification.
  *
  *  $Id: flist.c,v 1.4 2000/02/04 20:28:23 danh Exp $
+ * @(#)flist.c 1.2     00/12/24 22:21:14
  */
 
 #include <h/mh.h>
@@ -390,7 +391,8 @@
      * If recursing and directory has subfolders,
      * then build folder list for subfolders.
      */
-    if (AddFolder(dirName, showzero) && (recurse || searchdepth) && st.st_nlink > 2)
+    if (AddFolder(dirName, showzero) && (recurse || searchdepth) &&
+               (st.st_nlink > 2 || !nlink_valid(dirName)))
        BuildFolderListRecurse(dirName, &st, searchdepth - 1);
 }
 
@@ -406,6 +408,7 @@
     DIR *dir;
     struct dirent *dp;
     struct stat st;
+    int check_nlink;
 
     /*
      * Keep track of number of directories we've seen so we can
@@ -414,7 +417,11 @@
      * directories beginning with ".", since we don't bother to
      * stat them.  But that shouldn't generally be a problem.
      */
-    nlinks = s->st_nlink;
+    check_nlink = nlink_valid (dirName);
+    if (check_nlink)
+       nlinks = s->st_nlink;
+    else
+       nlinks = 1;
 
     if (!(dir = opendir(dirName)))
        adios(dirName, "can't open directory");
@@ -427,7 +434,8 @@
 
     while (nlinks && (dp = readdir(dir))) {
        if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
-           nlinks--;
+           if (check_nlink)
+               nlinks--;
            continue;
        }
        if (dp->d_name[0] == '.')
@@ -441,11 +449,12 @@
             * Check if this was really a symbolic link pointing
             * to a directory.  If not, then decrement link count.
             */
-           if (lstat (name, &st) == -1)
+           if (lstat (name, &st) == -1 && check_nlink)
                nlinks--;
            /* Add this folder to the list */
            if (AddFolder(name, showzero) &&
-                       (recurse || searchdepth) && st.st_nlink > 2)
+                       (recurse || searchdepth) && 
+                       (st.st_nlink > 2 || !nlink_valid(name)))
                BuildFolderListRecurse(name, &st, searchdepth - 1);
        }
     }


--- h/prototypes.h.old  Tue Dec 26 15:55:07 2000
+++ h/prototypes.h      Sun Dec 24 22:22:25 2000
@@ -3,6 +3,7 @@
  * prototypes.h -- various prototypes
  *
  * $Id: prototypes.h,v 1.4 2000/01/25 06:18:54 danh Exp $
+ * @(#)prototypes.h    1.2     00/12/24 22:22:25
  */
 
 /*
@@ -82,6 +83,7 @@
 void m_unknown(FILE *);
 int makedir (char *);
 char *new_fs (char *, char *, char *);
+int nlink_valid (char *);
 char *path(char *, int);
 int peekc(FILE *ib);
 int pidwait (pid_t, int);

Reply via email to