home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!munnari!basser!john
- From: lim@mullian.oz.AU (Lim Ngee Ching)
- Newsgroups: comp.sources.misc
- Subject: DU for MS DOS (MSC 4.0)
- Message-ID: <1149@basser.oz>
- Date: 9 Dec 87 15:15:08 GMT
- Sender: john@basser.oz
- Lines: 793
- Approved: john@basser.cs.su.oz.AU
-
-
- [Moderator's note:
-
- This software arrived as two postings, the second arriving before
- I had posted the first. The second shar contained new versions
- of the files du.c and msd_dir.c, and a new file showbug.c. I have
- repackaged these along with the other files from the first shar
- into a single shar. Here is the author's note from the first
- posting:]
-
- I have waited around long enough for a proper MS DOS DU, so I wrote my
- own.
-
- This "DU" compiles in MSC 4.0 under MS DOS. As such it has very strong
- MS DOS flavour. It is basically a superset of the Unix DU - a lot more
- options available - to cater for the quirks of MS DOS. Essentially it
- produces the same reading as CHKDSK in MS DOS except in cases where
- you have directories which used to hold a lot of files which has been
- erased - the erased directory entries will not be accounted for, and
- can't be without resorting to very low level FAT fiddling which is not
- worth the while. At the moment, it doesn't allow specification of files
- - only the whole directory - may be someone would like to change this.
- It also displays sizes in bytes and not kilobytes - a feature to suit
- MS DOS's various cluster sizes.
-
- Msd_dir.* are borrowed from the TAR package put together by Michael
- Rendell ({uunet,utai}michael@garfield) with some fairly kludgy modifi-
- cations and extensions. See read.me for some extra info (not much :-)).
- For now unshar this message and type 'make make.msc' to compile DU.
-
- -----------------------------------------------------------------------
- This program is placed in the public domain without any warranty. As
- far as I know it is not a virius ;-).
-
- From: Peter Lim, lim@mullian.oz
-
- [And the author's note from the second posting:
-
- -- John.]
-
- Oops ! I didn't test the program thoroughly enough. Just found one
- bug. Fixed here. It allows du .. if .. specifies the root directory.
- I also stumble on a rather serious bug in MSC 4.0 with stat().
- Read msd_dir.c for detail, a program SHOWBUG.C is included to
- demonstrate this bug. Hope I don't have to fix any more bug. :-)
-
- Peter Lim
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Wrapped by john on Thu Dec 10 02:05:11 EST 1987
- # Contents: read.me du.c du.hlp make.msc msd_dir.c msd_dir.h showbug.c
-
- echo x - read.me
- sed 's/^@//' > "read.me" <<'@//E*O*F read.me//'
- This program (DU) should be compiled at least using COMPACT memory model.
- The recursive nature would readily overflow a SMALL memory model program's
- data space. Beside that, the stack should be much bigger than the default
- value of 2048 (say 10k or 20k would be fine). However, one might consider
- using the xVARSTCK.OBJ supplied by Microsoft (see page 197, chapter 9 --
- Advanced Topics, of Microsoft C compiler User's Guide). Then one should use
- the /Gs or /Ox option during compilation.
-
-
- One probable compilation command would be :
-
- CL /Gs /Ox /AC du.c msd_dir.c cvarstck.obj -o du -link /STACK:20480
-
-
- Peter lim
- 07-Dec-87
- @//E*O*F read.me//
- chmod u=rw,g=r,o=r read.me
-
- echo x - du.c
- sed 's/^@//' > "du.c" <<'@//E*O*F du.c//'
- /*
- * DU - Disk Usage. A Unix style utility. Written by Peter Lim 07-Dec-87.
- *
- * Usage: du [-s] [-a] [-z] [-c] [-r] [-h] [-nnnn] [pathname(s) ... ]
- * where,
- * -s : Summary listing only (Toggle, default=off).
- * -a : Generate a list of all files
- * (Toggle, default=off).
- * -z : Show total statistics (Toggle, default=on).
- * -c : Show cluster size (Toggle, default=on).
- * -r : Recursive traversal of sub-directories
- * (Toggle, default=on).
- * -h : Include HIDDEN & SYSTEM files
- * (Toggle, default=off).
- * -nnnn : Force cluster size to be nnnn bytes.
- * nnnn = 0 releases previous forcing.
- * Default pathname is the current directory on current drive.
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "msd_dir.h"
- #include <dos.h>
- #include <strings.h>
- #include <ctype.h>
-
-
- unsigned long traverse_dir();
- unsigned long get_cluster_size();
- unsigned long get_path_size ();
- #define print_size(size, path) printf ("%-11lu%s\n", size, path)
-
- unsigned long bpc; /* number of bytes per cluster */
- int filecnt=0, dircnt=0;
- int summary=0, show_all=0, show_stat=1,
- show_cluster=1, force_cluster=0, recurse=1, incl_hidn=0;
- unsigned int att_mask;
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- unsigned long total=0;
- int path_specified=0;
-
- for (; --argc > 0; ) {
- *++argv;
- if (**argv == '-')
- switch ((*argv)[1]) {
- case 's' :
- case 'S' :
- summary = !summary;
- continue;
- case 'z' :
- case 'Z' :
- show_stat = !show_stat;
- continue;
- case 'a' :
- case 'A' :
- show_all = !show_all;
- continue;
- case 'c' :
- case 'C' :
- show_cluster = !show_cluster;
- continue;
- case 'r' :
- case 'R' :
- recurse = !recurse;
- continue;
- case 'h' :
- case 'H' :
- incl_hidn = !incl_hidn;
- continue;
- default :
- if (!sscanf (*argv, "-%lu", &bpc))
- printf ("Unknown option %s\n", *argv);
- else
- force_cluster = bpc ? 1 : 0;
- continue;
- }
- path_specified = 1;
- /* At this point we know at least one path is specified. */
- total += get_path_size(*argv);
- }
-
- if (!path_specified)
- total = get_path_size(".");
- /* If no pathname were specified. */
-
- if (show_stat) {
- printf ("Total %d files in %d directories.\n", filecnt, dircnt);
- printf ("Total disk space used = %lu bytes (%.2lfk).\n",
- total, total / 1024.0);
- }
- }
-
-
- unsigned long get_path_size (pathname)
- char *pathname;
- {
- unsigned char drive_id;
- unsigned long total;
-
- if (incl_hidn)
- att_mask = (A_HIDDEN | A_SYSTEM);
- else
- att_mask = 0; /* Set attribute mask for files to find.
- A_DIR will always be set. */
- if (!force_cluster) {
- if (isalpha (*pathname) && (pathname[1] == ':'))
- drive_id = *pathname - ((islower(*pathname)) ? 'a' : 'A') + 1;
- else
- drive_id = 0;
- if (!(bpc = get_cluster_size(drive_id))) {
- printf ("Invalid drive %c\:\n", *pathname);
- exit (1);
- }
- }
- if (show_cluster)
- printf ("Cluster size = %lu bytes.\n", bpc);
- total = traverse_dir(pathname);
- if (summary)
- print_size (total, pathname);
- /* At least say something even if only summary is required. */
- return (total);
- }
-
-
- unsigned long traverse_dir(cur_path)
- char *cur_path;
- {
- DIR *dp;
- struct direct *direntry;
- char s[MAXPATHLEN+1];
- char c;
- unsigned long total, file_size;
- unsigned int dir_ent_cnt; /* Count the number of directory entry. */
- #define bpdent (unsigned int) 32
- /* Number of bytes per directory entry,
- = 32 from DOS 2.10 tech ref pp. 4-5. lim@mullian.oz */
- int not_root_dir;
-
- total = 0;
- if (!(dp=opendir(cur_path, att_mask))) {
- printf ("Can't open directory \"%s\" or memory allocation failure.\n",
- cur_path);
- exit(2);
- }
-
- if (recurse) {
- while (direntry=readdir(dp))
- if (((*direntry).d_attribute == A_DIR)
- && (strcmp ((*direntry).d_name, "."))
- && (strcmp ((*direntry).d_name, ".."))) {
- strcpy (s, cur_path);
- if ((c = s[strlen(s)-1]) != '\\' &&
- c != '/' && c != ':')
- strcat (s, "\\");
- strcat (s, (*direntry).d_name);
- total += traverse_dir(s);
- }
- (void) rewinddir(dp);
- }
-
- dir_ent_cnt = not_root_dir = 0;
- while (direntry=readdir(dp)) {
- dir_ent_cnt++;
- if ((*direntry).d_attribute != A_DIR) {
- total += file_size = ( ((*direntry).d_size / bpc) +
- (((*direntry).d_size % bpc) ? 1 : 0) ) * bpc;
- if (show_all) {
- strcpy (s, cur_path);
- if ((c = s[strlen(s)-1]) != '\\' && c != '/')
- strcat (s, "\\");
- print_size (file_size, strcat (s, (*direntry).d_name));
- }
- filecnt++; /* Counting all files (exclude dir). */
- }
- else if (!strcmp ((*direntry).d_name, ".")) {
- dircnt++; /* Counting every occurance of ".". */
- not_root_dir = 1;
- /* Not root directory if "." exist. */
- }
- }
- if (not_root_dir)
- total += ( ((dir_ent_cnt * bpdent) / bpc) +
- (((dir_ent_cnt * bpdent) % bpc) ? 1 : 0) ) * bpc;
- /* Add the number of directory entry counted * bytes per entry rounded
- up to the nearest cluster. The only things missed by this method of
- counting are the directories with a lot of erased files. Can't be
- helped without resorting to very low level FAT probing.
- NOTE: The root directory uses zero byte here - complying
- with CHKDSK from MS DOS. Another MS DOS quirk. */
- if (!summary)
- print_size (total, cur_path);
-
- closedir(dp);
- return (total);
- }
-
-
- #define DOSI_GDFREE 0x36;
- static union REGS reg, nreg;
-
- unsigned long get_cluster_size(drive_id)
- unsigned char drive_id;
- {
- reg.h.ah = DOSI_GDFREE;
- reg.h.dl = drive_id;
- intdos(®, &nreg);
- if (nreg.x.ax == 0xffff)
- return ((unsigned long) 0);
- else
- return ((unsigned long) nreg.x.cx * nreg.x.ax);
- }
- @//E*O*F du.c//
- chmod u=rw,g=r,o=r du.c
-
- echo x - du.hlp
- sed 's/^@//' > "du.hlp" <<'@//E*O*F du.hlp//'
-
- DU - Disk Usage. A Unix style utility. Written by Peter Lim 07-Dec-87.
-
- Usage: du [-s] [-a] [-z] [-c] [-r] [-h] [-nnnn] [pathname(s) ... ]
- where,
- -s : Summary listing only (Toggle, default=off).
- -a : Generate a list of all files
- (Toggle, default=off).
- -z : Show total statistics (Toggle, default=on).
- -c : Show cluster size (Toggle, default=on).
- -r : Recursive traversal of sub-directories
- (Toggle, default=on).
- -h : Include HIDDEN & SYSTEM files
- (Toggle, default=off).
- -nnnn : Force cluster size to be nnnn bytes.
- nnnn = 0 releases previous forcing.
- Default pathname is the current directory on current drive.
-
- @//E*O*F du.hlp//
- chmod u=rw,g=r,o=r du.hlp
-
- echo x - make.msc
- sed 's/^@//' > "make.msc" <<'@//E*O*F make.msc//'
- CFLAGS = /AC
- LFLAGS = /STACK:20480
-
- @.c.obj:
- msc $(CFLAGS) $*;
-
- du.obj: du.c msd_dir.h
-
- msd_dir.obj: msd_dir.c msd_dir.h
-
- du.exe: du.obj msd_dir.obj
- link $(LFLAGS) du+msd_dir;
- @//E*O*F make.msc//
- chmod u=rw,g=r,o=r make.msc
-
- echo x - msd_dir.c
- sed 's/^@//' > "msd_dir.c" <<'@//E*O*F msd_dir.c//'
- /*
- * @(#)msd_dir.c 1.4 87/11/06 Public Domain.
- *
- * A public domain implementation of BSD directory routines for
- * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
- * August 1897
- *
- * Extended by Peter Lim (lim@mullian.oz) to overcome some MS DOS quirks
- * and returns 2 more pieces of information - file size & attribute.
- * Plus a little reshuffling of #define's positions December 1987
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "msd_dir.h"
- #include <malloc.h>
- #include <string.h>
- #include <ctype.h>
- #include <dos.h>
- #include <direct.h>
-
- #ifndef NULL
- # define NULL 0
- #endif /* NULL */
-
- /* dos call values */
- #define DOSI_FINDF 0x4e
- #define DOSI_FINDN 0x4f
- #define DOSI_SDTA 0x1a
- #define DOSI_GCDIR 0x47
-
- #define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
-
- /* what find first/next calls look use */
- typedef struct {
- char d_buf[21];
- char d_attribute;
- unsigned short d_time;
- unsigned short d_date;
- unsigned long d_size;
- char d_name[13];
- } Dta_buf;
-
- static char *getdirent();
- static void setdta();
- static void free_dircontents();
- static char *extgetcwd();
-
- static Dta_buf dtabuf;
- static Dta_buf *dtapnt = &dtabuf;
- static union REGS reg, nreg;
-
- #if defined(M_I86LM)
- static struct SREGS sreg;
- #endif
-
- DIR *
- opendir(pathname, att_mask)
- char *pathname;
- unsigned int att_mask;
- {
- struct stat statb;
- DIR *dirp;
- char c;
- char *s;
- struct _dircontents *dp;
- char nbuf[MAXPATHLEN + 1];
- char name[MAXPATHLEN + 1];
- unsigned char drive_id;
- char *phead;
-
- strcpy (name, pathname);
- /* Work on temporary buffer only. Never write it back,
- the calling argument may not have room for it ! */
- if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR) {
- /* Give it a second try, after modifying input pathname,
- before giving up to counter some MS DOS quirks.
- This kludge is fairly simple and will not handle weird
- though valid path name correctly such as multiple ../.. and
- other mix which eventually end up on the root directory. */
- if (isalpha (*name) && (name[1] == ':')) {
- drive_id = *name - ((islower(*name)) ? 'a' : 'A') + 1;
- phead = pathname+2;
- }
- else {
- drive_id = 0;
- phead = pathname;
- }
- if ((c = name[strlen(name) - 1]) == '\\' || c == '/')
- name[strlen(name) - 1] = NULL;
- /* Try removing one trailing / or \ */
- if (*phead == '.' || *phead == '\0') {
- /* If . or nothing specified, assume current directory
- and go get the directory. */
- if (extgetcwd (drive_id, name, MAXPATHLEN) == NULL)
- return (DIR *) NULL;
- strcpy (nbuf, name);
- /* There is an undocumented BUG in MSC 4.0 such that
- stat (root, ..) will cause the current directory on the
- specified drive to be changed to root if the current
- directory in question is exactly one level deep !
- So, keep current directory for chdir() back after doing
- stat (root, ..). lim@mullian.oz */
- if (*(phead+1) == '.') {
- /* i.e. ".." specified. Then backup one level. Firstly
- check that we are not already at the root. */
- if (name[strlen(name) - 1] == '\\')
- return (DIR *) NULL;
- while (name[strlen(name) - 1] != '\\')
- name[strlen(name) - 1] = NULL;
- if (*(phead+2) == '\\' || *(phead+2) == '/')
- /* Make sure we don't have a '\' double up. */
- strcat (name, phead+3);
- }
- else if (*(phead) == '.')
- /* Just plain "." specified. */
- strcat (name, phead+1);
- }
- else
- *nbuf = NULL; /* Don't chdir() wrongly. */
- if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
- return (DIR *) NULL;
- if (*nbuf)
- (void) chdir (nbuf); /* Fixing the stat() BUG ! */
- }
- if (Newisnull(dirp, DIR))
- return (DIR *) NULL;
- if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
- (void) strcat(strcpy(nbuf, name), "\\*.*");
- else
- (void) strcat(strcpy(nbuf, name), "*.*");
- dirp->dd_loc = 0;
- setdta();
- dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
- if ((s = getdirent(nbuf, att_mask | A_DIR)) == (char *) NULL)
- return dirp;
- do {
- if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
- (char *) malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
- {
- if (dp)
- free((char *) dp);
- free_dircontents(dirp->dd_contents);
- return (DIR *) NULL;
- }
- if (dirp->dd_contents)
- dirp->dd_cp = dirp->dd_cp->_d_next = dp;
- else
- dirp->dd_contents = dirp->dd_cp = dp;
- (void) strcpy(dp->_d_entry, s);
- dp->d_attribute = dtabuf.d_attribute;
- dp->d_size = dtabuf.d_size;
- /* A SUPER Kludge ! Using 'dtabuf' as global variable. lim@mullian.oz */
- dp->_d_next = (struct _dircontents *) NULL;
- } while ((s = getdirent((char *) NULL, att_mask | A_DIR)) != (char *) NULL);
- dirp->dd_cp = dirp->dd_contents;
-
- return dirp;
- }
-
- void
- closedir(dirp)
- DIR *dirp;
- {
- free_dircontents(dirp->dd_contents);
- free((char *) dirp);
- }
-
- struct direct *
- readdir(dirp)
- DIR *dirp;
- {
- static struct direct dp;
-
- if (dirp->dd_cp == (struct _dircontents *) NULL)
- return (struct direct *) NULL;
- dp.d_namlen = dp.d_reclen =
- strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
- dp.d_ino = 0;
- dp.d_attribute = dirp->dd_cp->d_attribute;
- dp.d_size = dirp->dd_cp->d_size;
- dirp->dd_cp = dirp->dd_cp->_d_next;
- dirp->dd_loc++;
-
- return &dp;
- }
-
- void
- seekdir(dirp, off)
- DIR *dirp;
- long off;
- {
- long i = off;
- struct _dircontents *dp;
-
- if (off < 0)
- return;
- for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
- ;
- dirp->dd_loc = off - (i + 1);
- dirp->dd_cp = dp;
- }
-
- long
- telldir(dirp)
- DIR *dirp;
- {
- return dirp->dd_loc;
- }
-
- static void
- free_dircontents(dp)
- struct _dircontents *dp;
- {
- struct _dircontents *odp;
-
- while (dp) {
- if (dp->_d_entry)
- free(dp->_d_entry);
- dp = (odp = dp)->_d_next;
- free((char *) odp);
- }
- }
-
- static char *
- getdirent(dir, att_mask)
- char *dir;
- unsigned int att_mask;
- {
- if (dir != (char *) NULL) { /* get first entry */
- reg.h.ah = DOSI_FINDF;
- reg.h.cl = att_mask;
- #if defined(M_I86LM)
- reg.x.dx = FP_OFF(dir);
- sreg.ds = FP_SEG(dir);
- #else
- reg.x.dx = (unsigned) dir;
- #endif
- } else { /* get next entry */
- reg.h.ah = DOSI_FINDN;
- #if defined(M_I86LM)
- reg.x.dx = FP_OFF(dtapnt);
- sreg.ds = FP_SEG(dtapnt);
- #else
- reg.x.dx = (unsigned) dtapnt;
- #endif
- }
- #if defined(M_I86LM)
- intdosx(®, &nreg, &sreg);
- #else
- intdos(®, &nreg);
- #endif
- if (nreg.x.cflag)
- return (char *) NULL;
-
- return dtabuf.d_name;
- }
-
- static void
- setdta()
- {
- reg.h.ah = DOSI_SDTA;
- #if defined(M_I86LM)
- reg.x.dx = FP_OFF(dtapnt);
- sreg.ds = FP_SEG(dtapnt);
- intdosx(®, &nreg, &sreg);
- #else
- reg.x.dx = (int) dtapnt;
- intdos(®, &nreg);
- #endif
- }
-
- static char *extgetcwd(drive_id, buffer, buffer_size)
- /* Extended get current directory on specified drive. Peter Lim 07-Dec-87. */
- unsigned char drive_id;
- char *buffer;
- int buffer_size;
- {
- char tmpbuffer[MAXPATHLEN+1];
-
- if (!drive_id)
- return (getcwd (buffer, buffer_size));
- /* If it is current drive, use the standard getcwd() */
-
- reg.h.ah = DOSI_GCDIR;
- reg.h.dl = drive_id;
- #if defined(M_I86LM)
- reg.x.si = FP_OFF(tmpbuffer);
- sreg.ds = FP_SEG(tmpbuffer);
- intdosx(®, &nreg, &sreg);
- #else
- reg.x.si = (int) tmpbuffer;
- intdos(®, &nreg);
- #endif
- if (nreg.x.ax == 0xf)
- return ((char *) NULL);
- /* Invalid drive specification. */
- else {
- if (drive_id)
- sprintf (buffer, "%c:\\%s", drive_id+'A'-1, tmpbuffer);
- else
- sprintf (buffer, "\\%s", tmpbuffer);
- return (buffer);
- }
- }
- @//E*O*F msd_dir.c//
- chmod u=rw,g=r,o=r msd_dir.c
-
- echo x - msd_dir.h
- sed 's/^@//' > "msd_dir.h" <<'@//E*O*F msd_dir.h//'
- /*
- * @(#)msd_dir.h 1.4 87/11/06 Public Domain.
- *
- * A public domain implementation of BSD directory routines for
- * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
- * August 1897
- *
- * Extended by Peter Lim (lim@mullian.oz) to overcome some MS DOS quirks
- * and returns 2 more pieces of information - file size & attribute.
- * Plus a little reshuffling of some #define's positions December 1987
- */
-
- #define rewinddir(dirp) seekdir(dirp, 0L)
-
- #define MAXNAMLEN 12
-
- #ifndef MAXPATHLEN
- # define MAXPATHLEN 255
- #endif /* MAXPATHLEN */
-
- /* attribute stuff */
- #define A_RONLY 0x01
- #define A_HIDDEN 0x02
- #define A_SYSTEM 0x04
- #define A_LABEL 0x08
- #define A_DIR 0x10
- #define A_ARCHIVE 0x20
-
- struct direct {
- ino_t d_ino; /* a bit of a farce */
- int d_reclen; /* more farce */
- int d_namlen; /* length of d_name */
- char d_name[MAXNAMLEN + 1]; /* garentee null termination */
- char d_attribute;
- unsigned long d_size;
- };
-
- struct _dircontents {
- char *_d_entry;
- char d_attribute;
- unsigned long d_size;
- struct _dircontents *_d_next;
- };
-
- typedef struct _dirdesc {
- int dd_id; /* uniquely identify each open directory */
- long dd_loc; /* where we are in directory entry is this */
- struct _dircontents *dd_contents; /* pointer to contents of dir */
- struct _dircontents *dd_cp; /* pointer to current position */
- } DIR;
-
- extern DIR *opendir();
- extern struct direct *readdir();
- extern void seekdir();
- extern long telldir();
- extern void closedir();
- @//E*O*F msd_dir.h//
- chmod u=rw,g=r,o=r msd_dir.h
-
- echo x - showbug.c
- sed 's/^@//' > "showbug.c" <<'@//E*O*F showbug.c//'
- /*
- * To show the bug associated with stat(), it works okay if the drive
- * letter entered is for the current drive.
- */
-
- #include <stdio.h>
- #include <dos.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <strings.h>
- #include <ctype.h>
- struct stat statb;
-
- static char *extgetcwd();
- #define DOSI_GCDIR 0x47
- static union REGS reg, nreg;
- #if defined(M_I86LM)
- static struct SREGS sreg;
- #endif
- #define MAXPATHLEN 128
-
- main()
- {
- char *s = ":\\tmp";
- char ss[MAXPATHLEN+1], dd[MAXPATHLEN+1];
- char c;
-
- printf ("Enter drive letter with directory \\tmp : ");
- c = getchar();
- if (isupper(c))
- c += 'a' - 'A';
- ss[0] = c;
- ss[1] = NULL;
- strcat (ss, s);
- chdir(ss);
- extgetcwd (c+1, ss, MAXPATHLEN);
- printf ("Current directory before stat() = %s\n", ss);
- dd[0] = c;
- dd[1] = NULL;
- strcat (dd, ":\\");
- stat(dd, &statb);
- extgetcwd (c+1, dd, MAXPATHLEN);
- printf ("Current directory after stat() = %s\n", dd);
- }
-
-
- static char *extgetcwd(drive_id, buffer, buffer_size)
- /* Extended get current directory on specified drive. Peter Lim 07-Dec-87. */
- unsigned char drive_id;
- char *buffer;
- int buffer_size;
- {
- char tmpbuffer[MAXPATHLEN+1];
-
- if (!drive_id)
- return (getcwd (buffer, buffer_size));
- /* If it is current drive, use the standard getcwd() */
-
- reg.h.ah = DOSI_GCDIR;
- reg.h.dl = drive_id;
- #if defined(M_I86LM)
- reg.x.si = FP_OFF(tmpbuffer);
- sreg.ds = FP_SEG(tmpbuffer);
- intdosx(®, &nreg, &sreg);
- #else
- reg.x.si = (int) tmpbuffer;
- intdos(®, &nreg);
- #endif
- if (nreg.x.ax == 0xf)
- return ((char *) NULL);
- /* Invalid drive specification. */
- else {
- if (drive_id)
- sprintf (buffer, "%c:\\%s", drive_id+'A'-1, tmpbuffer);
- else
- sprintf (buffer, "\\%s", tmpbuffer);
- return (buffer);
- }
- }
- @//E*O*F showbug.c//
- chmod u=rw,g=r,o=r showbug.c
-
- exit 0
-