diff options
| -rw-r--r-- | command_line/CmdLine/Src/OSLib/Generic.c | 20 | ||||
| -rw-r--r-- | command_line/CmdLine/Src/OSLib/MacSpecs.c | 367 | ||||
| -rw-r--r-- | command_line/CmdLine/Src/OSLib/Posix.c | 36 | ||||
| -rw-r--r-- | includes/oslib.h | 2 | 
4 files changed, 396 insertions, 29 deletions
| diff --git a/command_line/CmdLine/Src/OSLib/Generic.c b/command_line/CmdLine/Src/OSLib/Generic.c index a4e9fed..f2c2ac9 100644 --- a/command_line/CmdLine/Src/OSLib/Generic.c +++ b/command_line/CmdLine/Src/OSLib/Generic.c @@ -48,7 +48,7 @@ int WildCardMatch(char *wild, char *name) {          }      } -    return !name[0] || (name[0] == '/' && !name[1]); +    return !name[0] || (name[0] == OS_PATHSEP && !name[1]);  }  OSSpec *OS_MatchPath(const char *path) { @@ -58,7 +58,7 @@ OSSpec *OS_MatchPath(const char *path) {      const char *nptr;      if (path) { -        nptr = strrchr(path, '/'); +        nptr = strrchr(path, OS_PATHSEP);          if (!nptr) {              nptr = path;              strcpyn(wilddir, ".", -1, 256); @@ -89,7 +89,7 @@ OSSpec *OS_MatchPath(const char *path) {  char *OS_GetFileNamePtr(char *path) {      char *ptr; -    ptr = strrchr(path, '/'); +    ptr = strrchr(path, OS_PATHSEP);      return !ptr ? path : (ptr + 1);  } @@ -102,12 +102,12 @@ char *OS_GetDirName(const OSPathSpec *spec, char *buf, int size) {      path = OS_PathSpecToString(spec, STSbuf, 256);      pptr = path + strlen(path) - 1; -    if (pptr > path && *pptr == '/') { +    if (pptr > path && *pptr == OS_PATHSEP) {          *pptr = 0;          --pptr;      } -    while (pptr >= path && *pptr != '/') +    while (pptr >= path && *pptr != OS_PATHSEP)          pptr--;      strncpy(buf, pptr, size - 1); @@ -133,8 +133,8 @@ int OS_MakeSpec2(const char *path, const char *filename, OSSpec *spec) {      strncpy(bpath, path, pthlen);      eptr = bpath + pthlen; -    if (eptr[-1] != '/') -        *(eptr++) = '/'; +    if (eptr[-1] != OS_PATHSEP) +        *(eptr++) = OS_PATHSEP;      strcpy(eptr, filename);      return OS_MakeSpec(bpath, spec, 0); @@ -323,7 +323,7 @@ char *OS_SpecToStringRelative(const OSSpec *spec, const OSPathSpec *cwdspec, cha      while (cwd > cwdbuf) {          cwd--;          full--; -        if (*cwd == '/') +        if (*cwd == OS_PATHSEP)              break;      } @@ -334,7 +334,7 @@ char *OS_SpecToStringRelative(const OSSpec *spec, const OSPathSpec *cwdspec, cha          if (*(++cwd)) {              pptr = path;              while (*cwd) { -                if (*cwd == '/') +                if (*cwd == OS_PATHSEP)                      pptr += sprintf(pptr, "../");                  ++cwd;              } @@ -390,7 +390,7 @@ int OS_FindProgram(const char *filename, OSSpec *spec) {      strncpy(temp, filename, 256);      temp[255] = 0; -    if (!strchr(temp, '/')) { +    if (!strchr(temp, OS_PATHSEP)) {          plist = getenv("PATH");          err = OS_FindFileInPath(temp, plist, spec);          if (!err) diff --git a/command_line/CmdLine/Src/OSLib/MacSpecs.c b/command_line/CmdLine/Src/OSLib/MacSpecs.c index 8648324..defcab1 100644 --- a/command_line/CmdLine/Src/OSLib/MacSpecs.c +++ b/command_line/CmdLine/Src/OSLib/MacSpecs.c @@ -1,25 +1,392 @@  #include "oslib.h" +#include <errno.h> + +extern char STSbuf[256]; + +#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0) + +typedef struct DirNode { +    char *name; +    unsigned int dirID; +    union { +        struct DirNode *parent; +        struct VolNode *volume; +    } p; +    struct DirNode *list; +    struct DirNode *next; +} DirNode; + +typedef struct VolNode { +    UInt16 vRefNum; +    DirNode root; +    struct VolNode *next; +} VolNode; + +static unsigned int lastDirID = 3; +static unsigned int lastVolRef = 2; +static char stname[256]; +static char stpath[256]; +static char stdir[256]; +static char stvol[8]; +static unsigned int dirMapRows; +static DirNode **dirIDMap[256]; +static VolNode *vols; + +static int AddDirMapEntry(DirNode *node) { +    unsigned int row; +    unsigned int col; + +    row = node->dirID >> 8; +    col = node->dirID & 0xFF; + +    while (row >= dirMapRows) { +        if (row >= 256) { +            fprintf(stderr, "Fatal error:  too many directories referenced, out of memory\n"); +            return 0; +        } + +        dirIDMap[row] = calloc(sizeof(DirNode *), 256); +        if (!dirIDMap[row]) +            return 0; + +        dirMapRows++; +    } + +    dirIDMap[row][col] = node; +    return 1; +} + +static VolNode *FindOrAddVolRef(VolNode **list, char *name) { +    int sz; +    VolNode *vn; + +    while (*list) { +        if (OS_EqualPath(name, (*list)->root.name)) +            return *list; +        list = &(*list)->next; +    } + +    if (lastVolRef >= 256) +        return 0; + +    vn = malloc(sizeof(VolNode)); +    if (!vn) +        return 0; + +    vn->next = 0; +    vn->vRefNum = lastVolRef++; + +    sz = strlen(name) + 1; +    vn->root.name = malloc(sz); +    if (!vn->root.name) +        return 0; + +    strcpy(vn->root.name, name); +    vn->root.dirID = 2; +    vn->root.p.volume = vn; +    vn->root.list = 0; +    vn->root.next = 0; +    *list = vn; +    return vn; +} + +static DirNode *FindDirMapEntry(unsigned int dirID) { +    unsigned int row; +    unsigned int col; + +    row = dirID >> 8; +    col = dirID & 0xFF; +#line 166 +    OPTION_ASSERT(dirID != 2); + +    if (row >= dirMapRows) +        return 0; +    else +        return dirIDMap[row][col]; +} + +static DirNode *FindOrAddDirRef(DirNode *parent, char *name) { +    int sz; +    DirNode *dn; +    DirNode **list; + +    list = &parent->list; +    while (*list) { +        if (OS_EqualPath(name, (*list)->name)) +            return *list; +        list = &(*list)->next; +    } + +    if (lastDirID >= 0x10000) +        return 0; + +    sz = strlen(name) + 1; + +    dn = malloc(sizeof(DirNode)); +    if (!dn) +        return 0; +    dn->name = malloc(sz); +    if (!dn->name) +        return 0; +    strcpy(dn->name, name); + +    dn->list = 0; +    dn->next = 0; +    dn->dirID = lastDirID++; + +    if (!AddDirMapEntry(dn)) +        return 0; + +    dn->p.parent = parent; +    *list = dn; +    return dn; +} + +static int FindOrAdd(const OSPathSpec *path, unsigned int *vRefNum, unsigned int *dirID) { +    VolNode *vol; +    DirNode *level; +    char pb[256]; +    char voln[8]; +    char pathbuf[256]; +    char *ptr; +    char *st; +    char ch; + +    if (!OS_PathSpecToString(path, pathbuf, 256)) +        return 0; +    if (!pathbuf[0]) +        return 0; + +    ptr = OS_GetDirPtr(pathbuf); +    strncpy(voln, pathbuf, ptr - pathbuf); +    voln[ptr - pathbuf] = 0; +    strcpy(pb, ptr); + +    vol = FindOrAddVolRef(&vols, voln); +    if (!vol) +        return 0; + +    *vRefNum = vol->vRefNum; +    level = &vol->root; +    ptr = &pb[1]; +#line 267 +    OPTION_ASSERT(*pb == OS_PATHSEP); + +    while (*ptr) { +        st = ptr; +        while ((ch = *ptr) && *ptr != OS_PATHSEP) { +            ++ptr; +        } + +        *ptr = 0; + +        level = FindOrAddDirRef(level, st); +        if (!ch) +            break; +        ++ptr; +        if (!level) +            return 0; +    } + +    *dirID = level->dirID; +    return 1; +} + +static void StepVolDir(unsigned int *vRefNum, unsigned int *dirID, DirNode **node) { +    VolNode *step; + +    if (*vRefNum == 1) { +        *node = 0; +        return; +    } + +    if (*dirID == 2) { +        step = vols; +        while (step && step->vRefNum != *vRefNum) +            step = step->next; +        if (step) { +            *node = &step->root; +            *vRefNum = 1; +            *dirID = 1; +        } else { +            *node = 0; +        } +    } else { +        *node = FindDirMapEntry(*dirID); +        if (*node) +            *dirID = (*node)->p.parent->dirID; +    } +} + +static int ResolvePath(const OSPathSpec *path, unsigned int *vRefNum, unsigned int *dirID) { +    if (FindOrAdd(path, vRefNum, dirID)) { +        *vRefNum = -*vRefNum; +        return 1; +    } else { +        *vRefNum = 0; +        *dirID = 0; +        return 0; +    } +} + +static int ResolveVolDir(unsigned int vRefNum, unsigned int dirID, char *vol, char *dir) { +    DirNode *nodes[256]; +    DirNode *cur; +    int idx; +    int len; +    char *dptr; + +    vRefNum = -vRefNum; +    idx = 0; +    do { +        StepVolDir(&vRefNum, &dirID, &cur); +        if (cur) +            nodes[idx++] = cur; +    } while (cur); + +    if (idx) { +        strcpy(vol, nodes[--idx]->name); +    } else { +        vol[0] = 0; +        dir[0] = 0; +        return 0; +    } + +    dptr = dir; +    *(dptr++) = OS_PATHSEP; +    while (idx--) { +        len = strlen(nodes[idx]->name); +        if ((dptr - dir) + len + 1 > 256) { +            *dptr = 0; +            return 0; +        } else { +            memcpy(dptr, nodes[idx]->name, len); +            dptr += len; +            *(dptr++) = OS_PATHSEP; +        } +    } + +    *dptr = 0; +    return 1; +}  int OS_OSPathSpec_To_VolDir(const OSPathSpec *spec, SInt16 *vRefNum, SInt32 *dirID) { +    unsigned int vol; +    unsigned int dir; +    if (ResolvePath(spec, &vol, &dir)) { +        *vRefNum = vol; +        *dirID = dir; +        return 0; +    } else { +        *vRefNum = 0; +        *dirID = 0; +        return ENOENT; +    }  }  int OS_OSSpec_To_FSSpec(const OSSpec *spec, FSSpec *fss) { +    int err; +    SInt16 vRefNum; +    SInt32 dirID; +    char *s; + +    err = OS_OSPathSpec_To_VolDir(&spec->path, &vRefNum, &dirID); +    fss->vRefNum = vRefNum; +    fss->parID = dirID; +    if (err) return err; + +    s = OS_NameSpecToString(&spec->name, STSbuf, sizeof(STSbuf)); +    if (!s || strlen(s) >= 256) +        return ENAMETOOLONG; +    c2pstrcpy(fss->name, s); +    return 0;  }  int OS_VolDir_To_OSNameSpec(SInt16 vRefNum, SInt32 dirID, OSNameSpec *spec, SInt32 *parID) { +    unsigned int cv; +    unsigned int cd; +    DirNode *node; +    cv = -vRefNum; +    cd = dirID; +    StepVolDir(&cv, &cd, &node); +    if (!node) +        return ENOENT; + +    *parID = cd; +    return OS_MakeNameSpec(node->name, spec);  }  int OS_VolDir_To_OSPathSpec(SInt16 vRefNum, SInt32 dirID, OSPathSpec *spec) { +    int err; +    int vlen; +    int dlen; + +    if (!vRefNum || !dirID) { +        err = OS_GetCWD(spec); +        if (err) +            return err; +    } else { +        if (!ResolveVolDir(vRefNum, dirID, stvol, stdir)) +            return ENOENT; +        vlen = strlen(stvol); +        dlen = strlen(stdir); +        if (vlen + dlen < 256) { +            memcpy(spec->s, stvol, vlen); +            memcpy(spec->s + vlen, stdir, dlen + 1); +        } +    } + +    return 0;  }  int OS_FSSpec_To_OSSpec(const FSSpec *fss, OSSpec *spec) { +    int err; + +    err = OS_VolDir_To_OSPathSpec(fss->vRefNum, fss->parID, &spec->path); +    if (err) +        return err; +    p2cstrcpy(stname, fss->name); +    err = OS_MakeNameSpec(stname, &spec->name); +    if (err) +        return err; + +    return err;  }  int OS_GetRsrcOSSpec(const OSSpec *spec, OSSpec *rspec, Boolean create) { +    char dbuffer[256]; +    int err; + +    OS_PathSpecToString(&spec->path, dbuffer, sizeof(dbuffer)); +    err = OS_MakeSpec2(dbuffer, "resource.frk", rspec); +    if (err) +        return err; + +    err = OS_Status(rspec); +    if (err) { +        if (create) { +            err = OS_Mkdir(rspec); +            if (err) +                return err; +            // Windows version has a call to SetFileAttributes here +        } else { +            return err; +        } +        err = OS_MakeSpec2(dbuffer, "resource.frk", rspec); +        if (err) +            return err; +    } else if (OS_IsFile(rspec)) { +        return ENOTDIR; +    } + +    err = OS_MakeNameSpec(OS_NameSpecToString(&spec->name, STSbuf, sizeof(STSbuf)), &rspec->name); +    if (err) +        return err; +    return 0;  } diff --git a/command_line/CmdLine/Src/OSLib/Posix.c b/command_line/CmdLine/Src/OSLib/Posix.c index e836653..dc22651 100644 --- a/command_line/CmdLine/Src/OSLib/Posix.c +++ b/command_line/CmdLine/Src/OSLib/Posix.c @@ -31,7 +31,7 @@ int _plen = strlen((spec)->s);          \  if (_plen >= sizeof(pathbuf)) return 63;\  memcpy((pathbuf), (spec)->s, _plen + 1);\  if (_plen > 1) {                        \ -if ((pathbuf)[_plen - 1] == '/')        \ +if ((pathbuf)[_plen - 1] == OS_PATHSEP) \  (pathbuf)[_plen - 1] = 0;               \  }                                       \  } while (0) @@ -260,7 +260,7 @@ int OS_GetCWD(OSPathSpec *spec) {          return errno;      ptr = &spec->s[strlen(spec->s)]; -    if (ptr[-1] != '/') +    if (ptr[-1] != OS_PATHSEP)          strcpy(ptr, "/");      return 0;  } @@ -332,15 +332,13 @@ int OS_IsLegalPath(const char *path) {      fnlen = 0;      while (*scan) { -        if (*scan == '/') +        if (*scan == OS_PATHSEP)              fnlen = 0;          else              fnlen++;          ++pthlen;          if (fnlen > 63 || pthlen > 255)              return ENAMETOOLONG; -        //if ((fnlen = (*scan == '/') ? 0 : (fnlen + 1)) > 63 || ++pthlen > 255) -        //    return ENAMETOOLONG;          ++scan;      } @@ -348,7 +346,7 @@ int OS_IsLegalPath(const char *path) {  }  int OS_IsFullPath(const char *path) { -    return path[0] == '/'; +    return path[0] == OS_PATHSEP;  }  char *OS_GetDirPtr(char *path) { @@ -375,7 +373,7 @@ static int OS_CompactPath(char *src, char *dst) {      to = bptr;      while (*from) {          brk = from + 1; -        while (*brk && *brk != '/') +        while (*brk && *brk != OS_PATHSEP)              ++brk;          if ((brk - from) == 1) { @@ -386,7 +384,7 @@ static int OS_CompactPath(char *src, char *dst) {              if (to > bptr) {                  do {                      to--; -                } while (to >= bptr && *to != '/'); +                } while (to >= bptr && *to != OS_PATHSEP);              }              from = brk;          } else { @@ -396,8 +394,8 @@ static int OS_CompactPath(char *src, char *dst) {          }      } -    if (to == bptr || from[-1] == '/') -        *(to++) = '/'; +    if (to == bptr || from[-1] == OS_PATHSEP) +        *(to++) = OS_PATHSEP;      *to = 0;      if (!dst) @@ -421,7 +419,7 @@ int OS_CanonPath(char *src, char *dst) {      for (idx = 0; src[idx]; idx++) {          if (src[idx] == '\\') -            dst[idx] = '/'; +            dst[idx] = OS_PATHSEP;          else              dst[idx] = src[idx];      } @@ -451,8 +449,8 @@ int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {              return errno;          ptr = tmp + strlen(tmp) - 1; -        if (ptr[0] != '/') { -            ptr[1] = '/'; +        if (ptr[0] != OS_PATHSEP) { +            ptr[1] = OS_PATHSEP;              ptr[2] = 0;              ptr += 2;          } @@ -475,12 +473,12 @@ int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {      if (!stat(tmp, &st)) {          ptr = tmp + strlen(tmp); -        if (ptr[-1] == '/') +        if (ptr[-1] == OS_PATHSEP)              ptr--;          if ((st.st_mode & S_IFMT) == S_IFDIR) {              if (isfile)                  *isfile = 0; -            ptr[0] = '/'; +            ptr[0] = OS_PATHSEP;              ptr++;          } else {              if (isfile) @@ -494,7 +492,7 @@ int OS_MakeSpec(const char *path, OSSpec *spec, Boolean *isfile) {              *isfile = 1;      } -    ptr = strrchr(tmp, '/') + 1; +    ptr = strrchr(tmp, OS_PATHSEP) + 1;      len = ptr - tmp;      if (len >= 256) {          spec->path.s[0] = 0; @@ -561,7 +559,7 @@ int OS_MakeNameSpec(const char *name, OSNameSpec *spec) {      spec->s[0] = 0;      if (len > 63)          return ENAMETOOLONG; -    if (strchr(name, '/')) +    if (strchr(name, OS_PATHSEP))          return EISDIR;      if (strlen(name) > 63)          return ENAMETOOLONG; @@ -694,7 +692,7 @@ int OS_IsLink(const OSSpec *spec) {          return 0;      ptr = intbuf + strlen(intbuf) - 1; -    if (*ptr == '/') +    if (*ptr == OS_PATHSEP)          *ptr = 0;      if (lstat(intbuf, &st) < 0) @@ -716,7 +714,7 @@ int OS_ResolveLink(const OSSpec *link, OSSpec *target) {          return errno;      fn[len] = 0; -    sprintf(path, "%s%s", (fn[0] != '/') ? link->path.s : "", fn); +    sprintf(path, "%s%s", (fn[0] != OS_PATHSEP) ? link->path.s : "", fn);      return OS_MakeSpec(path, target, 0);  } diff --git a/includes/oslib.h b/includes/oslib.h index fadc81f..bb841ac 100644 --- a/includes/oslib.h +++ b/includes/oslib.h @@ -1,6 +1,8 @@  #pragma once  #include "common.h" +#define OS_PATHSEP '/' +  /**   * OS abstraction layer   */ | 
