diff options
Diffstat (limited to 'dmake/msdos/dirlib.c')
-rw-r--r-- | dmake/msdos/dirlib.c | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/dmake/msdos/dirlib.c b/dmake/msdos/dirlib.c new file mode 100644 index 000000000000..eaef928772af --- /dev/null +++ b/dmake/msdos/dirlib.c @@ -0,0 +1,285 @@ +/* + DIRLIB for MS-DOS + ----------------- + +Enclosed is an implementation of the `dirlib' package for MS-DOS. +The implementation is targeted for MS-C, although any reasonably +competent C compiler should manage. The package consists of: + + dir.h the header file + dir.c the functions + testdir.c a q&d test program + +The package tries to view directory naming in a Un*x light; in particular, +directories such as '/.' and '/..' (as well as `.' and `..' if your +current directory is root) are understood. Indefinite paths like +`/../.././../..' will correctly refer to the root (of the particular disk). +Names such as `a:////./../' are okay too. + +I've tried to be as sensible about DTA's as possible, since you never +know who will be using one; they are set before use, and reset afterwards. + +There is some cruft in the package, namely the way `seekdir' and +`telldir' are done. The code was derived from a little experimentation, +and may not work after a certain point (although I believe the 2.x version +to be solid). Caveat utilitor. + +Documentation for the package is available in the public domain; the +package's functionality was derived from this documentation. + +Bug reports and comments are welcome. Enjoy! + + - Matt + +------- +UUCP: {ucbvax,ihnp4,randvax,trwrb!trwspp,ism780}!ucla-cs!matt +ARPA: matt@LOCUS.UCLA.EDU +Ph: (213) 825-2756 + +-------- +Modified for use in dmake by Dennis Vadura. Mostly just clean up and an +effort to make correctly typed objects are passed to functions in find.c. +Also deleted all dos version 2.0 specific code. It is not required any +more. +*/ + +/* + * revision history: + * + * VER MM/DD/YY COMMENTS + * ---- -------- -------- + * 0.99 02/24/86 Beta release to INTERNET + */ + +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <dos.h> + +#include "dirent.h" + +extern int find_err; + + +static char * +getdcwd(drive) +int drive; +{ + union REGS r; + struct SREGS s; + static char xcwd[64]; + char far *cwd = xcwd; + + r.h.ah = 0x47; + r.h.dl = drive; + r.x.si = FP_OFF(cwd); + s.ds = FP_SEG(cwd); + intdosx(&r, &r, &s); + find_err = r.x.ax; + if (r.x.cflag) + return (char *) 0; + return xcwd; +} + + + +/* + * opendir + */ + +#define SUFFIX "\\*.*" +#define SLASH "\\" +#define streq(a,b) (strcmp(a,b)==0) + +DIR * +opendir(name) +char *name; +{ + register DIR *nd; + char *cwd; + char drive[3]; + int atroot = 0; + int rooted = 0; + + /* + * hack off drive designator if present + */ + + if (name[1] == ':') { + cwd = getdcwd(toupper(name[0]) - 'A' + 1); + drive[0] = name[0]; drive[1] = ':'; drive[2] = '\0'; + name += 2; + } + else { + cwd = getdcwd(0); + drive[0] = '\0'; + } + + /* is the name 'rooted'? */ + if ((*name == '/') || (*name == '\\')) ++rooted; + + /* see if we are at the root directory for this device */ + if (!*cwd) ++atroot; + + /* + * MSDOS '/' doesn't have a '.' or '..' + * also, double '/' sequences don't make sense. + * many ported programs expect them to work, so we fix it up... + */ + + /* chop off leading . and .. if at root */ + if (atroot && (*name == '.')) { + switch (*++name) { + case '\0': + case '/': + case '\\': + break; + + case '.': + switch (*++name) { + case '\0': + case '/': + case '\\': + break; + default: + --name; + --name; + } + break; + + default: + --name; + } + } + + /* chop off leading /'s, /.'s and /..'s to make naming sensible */ + while (*name && ((*name == '/') || (*name == '\\'))) { + if (*++name == '.') { + switch (*++name) { + case '\0': + case '/': + case '\\': + break; + + case '.': + switch (*++name) { + case '\0': + case '/': + case '\\': + break; + + default: + --name; + --name; + } + break; + + default: + --name; + } + } + } + + + /* + * name should now look like: path/path/path + * we must now construct name based on whether or not it + * was 'rooted' (started with a /) + */ + + if (rooted) cwd = ""; + + /* construct DIR */ + if (!(nd = (DIR *)malloc( + sizeof(DIR)+strlen(drive)+strlen(cwd)+strlen(SLASH)+ + strlen(name)+strlen(SUFFIX)))) + return (DIR *) 0; + + /* create long name */ + strcpy(nd->dd_name, drive); + if (*cwd) { + strcat(nd->dd_name, SLASH); + strcat(nd->dd_name, cwd); + } + if (*name) { + strcat(nd->dd_name, SLASH); + strcat(nd->dd_name, name); + } + strcat(nd->dd_name, SUFFIX); + + /* search */ + if (!findfirst(&nd->dd_name[0], &nd->dd_dta)) { + free((char *)nd); + errno = ENOENT; + return (DIR *) 0; + } + nd->dd_stat = 0; + return nd; +} + + +struct dirent * +readdir(dirp) +DIR *dirp; +{ + static struct dirent dir; + + if (dirp->dd_stat) + return (struct dirent *) 0; + + /* format structure */ + dir.d_ino = 0; /* not valid for DOS */ + dir.d_reclen = 0; + strcpy(dir.d_name, dirp->dd_dta.name); + dir.d_namlen = strlen(dir.d_name); + strlwr(dir.d_name); /* DOSism */ + + /* read ahead */ + if (findnext(&dirp->dd_dta) != NULL) + dirp->dd_stat = 0; + else + dirp->dd_stat = find_err; + + return &dir; +} + + +void +closedir(dirp) +DIR *dirp; +{ + free((char *)dirp); +} + + +void +seekdir(dirp, pos) +DIR *dirp; +long pos; +{ + /* + * check against DOS limits + */ + + if ((pos < 0) || (pos > 4095)) { + dirp->dd_stat = 1; + return; + } + + *(short *)&dirp->dd_dta.fcb[13] = pos + 1; + + /* read ahead */ + if (findnext(&dirp->dd_dta)) + dirp->dd_stat = 0; + else + dirp->dd_stat = find_err; +} + + +long +telldir(dirp) +DIR *dirp; +{ + return (long) (*(short *)&dirp->dd_dta.fcb[13] - 2); +} |