home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / i / iv26_w_2.zip / EXAMPLES / ICLASS / DIRECTOR.C < prev    next >
C/C++ Source or Header  |  1992-03-10  |  8KB  |  313 lines

  1. /*
  2.  * Copyright (c) 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Directory object implementation.
  25.  */
  26.  
  27. //#include <os/auth.h>
  28. //#include <os/fs.h>
  29. #include <string.h>
  30.  
  31. /* #include <sys/param.h> */
  32. #define MAXPATHLEN 128
  33.  
  34. #ifdef XD88
  35. #include <stdio.h>
  36. #include <sys/types.h>
  37. #endif
  38.  
  39. #include <sys/stat.h>
  40. #include <sys/types.h>
  41. #include <dir.h>
  42. #include <dos.h>
  43.  
  44. #include "director.h"
  45. #include "globals.h"
  46.  
  47. /*****************************************************************************/
  48.  
  49. Directory::Directory (const char* name) {
  50.     const int defaultSize = 256;
  51.  
  52.     strbufsize = defaultSize;
  53.     strbuf = new char*[strbufsize];
  54.     strcount = 0;
  55.     LoadDirectory(name);
  56. }
  57.  
  58. Directory::~Directory () {
  59.     Clear();
  60. }
  61.  
  62. const char* Directory::RealPath (const char* path) {
  63.     const char* realpath;
  64.  
  65.     if (*path == '\0') {
  66.         realpath = ".\\";
  67.     } else {
  68.         realpath = InterpTilde(InterpSlashSlash(path));
  69.     }
  70.     return realpath;
  71. }
  72.  
  73. boolean Directory::LoadDirectory (const char* name) {
  74.     char buf[MAXPATHLEN+2];
  75.  
  76.     strcpy(buf, ValidDirectories(RealPath(name)));
  77.     return Reset(buf);
  78. }
  79.  
  80. int Directory::Index (const char* name) {
  81.     for (int i = 0; i < strcount; ++i) {
  82.         if (strcmp(strbuf[i], name) == 0) {
  83.             return i;
  84.         }
  85.     }
  86.     return -1;
  87. }
  88.  
  89. boolean Directory::Reset (const char* path) {
  90.     char* p = new char[128];
  91.     ffblk fbl;
  92.  
  93.     strcpy(p, path);
  94.     if (p[strlen(p)] == '\\') {
  95.         strcat(p, "*.*");
  96.     } else {
  97.     strcat(p, "\\*.*");
  98.     }
  99.  
  100.     boolean successful = IsADirectory(path);
  101.  
  102.     if (successful) {
  103.         Clear();
  104.  
  105.     int done = findfirst(p, &fbl, FA_NORMAL);
  106.     while (!done) {
  107.         Insert(fbl.ff_name, Position(fbl.ff_name));
  108.         done = findnext(&fbl);
  109.     }
  110.     }
  111.     return successful;
  112. }
  113.  
  114. boolean Directory::IsADirectory (const char* path) {
  115.     struct stat filestats;
  116.     stat((char*)path, &filestats);
  117.     return filestats.st_mode & S_IFDIR;
  118. }
  119.  
  120. const char* Directory::Home (const char* name) {
  121.     char dir[MAXPATHLEN+1];
  122.     return getcwd(dir, MAXPATHLEN+1);
  123.  
  124. /*    struct passwd* pw =
  125.         (name == nil) ? getpwuid(getuid()) : getpwnam(name);
  126.     return (pw == nil) ? nil : pw->pw_dir;
  127. */
  128. }
  129.  
  130. inline boolean DotSlash (const char* path) {
  131.     return
  132.         path[0] != '\0' && path[0] == '.' &&
  133.         (path[1] == '\\' || path[1] == '\0');
  134. }
  135.  
  136. inline boolean DotDotSlash (const char* path) {
  137.     return
  138.         path[0] != '\0' && path[1] != '\0' &&
  139.         path[0] == '.' && path[1] == '.' &&
  140.         (path[2] == '\\' || path[2] == '\0');
  141. }
  142.  
  143. const char* Directory::Normalize (const char* path) {
  144.     static char newpath[MAXPATHLEN+1];
  145.     const char* buf;
  146.  
  147.     buf = InterpSlashSlash(path);
  148.     buf = ElimDot(buf);
  149.     buf = ElimDotDot(buf);
  150.     buf = InterpTilde(buf);
  151.  
  152.     strcpy(newpath, "\0");
  153.     if (*buf == '\0') {
  154. //        strcpy(newpath, ".\\");
  155.  
  156.     } else if (!DotSlash(buf) && !DotDotSlash(buf) && *buf != '\\') {
  157. //        strcpy(newpath, ".\\");
  158.         strcat(newpath, buf);
  159.  
  160.     } else {
  161.         strcpy(newpath, buf);
  162.     }
  163.  
  164.     if (IsADirectory(newpath) && newpath[strlen(newpath)-1] != '\\') {
  165.         strcat(newpath, "\\");
  166.     }
  167.     return newpath;
  168. }
  169.  
  170. const char* Directory::ValidDirectories (const char* path) {
  171.     static char buf[MAXPATHLEN+1];
  172.     strcpy(buf, path);
  173.     int i = strlen(path);
  174.  
  175.     while (!IsADirectory(RealPath(buf)) && i >= 0) {
  176.         for (--i; buf[i] != '\\' && i >= 0; --i);
  177.         buf[i+1] = '\0';
  178.     }
  179.     return buf;
  180. }
  181.  
  182. const char* Directory::InterpSlashSlash (const char* path) {
  183.     for (int i = strlen(path)-1; i > 0; --i) {
  184.         if (path[i] == '\\' && path[i-1] == '\\') {
  185.             return &path[i];
  186.         }
  187.     }
  188.     return path;
  189. }
  190.  
  191. const char* Directory::ElimDot (const char* path) {
  192.     static char newpath[MAXPATHLEN+1];
  193.     const char* src;
  194.     char* dest = newpath;
  195.  
  196.     for (src = path; src < &path[strlen(path)]; ++src) {
  197.         if (!DotSlash(src)) {
  198.             *dest++ = *src;
  199.  
  200.         } else if (*(dest-1) == '\\') {
  201.             ++src;
  202.  
  203.         } else {
  204.             *dest++ = *src;
  205.         }
  206.     }
  207.     *dest = '\0';
  208.     return newpath;
  209. }
  210.  
  211. static boolean CollapsedDotDotSlash (const char* path, const char*& start) {
  212.     if (path == start || *(start-1) != '\\') {
  213.         return false;
  214.  
  215.     } else if (path == start-1 && *path == '\\') {
  216.         return true;
  217.  
  218.     } else if (path == start-2) {               // NB: won't handle '//' right
  219.         start = path;
  220.         return *start != '.';
  221.  
  222.     } else if (path < start-2 && !DotDotSlash(start-3)) {
  223.         for (start -= 2; path <= start; --start) {
  224.             if (*start == '\\') {
  225.                 ++start;
  226.                 return true;
  227.             }
  228.         }
  229.         start = path;
  230.         return true;
  231.     }
  232.     return false;
  233. }
  234.  
  235. const char* Directory::ElimDotDot (const char* path) {
  236.     static char newpath[MAXPATHLEN+1];
  237.     const char* src;
  238.     char* dest = newpath;
  239.  
  240.     for (src = path; src < &path[strlen(path)]; ++src) {
  241.         if (DotDotSlash(src) && CollapsedDotDotSlash(newpath, (const char*)dest)) {
  242.             src += 2;
  243.         } else {
  244.             *dest++ = *src;
  245.         }
  246.     }
  247.     *dest = '\0';
  248.     return newpath;
  249. }
  250.  
  251. const char* Directory::InterpTilde (const char* path) {
  252.     static char realpath[MAXPATHLEN+1];
  253.     const char* beg = strrchr(path, '~');
  254.     boolean validTilde = beg != NULL && (beg == path || *(beg-1) == '\\');
  255.  
  256.     if (validTilde) {
  257.         const char* end = strchr(beg, '\\');
  258.         int length = (end == nil) ? strlen(beg) : end - beg;
  259.         const char* expandedTilde = ExpandTilde(beg, length);
  260.  
  261.         if (expandedTilde == nil) {
  262.             validTilde = false;
  263.         } else {
  264.             strcpy(realpath, expandedTilde);
  265.             if (end != nil) {
  266.                 strcat(realpath, end);
  267.             }
  268.         }
  269.     }
  270.     return validTilde ? realpath : path;
  271. }
  272.  
  273. const char* Directory::ExpandTilde (const char* tildeName, int length) {
  274.     const char* name = nil;
  275.  
  276.     if (length > 1) {
  277.         static char buf[MAXPATHLEN+1];
  278.         strncpy(buf, tildeName+1, length-1);
  279.         buf[length-1] = '\0';
  280.         name = buf;
  281.     }
  282.     return Home(name);
  283. }
  284.  
  285. void Directory::Insert (const char* s, int index) {
  286.     BufInsert(strdup(s), index, (const void**&) strbuf, strbufsize, strcount);
  287. }
  288.  
  289. void Directory::Remove (int index) {
  290.     if (0 <= index && index < strcount) {
  291.         delete strbuf[index];
  292.         BufRemove(index, (const void**) strbuf, strcount);
  293.     }
  294. }
  295.  
  296. void Directory::Clear () {
  297.     for (int i = 0; i < strcount; ++i) {
  298.         delete strbuf[i];
  299.     }
  300.     strcount = 0;
  301. }
  302.  
  303. int Directory::Position (const char* s) {
  304.     int i;
  305.  
  306.     for (i = 0; i < strcount; ++i) {
  307.         if (strcmp(s, strbuf[i]) < 0) {
  308.             return i;
  309.         }
  310.     }
  311.     return strcount;
  312. }
  313.