home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume39 / enh-du2 / patch01 < prev    next >
Text File  |  1993-09-07  |  54KB  |  1,684 lines

  1. Newsgroups: comp.sources.misc
  2. From: chip@chinacat.unicom.com (Chip Rosenthal)
  3. Subject: v39i072:  enh-du2 - enhanced du (disk usage) + utilities, Patch01
  4. Message-ID: <1993Sep7.124535.29713@sparky.sterling.com>
  5. X-Md4-Signature: ca5bd51e1af0d34705416dda48eec906
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Unicom Systems Development, Austin, TX
  8. Date: Tue, 7 Sep 1993 12:45:35 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: chip@chinacat.unicom.com (Chip Rosenthal)
  12. Posting-number: Volume 39, Issue 72
  13. Archive-name: enh-du2/patch01
  14. Environment: UNIX
  15. Patch-To: enh-du2: Volume 39, Issues 35-36
  16.  
  17. "enh-du2" is a highly-portable, high-performance, POSIX-conformant
  18. reimplementation of the "du" command.  This package includes, in
  19. addition to the enhanced "du" command, a couple of handy utilities.
  20. The package appears in comp.sources.misc volume 39, issues 35 and 36.
  21.  
  22. >From the Update-Notes file:
  23.  
  24. Patch:        1
  25. Version:    from 2.0 to 2.1
  26. Severity:    critical for SPARC users, moderate for others
  27.  
  28. Highlights:    Document critical bug on multi-processor SPARC systems.
  29.         Added option to dereference symlinks.  "dusort" now
  30.         handles files with embedded spaces.  Several portability
  31.         improvements.
  32.  
  33. Index: patchlevel.h
  34. Prereq: "2.0"
  35. *** PL0/patchlevel.h    Tue Aug 24 18:00:15 1993
  36. --- patchlevel.h    Fri Sep  3 18:43:15 1993
  37. ***************
  38. *** 1,3 ****
  39. ! /* @(#) patchlevel.h 1.13 93/08/18 00:09:11 */
  40. ! #define VERSION "2.0"
  41. --- 1,2 ----
  42. ! /* @(#) patchlevel.h 1.16 93/09/03 18:43:08 */
  43. ! #define VERSION "2.1"
  44. Index: Makefile
  45. *** PL0/Makefile    Tue Aug 24 18:00:13 1993
  46. --- Makefile    Wed Aug 25 03:56:59 1993
  47. ***************
  48. *** 1,4 ****
  49. ! # @(#) Makefile 1.20 93/08/18 00:08:53
  50.   
  51.   ##############################################################################
  52.   #
  53. --- 1,4 ----
  54. ! # @(#) Makefile 1.22 93/08/25 03:56:46
  55.   
  56.   ##############################################################################
  57.   #
  58. ***************
  59. *** 83,90 ****
  60.   LINTFLAGS = $(CDEFS) -DNO_PROTOTYPE -DPTRTYPE=char
  61.   
  62.   FILES = README du.c duentry.c fsinfo.c dusort.c \
  63. !     patchlevel.h config.h du.h stdlib.h \
  64. !     Makefile ngsizes du.1 dusort.1 ngsizes.1
  65.   
  66.   all : du dusort ngsizes du.1 dusort.1 ngsizes.1
  67.   
  68. --- 83,90 ----
  69.   LINTFLAGS = $(CDEFS) -DNO_PROTOTYPE -DPTRTYPE=char
  70.   
  71.   FILES = README du.c duentry.c fsinfo.c dusort.c \
  72. !     patchlevel.h config-dist du.h stdlib.h \
  73. !     Makefile ngsizes du.1 dusort.1 ngsizes.1 Update-Notes
  74.   
  75.   all : du dusort ngsizes du.1 dusort.1 ngsizes.1
  76.   
  77. Index: README
  78. *** PL0/README    Tue Aug 24 18:00:09 1993
  79. --- README    Fri Sep  3 18:08:40 1993
  80. ***************
  81. *** 1,4 ****
  82. ! @(#) README 1.15 93/08/18 00:08:57
  83.   
  84.   "enh-du2" is a highly-portable, high-performance, POSIX-conformant
  85.   reimplementation of the "du" command.  It also adds some helpful
  86. --- 1,4 ----
  87. ! @(#) README 1.22 93/09/03 18:08:34
  88.   
  89.   "enh-du2" is a highly-portable, high-performance, POSIX-conformant
  90.   reimplementation of the "du" command.  It also adds some helpful
  91. ***************
  92. *** 10,31 ****
  93.   couple of handy utilities.  The "dusort" filter formats the output of
  94.   "du" nicely.  (Even if you aren't interested in the "du" program itself
  95.   check out this filter.)  The "ngsizes" script produces a summary of
  96. ! disk space used by the usenet news system.  It puts some of the
  97.   "enh-du2" features to good use.
  98.   
  99.   
  100.   === Contents =================================================================
  101.   
  102.       - Overview
  103.       - Installation
  104.       - Credits
  105.   
  106.   
  107. - === Overview =================================================================
  108.   
  109. ! Word to the impatient:  Edit "Makefile" and "config.h", then run "make".
  110.   
  111. ! This version supercedes the "enh-du" published in comp.sources.misc
  112.   volume 14.  The update is not intended to provide an explosion of
  113.   chrome and bloat (aka "gratuitous features").  This release mainly
  114.   improves portability, especially in heterogeneous networked environments.
  115. --- 10,41 ----
  116.   couple of handy utilities.  The "dusort" filter formats the output of
  117.   "du" nicely.  (Even if you aren't interested in the "du" program itself
  118.   check out this filter.)  The "ngsizes" script produces a summary of
  119. ! disk space used by the Usenet news system.  It puts some of the
  120.   "enh-du2" features to good use.
  121.   
  122. +     *** IMPORTANT NOTE *******************************************
  123. +     *                                                            *
  124. +     * If you are running a multi-processor SPARC system do NOT   *
  125. +     * attempt to install this package until you fully read these *
  126. +     * notes.  Failure to do so could _crash_ your machine!       *
  127. +     *                                                            *
  128. +     **************************************************************
  129.   
  130.   === Contents =================================================================
  131.   
  132.       - Overview
  133.       - Installation
  134. +     - Urgent Note to SPARC Users
  135.       - Credits
  136.   
  137. + Word to the impatient:  Copy "config-dist" to "config.h", configure it
  138. + and and the "Makefile", then run "make".
  139.   
  140.   
  141. ! === Overview =================================================================
  142.   
  143. ! This version supersedes the "enh-du" published in comp.sources.misc
  144.   volume 14.  The update is not intended to provide an explosion of
  145.   chrome and bloat (aka "gratuitous features").  This release mainly
  146.   improves portability, especially in heterogeneous networked environments.
  147. ***************
  148. *** 58,64 ****
  149.   been added to display a file count in addition to the disk usage.
  150.   
  151.   To give you a feel for what this program can do, here is the output
  152. ! of "du -h".  Portions of this message are site dependant, and so your
  153.   mileage may vary.
  154.   
  155.   du - version 2.0
  156. --- 68,74 ----
  157.   been added to display a file count in addition to the disk usage.
  158.   
  159.   To give you a feel for what this program can do, here is the output
  160. ! of "du -h".  Portions of this message are site dependent, and so your
  161.   mileage may vary.
  162.   
  163.   du - version 2.0
  164. ***************
  165. *** 91,96 ****
  166. --- 101,108 ----
  167.   are using something else, you've got a bit of work to do.  Here are the
  168.   steps to bring up the package:
  169.   
  170. +   - Copy "config-dist" to "config.h".
  171.     - Customize the "config.h" file for your system.
  172.   
  173.     - Customize the definitions at the top of the "Makefile".
  174. ***************
  175. *** 105,121 ****
  176.   
  177.       HP/9000 series 400    HP-UX 8.02
  178.       HP/9000 series 800    HP-UX 8.02
  179. !     IBM RS/6000        AIX3.1
  180.       NCR Tower        SysVr3.1 (NCR release 03.00.00)
  181. !     Sun SPARC        SunOS 4.1.2, Solaris 2.1
  182.       AT&T 3B1        SysVr3.2 (ver 3.51m)
  183.       AT&T 3B2        SysVr3.1
  184. !     386            AT&T SysV 3.2.2.3
  185. !     386            ISC SysVr3.2 versions 2.0.2, 2.2, 3.0.1
  186. !     386            MicroPort SysV 3.0U3.0e
  187. !     386            SCO Xenix 2.3.X
  188. !     386            SCO Unix 3.2v2, 3.2v4
  189. !     386            BSDI versions 0.9.2, 1.0
  190.   
  191.   If you get stuck configuring "enh-du", some possibly helpful information
  192.   follows.  I'll show you the settings I used when testing the package on
  193. --- 117,145 ----
  194.   
  195.       HP/9000 series 400    HP-UX 8.02
  196.       HP/9000 series 800    HP-UX 8.02
  197. !     IBM PS/2        AIX 1.3
  198. !     IBM RS/6000        AIX 3.1
  199.       NCR Tower        SysVr3.1 (NCR release 03.00.00)
  200. !     Sun SPARC        SunOS 4.1.2, 4.1.3 [see next section!!!]
  201. !     Sun SPARC        Solaris 2.1, 2.2
  202. !     DEC MIPS        Ultrix 4.3a
  203.       AT&T 3B1        SysVr3.2 (ver 3.51m)
  204.       AT&T 3B2        SysVr3.1
  205. !     Sequent S81        Dynix 3.0.17
  206. !     NeXT            NeXTSTEP 3.1
  207. !     NCR 3000 series        NCR releases 1.01.00.14, 02.00.02.02
  208. !     x86            AT&T SysV 3.2.2.3
  209. !     x86            ISC SysVr3.2 versions 2.0.2, 2.2, 3.0.1
  210. !     x86            MicroPort SysV 3.0U3.0e
  211. !     x86            SCO Xenix 2.3.X
  212. !     x86            SCO Unix 3.2v2, 3.2v4
  213. !     x86            BSDI versions 0.9.2, 1.0
  214. !     x86            Linux 0.99pl12 (gcc 2.4.5/libc 4.4.1)
  215. !     x86            Coherent 4.0.1
  216. ! If you bring up this package up on something other than the above,
  217. ! I'd like to hear about it.  Be sure to let me know the specific
  218. ! machine model number and operating system version/release number.
  219.   
  220.   If you get stuck configuring "enh-du", some possibly helpful information
  221.   follows.  I'll show you the settings I used when testing the package on
  222. ***************
  223. *** 138,143 ****
  224. --- 162,168 ----
  225.   USE_DIR_xxxx    DIRENT    -    -    -    -    -    -    -
  226.   USE_MOUNT_xxxx    MNTTAB    -    -    -    R4MNTTAB MNTENT    FSTAB    -
  227.   USE_STATFS_xxxx    SYSV    -    -    -    -    SUN    BSD    -
  228. + USE_GETCWD_xxxx    GETCWD    -    -    -    -    -    -    -
  229.   USE_SYMLINKS    disab    enab    -    -    enab    enab    enab    -
  230.   USE_STBLOCKS    disab    -    -    -    enab    enab    enab    -
  231.   BROKE_STBLOCKS    disab    -    -    -    -    -    -    -
  232. ***************
  233. *** 158,163 ****
  234. --- 183,223 ----
  235.   SunOS 4.1.2            (empty)        (empty)
  236.   BSDI 1.0            (empty)        (empty)
  237.   AT&T 3B2 and NCR Tower        -I.        -lmalloc
  238. + === Urgent Note to SPARC Users ===============================================
  239. + If you are running a multi-processor SPARC system do NOT attempt to
  240. + install this package until you fully read this section.  Failure to
  241. + do so could _crash_ your machine!
  242. + I have three independant reports from people who tried to run enh-du2
  243. + on their MP SPARC systems and the machine paniced.  Two of these people
  244. + were using SunOS 4.1.2 and the third was using SunOS 4.1.3.  I have
  245. + another report that said enh-du2 worked perfectly fine on a 630MP
  246. + running SunOS 4.1.3 with the jumbo patch 100726-09.  The person who
  247. + encountered the panic under 4.1.3 confirmed to me that this patch was
  248. + _not_ installed on his system.
  249. + Therefore, based upon these reports, I strongly advise anybody running
  250. + SunOS on an MP SPARC machine without patch 100726-009 to avoid this
  251. + package.  Furthermore, it appears that the aforementioned patch resolves
  252. + the system problem that enh-du2 trips over.
  253. + I have a gazillion uneventful reports from users of uniprocessor SPARC
  254. + systems (as well as first hand experience).  The problems appear to
  255. + be confined solely to MP SPARC systems.
  256. + All users should be assured that enh-du2 does NOT require any special
  257. + privileges.  It need not (and should not) be run setuid.  It does not
  258. + do any bizarre system or device operations.  It runs as a plain old,
  259. + normal user process.  Nothing it does should be capable of jeapordizing
  260. + a properly functioning system.  While it is almost certain there are
  261. + bugs lurking somewhere in this program (*sigh* aren't there always),
  262. + there is no way this program should be able to damage a machine.  The
  263. + fact that enh-du2 can cause certain machines to panic almost surely
  264. + indicates some sort of severe bug in the system hardware or operating
  265. + system.
  266.   
  267.   
  268.   === Credits ==================================================================
  269. Index: Update-Notes
  270. *** PL0/Update-Notes    Wed Aug 25 03:57:45 1993
  271. --- Update-Notes    Fri Sep  3 18:08:41 1993
  272. ***************
  273. *** 0 ****
  274. --- 1,70 ----
  275. + # @(#) Update-Notes 1.3 93/09/03 18:02:09
  276. + ------------------------------------------------------------------------------
  277. + Patch:        1
  278. + Version:    from 2.0 to 2.1
  279. + Severity:    critical for SPARC users, moderate for others
  280. + Highlights:    Document critical bug on multi-processor SPARC systems.
  281. +         Added option to dereference symlinks.  "dusort" now
  282. +         handles files with embedded spaces.  Several portability
  283. +         improvements.
  284. + Installation:    Apply this patch to the distributed enh-du2 v2.0 sources.
  285. +         NEW INSTALLATION - If this is a new installation, delete
  286. +         the "config.h" distributed in the base package.  If there
  287. +         are additional updates, apply those patches.  Otherwise,
  288. +         read and follow the instructions in the README file.
  289. +         UPDATE INSTALLATION - This patch creates a new file
  290. +         called "config-dist" to avoid stepping on changes you
  291. +         made to "config.h".  You must recreate your "config.h"
  292. +         file from "config-dist".  You should be able to use
  293. +         the same exact configuration setup as you did for the
  294. +         v2.0 release.
  295. + Modified README with notes on *major* problem with multi-processor
  296. + SPARC.  This patch does NOT fix the problem, it just documents it.
  297. + Based upon reports from Bob Wakehouse <bob@tv.tv.tek.com>, Keith
  298. + Thompson <kst@flash.alsys.com>, and Szymon Sokol <szymon@uci.agh.edu.pl>.
  299. + Added "-S" option to dereference symlinks.  Thanks to John Henders
  300. + <jhenders@jonh.wimsey.bc.ca> for the suggestion.
  301. + Renamed "config.h" to "config-dist" to avoid stomping on user's changes.
  302. + Ported to Ultrix based upon report from John Stoffel <john@wpi.edu>.
  303. + Ported to NeXT based upon report from Vince DeMarco <vince@whatnxt.cuc.ab.ca>.
  304. + Added USE_GETCWD_xxxx definitions for systems that don't have getcwd().
  305. + Fix type of Curr_time from long to time_t.
  306. + Removed obsolete "-d" option as threatened.
  307. + Display pathconf() failure diagnostic when compiled with DEBUG.
  308. + Modified "dusort" to make field delimiter the tab character instead
  309. + of any set of whitespace characters.  This allows filenames with
  310. + embedded spaces.  Based upon bug report from Kevin Ruland
  311. + <kevin@rodin.wustl.edu>.
  312. + Added "-f" option to "dusort" to allow specification of field seperator.
  313. + Updated list of tested systems in README based upon reports from
  314. + Shabtai Lerner <slerner@eingedi.newton.ma.us>, Juha Laiho
  315. + <jlaiho@ichaos.nullnet.fi>, Fred Smith <fcshome!fredex>, Matthew
  316. + Costello <mattc@ncr-sd.sandiego.ncr.com>, Hans de Graaff
  317. + <j.j.degraaff@duticai.twi.tudelft.nl>, and <stevenh@sci.kun.nl>.
  318. + Fixed some typos in the README file.
  319. + Introduced (this) Update-Notes file with information on patch changes.
  320. + ------------------------------------------------------------------------------
  321. + [end of update information]
  322. Index: config-dist
  323. *** PL0/config-dist    Sat Aug 28 13:09:08 1993
  324. --- config-dist    Wed Sep  1 04:10:12 1993
  325. ***************
  326. *** 0 ****
  327. --- 1,198 ----
  328. + /* @(#) config-dist 1.17 93/08/29 20:49:32 
  329. +  *
  330. +  * "du" enhanced disk usage summary - version 2.
  331. +  *
  332. +  * Copyright 1990-1993, Unicom Systems Development.  All rights reserved.
  333. +  * See accompanying README file for terms of distribution and use.
  334. +  *
  335. +  * Edit at tabstops=8.
  336. +  *
  337. +  * This file must be configured for the target system.  Warning -- a lot
  338. +  * of this stuff is pretty obscure and esoteric.  That's unavoidable.
  339. +  * After all, we are dealing with some very low-level system facilities.
  340. +  * Moreover, some vendors take it upon themself to "value add" their Unix
  341. +  * to death, which just makes this task more difficult.
  342. +  *
  343. +  * With patience (and a good file pager) you will persevere!  I've tried
  344. +  * to provide hints and assistance wherever possible.  Nonetheless, chances
  345. +  * are very good that you will need to trawl through your /usr/include
  346. +  * directory to determine which selections are correct.
  347. +  *
  348. +  * If you get stuck, consult the README.  You'll find some hints for a
  349. +  * handful of systems that I have personally used.  If you have any
  350. +  * suggestions on how to make this task easier, let me know.
  351. +  */
  352. + /*
  353. +  * Select one of the following.  It says how to read directories.
  354. +  */
  355. + #define USE_DIR_DIRENT        /* use <dirent.h>, struct dirent       common */
  356. + /*#define USE_DIR_SYSDIR    /* use <sys/dir.h>, struct direct     old BSD */
  357. + /*#define USE_DIR_SYSNDIR    /* use <sys/ndir.h>, struct direct  old XENIX */
  358. + /*
  359. +  * Select one of the following.  It says how to look for mounted filesystems.
  360. +  */
  361. + #define USE_MOUNT_MNTTAB    /* use <mnttab.h>, use /etc/mnttab       SysV */
  362. + /*#define USE_MOUNT_R4MNTTAB    /* use <sys/mnttab.h>, /etc/mnttab     SysVr4 */
  363. + /*#define USE_MOUNT_MNTENT    /* use <mntent.h>, use /etc/mtab   SunOS,HPUX */
  364. + /*#define USE_MOUNT_FSTAB    /* use <fstab.h>, use /etc/fstab          BSD */
  365. + /*#define USE_MOUNT_MNTCTL    /* use <sys/mntctl.h>, use mntctl()       AIX */
  366. + /*
  367. +  * Select one of the following.  It says where your "struct statfs" is
  368. +  * defined -- or that your system doesn't support the "statfs()" call.
  369. +  */
  370. + #define USE_STATFS_SYSV        /* include <sys/statfs.h>                     */
  371. + /*#define USE_STATFS_BSD    /* include <sys/mount.h>              */
  372. + /*#define USE_STATFS_SUN    /* include <sys/vfs.h>, SysV-style stafs()    */
  373. + /*#define USE_STATFS_HPUX    /* include <sys/vfs.h>, BSD-style statfs()    */
  374. + /*#define USE_STATFS_ULTRIX    /* Ultrix-style statfs()              */
  375. + /*#define USE_STATFS_NONE    /* statfs() call not available, e.g. S5R2     */
  376. + /*
  377. +  * Selet one of the following.  It says what procedure is available to
  378. +  * get the current working directory.
  379. +  */
  380. + #define USE_GETCWD_GETCWD    /* use getcwd()                   common */
  381. + /*#define USE_GETCWD_GETCD    /* use getwd()            old BSD, NeXT */
  382. + /*#define USE_GETCWD_NONE    /* must run "pwd" command     ancient systems */
  383. + /*
  384. +  * Enable USE_SYMLINKS if you have symbolic links, else comment it out.
  385. +  *
  386. +  * It is important you enable this if appropriate.  It prevents "du" from
  387. +  * following symlinks that point to directories, and thus reporting bogus
  388. +  * results or ending up in strange twisted loops.
  389. +  */
  390. + /*#define USE_SYMLINKS         /* enable for SysVr4, Sun, etc. */
  391. + /*
  392. +  * Enable USE_STBLOCKS if the "stat" structure in your <sys/stat.h> file
  393. +  * has an "st_blocks" member, else comment it out.
  394. +  *
  395. +  * It is important to enable this if appropriate for two reasons.  First,
  396. +  * performance of "du" is *significantly* improved if "st_blocks"
  397. +  * information can be used.  Second, it will avoid reporting errors on
  398. +  * so-called "sparse" files.
  399. +  */
  400. + /*#define USE_STBLOCKS        /* enable for SysVr4, Sun, etc. */
  401. + /*
  402. +  * Leave BROKE_STBLOCKS undefined unless you really need it.
  403. +  *
  404. +  * If you didn't define USE_STBLOCKS above then don't even bother
  405. +  * reading this -- just leave BROKE_STBLOCKS undefined.
  406. +  *
  407. +  * This definition is provided as a workaround for certain vendors who
  408. +  * are a little confused about how Unix is supposed to work.  The
  409. +  * "st_blocks" information returned by stat(2) is supposed to be in
  410. +  * 512-byte blocks.  Some vendors botch this.  AIX, for example, properly
  411. +  * reports local filesystems in 512-byte blocks, but across the network
  412. +  * reports in 1024-byte blocks.  HPUX does the exact opposite.
  413. +  *
  414. +  * If you define BROKE_STBLOCKS, then "du" will try to calculate how
  415. +  * "st_blocks" should be interpreted rather than assuming 512-byte blocks.
  416. +  * This calculation, unfortunately, will fail for filesystems that use
  417. +  * fragments and the "f_bsize" value reported by statfs(2) is the block
  418. +  * size instead of the fragment size (e.g. Solaris, BSDI).
  419. +  *
  420. +  * So, enable BROKE_STBLOCKS only if all the following is true:
  421. +  *
  422. +  *    - You have defined USE_STBLOCKS.  If you haven't, BROKE_STBLOCKS
  423. +  *      is ignored anyway.
  424. +  *
  425. +  *    - "du" is reporting wrong values, usually either twice or half
  426. +  *      the correct size.
  427. +  *
  428. +  *    - Either you do not have a fast filesystem with fragments or
  429. +  *      "f_bsize" indicates the size of the fragment.
  430. +  *
  431. +  * (Please send a note to the author if you wish you could use
  432. +  * BROKE_STBLOCKS but can't because your system uses fragments.)
  433. +  */
  434. + /*#define BROKE_STBLOCKS    /* enable for HPUX, networked AIX */
  435. + /*
  436. +  * If your system has the ANSI <stdarg.h> facility then enable USE_STDARG.
  437. +  * If your system only has the older <varargs.h> then disable it.
  438. +  */
  439. + #define USE_STDARG        /* enable on ANSI-compliant systems */
  440. + /*
  441. +  * Enable USE_UNISTD if your system has a <unistd.h> file.
  442. +  * If you don't have this header file then disable it.
  443. +  */
  444. + #define USE_UNISTD        /* enable on ANSI-compliant systems */
  445. + /*
  446. +  * Enable USE_PATHCONF if your system has the POSIX pathconf() facility,
  447. +  * else comment it out.
  448. +  *
  449. +  * ===>    For some reason, this is the definition people seem to flub up
  450. +  *    most frequently.  If your system is an older, pre-POSIX system
  451. +  *    that lacks pathconf() then do NOT enable this.  If you ain't
  452. +  *    got it, I can't use it!
  453. +  *
  454. +  * If you enable USE_PATHCONF you *must* also have enabled USE_UNISTD.
  455. +  * If you disable USE_PATHCONF then we will make a (usually reasonable)
  456. +  * guess at how much space to reserve to hold pathnames.
  457. +  */
  458. + #define USE_PATHCONF        /* enable on POSIX-compliant systems */
  459. + /*
  460. +  * PTRTYPE indicates what your compiler uses as a generic pointer type.
  461. +  * Most modern compilers will accept "void".  Crufty compilers use "char".
  462. +  */
  463. + #ifndef PTRTYPE
  464. + #define PTRTYPE void        /* use (void *) as a generic pointer    */
  465. + /*#define PTRTYPE char        /* use (char *) as a generic pointer    */
  466. + #endif
  467. + /*
  468. +  * ### YOU ARE NOW FINISHED WITH THE ESSENTIAL CONFIGURATIONS ###
  469. +  * 
  470. +  * Congratulations!  You made it.  You are now ready to roll.
  471. +  *
  472. +  * You might, however, want to glance through the following definitions.
  473. +  * These allow you to tailor "du" behavior according to your site-specific
  474. +  * preferences.
  475. +  */
  476. + /*
  477. +  * REPORT_BLOCKSIZE specifies default block size to use for reporting
  478. +  * disk usage, usually either "512" or "1024".  Most versions of "du"
  479. +  * (including POSIX conformant versions) use 512.  Others, such as SunOS,
  480. +  * use 1024.  Pick whatever you prefer.  This choice does not effect the
  481. +  * usage calculations or accuracy, only how the results are displayed,
  482. +  * and there are command line switches that will override the default
  483. +  * selected here.
  484. +  */
  485. + #define REPORT_BLKSIZE        512    /* report in 512-byte blocks    */
  486. + /*#define REPORT_BLKSIZE    1024    /* report in 1024-byte blocks   */
  487. + /*
  488. +  * PRINT_ERRORS controls whether or not error messages (e.g. "permission
  489. +  * denied", etc.) are displayed.  When defined, these error messages are
  490. +  * displayed.  When disabled, the errors are silently ignored -- which
  491. +  * is traditional "du" behavior.  I think it makes more sense to print
  492. +  * the errors (i.e. enable PRINT_ERRORS).  If, however, you disable this
  493. +  * to obtain backward compatibility, you will get a "-r" command line
  494. +  * option that will turn error messages back on.
  495. +  */
  496. + #define PRINT_ERRORS        /* display errors by default if enabled */
  497. + /*
  498. +  * TIMEOUT is a release hatch for hung NFS servers.  If you define
  499. +  * this value, "du" will unceremoniously kill itself after this many
  500. +  * seconds of inactivity.
  501. +  */
  502. + /*#define TIMEOUT    300    /* timeout value in seconds        */
  503. + /*
  504. +  * MAX_BREAK is maximum number of columns which can be requested by the
  505. +  * "-c" option (breakdown usage by age).  Increasing this value will
  506. +  * increase the memory usage, but not by much.
  507. +  */
  508. + #define MAX_BREAK    64    /* max columns in breakdown by age    */
  509. Index: du.1
  510. *** PL0/du.1    Tue Aug 24 18:00:09 1993
  511. --- du.1    Sun Aug 29 20:39:52 1993
  512. ***************
  513. *** 1,4 ****
  514. ! .\" @(#) du.1 1.13 93/08/18 00:08:59
  515.   .TH DU 1
  516.   .SH NAME
  517.   du \- Summarizes disk usage.
  518. --- 1,4 ----
  519. ! .\" @(#) du.1 1.14 93/08/29 20:39:20
  520.   .TH DU 1
  521.   .SH NAME
  522.   du \- Summarizes disk usage.
  523. ***************
  524. *** 5,11 ****
  525.   .SH SYNTAX
  526.   .B du
  527.   [
  528. ! .B \-abCdfFhiklLstu
  529.   ] [
  530.   .B \-B
  531.   size ] [
  532. --- 5,11 ----
  533.   .SH SYNTAX
  534.   .B du
  535.   [
  536. ! .B \-abCdfFhiklLsStu
  537.   ] [
  538.   .B \-B
  539.   size ] [
  540. ***************
  541. *** 220,225 ****
  542. --- 220,237 ----
  543.   reports the disk usage for each directory it encounters.  This
  544.   option suppresses that information and instead reports just a
  545.   total usage for each of the items specified on the command line.
  546. + .IP "\-S" 10
  547. + This option is available only on systems that support symbolic links
  548. + (symlinks).  Normally,
  549. + .I du
  550. + accumulates the usage of the symlink itself and not the entry to which
  551. + it points.  When this option is specified,
  552. + .I du
  553. + will dereference symlinks and will accumulate the usage of the entry
  554. + to which they point.  Moreover, if a symlink is encountered that points
  555. + to a directory, then
  556. + .I du
  557. + will descend into that directory.
  558.   .IP "\-t" 10
  559.   A grand total of all items specified on the command line will be
  560.   accumulated and displayed.  For example, the command
  561. ***************
  562. *** 267,272 ****
  563. --- 279,305 ----
  564.   .BR \-a ,
  565.   all files will be displayed, but ones not owned by the specified
  566.   user will be shown as zero sized.
  567. + .P
  568. + The
  569. + .B \-S
  570. + option works in strange and mysterious ways; the following apply when
  571. + it is used.  This option introduces significant amounts of overhead
  572. + and degrades the performance severely.  You can create loops with
  573. + symlinks, and
  574. + .I du
  575. + will happily spin round and round until it bails out with an error.
  576. + If the
  577. + .I name
  578. + specified on the command line is not a full pathname, then
  579. + .I du
  580. + will convert it to one.  The full pathname and not the specified
  581. + .I name
  582. + will be displayed in the results.  Note that specifying no name is
  583. + equivalent to specifying ``.''.  The
  584. + .B \-L
  585. + option to average usage across links cannot be used.  The other options
  586. + that specify link handling should work.  The default behavior, to
  587. + count a file only once, applies even when symlinks are dereferenced.
  588.   .P
  589.   If two or more directory trees specified on the command line are not
  590.   disjoint, then the usage calculations will be corrupted by the presence
  591. Index: du.c
  592. *** PL0/du.c    Tue Aug 24 18:00:14 1993
  593. --- du.c    Sun Aug 29 20:49:36 1993
  594. ***************
  595. *** 1,5 ****
  596.   #ifndef lint
  597. ! static char SCCSID[] = "@(#) du.c 1.16 93/08/18 00:09:01";
  598.   #endif
  599.   static char Copyright[] = "@(#) Copyright 1990-1993, Unicom Systems Development, Inc.  All rights reserved.";
  600.   
  601. --- 1,5 ----
  602.   #ifndef lint
  603. ! static char SCCSID[] = "@(#) du.c 1.18 93/08/29 20:49:18";
  604.   #endif
  605.   static char Copyright[] = "@(#) Copyright 1990-1993, Unicom Systems Development, Inc.  All rights reserved.";
  606.   
  607. ***************
  608. *** 28,35 ****
  609.   #else
  610.   # include <varargs.h>
  611.   #endif
  612. - #include <sys/types.h>
  613. - #include <sys/stat.h>
  614.   #define INTERN
  615.   #include "du.h"
  616.   #include "patchlevel.h"
  617. --- 28,33 ----
  618. ***************
  619. *** 64,70 ****
  620.       /* 
  621.        * Crack command line options.
  622.        */
  623. !     while ((i = getopt(argc, argv, "abB:c:CDdfFhiklLrstuU:")) != EOF) {
  624.           switch (i) {
  625.               case 'a':    Handle_output = PR_EVERYTHING;        break;
  626.               case 'b':   Report_blksize = 1;                    break;
  627. --- 62,68 ----
  628.       /* 
  629.        * Crack command line options.
  630.        */
  631. !     while ((i = getopt(argc, argv, "abB:c:CDfFhiklLrsStuU:")) != EOF) {
  632.           switch (i) {
  633.               case 'a':    Handle_output = PR_EVERYTHING;        break;
  634.               case 'b':   Report_blksize = 1;                    break;
  635. ***************
  636. *** 71,79 ****
  637.               case 'B':   Report_blksize = atoi(optarg);        break;
  638.               case 'c':    set_breakdown(optarg);                break;
  639.               case 'C':    Do_file_counts = TRUE;                break;
  640. - #ifdef OBSOLETEOPT
  641. -             case 'd':    Do_descend_dirs = FALSE;            break;
  642. - #endif
  643.               case 'f':    Handle_filesys = FS_NEVER_CROSS;    break;
  644.               case 'F':    Handle_filesys = FS_LOCAL_ONLY;        break;
  645.               case 'h':    do_help();                            exit(0);
  646. --- 69,74 ----
  647. ***************
  648. *** 83,88 ****
  649. --- 78,86 ----
  650.               case 'L':    Handle_links = LK_COUNT_AVERAGE;    break;
  651.               case 'r':    Do_print_errors = TRUE;                break;
  652.               case 's':    Handle_output = PR_TOTALS_ONLY;        break;
  653. + #ifdef USE_SYMLINKS
  654. +             case 'S':    Follow_symlinks = TRUE;                break;
  655. + #endif
  656.               case 't':    Do_print_grand_total = TRUE;        break;
  657.               case 'u':    Handle_links = LK_COUNT_NONE;        break;
  658.               case 'U':    Selected_user = get_userid(optarg);    break;
  659. ***************
  660. *** 94,99 ****
  661. --- 92,107 ----
  662.           }
  663.       }
  664.   
  665. +     /*
  666. +      * Sanity checks.
  667. +      */
  668. + #ifdef USE_SYMLINKS
  669. +     if (Follow_symlinks && Handle_links == LK_COUNT_AVERAGE) {
  670. +         errmssg(ERR_ABORT, 0,
  671. +             "cannot average usage (-L) when dereferencing symlinks (-S)");
  672. +     }
  673. + #endif
  674.   #ifdef TIMEOUT
  675.       /*
  676.        * Install the handler to trap timeouts.
  677. ***************
  678. *** 143,151 ****
  679.       "                  (Use \"0\" to report in native filesystem blocks.)",
  680.       "    -c n,n,...  Breakdown by age, one col for each \"n\" days or older.",
  681.       "    -C          Display file counts as well as disk usage.",
  682. - #ifdef OBSOLETEOPT
  683. -     "    -d          Do not descend into directories.",
  684. - #endif
  685.       "    -f          Do not cross any filesystem mount points.",
  686.       "    -F          Do not cross remote filesystem mount points.",
  687.       "    -h          Display this help message.",
  688. --- 151,156 ----
  689. ***************
  690. *** 157,162 ****
  691. --- 162,170 ----
  692.       "    -r          Print (do not suppress) errors which occur during scan.",
  693.   #endif
  694.       "    -s          Only report a total for each argument on command line.",
  695. + #ifdef USE_SYMLINKS
  696. +     "    -S          Dereference and follow symlinks.",
  697. + #endif
  698.       "    -t          Report a grand total of all items.",
  699.       "    -u          Skip (do not count) multiply linked files entirely.",
  700.       "    -U user     Report only usage by given user (specify name or id num).",
  701. Index: du.h
  702. *** PL0/du.h    Tue Aug 24 18:00:14 1993
  703. --- du.h    Sun Aug 29 23:43:53 1993
  704. ***************
  705. *** 1,4 ****
  706. ! /* @(#) du.h 1.15 93/08/18 00:09:02 
  707.    *
  708.    * "du" enhanced disk usage summary - version 2.
  709.    *
  710. --- 1,4 ----
  711. ! /* @(#) du.h 1.20 93/08/29 23:43:15
  712.    *
  713.    * "du" enhanced disk usage summary - version 2.
  714.    *
  715. ***************
  716. *** 59,80 ****
  717.   
  718.   
  719.   /*
  720. !  * Structure to accumulate usage statistics.
  721.    *
  722. !  * The statistics are accumulated in a chronological breakdown, as
  723. !  * specified by "Num_break" and the "Breakdown[]" array.  "Num_break"
  724. !  * indicates the number of columns in the breakdown, and "Breakdown[]"
  725. !  * specifies the age for each of those columns.
  726. !  *
  727. !  * The "Num_break" value will range from 1 to MAX_BREAK.  The "blocks[n]"
  728. !  * value accumulates the disk usage of all filesystem entries "Breakdown[n]"
  729. !  * days or older.  The "files[n]" value counts the number of filesystem
  730. !  * entries that contributed to that total.
  731. !  *
  732. !  * By default, "Num_break" will be 1 and "Breakdown[0]" will be 0.  That
  733. !  * says accumulate a single set of statistics for all filesystem entries
  734. !  * zero days old or older (i.e. everything).
  735. !  *
  736.    */
  737.   struct dusage {
  738.       long blocks[MAX_BREAK];    /* accumulated disk usage                    */
  739. --- 59,84 ----
  740.   
  741.   
  742.   /*
  743. !  * (struct dusage) - structure to accumulate usage statistics.
  744.    *
  745. !  * The disk usage statistics are maintained in a chronological breakdown
  746. !  * and stored in a (struct dusage).  The breakdown conditions are specified
  747. !  * by the "Breakdown[]" array and the "Num_break" value.  The "Num_break"
  748. !  * value ranges from 1 to MAX_BREAK and specifies how many elements of
  749. !  * the "Breakdown[]" array are used.
  750. !  *
  751. !  * Each element of the "Breakdown[]" array is a number of days.  The
  752. !  * arrays in the (struct dusage) contain the usage information corresponding
  753. !  * to this breakdown.  That is, the "blocks[N]" value accumulates the
  754. !  * number of disk blocks used by filesystem entries that are "Breakdown[N]"
  755. !  * days or older.  The "files[N]" value accumulates the number of filesystem
  756. !  * entries encountered that are "Breakdown[N]" days or older.
  757. !  *
  758. !  * The default condition is "Num_break" equals one, and "Breakdown[0]"
  759. !  * equals zero.  That is, there is just a single entry in the chronological
  760. !  * breakdown, and it corresponds to all filesystem entries zero days or
  761. !  * older (which means everything).  A different breakdown can be set with
  762. !  * the "-c" command line option.
  763.    */
  764.   struct dusage {
  765.       long blocks[MAX_BREAK];    /* accumulated disk usage                    */
  766. ***************
  767. *** 135,152 ****
  768.    */
  769.   EXTERN BOOL Do_file_counts INIT(FALSE);
  770.   
  771. ! #ifdef OBSOLETEOPT
  772.   /*
  773. !  * If true, descend into directories and accumulate usage (subject to
  774. !  * filesystem handling at mount points).  If false, do not descend into
  775. !  * directories and simply report the usage of the directory filesystem
  776. !  * entry (i.e. sans contents) as its usage.
  777. !  *
  778. !  * This is a pretty useless option, but was present in the original
  779. !  * "enh-du".  Unless somebody tells me they really use it, it is
  780. !  * subject to removal in a future version.
  781.    */
  782. ! EXTERN BOOL Do_descend_dirs INIT(TRUE);
  783.   #endif
  784.   
  785.   /*
  786. --- 139,152 ----
  787.    */
  788.   EXTERN BOOL Do_file_counts INIT(FALSE);
  789.   
  790. ! #ifdef USE_SYMLINKS
  791.   /*
  792. !  * If true, dereference symlinks.  This means that the disk usage of the
  793. !  * entry to which the symlink points will be counted, instead of the usage
  794. !  * of the symlink itself.  Moreover, if the symlink points to a directory
  795. !  * then we will descend into it.
  796.    */
  797. ! EXTERN BOOL Follow_symlinks INIT(FALSE);
  798.   #endif
  799.   
  800.   /*
  801. ***************
  802. *** 186,192 ****
  803.   
  804.   /*
  805.    * Number of columns in the chronological breakdown.
  806. !  * Specifies number of elements in "Breakdown[]" that are actually used.
  807.    */
  808.   EXTERN int Num_break INIT(1);
  809.   
  810. --- 186,192 ----
  811.   
  812.   /*
  813.    * Number of columns in the chronological breakdown.
  814. !  * See comments in the (struct dusage) declaration for more info.
  815.    */
  816.   EXTERN int Num_break INIT(1);
  817.   
  818. ***************
  819. *** 193,199 ****
  820.   /*
  821.    * Current time, used for calculation of the chronological breakdown.
  822.    */
  823. ! EXTERN long Curr_time;
  824.   
  825.   
  826.   #if defined(__STDC__) && !defined(NO_PROTOTYPE)
  827. --- 193,199 ----
  828.   /*
  829.    * Current time, used for calculation of the chronological breakdown.
  830.    */
  831. ! EXTERN time_t Curr_time;
  832.   
  833.   
  834.   #if defined(__STDC__) && !defined(NO_PROTOTYPE)
  835. ***************
  836. *** 212,225 ****
  837.   void set_usage __ARGS((struct dusage *, time_t, long));
  838.   void add_usage __ARGS((struct dusage *, struct dusage *));
  839.   void print_usage __ARGS((char *, struct dusage *));
  840. - int max_path_len __ARGS((char *));
  841.   void du_entry __ARGS((char *, struct dusage *));
  842. ! int du_dir __ARGS((char *, struct stat    *, struct fsinfo *, struct dusage *));
  843.   void fs_initinfo __ARGS((void));
  844.   struct fsinfo *fs_getinfo __ARGS((struct stat *));
  845.   int fs_linkdone __ARGS((struct fsinfo *, struct stat *));
  846.   long fs_numblocks __ARGS((struct fsinfo *, struct stat *));
  847.   
  848.   extern int errno;
  849.   
  850. --- 212,225 ----
  851.   void set_usage __ARGS((struct dusage *, time_t, long));
  852.   void add_usage __ARGS((struct dusage *, struct dusage *));
  853.   void print_usage __ARGS((char *, struct dusage *));
  854.   void du_entry __ARGS((char *, struct dusage *));
  855. ! int du_dir __ARGS((char *, struct stat *, struct fsinfo *, struct dusage *));
  856. ! int max_path_len __ARGS((char *));
  857. ! char *get_curr_dir __ARGS((void));
  858.   void fs_initinfo __ARGS((void));
  859.   struct fsinfo *fs_getinfo __ARGS((struct stat *));
  860.   int fs_linkdone __ARGS((struct fsinfo *, struct stat *));
  861.   long fs_numblocks __ARGS((struct fsinfo *, struct stat *));
  862.   
  863.   extern int errno;
  864.   
  865. Index: duentry.c
  866. *** PL0/duentry.c    Tue Aug 24 18:00:10 1993
  867. --- duentry.c    Fri Sep  3 17:56:14 1993
  868. ***************
  869. *** 1,5 ****
  870.   #ifndef lint
  871. ! static char SCCSID[] = "@(#) duentry.c 1.18 93/08/18 00:09:03";
  872.   #endif
  873.   
  874.   /*
  875. --- 1,5 ----
  876.   #ifndef lint
  877. ! static char SCCSID[] = "@(#) duentry.c 1.25 93/09/03 17:56:09";
  878.   #endif
  879.   
  880.   /*
  881. ***************
  882. *** 34,76 ****
  883.   #    define dirent direct
  884.   #endif
  885.   
  886. - #ifndef USE_SYMLINKS
  887. - #    define lstat stat
  888. - #endif
  889.   /*
  890. !  * Determine maximum pathlength of an entry on the filesystem containing "file".
  891.    */
  892. ! int max_path_len(fname)
  893. ! register char *fname;
  894. ! {
  895. ! #ifdef USE_PATHCONF
  896. !     register int len;
  897. !     if ((len = pathconf(fname, _PC_PATH_MAX)) > 0)
  898. !         return len;
  899. ! #ifdef notdef
  900. !     errmssg(ERR_WARN, errno, "could not get max pathname for \"%s\"", fname);
  901. ! #endif
  902.   #endif
  903.   
  904.   /*
  905. !  * If pathconf() is not available or fails, we need to take a stab.  If
  906. !  * the POSIX PATH_MAX parameter is available we will use that.  If not,
  907. !  * we will try to use the MAXNAMLEN that should be in whatever header
  908. !  * file USE_DIR_XXXX pulled in.  If all that fails, we'll just make a
  909. !  * guess of 1024.  Note that we do NOT want to use _POSIX_PATH_MAX.  That
  910. !  * specifies the minimum value that a conformant system must support.
  911.    */
  912. - #ifndef PATH_MAX
  913. - # ifdef MAXNAMLEN
  914. - #  define PATH_MAX MAXNAMLEN
  915. - # else
  916. - #  define PATH_MAX 1024
  917. - # endif
  918. - #endif
  919. -     return PATH_MAX;
  920. - }
  921.   
  922.   
  923.   /*
  924. --- 34,86 ----
  925.   #    define dirent direct
  926.   #endif
  927.   
  928.   /*
  929. !  * Pointer to the procedure we want to use to retrieve inode status.
  930. !  * Will point to either stat() or lstat(), depending upon how symlinks
  931. !  * are being handled.
  932.    */
  933. ! static int (*stat_proc) __ARGS((const char *, struct stat *));
  934. ! #ifdef USE_SYMLINKS
  935. ! /* Gee, Sun.  Forget something in your <sys/stat.h> file? */
  936. ! int lstat __ARGS((const char *path, struct stat *));
  937.   #endif
  938.   
  939.   /*
  940. !  * Symlink handling is messy enough and craps up the logic enough that
  941. !  * it's worth discussing a little...
  942. !  *
  943. !  * This utility obtains the disk usage of a subdirectory by doing a chdir
  944. !  * into it, scanning it, and then doing a chdir back to the parent
  945. !  * directory when done.  Normally, that last part is just a simple
  946. !  * chdir("..").  When symlinks are being dereferenced (-S specified) that
  947. !  * may not work.
  948. !  *
  949. !  * When symlinks are dereferenced, we must use an explicit pathname instead
  950. !  * of ".." to chdir back to the parent.  Say, for example, "/foo/bar/baz"
  951. !  * is a symlink to /blurfl/bonk.  To get the usage of subdirectory "baz"
  952. !  * we do a chdir("baz"), scan it, and then go back to the parent.  A
  953. !  * chdir(".."), unfortunately, will not put us in "/foo/bar", but instead
  954. !  * in "/blurfl".  We must specify the full pathname "/foo/bar" instead
  955. !  * of "..".  We should, however, do this _only_ when symlinks are being
  956. !  * dereferenced; it incurs a significant performance penalty.
  957. !  *
  958. !  * Since we need to use full pathnames when symlinks are dereferenced,
  959. !  * we cannot accept relative pathnames from the user.  Consider, again
  960. !  * using the above example, what happens when user runs "cd /foo ; du .".
  961. !  * When the scan of subdirectory "baz" completes, as already discussed,
  962. !  * we need to move out of it by saying chdir("/foo/bar").  In order to
  963. !  * do this, we need to expand the pathname "." given to us by the user
  964. !  * into the full, rooted pathname "/foo".
  965. !  *
  966. !  * There is one last twist.  By default, we try to count files only once.
  967. !  * To avoid a lot of unnecessary work, we normally do the checks only if
  968. !  * st_nlink is greater than one (i.e. the file has multiple hard links).
  969. !  * When dereferencing symlinks, however, we can visit a file multiple
  970. !  * times even if it does not have multiple hard links.  In this case we
  971. !  * need to perform those checks for _every_ file, and not just the ones
  972. !  * where st_nlink > 1.  (Oy! The overhead!)
  973.    */
  974.   
  975.   
  976.   /*
  977. ***************
  978. *** 86,92 ****
  979.   {
  980.       struct stat sbuf;
  981.       struct fsinfo *fsinfo;
  982. !     static char *curr_dir = NULL;
  983.   
  984.   #ifdef TIMEOUT
  985.       alarm(TIMEOUT);
  986. --- 96,102 ----
  987.   {
  988.       struct stat sbuf;
  989.       struct fsinfo *fsinfo;
  990. !     static char *start_dir = NULL;
  991.   
  992.   #ifdef TIMEOUT
  993.       alarm(TIMEOUT);
  994. ***************
  995. *** 93,101 ****
  996.   #endif
  997.   
  998.       /*
  999.        * Get the information on this entry.
  1000.        */
  1001. !     if (lstat(entry, &sbuf) != 0) {
  1002.           errmssg(ERR_WARN, errno, "could not stat \"%s\"", entry);
  1003.           return;
  1004.       }
  1005. --- 103,120 ----
  1006.   #endif
  1007.   
  1008.       /*
  1009. +      * Determine what procedure should be used to retrieve inode status.
  1010. +      */
  1011. + #ifdef USE_SYMLINKS
  1012. +     stat_proc = (Follow_symlinks ? stat : lstat);
  1013. + #else
  1014. +     stat_proc = stat;
  1015. + #endif
  1016. +     /*
  1017.        * Get the information on this entry.
  1018.        */
  1019. !     if ((*stat_proc)(entry, &sbuf) != 0) {
  1020.           errmssg(ERR_WARN, errno, "could not stat \"%s\"", entry);
  1021.           return;
  1022.       }
  1023. ***************
  1024. *** 107,114 ****
  1025.   
  1026.       /*
  1027.        * If this isn't a directory then simply get its size.  Note that we
  1028. !      * won't say what size is unless "-s" or "-a" was specified.  Kind of
  1029. !      * silly, but that's documented behaviour.
  1030.        */
  1031.       if (!S_ISDIR(sbuf.st_mode)) {
  1032.           set_usage(ent_usage, sbuf.st_mtime, fs_numblocks(fsinfo, &sbuf));
  1033. --- 126,133 ----
  1034.   
  1035.       /*
  1036.        * If this isn't a directory then simply get its size.  Note that we
  1037. !      * won't say what that size is unless "-s" or "-a" was specified.  Kind
  1038. !      * of silly, but du is documented to work that way.
  1039.        */
  1040.       if (!S_ISDIR(sbuf.st_mode)) {
  1041.           set_usage(ent_usage, sbuf.st_mtime, fs_numblocks(fsinfo, &sbuf));
  1042. ***************
  1043. *** 117,153 ****
  1044.           return;
  1045.       }
  1046.   
  1047. - #ifdef OBSOLETEOPT
  1048. -     /*
  1049. -      * If we aren't supposed to descend into directories then just get
  1050. -      * it's size.
  1051. -      */
  1052. -     if (!Do_descend_dirs) {
  1053. -         set_usage(ent_usage, sbuf.st_mtime, fs_numblocks(fsinfo, &sbuf));
  1054. -         print_usage(entry, ent_usage);
  1055. -         return;
  1056. -     }
  1057. - #endif
  1058.       /*
  1059.        * We are about to descend down this directory entry.  We need to
  1060.        * know where we started out so that we can return when done.
  1061.        */
  1062. !     if (curr_dir == NULL) {
  1063. !         int len;
  1064. !         extern char *getcwd();
  1065. !         len = max_path_len(".") + 2; /* getcwd() wants two extra bytes */
  1066. !         curr_dir = (char *) xmalloc((unsigned)len);
  1067. !         if (errno = 0, getcwd(curr_dir, len) == NULL)
  1068. !             errmssg(ERR_ABORT, errno,
  1069. !                 "could not get current working directory");
  1070. !     }
  1071.   
  1072.       /*
  1073. !      * We need to initiate a recursive search through "du_dir()".  Normally
  1074. !      * "du_dir()" displays the disk usage of the directory scanned, except
  1075. !      * when "PR_TOTALS_ONLY" (-s) mode is set.  In that case it won't
  1076. !      * print anything at all, so we need to do it here.
  1077.        */
  1078.       zero_usage(ent_usage);
  1079.       if (chdir(entry) != 0) {
  1080. --- 136,151 ----
  1081.           return;
  1082.       }
  1083.   
  1084.       /*
  1085.        * We are about to descend down this directory entry.  We need to
  1086.        * know where we started out so that we can return when done.
  1087.        */
  1088. !     if (start_dir == NULL)
  1089. !         start_dir = get_curr_dir();
  1090.   
  1091.       /*
  1092. !      * The user specified a directory.  We need to initiate a recursive
  1093. !      * scan through "du_dir()".
  1094.        */
  1095.       zero_usage(ent_usage);
  1096.       if (chdir(entry) != 0) {
  1097. ***************
  1098. *** 154,165 ****
  1099.           errmssg(ERR_WARN, errno, "could not chdir to \"%s\"", entry);
  1100.           return;
  1101.       }
  1102.       if (du_dir(entry, &sbuf, fsinfo, ent_usage) == 0) {
  1103.           if (Handle_output == PR_TOTALS_ONLY)
  1104.               print_usage(entry, ent_usage);
  1105.       }
  1106. !     if (chdir(curr_dir) != 0)
  1107. !         errmssg(ERR_ABORT, errno, "could not chdir back to \"%s\"", curr_dir);
  1108.   
  1109.   }
  1110.   
  1111. --- 152,178 ----
  1112.           errmssg(ERR_WARN, errno, "could not chdir to \"%s\"", entry);
  1113.           return;
  1114.       }
  1115. + #ifdef USE_SYMLINKS
  1116. +     if (Follow_symlinks && entry[0] != '/') {
  1117. +         /*
  1118. +           * If we are dereferencing symlinks then, as discussed at the top
  1119. +          * of this file, we require a fully rooted pathname.  Note that
  1120. +          * this messes up the name that will be printed in the output.
  1121. +          * Also note that this is a memory leak.  So sue me.
  1122. +           */
  1123. +         entry = get_curr_dir();
  1124. +     }
  1125. + #endif
  1126.       if (du_dir(entry, &sbuf, fsinfo, ent_usage) == 0) {
  1127. +         /*
  1128. +          * If the user enabled PR_TOTALS_ONLY (the -s option) then du_dir()
  1129. +          * does not print anything.  We need to print that total here.
  1130. +          */
  1131.           if (Handle_output == PR_TOTALS_ONLY)
  1132.               print_usage(entry, ent_usage);
  1133.       }
  1134. !     if (chdir(start_dir) != 0)
  1135. !         errmssg(ERR_ABORT, errno, "could not chdir back to \"%s\"", start_dir);
  1136.   
  1137.   }
  1138.   
  1139. ***************
  1140. *** 245,251 ****
  1141.           /*
  1142.            * Get the information on this entry.
  1143.            */
  1144. !         if (lstat(dp->d_name, &ent_stat) != 0) {
  1145.               errmssg(ERR_WARN, errno,
  1146.                   "could not stat \"%s/%s\"", dir_name, dp->d_name);
  1147.               continue;
  1148. --- 258,264 ----
  1149.           /*
  1150.            * Get the information on this entry.
  1151.            */
  1152. !         if ((*stat_proc)(dp->d_name, &ent_stat) != 0) {
  1153.               errmssg(ERR_WARN, errno,
  1154.                   "could not stat \"%s/%s\"", dir_name, dp->d_name);
  1155.               continue;
  1156. ***************
  1157. *** 283,288 ****
  1158. --- 296,310 ----
  1159.                           "internal error - bad \"Handle_links\" value \"%d\"",
  1160.                           Handle_links);
  1161.                   }
  1162. + #ifdef USE_SYMLINKS
  1163. +             /*
  1164. +              * Make sure that files with a single link aren't duplicated
  1165. +              * due to dereferencing of symlinks.
  1166. +              */
  1167. +             } else if (Follow_symlinks && Handle_links == LK_COUNT_FIRST
  1168. +                     && fs_linkdone(dir_fsinfo, &ent_stat)) {
  1169. +                 continue;
  1170. + #endif
  1171.               }
  1172.   
  1173.               /*
  1174. ***************
  1175. *** 348,354 ****
  1176.                   if (Do_accum_subdirs)
  1177.                       add_usage(dir_usage, &ent_usage);
  1178.               }
  1179. !             if (chdir("..") != 0) {
  1180.                   errmssg(ERR_ABORT, errno,
  1181.                       "could not chdir back to \"%s\"", dir_name);
  1182.               }
  1183. --- 370,382 ----
  1184.                   if (Do_accum_subdirs)
  1185.                       add_usage(dir_usage, &ent_usage);
  1186.               }
  1187. !             if (
  1188. ! #ifdef USE_SYMLINKS
  1189. !                 chdir(Follow_symlinks ? dir_name : "..") != 0
  1190. ! #else
  1191. !                 chdir("..") != 0
  1192. ! #endif
  1193. !             ) {
  1194.                   errmssg(ERR_ABORT, errno,
  1195.                       "could not chdir back to \"%s\"", dir_name);
  1196.               }
  1197. ***************
  1198. *** 365,369 ****
  1199. --- 393,485 ----
  1200.           print_usage(dir_name, dir_usage);
  1201.       (void) free((PTRTYPE *)ent_pathname);
  1202.       return 0;
  1203. + }
  1204. + /*
  1205. +  * Determine maximum pathlength of an entry on the filesystem containing "file".
  1206. +  */
  1207. + int max_path_len(fname)
  1208. + register char *fname;
  1209. + {
  1210. + #ifdef USE_PATHCONF
  1211. +     register int len;
  1212. +     if ((len = pathconf(fname, _PC_PATH_MAX)) > 0)
  1213. +         return len;
  1214. + #ifdef DEBUG
  1215. +     /*
  1216. +      * I've seen some systems where pathconf() will fail, most notably
  1217. +      * on NFS filesystems.  So, the diagnostic is normally suppressed.
  1218. +      */
  1219. +     errmssg(ERR_WARN, errno, "pathconf() could not get path_max for \"%s\"", fname);
  1220. + #endif
  1221. + #endif
  1222. + /*
  1223. +  * If pathconf() is not available or fails, we need to take a stab.  If
  1224. +  * the POSIX PATH_MAX parameter is available we will use that.  If not,
  1225. +  * we will try to use the MAXNAMLEN that should be in whatever header
  1226. +  * file USE_DIR_XXXX pulled in.  If all that fails, we'll just make a
  1227. +  * guess of 1024.  Note that we do NOT want to use _POSIX_PATH_MAX.  That
  1228. +  * specifies the minimum value that a conformant system must support.
  1229. +  */
  1230. + #ifndef PATH_MAX
  1231. + # ifdef MAXNAMLEN
  1232. + #  define PATH_MAX MAXNAMLEN
  1233. + # else
  1234. + #  define PATH_MAX 1024
  1235. + # endif
  1236. + #endif
  1237. +     return PATH_MAX;
  1238. + }
  1239. + /*
  1240. +  * Get the current working directory.
  1241. +  */
  1242. + char *get_curr_dir()
  1243. + {
  1244. +     char *d;
  1245. +     int maxlen, ok;
  1246. +     maxlen = max_path_len(".");
  1247. +     d = xmalloc(maxlen+2);    /* getcwd() wants two extra bytes */
  1248. +     errno = 0;
  1249. + #ifdef USE_GETCWD_GETCWD
  1250. +     {
  1251. + #ifndef USE_UNISTD
  1252. +         extern char *getcwd();
  1253. + #endif
  1254. +         ok = (getcwd(d, maxlen) != NULL);
  1255. +     }
  1256. + #endif
  1257. + #ifdef USE_GETCWD_GETWD
  1258. +     {
  1259. +         extern char *getwd();
  1260. +         ok = (getwd(d) != NULL);
  1261. +     }
  1262. + #endif
  1263. + #ifdef USE_GETCWD_NONE
  1264. +     {
  1265. +         FILE *fp;
  1266. +         char *s;
  1267. +         ok = ((fp = popen("pwd", "r")) != NULL
  1268. +                 && fgets(d, maxlen, fp) != NULL && pclose(fp) == 0);
  1269. +         if (ok && (s = strchr(d, '\n')) != NULL)
  1270. +             *s = '\0';
  1271. +     }
  1272. + #endif
  1273. +     if (!ok)
  1274. +         errmssg(ERR_ABORT, errno, "could not get current working directory");
  1275. + #ifdef DEBUG
  1276. +     Dprintf(stderr, "*** cwd=\"%s\"\n", d);
  1277. + #endif
  1278. +     return d;
  1279.   }
  1280.   
  1281. Index: dusort.1
  1282. *** PL0/dusort.1    Tue Aug 24 18:00:14 1993
  1283. --- dusort.1    Tue Aug 24 18:00:35 1993
  1284. ***************
  1285. *** 1,4 ****
  1286. ! .\" @(#) dusort.1 1.5 93/08/18 00:09:04
  1287.   .TH DUSORT 1
  1288.   .SH NAME
  1289.   dusort \- Sort disk usage summaries.
  1290. --- 1,4 ----
  1291. ! .\" @(#) dusort.1 1.6 93/08/24 18:00:31
  1292.   .TH DUSORT 1
  1293.   .SH NAME
  1294.   dusort \- Sort disk usage summaries.
  1295. ***************
  1296. *** 5,10 ****
  1297. --- 5,13 ----
  1298.   .SH SYNTAX
  1299.   .B dusort
  1300.   [
  1301. + .B \-f
  1302. + delim
  1303. + ] [
  1304.   .B \-t
  1305.   threshold ] [ file ]
  1306.   .SH DESCRIPTION
  1307. ***************
  1308. *** 19,30 ****
  1309.   and produces a listing to the standard output.  The listing will show
  1310.   the contents of the directories sorted in descending order, and indented
  1311.   under their parent directory.  The input data lines must have at least
  1312. ! two white-space delimited fields.  The first field is the disk usage
  1313. ! and the last field is the pathname.  The
  1314. ! .B \-t
  1315. ! option suppresses any entries less than
  1316.   .I threshold
  1317. ! disk blocks.
  1318.   .SH SEE ALSO
  1319.   du(1L)
  1320.   .SH BUGS
  1321. --- 22,45 ----
  1322.   and produces a listing to the standard output.  The listing will show
  1323.   the contents of the directories sorted in descending order, and indented
  1324.   under their parent directory.  The input data lines must have at least
  1325. ! two fields:  the disk usage value in the first field of the line and
  1326. ! the pathname in the last field of the line.  There may be additional
  1327. ! fields between these two; they will be ignored.  The tab character is
  1328. ! the default field delimiter.
  1329. ! .P
  1330. ! The following options are available.
  1331. ! .IP "\-f \fIdelim\fP" 12
  1332. ! Changes the field delimiter.  The field delimiter will be a sequence of
  1333. ! one or more of the characters specified by the
  1334. ! .I delim
  1335. ! argument.
  1336. ! .IP "\-t \fIthreshold\fP" 12
  1337. ! Normally,
  1338. ! .I dusort
  1339. ! lists all entries given to it.  This option sets a threshold, and any
  1340. ! input with a disk usage value less than the
  1341.   .I threshold
  1342. ! argument will be discarded.
  1343.   .SH SEE ALSO
  1344.   du(1L)
  1345.   .SH BUGS
  1346. Index: dusort.c
  1347. *** PL0/dusort.c    Tue Aug 24 18:00:15 1993
  1348. --- dusort.c    Fri Aug 27 16:54:37 1993
  1349. ***************
  1350. *** 1,4 ****
  1351. ! /* @(#) dusort.c 1.7 93/08/18 00:09:05
  1352.    *
  1353.    * disk usage sorter
  1354.    *
  1355. --- 1,4 ----
  1356. ! /* @(#) dusort.c 1.9 93/08/27 16:25:24
  1357.    *
  1358.    * disk usage sorter
  1359.    *
  1360. ***************
  1361. *** 19,27 ****
  1362.   #include <ctype.h>
  1363.   #include <string.h>
  1364.   
  1365. ! #define USAGE        "usage: %s [-t threshold] [file]\n"
  1366.   #define INDENT        4
  1367.   #define LISTINCR    16
  1368.   #define TRUE        1
  1369.   #define FALSE        0
  1370.   
  1371. --- 19,28 ----
  1372.   #include <ctype.h>
  1373.   #include <string.h>
  1374.   
  1375. ! #define USAGE        "usage: %s [-t threshold] [-f delim] [file]\n"
  1376.   #define INDENT        4
  1377.   #define LISTINCR    16
  1378. + #define DFLT_DELIM    "\t"
  1379.   #define TRUE        1
  1380.   #define FALSE        0
  1381.   
  1382. ***************
  1383. *** 63,69 ****
  1384.   int argc;
  1385.   char *argv[];
  1386.   {
  1387. !     char buf[1024], *fname, *last_field, *bufp, *s;
  1388.       int lineno, leading_slash, i;
  1389.       long size;
  1390.       struct duentry *du_root, *p, *p1;
  1391. --- 64,70 ----
  1392.   int argc;
  1393.   char *argv[];
  1394.   {
  1395. !     char buf[1024], *field_delim, *fname, *last_field, *s;
  1396.       int lineno, leading_slash, i;
  1397.       long size;
  1398.       struct duentry *du_root, *p, *p1;
  1399. ***************
  1400. *** 74,86 ****
  1401.        * Initialize.
  1402.        */
  1403.       Threshold = 0L;
  1404.       du_root = make_entry("", FALSE);
  1405.   
  1406.       /*
  1407.        * Crack command line.
  1408.        */
  1409. !     while ((i = getopt(argc, argv, "t:")) != EOF) {
  1410.           switch (i) {
  1411.           case 't':
  1412.               if ((Threshold=atol(optarg)) <= 0L && strcmp(optarg, "0") != 0) {
  1413.                   fprintf(stderr, "%s: bad threshold value \"%s\"\n",
  1414. --- 75,91 ----
  1415.        * Initialize.
  1416.        */
  1417.       Threshold = 0L;
  1418. +     field_delim = DFLT_DELIM;
  1419.       du_root = make_entry("", FALSE);
  1420.   
  1421.       /*
  1422.        * Crack command line.
  1423.        */
  1424. !     while ((i = getopt(argc, argv, "f:t:")) != EOF) {
  1425.           switch (i) {
  1426. +         case 'f':
  1427. +             field_delim = optarg;
  1428. +             break;
  1429.           case 't':
  1430.               if ((Threshold=atol(optarg)) <= 0L && strcmp(optarg, "0") != 0) {
  1431.                   fprintf(stderr, "%s: bad threshold value \"%s\"\n",
  1432. ***************
  1433. *** 123,150 ****
  1434.       while (++lineno, fgets(buf, sizeof(buf), stdin) != NULL) {
  1435.   
  1436.           /*
  1437. !          * Break the line up into fields.  Save the first field as the size.
  1438.            */
  1439. !         s = NULL;
  1440. !         bufp = buf;
  1441. !         i = 0;
  1442. !         while (last_field = s, (s = strtok(bufp, " \t\n")) != NULL) {
  1443. !             bufp = NULL;
  1444. !             if (i++ == 0)
  1445. !                 size = atol(s);
  1446. !         }
  1447. !         if (i < 2) {
  1448.               fprintf(stderr, "%s(%d): line ignored\n", fname, lineno);
  1449.               continue;
  1450.           }
  1451.   
  1452.           /*
  1453. !          * Ignore this entry if it is smaller than what we want.
  1454.            */
  1455. !         if (size < Threshold)
  1456.               continue;
  1457.   
  1458.           /*
  1459.            * Break the pathname into components, and descend down
  1460.            * into the tree, creating nodes as required.
  1461.            */
  1462. --- 128,165 ----
  1463.       while (++lineno, fgets(buf, sizeof(buf), stdin) != NULL) {
  1464.   
  1465.           /*
  1466. !          * Locate end of the first field.
  1467.            */
  1468. !         for (s = buf ; *s != '\0' && strchr(field_delim, *s) == NULL ; ++s)
  1469. !             ;
  1470. !         if (*s == '\0') {
  1471.               fprintf(stderr, "%s(%d): line ignored\n", fname, lineno);
  1472.               continue;
  1473.           }
  1474.   
  1475.           /*
  1476. !          * Save the field as the size.  Ignore line if size is below threshold.
  1477.            */
  1478. !         *s = '\0';
  1479. !         if ((size = atol(buf)) < Threshold)
  1480.               continue;
  1481.   
  1482.           /*
  1483. +          * Move to the end of the line and trim the trailing newline.
  1484. +          */
  1485. +         ++s;
  1486. +         s += strlen(s)-1;
  1487. +         if (*s == '\n')
  1488. +             *s-- = '\0';
  1489. +         /*
  1490. +          * Locate the start of the last field.
  1491. +          */
  1492. +         while (*s != '\0' && strchr(field_delim, *s) == NULL)
  1493. +             --s;
  1494. +         last_field = s+1;
  1495. +         /*
  1496.            * Break the pathname into components, and descend down
  1497.            * into the tree, creating nodes as required.
  1498.            */
  1499. ***************
  1500. *** 314,320 ****
  1501.   }
  1502.   
  1503.   
  1504. ! static char malloc_error[] = "error - out of memory [malloc failed]\n";
  1505.   
  1506.   char *xstrdup(s)
  1507.   register char *s;
  1508. --- 329,335 ----
  1509.   }
  1510.   
  1511.   
  1512. ! static char malloc_errmssg[] = "error - out of memory [malloc failed]\n";
  1513.   
  1514.   char *xstrdup(s)
  1515.   register char *s;
  1516. ***************
  1517. *** 321,327 ****
  1518.   {
  1519.       register char *s1;
  1520.       if ((s1 = (char *) malloc((unsigned)strlen(s)+1)) == NULL) {
  1521. !         fputs(malloc_error, stderr);
  1522.           exit(1);
  1523.       }
  1524.       return strcpy(s1, s);
  1525. --- 336,342 ----
  1526.   {
  1527.       register char *s1;
  1528.       if ((s1 = (char *) malloc((unsigned)strlen(s)+1)) == NULL) {
  1529. !         fputs(malloc_errmssg, stderr);
  1530.           exit(1);
  1531.       }
  1532.       return strcpy(s1, s);
  1533. ***************
  1534. *** 332,338 ****
  1535.   {
  1536.       register PTRTYPE *s;
  1537.       if ((s = malloc(n)) == NULL) {
  1538. !         fputs(malloc_error, stderr);
  1539.           exit(1);
  1540.       }
  1541.       return s;
  1542. --- 347,353 ----
  1543.   {
  1544.       register PTRTYPE *s;
  1545.       if ((s = malloc(n)) == NULL) {
  1546. !         fputs(malloc_errmssg, stderr);
  1547.           exit(1);
  1548.       }
  1549.       return s;
  1550. ***************
  1551. *** 343,349 ****
  1552.   register unsigned n;
  1553.   {
  1554.       if ((s = (s == NULL ? malloc(n) : realloc(s, n))) == NULL) {
  1555. !         fputs(malloc_error, stderr);
  1556.           exit(1);
  1557.       }
  1558.       return s;
  1559. --- 358,364 ----
  1560.   register unsigned n;
  1561.   {
  1562.       if ((s = (s == NULL ? malloc(n) : realloc(s, n))) == NULL) {
  1563. !         fputs(malloc_errmssg, stderr);
  1564.           exit(1);
  1565.       }
  1566.       return s;
  1567. Index: fsinfo.c
  1568. *** PL0/fsinfo.c    Tue Aug 24 18:00:11 1993
  1569. --- fsinfo.c    Thu Aug 26 05:22:46 1993
  1570. ***************
  1571. *** 1,5 ****
  1572.   #ifndef lint
  1573. ! static char SCCSID[] = "@(#) fsinfo.c 1.25 93/08/18 00:09:06";
  1574.   #endif
  1575.   
  1576.   /*
  1577. --- 1,5 ----
  1578.   #ifndef lint
  1579. ! static char SCCSID[] = "@(#) fsinfo.c 1.27 93/08/26 05:22:39";
  1580.   #endif
  1581.   
  1582.   /*
  1583. ***************
  1584. *** 116,121 ****
  1585. --- 116,134 ----
  1586.   #    include <sys/vfs.h>
  1587.   #    define STATFS(MNT, PTR, PSIZE, FSTYPE) \
  1588.           statfs(MNT, PTR)
  1589. + #endif
  1590. + #ifdef USE_STATFS_ULTRIX
  1591. + #    include <sys/param.h>
  1592. + #    include <sys/mount.h>
  1593. +     struct statfs {
  1594. +         long f_bsize, f_files;
  1595. +     };
  1596. +     static struct fs_data fs_data;
  1597. + #    define STATFS(MNT, PTR, PSIZE, FSTYPE) \
  1598. +         (statfs(MNT, &fs_data) != 1 ? -1 : ( \
  1599. +             (PTR)->f_bsize = fs_data.fd_bsize, \
  1600. +             (PTR)->f_files = fs_data.fd_gfree, \
  1601. +             0))
  1602.   #endif
  1603.   #ifdef USE_STATFS_NONE
  1604.   #    include <sys/param.h>
  1605.  
  1606. -- 
  1607. Chip Rosenthal  512-447-0577 | I'm going out where the lights don't shine so
  1608. Unicom Systems Development   | bright.  When I get back you can treat me like
  1609. <chip@chinacat.Unicom.COM>   | a Saturday night.  -Jimmie Dale Gilmore
  1610.  
  1611. exit 0 # Just in case...
  1612.