Occasionally somebody sends in a patch which gives folder the
optimization of assuming that the number of subdirectories in each
directory is exactly st_nlink - 2. I've finally installed 6.8.4 and
while I was at it I've put together this patch which I believes provides
the st_nlink optimization in a way which is more complete than usual
(basically, it's documented and configurable).
I've heard that under AFS the st_nlink of a directory isn't always 2
more than the number of subdirectories. Does anybody know what it
actually is? (Is it always constant, or is it the number of
subdirectories - some other number?) Does anybody know how some common
NFS implementations for non-Unix operating systems handle st_nlink for
directories? I'd like to make the docs a little more clear on these
points, but I'm out of my experience.
-Roderick
Index: conf/doc/folder.rf
Prereq: 1.15
*** conf/doc/folder.rf Tue Nov 30 23:00:16 1993
--- ../mh/conf/doc/folder.rf Fri May 3 19:05:26 1996
***************
*** 207,210 ****
--- 207,224 ----
There is no way to restore the default behavior
(to ask the user whether to create a non-existant folder)
after `\-create' or `\-nocreate' is given.
+ @BEGIN: NLINK_HACK
+ .sp
+ \fIMH\fR assumes that directories to which there are at least 2 links
+ have exactly st_nlink\-2 subdirectories. This greatly speeds up the
+ normal case, but it causes \fIfolder\fR to become confused by folders
+ whose only subfolders are symbolic links to directories rather than
+ directories themselves (it won't see the subfolders). If you have a
+ folder like that you can get more correct behavior from \fIfolder\fR by
+ creating a dummy folder inside it (`folder @.dummy', eg), though this
+ is distasteful in that you'll see the .dummy subfolder listed along with
+ your normal folders. If this bothers you too much you'll have to
+ recompile \fIMH\fR without the NLINK_HACK option set and take the speed
+ penalty.
+ @END: NLINK_HACK
.En
Index: conf/mh-gen.8
Prereq: 2.119
*** conf/mh-gen.8 Wed May 1 12:17:31 1996
--- ../mh/conf/mh-gen.8 Fri May 3 18:52:39 1996
***************
*** 749,754 ****
--- 762,788 ----
option and get an undefined symbol \*(lq\(ru\^\(ruruserpass\*(rq
when compiling, then you should omit this option.
(See also `NORUSERPASS'.)
+
+ .ti -.5i
+ NLINK_HACK
+ .br
+ This is a (rather dramatic under certain circumstances) speed hack. If
+ this is set then an optimization is used when scanning for folders
+ recursively: For any directory which has at least 2 links it's assumed
+ that the number of subdirectories is st_nlink - 2. This is true for
+ most Unix file systems, but isn't true for AFS file systems and might not
+ be true for file systems remotely mounted from non-Unix systems. If the
+ st_nlink value returned by these systems is 0 or 1 all will be well (I
+ don't know if this is the case or not), but if it's at least 2 but not
+ always n_subdirs + 2 then \fIMH\fR will miss some subfolders. Another
+ way that this can be broken is if you have a folder whose subfolders are
+ all symbolic links to other directories (if there's at least one real
+ subdirectory then the code will handle it).
+
+ Note that the code which implements this option assumes that you've got
+ symbolic links (or more precisely, lstat(2)). If you don't have
+ lstat(2) the algorithm can be made both more correct and more efficient,
+ but I haven't bothered to code this up in a selectable manner.
.ti -.5i
NOIOCTLH
Index: conf/mhconfig.c
Prereq: 2.73
*** conf/mhconfig.c Wed May 1 12:17:32 1996
--- ../mh/conf/mhconfig.c Fri May 3 18:31:28 1996
***************
*** 138,144 ****
"MIME", 0, /* multi-media extensions */
"MPOP", 0, /* mobile pop */
"MSGID", 0, /* slocal dup surpression */
! "NORUSERPASS", 0, /* no ruserpass(3) */
"TMA", 0, /* trusted mail */
"TTYD", 0,
"UCI", 0,
--- 139,146 ----
"MIME", 0, /* multi-media extensions */
"MPOP", 0, /* mobile pop */
"MSGID", 0, /* slocal dup surpression */
! "NLINK_HACK", 0, /* assume st_nlink-2 subdirs */
! "NORUSERPASS", 0, /* no ruserpass(3) */
"TMA", 0, /* trusted mail */
"TTYD", 0,
"UCI", 0,
Index: uip/folder.c
Prereq: 2.11
*** uip/folder.c Tue Nov 30 23:01:36 1993
--- ../mh/uip/folder.c Fri May 3 18:29:54 1996
***************
*** 544,550 ****
--- 544,563 ----
register struct direct *dp;
#endif /* SYS5DIR */
register DIR * dd;
+ #ifdef NLINK_HACK
+ register int dirs_left;
+ #endif
+ #ifdef NLINK_HACK
+ if (stat (name, &st) != NOTOK && st.st_nlink > 1) {
+ dirs_left = st.st_nlink - 2;
+ if (dirs_left == 0)
+ return;
+ }
+ else
+ dirs_left = -1;
+ #endif
+
cp = name + strlen (name);
*cp++ = '/';
*cp = '\0';
***************
*** 564,571 ****
#endif /* SYS5DIR */
continue;
(void) strcpy (cp, dp -> d_name);
! if (stat (name, &st) != NOTOK && (st.st_mode & S_IFMT) == S_IFDIR)
addfold (base);
}
closedir (dd);
--- 577,594 ----
#endif /* SYS5DIR */
continue;
(void) strcpy (cp, dp -> d_name);
! if (stat (name, &st) != NOTOK && (st.st_mode & S_IFMT) == S_IFDIR) {
addfold (base);
+ #ifdef NLINK_HACK
+ /* This might really be a symlink to a directory, don't
+ decrement dirs_left unless it's an actual directory. */
+ if (lstat (name, &st) != NOTOK
+ && (st.st_mode & S_IFMT) == S_IFDIR) {
+ if (dirs_left > 0 && --dirs_left == 0)
+ break;
+ }
+ #endif
+ }
}
closedir (dd);
--
Roderick Schertler
roderick(_at_)gate(_dot_)net