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);