home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / OSLib / Generic.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  13.7 KB  |  643 lines

  1.  
  2. /*
  3.  *    Operating system library generic utilities.
  4.  *
  5.  */
  6.  
  7. #include "OSLib.h"
  8.  
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #if __MWERKS__ && !__INTEL__
  13. #include <alloca.h>
  14. #else
  15. #include <malloc.h>
  16. #endif
  17. #include <ctype.h>
  18.  
  19. #include <stdlib.h>
  20. #include <assert.h>
  21.  
  22. char        STSbuf[OS_PATHSIZE];
  23.  
  24. /*    perform wildcard matching on a path; 
  25.     if path is non-NULL, start a search
  26.     else continue searching; 
  27.     return NULL if no match found           */
  28. static OSSpec wildmatch;
  29. static OSDirRef wilddirref;
  30. static char wilddir[OS_MAXPATHLEN];
  31. static char wildname[OS_MAXNAMELEN];
  32.  
  33. #if defined(OS_IS_CASE_INSENSITIVE)
  34. #define EQU(x,y) (tolower(x)==tolower(y))
  35. #else
  36. #define EQU(x,y) ((x)==(y))
  37. #endif
  38.  
  39. /*    Simple wildcard matcher.  Fails if '*' is not followed by a character or EOS. */
  40. static int
  41. WildCardMatch(const char *wild, const char *name)
  42. {
  43.     if (*name == 0)
  44.         return 0;
  45.  
  46.     while (*wild) {
  47.         if (*wild == '*') {
  48.             const char  next = *++wild;
  49.             const char *prev = NULL;
  50.  
  51.             while (*name) {
  52.                 if (EQU(*name, next))
  53.                     prev = name;
  54.                 name++;
  55.             }
  56.             if (prev != NULL)
  57.                 name = prev;
  58.             if (!EQU(*name, next))    /* allows matching next==0 */
  59.                 return 0;
  60.         } else if (*wild == '?' && *name) {
  61.             ++wild;
  62.             ++name;
  63.             if (!*wild && *name)
  64.                 return 0;
  65.         } else if (EQU(*wild, *name)) {
  66.             ++wild;
  67.             ++name;
  68.         } else
  69.             return 0;
  70.     }
  71.     return *name == 0 || (*name == OS_PATHSEP && *(name + 1) == 0);
  72. }
  73.  
  74. /*    This routine matches a patch with a wildcard at the end.
  75.     It fails if the wildcard is in the directory part.
  76.     Only matches files, not directories.
  77. */
  78. OSSpec     *
  79. OS_MatchPath(const char *path)
  80. {
  81.     OSError     err;
  82.     char        filename[OS_NAMESIZE];
  83.     bool        isfile;
  84.  
  85.     if (path != NULL) {
  86.         OSSpec      spec;
  87.         const char *nptr;
  88.  
  89.         /*  Note: this fails in WinNT if the wildcard
  90.            characters are present in path.  We need
  91.            to break the path at the wildcard and match
  92.            from there on.
  93.          */
  94.         nptr = strrchr(path, OS_PATHSEP);
  95.         if (nptr == NULL) {
  96.             nptr = path;
  97.             strcpyn(wilddir, OS_CWDSTR, -1, OS_PATHSIZE);
  98.         } else {
  99.             nptr++;
  100.             strcpyn(wilddir, path, nptr - path, OS_PATHSIZE);
  101.         }
  102.  
  103.         err = OS_MakePathSpec(NULL, wilddir, &spec.path);
  104.         if (err != OS_NOERR)
  105.             return NULL;
  106.  
  107.         strcpyn(wildname, nptr, -1, OS_NAMESIZE);
  108.         if ((err = OS_MakeNameSpec(wildname, &spec.name)) != OS_NOERR)
  109.             return NULL;
  110.  
  111.         if ((err = OS_OpenDir(&spec.path, &wilddirref)) != OS_NOERR)
  112.             return NULL;
  113.     }
  114.  
  115.     while ((err = OS_ReadDir(&wilddirref, &wildmatch, filename, &isfile)) ==
  116.            OS_NOERR) {
  117.         /*  This inherently matches only filenames. */
  118.         if (isfile && WildCardMatch(wildname, filename))
  119.             return &wildmatch;
  120.     }
  121.  
  122.     OS_CloseDir(&wilddirref);
  123.     return NULL;
  124. }
  125.  
  126. /*    Return pointer to filename part of path */
  127. const char *
  128. OS_GetFileNamePtr(const char *path)
  129. {
  130.     const char *ptr = strrchr(path, OS_PATHSEP);
  131.  
  132.     if (ptr == NULL)
  133.         ptr = path;
  134.     else
  135.         ptr++;
  136.  
  137.     return ptr;
  138. }
  139.  
  140. /*    make OSSpec from a path and filename */
  141. OSError
  142. OS_MakeSpec2(const char *path, const char *filename, OSSpec * spec)
  143. {
  144.     char        bpath[OS_PATHSIZE], *eptr;
  145.     int         pthlen, fnlen;
  146.  
  147.     if (path == NULL)
  148.         path = "";
  149.     if (filename == NULL)
  150.         filename = "";
  151.  
  152.     fnlen = strlen(filename);
  153.     pthlen = strlen(path);
  154.     if (fnlen + pthlen + 1 > OS_MAXPATHLEN)    // 1 for OS_PATHSEP
  155.         return OS_FNTLERR;
  156.  
  157.     strncpy(bpath, path, pthlen);
  158.  
  159.     eptr = bpath + pthlen;
  160.     if (*(eptr - 1) != OS_PATHSEP)
  161.         *eptr++ = OS_PATHSEP;
  162.  
  163.     strcpy(eptr, filename);
  164.  
  165.     return OS_MakeSpec(bpath, spec, NULL);
  166. }
  167.  
  168. /*    make OSSpec given an OSPathSpec (which may be NULL) and 
  169.     filename, relative path, or full path (which may be NULL);
  170.     if 'noRelative' and filename is relative, or if filename is a full path, 
  171.     ignore 'path'.
  172. */
  173. OSError
  174. OS_MakeSpecWithPath(const OSPathSpec * path, const char *filename, bool noRelative,
  175.                     OSSpec * spec)
  176. {
  177.     if (filename == NULL) {
  178.         if (path)
  179.             spec->path = *path;
  180.         else
  181.             OS_GetCWD(&spec->path);
  182.         return OS_MakeNameSpec("", &spec->name);
  183.     }
  184.         else
  185.         if ((!noRelative || strpbrk(filename, "/\\:") == NULL) &&
  186.             !OS_IsFullPath(filename)) {
  187.         char        buf[OS_PATHSIZE];
  188.         char       *mptr, *eptr;
  189.  
  190.         if (path)
  191.             OS_PathSpecToString2(path, buf);
  192.         else
  193.             *buf = 0;
  194.             
  195. #warning bugfix            
  196.         mptr = buf + OS_PATHSIZE - strlen(filename) - 1;
  197.  
  198.         eptr = buf + strlen(buf);
  199.         if (eptr > mptr)
  200.             strcpy(mptr, filename);
  201.         else
  202.             strcpy(eptr, filename);
  203.  
  204.         return OS_MakeSpec(buf, spec, NULL);
  205.     } else
  206.         return OS_MakeSpec(filename, spec, NULL);
  207. }
  208.  
  209. /*    change extension of a name */
  210. OSError
  211. OS_NameSpecChangeExtension(OSNameSpec * spec, char *ext, bool append)
  212. {
  213.     char        tmp[OS_NAMESIZE];
  214.     char       *per;
  215.  
  216.     OS_NameSpecToString2(spec, tmp);
  217.     if (!append) {
  218.         per = strrchr(tmp, '.');
  219.         if (per == NULL)
  220.             per = tmp + strlen(tmp);
  221.     } else
  222.         per = tmp + strlen(tmp);
  223.  
  224.     if (strlen(tmp) + strlen(ext) > OS_NAMESIZE)
  225.         per = tmp + OS_NAMESIZE - strlen(ext) - 1;
  226.  
  227.     strcpy(per, ext);
  228.     return OS_MakeNameSpec(tmp, spec);
  229. }
  230.  
  231. /*    set the extension of a name; if ext begins with '.', append the extension, else replace it */
  232. OSError
  233. OS_NameSpecSetExtension(OSNameSpec * spec, char *ext)
  234. {
  235.     char        tmp[OS_NAMESIZE];
  236.     char       *per;
  237.  
  238.     OS_NameSpecToString2(spec, tmp);
  239.     if (*ext != '.') {
  240.         per = strrchr(tmp, '.');
  241.         if (per == NULL)
  242.             per = tmp + strlen(tmp);
  243.  
  244.         if (*ext)                // allow deleting extension
  245.             if (strlen(tmp) + 1 >= OS_NAMESIZE)
  246.                 *(per - 1) = '.';
  247.             else
  248.                 *per++ = '.';
  249.     } else {
  250.         per = tmp + strlen(tmp);
  251.     }
  252.  
  253.     if (strlen(tmp) + strlen(ext) > OS_NAMESIZE)
  254.         per = tmp + OS_NAMESIZE - strlen(ext) - 1;
  255.  
  256.     strcpy(per, ext);
  257.     return OS_MakeNameSpec(tmp, spec);
  258. }
  259.  
  260. /*    This silly routine shortens an overlong concatenation by
  261.     inserting "..." in the middle of the string. 
  262. */
  263. char       *
  264. OS_CompactPaths(char *buf, const char *p, const char *n, int size)
  265. {
  266.     int         plen = p ? strlen(p) : 0;
  267.     int         nlen = n ? strlen(n) : 0;
  268.  
  269.     if (plen + nlen + 1 <= size) {
  270.         sprintf(buf, "%s%s", p ? p : "", n ? n : "");
  271.         return buf;
  272.     } else {
  273.         char       *ptr = buf;
  274.         int         bidx = 0;
  275.         int         pnidx = 0;
  276.         int         diff = (plen + nlen) - (size);
  277.  
  278.         while (plen > 0 && nlen > 0) {
  279.             if (plen > 0) {
  280.                 *ptr++ = *p++;
  281.                 plen--;
  282.             } else if (nlen > 0) {
  283.                 *ptr++ = *n++;
  284.                 nlen--;
  285.             }
  286.  
  287.             bidx++;
  288.             if (bidx == size / 2 - 2) {
  289.                 *ptr++ = '.';
  290.                 *ptr++ = '.';
  291.                 *ptr++ = '.';
  292.                 bidx += 3;
  293.  
  294.                 if (plen > 0) {
  295.                     plen -= diff / 2;
  296.                     if (plen < 0) {
  297.                         n -= plen;
  298.                         nlen += plen;
  299.                         plen = 0;
  300.                     }
  301.                 } else {
  302.                     n += diff / 2;
  303.                     nlen -= diff / 2;
  304.                 }
  305.             }
  306.         }
  307.         *ptr = 0;
  308.         return buf;
  309.     }
  310. }
  311.  
  312. char       *
  313. OS_SpecToStringRelative(const OSSpec * spec, const OSPathSpec * cwdspec,
  314.                         char *path, int size)
  315. {
  316.     char        fullbuf[OS_PATHSIZE], *full = fullbuf;
  317.     char        cwdbuf[OS_PATHSIZE], *cwd = cwdbuf;
  318.     OSPathSpec  mycwdspec;
  319.  
  320.     OS_SpecToString(spec, fullbuf, OS_PATHSIZE);
  321.  
  322.     if (size == 0)
  323.         size = OS_PATHSIZE;
  324.     if (path == NULL && (path = (char *) malloc(size)) == NULL)
  325.         return NULL;
  326.  
  327.     if (cwdspec == NULL) {
  328.         OS_GetCWD(&mycwdspec);
  329.         cwdspec = &mycwdspec;
  330.     }
  331.  
  332.     if (OS_PathSpecToString(cwdspec, cwdbuf, OS_PATHSIZE) == NULL) {
  333.         memcpy(path, fullbuf, size - 1);
  334.         path[size - 1] = 0;
  335.         return path;
  336.     }
  337.  
  338.     /*  find longest common prefix of full and cwd  */
  339.     while (*cwd && EQU(*full, *cwd)) {
  340.         full++;
  341.         cwd++;
  342.     }
  343.  
  344.     /*  if prefix is less than a third the length of the fullpath, abort */
  345.     if (cwd - cwdbuf < strlen(fullbuf) / 2 &&
  346.         strlen(cwd) > strlen(fullbuf) / 2) {
  347.         memcpy(path, fullbuf, size - 1);
  348.         path[size - 1] = 0;
  349.         return path;
  350.     }
  351.  
  352.     /*  backtrack, if necessary, up to previous OS_PATHSEP
  353.        [don't match foo with fool]
  354.      */
  355. #if !defined(OS_REL_PATH_HAS_SEP)
  356.     while (cwd > cwdbuf) {
  357.         full--;
  358.         cwd--;
  359.         if (*cwd == OS_PATHSEP)
  360.             break;
  361.     }
  362. #else
  363.     while (cwd > cwdbuf) {
  364.         if (*(cwd - 1) == OS_PATHSEP)
  365.             break;
  366.         full--;
  367.         cwd--;
  368.     }
  369. #endif
  370.  
  371.     /*  complete mismatch --> out  */
  372.     if (cwd == cwdbuf) {
  373.         strncpy(path, full, size - 1);
  374.         path[size - 1] = 0;
  375.     } else {
  376. #if !defined(OS_REL_PATH_HAS_SEP)
  377.         /*  skip OS_PATHSEP (relative dirs don't have 'em)  */
  378.         cwd++;
  379.         full++;
  380. #endif
  381.  
  382.         /*  if cwd has more than full, need OS_PDSTR's and the rest of full... */
  383.         if (*cwd) {
  384.             char       *pptr = path;
  385.  
  386.             while (*cwd) {
  387. #if defined(OS_REL_PATH_HAS_SEP)
  388.                 cwd++;
  389.                 if (*cwd == OS_PATHSEP)
  390.                     pptr += sprintf(pptr, OS_PDSTR);
  391. #else
  392.                 if (*cwd == OS_PATHSEP)
  393.                     pptr += sprintf(pptr, OS_PDSTR);
  394.                 cwd++;
  395. #endif
  396.             }
  397.             strcpy(pptr, full);
  398.         }
  399.         /*  if cwd has less, then use the part of full that doesn't match  */
  400.         else {
  401.             strncpy(path, full, size - 1);
  402.             path[size - 1] = 0;
  403.         }
  404.     }
  405.  
  406.     return path;
  407. }
  408.  
  409. /*    Search for a file in a list; if not found, returns error and
  410.     creates OSSpec in first directory in plist. */
  411. OSError
  412. OS_FindFileInPath(const char *filename, const char *plist, OSSpec * spec)
  413. {
  414.     const char *next;
  415.     char        path[OS_PATHSIZE];
  416.     OSError     err;
  417.     OSSpec      first;
  418.     bool        madefirst = false;
  419.  
  420.     while (plist && *plist) {
  421.         next = strchr(plist, OS_ENVSEP);
  422.         if (next == NULL)
  423.             next = strpbrk(plist, OS_ENVSEPLIST);
  424.         if (next == NULL)
  425.             next = plist + strlen(plist);
  426.  
  427.         strcpyn(path, plist, next - plist, OS_MAXPATHLEN);
  428.  
  429. //      printf("searching '%s' for '%s'\n",path,filename);
  430.         if ((err = OS_MakeSpec2(path, filename, spec)) == OS_NOERR) {
  431.             err = OS_FIDERR;
  432.             if (*filename && (err = OS_Status(spec)) == OS_NOERR)
  433.                 return OS_NOERR;
  434.             if (!madefirst) {
  435. //                printf("%s\n", OS_SpecToString1(spec));
  436.                 first = *spec;    // use this if all else fails
  437.                 madefirst = true;
  438.             }
  439.         }
  440.  
  441.         plist = (*next) ? next + 1 : NULL;
  442.     }
  443.  
  444.     if (madefirst)
  445.         *spec = first;
  446.  
  447.     return err;
  448. }
  449.  
  450. /*    Search for a place to create file in a list; 
  451.     if not possible, returns error */
  452. OSError
  453. OS_CreateFileInPath(const char *filename, const char *plist, 
  454.                     OSSpec * spec, OSFileType *type)
  455. {
  456.     const char *next;
  457.     char        path[OS_PATHSIZE];
  458.     OSError     err;
  459.  
  460.     while (plist && *plist) {
  461.         next = strchr(plist, OS_ENVSEP);
  462.         if (next == NULL)
  463.             next = strpbrk(plist, OS_ENVSEPLIST);
  464.         if (next == NULL)
  465.             next = plist + strlen(plist);
  466.  
  467.         strcpyn(path, plist, next - plist, OS_MAXPATHLEN);
  468.  
  469.         if ((err = OS_MakeSpec2(path, filename, spec)) == OS_NOERR) {
  470.             if ((err = OS_Create(spec, type)) == OS_NOERR)
  471.                 return OS_NOERR;
  472.         }
  473.  
  474.         plist = (*next) ? next + 1 : NULL;
  475.     }
  476.  
  477.     return err;
  478. }
  479.  
  480. /*    Search for an executable using the OS standards;
  481.     if relative path or not found, make spec in CWD  */
  482.  
  483. //#define SRCH_DEBUG 1
  484. OSError
  485. OS_FindProgram(const char *filename, OSSpec * spec)
  486. {
  487.     char       *plist;
  488.     OSError     err;
  489.     char        temp[OS_PATHSIZE];
  490.  
  491.     strncpy(temp, filename, OS_PATHSIZE);
  492.     temp[OS_PATHSIZE - 1] = 0;
  493. #if defined(WIN32_FS)
  494.     if (strlen(temp) < 4 || strcasecmp(temp + strlen(temp) - 4, ".exe") != 0)
  495.         strcatn(temp, ".exe", OS_PATHSIZE);
  496. #endif
  497.  
  498. #if SRCH_DEBUG
  499.     printf("Searching for '%s'\n", temp);
  500. #endif
  501.  
  502.     if (strchr(temp, OS_PATHSEP) == NULL) {
  503.         /*  Windows wants us to search its directories first.
  504.          */
  505.  
  506. #if defined(WIN32_FS)
  507.         {
  508.             char        path[OS_PATHSIZE];
  509.             int         len;
  510.  
  511.             extern      __declspec(dllimport) __stdcall int
  512.                         GetSystemDirectoryA(char *path, int size);
  513.             extern      __declspec(dllimport) __stdcall int
  514.                         GetWindowsDirectoryA(char *path, int size);
  515.  
  516.             len = GetSystemDirectoryA(path, OS_PATHSIZE);
  517.             if (len != 0) {
  518. #if SRCH_DEBUG
  519.                 printf("Searching Windows system directory '%s' for '%s'\n",
  520.                        path, temp);
  521. #endif
  522.                 if ((err = OS_MakeSpec2(path, temp, spec)) == OS_NOERR) {
  523.                     err = OS_Status(spec);
  524.                     if (err != OS_NOERR) {
  525. #if SRCH_DEBUG
  526.                         printf("Not found at '%s', error '%s'\n",
  527.                                OS_SpecToString1(spec), OS_GetErrText(err));
  528. #endif
  529.                     } else {
  530. #if SRCH_DEBUG
  531.                         printf("Found '%s' at '%s'\n", temp,
  532.                                OS_SpecToString1(spec));
  533. #endif
  534.                         return err;
  535.                     }
  536.                 }
  537.             }
  538.  
  539.             len = GetWindowsDirectoryA(path, OS_PATHSIZE);
  540.             if (len != 0) {
  541. #if SRCH_DEBUG
  542.                 printf("Searching Windows directory '%s' for '%s'\n", path,
  543.                        temp);
  544. #endif
  545.                 if ((err = OS_MakeSpec2(path, temp, spec)) == OS_NOERR) {
  546.                     err = OS_Status(spec);
  547.                     if (err != OS_NOERR) {
  548. #if SRCH_DEBUG
  549.                         printf("Not found at '%s', error '%s'\n",
  550.                                OS_SpecToString1(spec), OS_GetErrText(err));
  551. #endif
  552.                     } else {
  553. #if SRCH_DEBUG
  554.                         printf("Found '%s' at '%s'\n", temp,
  555.                                OS_SpecToString1(spec));
  556. #endif
  557.                         return err;
  558.                     }
  559.                 }
  560.             }
  561.         }
  562. #endif
  563.  
  564. #if defined(POSIX_FS) || defined(WIN32_FS)
  565.         plist = getenv("PATH");
  566. #elif defined(MAC_FS)
  567.         plist = getenv("Commands");
  568. #else
  569. #error
  570. #endif
  571.  
  572. #if SRCH_DEBUG
  573.         printf("Searching path '%s' for '%s'\n", plist, temp);
  574. #endif
  575.         err = OS_FindFileInPath(temp, plist, spec);
  576.         if (err == OS_NOERR) {
  577. #if SRCH_DEBUG
  578.             printf("Found '%s' at '%s'\n", temp, OS_SpecToString1(spec));
  579. #endif
  580.             return OS_NOERR;
  581.         }
  582.     }
  583.  
  584.     /*  Default to CWD  */
  585. #if SRCH_DEBUG
  586.     printf("Using '%s'\n", temp);
  587. #endif
  588.  
  589.     if ((err = OS_MakeFileSpec(temp, spec)) == OS_NOERR)
  590.         err = OS_Status(spec);
  591. #if SRCH_DEBUG
  592.     if (err != OS_NOERR) {
  593.         printf("Not found at '%s', error '%s'\n", temp, OS_GetErrText(err));
  594.     }
  595. #endif
  596.     return err;
  597. }
  598.  
  599.  
  600. /****************************************/
  601.  
  602. /*    Handle routines.  */
  603.  
  604. /*    Copy a handle. */
  605. OSError
  606. OS_CopyHandle(OSHandle * hand, OSHandle * copy)
  607. {
  608.     OSError     err;
  609.     OSSize      sz;
  610.     void       *f, *t;
  611.  
  612.     if ((err = OS_GetHandleSize(hand, &sz)) == OS_NOERR &&
  613.         (err = OS_NewHandle(sz, copy)) == OS_NOERR) {
  614.         f = OS_LockHandle(hand);
  615.         t = OS_LockHandle(copy);
  616.         memcpy(t, f, sz);
  617.         OS_UnlockHandle(hand);
  618.         OS_UnlockHandle(copy);
  619.         return OS_NOERR;
  620.     } else {
  621.         OS_FreeHandle(copy);
  622.         return err;
  623.     }
  624. }
  625.  
  626. /*    Append data to a handle. */
  627. OSError
  628. OS_AppendHandle(OSHandle * hand, void *data, OSSize len)
  629. {
  630.     OSError     err;
  631.     OSSize      sz;
  632.     void       *buffer;
  633.  
  634.     if ((err = OS_GetHandleSize(hand, &sz)) == OS_NOERR &&
  635.         (err = OS_ResizeHandle(hand, sz + len)) == OS_NOERR &&
  636.         (buffer = OS_LockHandle(hand)) != NULL) {
  637.         memcpy((char *) buffer + sz, data, len);
  638.         OS_UnlockHandle(hand);
  639.         return OS_NOERR;
  640.     } else
  641.         return err;
  642. }
  643.