home *** CD-ROM | disk | FTP | other *** search
- /*
- os2dir.c -mla
-
- % OS/2-specific file and directory handling functions.
-
- OWL-PC 1.2
- Copyright (c) 1990 by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 9/15/90 ted Fixed srchcnt and hdir initialization for DosFindFirst.
- 9/15/90 ted Fixed case in odir_Split when spec is NULL.
- 10/20/90 mla changed ostrlower to os2dir_StripCase & added (char) cast
- 10/28/90 mla updated, preened
- */
- /* -------------------------------------------------------------------------- */
- #include <ctype.h>
- #include <time.h>
-
- #include "os2priv.h"
- #include "oaktag.h"
- #include "oaktime.h"
- #include "oakdir.h"
-
- /* mask to ignore bit not used in the masks for odir_Open */
- #define OFILE_MASK 0x07
-
- /* DOS path separator character */
- #define OFILE_SEPCHAR '\\'
-
- /* os/2 file type filter function */
- OSTATIC boolean typemask(byte type, byte mask);
-
- /* OS/2 dependent directory info here (what odir_type points to) */
- typedef struct _os2dir {
- boolean first;
- char path[OFILE_PATHLEN];
- FILEFINDBUF file_buf;
- HDIR hdir;
- USHORT srchcnt;
- byte file_type;
- } os2dir_struct;
- /* -------------------------------------------------------------------------- */
-
- odir_type os2dir_Open(char *user_spec, byte file_type)
- /*
- This routine opens an oakland directory stream and returns a handle to it.
- The handle is then used in calls to odir_Read, and odir_Close.
- If the stream cannot be opened for any reason NULL is returned.
-
- The first parameter is a string which should specify a path to the
- directory and a mask to use to filter the filenames in the directory.
- If the first paramater is specifies only a path (no file mask), the
- indicated directory is used and the filenames are not filtered. If the
- first paramater is NULL or "", the current directory is used and
- the filenames are not filtered.
-
- The second parameter is a mask which is used to filter the directory
- entries by type. Defined masks are:
- OFILE_ALL - does no type filtering. Everything available from
- the opering system.
- OFILE_DIRS - Returns subdirectories within the specified directory.
- OFILE_FILES - Returns files in the specified directory.
- The masks can be used alone or in combination with each other by bitwise
- or'ing the masks together. If OFILE_ALL is used in conjuction with other
- masks, it has the same effect as if used alone.
- */
- {
- os2dir_struct *odirp;
- char *internal_spec, dummy_name[OFILE_NAMELEN];
- USHORT os2type;
-
- /* specify os2type such that os/2 will filter file types for us */
- if (file_type & OFILE_ALL) {
- os2type = FILE_NORMAL | FILE_READONLY | FILE_HIDDEN
- | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
- }
- else if ((file_type & (OFILE_DIRS | OFILE_FILES)) == 0) {
-
- return(NULL);
- }
-
- os2type = 0;
- if (file_type & OFILE_DIRS) {
- os2type |= FILE_DIRECTORY;
- }
- if (file_type & OFILE_FILES) {
- os2type |= FILE_NORMAL | FILE_READONLY | FILE_SYSTEM | FILE_ARCHIVED;
- }
-
- /* allocate the odir struct */
- if ((odirp = (os2dir_struct *) omalloc(ID_ODIR, sizeof(os2dir_struct))) == NULL) {
- return (NULL);
- }
-
- /* adjust path to include a wildcard for filenames */
- if (user_spec == NULL || *user_spec == '\0') {
- if ((internal_spec = (char *) omalloc(OA_NOTAG, 4)) == NULL) {
- ofree(ID_ODIR, odirp);
- odirp = NULL;
- return(NULL);
- }
- strcpy(internal_spec, OFILE_WILDCARD);
- }
- else {
- if (user_spec[strlen(user_spec) - 1] == OFILE_SEPCHAR
- || user_spec[strlen(user_spec) - 1] == ':') {
- /* user_spec is just a path (no file mask) */
- if ((internal_spec = (char *) omalloc(OA_NOTAG, strlen(user_spec)
- + strlen(OFILE_WILDCARD) + 1)) == NULL) {
- ofree(ID_ODIR, odirp);
- odirp = NULL;
- return(NULL);
- }
- strcpy(internal_spec, user_spec);
- strcat(internal_spec, OFILE_WILDCARD);
- }
- else {
- if ((internal_spec = (char *) omalloc(OA_NOTAG, strlen(user_spec)))
- == NULL) {
- ofree(ID_ODIR, odirp);
- odirp = NULL;
- return(NULL);
- }
- strcpy(internal_spec, user_spec);
- }
- }
-
- odirp->srchcnt = 1;
- if (os2data->dosbox) {
- odirp->hdir = HDIR_SYSTEM;
- }
- else odirp->hdir = HDIR_CREATE;
-
- /* If no more matches */
- if (DosFindFirst(internal_spec, &odirp->hdir, os2type, &odirp->file_buf,
- sizeof(FILEFINDBUF), &odirp->srchcnt, 0L) != 0) {
-
- ofree(ID_ODIR, odirp);
- odirp = NULL;
- }
- ofree(OA_NOTAG, internal_spec);
-
- if (odirp == NULL) {
- return(NULL);
- }
- odirp->first = TRUE;
-
- /* pass requested attrs down so read can set ofile attrs correctly */
- odirp->file_type = file_type;
-
- /* pass the path down so it can be appended to the filenames when output */
- os2dir_Split(user_spec, odirp->path, sizeof(odirp->path), dummy_name, sizeof(dummy_name));
-
- return((odir_type) odirp);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_Read(odir_type odirpa, ofile_struct *file_info)
- /*
- This routine reads the next entry from an oakland directory stream.
- If an entry is found to return, odir_Read returns TRUE. If there
- are no more entries in the stream, it returns FALSE.
-
- The first parameter is the directory stream from which to fetch an entry.
-
- The second parameter is a pointer to an ofile_struct where the information
- about the entry will be stored. Once the information has been put into
- the ofile_struct, the following macros may be used to access it:
- ofile_GetType() - returns the type of the file: OFILE_ALL if it was
- specified in the call to odir_Open for this stream,
- OFILE_FILES for files, and OFILE_DIRS for dirs.
- ofile_GetTime() - returns an ansi struct tm with the date and time
- the file was last modified.
- ofile_GetSize() - returns the size of the file in bytes.
- ofile_GetSpec() - returns the spec for the file including a path
- starting where the spec given to odir_Open started.
- They each take a single parameter: the ofile_struct of the entry of
- interest. (Note: NOT a pointer to the ofile_struct)
- */
- {
- os2dir_struct *odirp;
- boolean foundone;
-
- odirp = (os2dir_struct *) odirpa;
-
- if (odirp == NULL) {
- return(FALSE);
- }
-
- if (odirp->first) { /* If first use the first buf full */
- odirp->first = FALSE;
- foundone = TRUE;
- }
- else { /* Otherwise get a new buf full */
- /* If no more matches */
- odirp->srchcnt = 1;
- if (DosFindNext(odirp->hdir, &odirp->file_buf, sizeof(FILEFINDBUF),
- &odirp->srchcnt) != 0) {
- foundone = FALSE;
- }
- else {
- foundone = TRUE;
- }
- }
-
- if (foundone) {
- /* Copy from OS/2 buf structure into OS-independent file_info structure */
-
- /* files attributes */
- if (odirp->file_type & OFILE_ALL) {
- file_info->type = OFILE_ALL;
- }
- else {
- switch (OFILE_MASK & odirp->file_type) {
- case OFILE_DIRS:
- case OFILE_FILES:
- file_info->type = odirp->file_type;
- break;
- case OFILE_DIRS | OFILE_FILES:
- if (odirp->file_buf.attrFile & FILE_DIRECTORY) {
- file_info->type = OFILE_DIRS;
- }
- else {
- file_info->type = OFILE_FILES;
- }
- break;
- }
- }
-
- /* time of last write */
- file_info->time.tm_hour = odirp->file_buf.ftimeLastWrite.hours;
- file_info->time.tm_min = odirp->file_buf.ftimeLastWrite.minutes;
- file_info->time.tm_sec = odirp->file_buf.ftimeLastWrite.twosecs * 2;
-
- /* date of last write */
- file_info->time.tm_year = odirp->file_buf.fdateLastWrite.year;
- file_info->time.tm_mon = odirp->file_buf.fdateLastWrite.month;
- file_info->time.tm_mday = odirp->file_buf.fdateLastWrite.day;
-
- /* calculate weekday, yearday, and dst values */
- tm_Adjust(&file_info->time);
-
- file_info->size = odirp->file_buf.cbFileAlloc; /* size of file */
-
- os2dir_Join(file_info->spec, sizeof(file_info->spec), odirp->path,
- odirp->file_buf.achName); /* name of file */
- os2dir_StripCase(file_info->spec);
- }
-
- return(foundone);
- }
- /* -------------------------------------------------------------------------- */
-
- void os2dir_Close(odir_type odirpa)
- /*
- This routine closes an oakland directory stream and frees all resources
- it used.
-
- It's single parameter is the hanlde to the stream to close.
- */
- {
- os2dir_struct *odirp;
-
- odirp = (os2dir_struct *) odirpa;
-
- if (odirp != NULL) {
- DosFindClose(odirp->hdir);
- ofree(ID_ODIR, odirp);
- }
- return;
- }
-
- /* -------------------------------------------------------------------------- */
-
- boolean os2file_IsValid(char *name, boolean wildok)
- /*
- determines if a filename is valid under the operating system.
- */
- {
- char goodchrs[13];
- int i, dots, dot = -1;
-
- if (wildok == TRUE) {
- strcpy(goodchrs, "@!-{}_`^~.*?");
- }
- else {
- strcpy(goodchrs, "@!-{}_`^~.");
- }
-
- for (dots = i = 0; name[i] != '\0'; i++) {
- if (!(name[i] > 64 && name[i] < 91) /* [a-z] */
- && !(name[i] > 96 && name[i] < 123) /* [A-Z] */
- && !(name[i] > 47 && name[i] < 58) /* [0-9] */
- && !(name[i] > 34 && name[i] < 42) /* [#$%&'()] */
- && !strchr(goodchrs, name[i])) {
-
- return(FALSE);
- }
-
- /* only one dot allowed and not in the first position */
- if (name[i] == '.') {
- if (++dots > 1 || i == 0) {
-
- return(FALSE);
- }
-
- dot = i;
- }
- }
-
- if (dot == -1) { /* there was no dot */
- if (i > 8) {
-
- return(FALSE);
- }
- }
- else if (i - dot > 4 || dot > 8) {
-
- return(FALSE);
- }
-
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_IsValid(char *dir)
- /*
- determines if a directory is valid under the operating system.
- */
- {
- char *s, *start;
- int i;
-
- /* empty string is valid (current dir) */
- if (*dir == '\0') {
- return(TRUE);
- }
-
- s = dir;
-
- /* drive */
- if (isalpha(*s) && *(s + 1) == ':') {
- s += 2;
- }
-
- /* main loop */
- while (*s != '\0') {
-
- /* slash */
- if (*s == OFILE_SEPCHAR) {
- s++;
-
- /* skip all adjacent slashs */
- while (*s == OFILE_SEPCHAR) {
- s++;
- }
- }
-
- /* directories */
- start = s;
-
- for (i = 0; *s != '\0' && *s != '.' && *s != OFILE_SEPCHAR; s++) {
-
- /* is this a legal directory char */
- if ((*s > 64 && *s < 91) /* [a-z] */
- || (*s > 96 && *s < 123) /* [A-Z] */
- || (*s > 47 && *s < 58) /* [0-9] */
- || (*s > 34 && *s < 42) /* [#$%&'()] */
- || strchr("@!-{}_`^~", *s)) {
-
- i++;
- if (i == 8) {
- /* skip till '.', OFILE_SEPCHAR or '\0' */
- for (s++; *s != '.' && *s != '\0' && *s != OFILE_SEPCHAR; s++)
- ;
- break;
- }
- }
- else {
- return(FALSE);
- }
- }
-
- /* now where at either a '.', OFILE_SEPCHAR or '\0' in the source string */
-
- /* dot */
- /* '..' = parent directory case */
- if (*s == '.' && *(s + 1) == '.'
- && (*(s + 2) == OFILE_SEPCHAR || *(s + 2) == '\0')) {
- s += 2;
- continue;
- }
-
- /* '.' = current directory case */
- if (*s == '.' && (*(s + 1) == OFILE_SEPCHAR || *(s + 1) == '\0')) {
- s++;
- continue;
- }
-
- if (*s == '.') {
-
- /* if the dot is the first char, this spec is invalid */
- if (s == start) {
- return(FALSE);
- }
- s++;
-
- /* dot not allowed in last position */
- if (*s == OFILE_SEPCHAR || *s == '\0') {
- return(FALSE);
- }
-
- /* extention */
- for (i = 0; *s != '\0' && *s != OFILE_SEPCHAR; s++) {
-
- /* is this a legal directory char */
- if ((*s > 64 && *s < 91) /* [a-z] */
- || (*s > 96 && *s < 123) /* [A-Z] */
- || (*s > 47 && *s < 58) /* [0-9] */
- || (*s > 34 && *s < 42) /* [#$%&'()] */
- || strchr("@!-{}_`^~", *s)) {
-
- i++;
- if (i > 3) {
- return(FALSE);
- }
- }
- else {
- return(FALSE);
- }
- }
- }
- }
-
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_MakePath(char *dirbuf, int buflen, char *dir)
- /*
- if the supplied string is not empty, we modify it to indicate a path
- */
- {
- int dirlen;
-
- if (*dir == '\0') {
- *dirbuf = '\0';
-
- return(TRUE);
- }
-
- dirlen = strlen(dir);
-
- if (dir[dirlen - 1] == OFILE_SEPCHAR) {
- if (buflen > dirlen) {
- if (dirbuf != dir) {
- strcpy(dirbuf, dir);
- }
-
- return(TRUE);
- }
- }
- else {
- if (buflen > dirlen + 1) {
- if (dirbuf != dir) {
- strcpy(dirbuf, dir);
- }
- dirbuf[dirlen] = OFILE_SEPCHAR;
- dirbuf[dirlen + 1] = '\0';
-
- return(TRUE);
- }
- }
- return(FALSE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_Ascend(char *newpath, int maxnewpath, char *oldpath)
- /*
- This routine forms a string representing the path to the parent directory
- of the path represented by the given string. It does no checking with
- the directory system to verify either of the paths are valid; It simply
- minipulates the strings.
-
- The first parameter points to the location where the result string should
- be stored.
-
- The second parameter is the size of the available space pointer to by
- the first parameter.
-
- The third parameter is the supplied string representing the starting path.
- The path must end with the separator character for paths of the operating
- system and be null terminated. Under OS2 the is '\\'.
-
- It returns TRUE if successful, FALSE otherwise.
- */
- {
- int i; /* the new path length */
-
- os2dir_MakePath(newpath, maxnewpath, oldpath);
- i = strlen(newpath);
-
- /* can't ascend above root directory */
- if (i == 1 && newpath[0] == OFILE_SEPCHAR) {
-
- return(FALSE);
- }
-
- /* if there isn't a subdir availiable to chop, append "../" to ascend */
- if (i == 0 || (newpath[i - 2] == '.' && newpath[i - 3] == '.')) {
- if (i + 3 <= maxnewpath) {
-
- /* strcat "../" */
- newpath[i] = '.';
- newpath[i + 1] = '.';
- newpath[i + 2] = OFILE_SEPCHAR;
- newpath[i + 3] = '\0';
-
- return(TRUE);
- }
- return(FALSE);
- }
-
- /* chop last subdir */
- for (i -= 2; newpath[i] != OFILE_SEPCHAR && newpath[i] != ':' && i > 0; i--)
- ;
- if (newpath[i] == OFILE_SEPCHAR || newpath[i] == ':') {
- newpath[i + 1] = '\0';
- }
- else {
- *newpath = '\0';
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_Descend(char *newpath, int maxnewpath, char *oldpath, char *subdir)
- /*
- This routine forms a string representing the path to a child directory
- of the path represented by the given string. It does no checking with
- the directory system to verify either of the paths are valid; It simply
- minipulates the strings.
-
- The first parameter points to the location where the result string should
- be stored.
-
- The second parameter is the size of the available space pointer to by
- the first parameter.
-
- The third parameter is the supplied string representing the starting path.
- The path must end with the separator character for paths of the operating
- system and be null terminated. Under Dos the is '\\'.
-
- The fourth parameter is a string indicating into which subdirectory
- to descend
-
- It returns TRUE if successful, FALSE otherwise.
- */
- {
- int oldpathlen, subdirlen;
-
- oldpathlen = strlen(oldpath);
- subdirlen = strlen(subdir);
-
- if (oldpathlen + subdirlen < maxnewpath) {
- if (newpath != oldpath) {
- strcpy(newpath, oldpath);
- }
- newpath += oldpathlen;
- strcpy(newpath, subdir);
- newpath += subdirlen;
- if (*(newpath - 1) != OFILE_SEPCHAR) {
- *newpath = OFILE_SEPCHAR;
- newpath++;
- }
- *newpath = '\0';
- return(TRUE);
- }
- return(FALSE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_Split(char *spec, char *path, int maxpath, char *name, int maxname)
- /*
- This routine separates a string representing a file spec into a string
- representing the path of the spec and a string representing the filename
- of the spec. If supplied with only a filename, it sets the path to "".
- If supplied with only a path (terminated with the operating systems path
- separator character), it sets the filename to "". If supplied with "", it
- sets both the path and name to "". It does no checking with the directory
- system to verify either the path or the filename is valid; It simply
- manipulates the strings.
-
- The first parameter is the supplied file spec.
-
- The second parameter points to the location where the result path
- string should be stored, it can be NULL if the path is to be ignored.
-
- The third parameter is the size of the available space pointed to by
- the second parameter. If the second parameter is NULL, the value of
- this parameter is ignored.
-
- The fourth parameter points to the location where the result filename
- string should be stored, it can be NULL if the name is to be ignored.
-
- The fifth parameter is the size of the available space pointed to by
- the fourth parameter. If the fourth parameter is NULL, the value of
- this parameter is ignored.
-
-
- It returns TRUE if successful, FALSE otherwise.
- */
- {
- int pathlen, namelen, i, last = -1, colon = -1;
-
- if (spec == NULL) {
- return(FALSE);
- }
-
- for (i = 0; spec[i] != '\0'; i++) {
- if (spec[i] == OFILE_SEPCHAR) {
- last = i;
- }
- else if (spec[i] == ':') {
- colon = i;
- }
- }
-
- if (last != -1) { /* path and name provided */
- pathlen = last + 1;
- namelen = strlen(spec + last + 1);
-
- if (path != NULL) {
- if (pathlen < maxpath) {
- strncpy(path, spec, pathlen);
- path[pathlen] = '\0';
- }
- else {
- return(FALSE);
- }
- }
- if (name != NULL) {
- if (namelen < maxname) {
- strcpy(name, spec + last + 1);
- }
- else {
- return(FALSE);
- }
- }
- }
- else { /* only name provided */
- if (colon == -1) {
- if (path != NULL) {
- *path = '\0';
- }
- if (name != NULL) {
- if ((int)strlen(spec) < maxname) {
- strcpy(name, spec);
- }
- else {
- return(FALSE);
- }
- }
- }
- else { /* there is a colon but no slash's */
- pathlen = colon + 1;
- namelen = strlen(spec + colon + 1);
-
- if (path != NULL) {
- if (pathlen < maxpath) {
- strncpy(path, spec, pathlen);
- path[pathlen] = '\0';
- }
- else {
- return(FALSE);
- }
- }
- if (name != NULL) {
- if (namelen < maxname) {
- strcpy(name, spec + colon + 1);
- }
- else {
- return(FALSE);
- }
- }
- }
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_Join(char *spec, int maxspec, char *path, char *name)
- /*
- This routine connects a string representing the path of a spec and
- a string representing the filename of a spec to form a string representing
- a complete file spec. It does no checking with the directory system to
- verify either of the paths or the filename are valid;
- It simply minipulates the strings. The first and third parameters or
- the first and fourth parameters are allowed to point to the same space
- since they may all be paths.
-
- The first parameter points to the location where the result spec
- string should be stored.
-
- The second parameter is the size of the available space pointer to by
- the first parameter.
-
- The third parameter is the supplied path.
-
- The fourth parameter is the supplied filename.
-
- It returns TRUE if successful, FALSE otherwise.
- */
- {
- int pathlen, namelen;
- char strbuf[OFILE_PATHLEN];
-
- pathlen = strlen(path);
- namelen = strlen(name);
-
- if (pathlen + namelen < maxspec) {
- strcpy(strbuf, path);
- strcat(strbuf, name);
- strcpy(spec, strbuf);
- return(TRUE);
- }
- else {
- return(FALSE);
- }
- }
- /* -------------------------------------------------------------------------- */
-
- char *os2dir_StripCase(char *str)
- /*
- This function converts all uppercase characters in the supplied string
- into lowercase.
- */
- {
- for (; *str != '\0'; str++) {
- *str = (char)otolower(*str);
- }
- return(str);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean os2dir_GetCurrDir(char *buf, int len)
- {
- ULONG dmap;
- USHORT dnum, buflen;
-
- DosQCurDisk(&dnum, &dmap);
- buflen = len;
-
- if (DosQCurDir(dnum, buf + 1, &buflen) == 0) {
- *buf = OFILE_SEPCHAR;
-
- return(TRUE);
- }
- return(FALSE);
- }
-