home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 182.lha / PathDev / support.c < prev   
C/C++ Source or Header  |  1988-10-22  |  12KB  |  501 lines

  1. #include "dos.h"
  2.  
  3. extern PORT    *DosPort;   /*  Our DOS port... this is slick...       */
  4. extern PROC    *DosProc;   /*    Our Process                      */
  5. extern DEVNODE  *DosNode;   /*    Our DOS node.. created by DOS for us      */
  6. extern DEVLIST  *DevList;   /*    Device List structure for our volume node */
  7. extern void    *SysBase;   /*    EXEC library base                  */
  8. extern DOSLIB    *DOSBase;   /*    DOS library base for debug process      */
  9. extern RAMFILE    RFRoot;     /*    Directory/File structure    (root node)   */
  10. extern LIST    FHBase;     /*    Open Files                  */
  11. extern LIST    LCBase;     /*    Open Locks                  */
  12. extern long    TotalBytes; /*    total bytes of data in filesystem      */
  13. extern RAMFILE    xpath;        /*  This is used in case of off device path   */
  14. extern char    *buf1;        /*  This holds the translated path names      */
  15.  
  16. RAMFILE * checkoutpath();
  17. RAMFILE * vsearchpath();
  18. void *DeviceProc();
  19.  
  20. /*
  21.  *  PACKET ROUTINES.    Dos Packets are in a rather strange format as you
  22.  *  can see by this and how the PACKET structure is extracted in the
  23.  *  GetMsg() of the main routine.
  24.  */
  25.  
  26. void
  27. returnpacket(packet)
  28. register struct DosPacket *packet;
  29. {
  30.     register struct Message *mess;
  31.     register struct MsgPort *replyport;
  32.  
  33.     replyport             = packet->dp_Port;
  34.     mess             = packet->dp_Link;
  35.     packet->dp_Port         = DosPort;
  36.     mess->mn_Node.ln_Name    = (char *)packet;
  37.     mess->mn_Node.ln_Succ    = NULL;
  38.     mess->mn_Node.ln_Pred    = NULL;
  39.     PutMsg(replyport, mess);
  40. }
  41.  
  42. /*
  43.  *  Are there any packets queued to our device?
  44.  */
  45.  
  46. packetsqueued()
  47. {
  48.     return ((void *)DosPort->mp_MsgList.lh_Head !=
  49.         (void *)DosPort->mp_MsgList.lh_Tail);
  50. }
  51.  
  52. /*
  53.  *  DOS MEMORY ROUTINES
  54.  *
  55.  *  DOS makes certain assumptions about LOCKS.    A lock must minimally be
  56.  *  a FileLock structure, with additional private information after the
  57.  *  FileLock structure.  The longword before the beginning of the structure
  58.  *  must contain the length of structure + 4.
  59.  *
  60.  *  NOTE!!!!! The workbench does not follow the rules and assumes it can
  61.  *  copy lock structures.  This means that if you want to be workbench
  62.  *  compatible, your lock structures must be EXACTLY sizeof(struct FileLock).
  63.  */
  64.  
  65. void *
  66. dosalloc(bytes)
  67. register ulong bytes;
  68. {
  69.     register ulong *ptr;
  70.  
  71.     bytes += 4;
  72.     ptr = AllocMem(bytes, MEMF_PUBLIC|MEMF_CLEAR);
  73.     *ptr = bytes;
  74.     return(ptr+1);
  75. }
  76.  
  77. dosfree(ptr)
  78. register ulong *ptr;
  79. {
  80.     --ptr;
  81.     FreeMem(ptr, *ptr);
  82. }
  83.  
  84. /*
  85.  *  Convert a BSTR into a normal string.. copying the string into buf.
  86.  *  I use normal strings for internal storage, and convert back and forth
  87.  *  when required.
  88.  */
  89.  
  90. void
  91. btos(bstr,buf)
  92. ubyte *bstr;
  93. ubyte *buf;
  94. {
  95.     bstr = BTOC(bstr);
  96.     bmov(bstr+1,buf,*bstr);
  97.     buf[*bstr] = 0;
  98. }
  99.  
  100. /*
  101.  *  Some EXEC list handling routines not found in the EXEC library.
  102.  */
  103.  
  104. void *
  105. NextNode(node)
  106. NODE *node;
  107. {
  108.     node = node->mln_Succ;
  109.     if (node->mln_Succ == NULL)
  110.     return(NULL);
  111.     return(node);
  112. }
  113.  
  114. void *
  115. GetHead(list)
  116. LIST *list;
  117. {
  118.     if ((void *)list->mlh_Head != (void *)&list->mlh_Tail)
  119.     return(list->mlh_Head);
  120.     return(NULL);
  121. }
  122.  
  123. /*
  124.  *  Compare two names which are at least n characters long each,
  125.  *  ignoring case.
  126.  */
  127.  
  128. nccmp(p1,p2,n)
  129. register ubyte *p1, *p2;
  130. register short n;
  131. {
  132.     while (--n >= 0) {
  133.     if ((p1[n]|0x20) != (p2[n]|0x20))
  134.         return(0);
  135.     }
  136.     return(1);
  137. }
  138.  
  139. /*
  140.  *  Create a file or directory and link it into it's parent directory.
  141.  */
  142.  
  143. RAMFILE *
  144. createramfile(parentdir, type, name)
  145. RAMFILE *parentdir;
  146. char *name;
  147. {
  148.     register RAMFILE *ramfile;
  149.  
  150.     ramfile = AllocMem(sizeof(RAMFILE), MEMF_CLEAR|MEMF_PUBLIC);
  151.     AddTail(&parentdir->list, ramfile);
  152.     ramfile->parent = parentdir;
  153.     ramfile->name = AllocMem(strlen(name)+1, MEMF_PUBLIC);
  154.     strcpy(ramfile->name, name);
  155.     ramfile->type = type;
  156.     ramfile->protection = 0;
  157.     NewList(&ramfile->list);
  158.     DateStamp(&ramfile->date);
  159.     DateStamp(&ramfile->parent->date);
  160.     return(ramfile);
  161. }
  162.  
  163. /*
  164.  *  Free all data associated with a file
  165.  */
  166.  
  167. void
  168. freedata(ramfile)
  169. RAMFILE *ramfile;
  170. {
  171.     FENTRY *fen;
  172.  
  173.     TotalBytes -= ramfile->bytes;
  174.     while (fen = RemHead(&ramfile->list)) {
  175. /*DB*/    dbprintf("FREE FEN: %08lx %08lx %ld\n", fen, fen->buf, fen->bytes);
  176.     FreeMem(fen->buf, fen->bytes);
  177.     FreeMem(fen, sizeof(*fen));
  178.     }
  179.     ramfile->bytes = 0;
  180.     DateStamp(&ramfile->date);
  181.     DateStamp(&ramfile->parent->date);
  182. }
  183.  
  184. /*
  185.  *  Unlink and remove a file.  Any data associated with the file or
  186.  *  directory has already been freed up.
  187.  */
  188.  
  189. void
  190. freeramfile(ramfile)
  191. RAMFILE *ramfile;
  192. {
  193.     Remove(ramfile);        /*  unlink from parent directory    */
  194.     if (ramfile->name)
  195.     FreeMem(ramfile->name,strlen(ramfile->name)+1);
  196.     if (ramfile->comment)
  197.     FreeMem(ramfile->comment,strlen(ramfile->comment)+1);
  198.     FreeMem(ramfile,sizeof(*ramfile));
  199. }
  200.  
  201. /*
  202.  *  The lock function.    The file has already been checked to see if it
  203.  *  is lockable given the mode.
  204.  */
  205.  
  206. LOCK *
  207. ramlock(ramfile, mode)
  208. RAMFILE *ramfile;
  209. {
  210.     LOCK *lock = dosalloc(sizeof(LOCK));
  211.     LOCKLINK *ln;
  212.  
  213.     if (mode != ACCESS_WRITE)
  214.     mode = ACCESS_READ;
  215.     ln = AllocMem(sizeof(LOCKLINK), MEMF_PUBLIC);
  216.     AddHead(&LCBase,ln);
  217.     ln->lock = lock;
  218.     lock->fl_Link= (long)ln;
  219.     lock->fl_Key = (long)ramfile;
  220.     lock->fl_Access = mode;
  221.     lock->fl_Task = DosPort;
  222.     lock->fl_Volume = (BPTR)CTOB(DosNode);
  223.     if (mode == ACCESS_READ)
  224.     ++ramfile->locks;
  225.     else
  226.     ramfile->locks = -1;
  227.     return(lock);
  228. }
  229.  
  230. void
  231. ramunlock(lock)
  232. LOCK *lock;
  233. {
  234.     RAMFILE *file = (RAMFILE *)lock->fl_Key;
  235.  
  236.     Remove(lock->fl_Link);            /* unlink from list */
  237.     FreeMem(lock->fl_Link, sizeof(LOCKLINK));    /* free link node   */
  238.     if (lock->fl_Access == ACCESS_READ)     /* undo lock effect */
  239.     --file->locks;
  240.     else
  241.     file->locks = 0;
  242.     dosfree(lock);                /* free lock        */
  243. }
  244.  
  245. /*
  246.  *  GETLOCKFILE(bptrlock)
  247.  *
  248.  *  Return the RAMFILE entry (file or directory) associated with the
  249.  *  given lock, which is passed as a BPTR.
  250.  *
  251.  *  According to the DOS spec, the only way a NULL lock will ever be
  252.  *  passed to you is if the DosNode->dn_Lock is NULL, but I'm not sure.
  253.  *  In anycase, If a NULL lock is passed to me I simply assume it means
  254.  *  the root directory of the RAM disk.
  255.  */
  256.  
  257. RAMFILE *
  258. getlockfile(lock)
  259. void *lock;        /*  actually BPTR to LOCK */
  260. {
  261.     register LOCK *rl = BTOC(lock);
  262.  
  263.     if (rl) return((RAMFILE *)rl->fl_Key);
  264.     return(&RFRoot);
  265. }
  266.  
  267. /*
  268.  *  Search the specified path beginning at the specified directory.
  269.  *  The directory pointer is updated to the directory containing the
  270.  *  actual file.  Return the file node or NULL if not found.  If the
  271.  *  path is illegal (an intermediate directory was not found), set *ppar
  272.  *  to NULL and return NULL.
  273.  *
  274.  *  *ppar may also be set to NULL if the search path IS the root.
  275.  *
  276.  *  If pptr not NULL, Set *pptr to the final component in the path.
  277.  */
  278.  
  279. char *rindex();
  280.  
  281. RAMFILE *
  282. searchpath(ppar,buf,pptr)
  283. RAMFILE **ppar;
  284. char *buf;
  285. char **pptr;
  286. {
  287.     RAMFILE *file = *ppar;
  288.     RAMFILE *srch;
  289.     short len;
  290.     char *ptr;
  291.  
  292.     ptr = rindex(buf,':');
  293.     if (ptr) buf = ptr+1;
  294.  
  295.     *ppar = NULL;
  296.     for (;*buf && file;) {
  297.     ptr = getpathelement(&buf,&len);
  298.     if (*ptr == '/') {          /*  go back a directory */
  299.         if (!file->parent) {    /*    no parent directory */
  300.         return(NULL);
  301.         }
  302.         file = file->parent;
  303.         continue;
  304.     }
  305.     if (file->type == FILE_FILE)
  306.         return(checkoutpath(file,ptr));
  307.     for (srch = GetHead(&file->list); srch; srch = NextNode(srch)) {
  308.         if (srch->type && strlen(srch->name) == len && nccmp(srch->name, ptr, len)) {
  309.         file = srch;        /*    element found        */
  310.         break;
  311.         }
  312.     }
  313.     if (srch == NULL) {
  314.         if (*buf == 0)    /*  Element not found.    If it was the final */
  315.         *ppar = file;    /*  element the parent directory is valid   */
  316.         if (pptr)
  317.         *pptr = ptr;
  318.         return(NULL);
  319.     }
  320.     }
  321.     if (pptr)
  322.     *pptr = ptr;
  323.     *ppar = file->parent;
  324.     return(file);
  325. }
  326.  
  327. RAMFILE *
  328. vsearchpath(ppar,buf,pptr)
  329. RAMFILE **ppar;
  330. char *buf;
  331. char **pptr;
  332. {
  333.     RAMFILE *file = *ppar;
  334.     RAMFILE *srch;
  335.     short len;
  336.     char *ptr;
  337.  
  338.     ptr = rindex(buf,':');    /* this fixes up the colon treatment */
  339.     if (ptr) buf = ptr+1;
  340.  
  341.     *ppar = NULL;
  342.     for (;*buf && file;) {
  343.     ptr = getpathelement(&buf,&len);
  344.     if (*ptr == '/') {          /*  go back a directory */
  345.         if (!file->parent) {    /*    no parent directory */
  346.         return(NULL);
  347.         }
  348.         file = file->parent;
  349.         continue;
  350.     }
  351.     if (file->type == FILE_FILE)
  352.         return(NULL);
  353.     for (srch = GetHead(&file->list); srch; srch = NextNode(srch)) {
  354.         if (srch->type && strlen(srch->name) == len && nccmp(srch->name, ptr, len)) {
  355.         file = srch;        /*    element found        */
  356.         break;
  357.         }
  358.     }
  359.     if (srch == NULL) {
  360.         if (*buf == 0)    /*  Element not found.    If it was the final */
  361.         *ppar = file;    /*  element the parent directory is valid   */
  362.         if (pptr)
  363.         *pptr = ptr;
  364.         return(NULL);
  365.     }
  366.     }
  367.     if (pptr)
  368.     *pptr = ptr;
  369.     *ppar = file->parent;
  370.     return(file);
  371. }
  372. typedef struct {
  373.     FENTRY *fentry;
  374.     long offset;
  375. } SFH;    /* simple file handle */
  376.  
  377. RAMFILE *
  378. checkoutpath(file,path)
  379. RAMFILE *file;
  380. char *path;
  381. {
  382.     SFH fh;
  383.     int lck;
  384.  
  385.     fh.fentry = GetHead(&file->list);
  386.     fh.offset = 0;
  387.     while (getnexttry(&fh,buf1)) {
  388.         strcat(buf1,path);
  389.         if (DeviceProc(buf1) == DosPort) {
  390.             /* refers to us.. ignore */
  391.             continue;
  392.         }
  393.         if (!index(buf1,':')) {
  394.             /* not an absolute path */
  395.             continue;
  396.         }
  397.         if (lck = Lock(buf1,ACCESS_READ)) {
  398.             UnLock(lck);
  399.             return(&xpath);
  400.         }
  401.     }
  402.     return(0);
  403. }
  404.  
  405. getnexttry(fh,buf)
  406. register SFH *fh;
  407. register char *buf;
  408. {
  409.     register int i;
  410.     register FENTRY *fe;
  411.  
  412.     fe = fh->fentry;
  413.     i  = fh->offset;
  414.  
  415.     for (fe = fh->fentry; fe ; fe = NextNode(fe)) {
  416.         for (; i<fe->bytes; i++) {
  417.             *buf = fe->buf[i];
  418.             if (*buf == '\n') {
  419.                 *buf = 0;
  420.                 fh->fentry = fe;
  421.                 fh->offset = ++i;
  422.                 return(1);
  423.             }
  424.             buf++;
  425.         }
  426.         i=0;
  427.     }
  428.     return(0);
  429. }
  430.  
  431.  
  432. /*
  433.  *  Return the next path element in the string.  The routine effectively
  434.  *  removes any trailing '/'s, but treats ':' as part of the next component
  435.  *  (i.e. ':' is checked and skipped in SEARCHPATH()).
  436.  */
  437.  
  438. char *
  439. getpathelement(pstr,plen)
  440. char **pstr;
  441. short *plen;
  442. {
  443.     char *base;
  444.     register char *ptr = *pstr;
  445.     register short len = 0;
  446.  
  447.     if (*(base = ptr)) {
  448.     if (*ptr == '/') {
  449.         ++ptr;
  450.         ++len;
  451.     } else {
  452.         while (*ptr && *ptr != '/') {
  453.         ++ptr;
  454.         ++len;
  455.         }
  456.         if (*ptr == '/')
  457.         ++ptr;
  458.     }
  459.     }
  460.     *pstr = ptr;
  461.     *plen = len;
  462.     return(base);
  463. }
  464.  
  465.  
  466. char *
  467. typetostr(ty)
  468. {
  469.     switch(ty) {
  470.     case ACTION_DIE:        return("DIE");
  471.     case ACTION_OPENRW:     return("OPEN-RW");
  472.     case ACTION_OPENOLD:    return("OPEN-OLD");
  473.     case ACTION_OPENNEW:    return("OPEN-NEW");
  474.     case ACTION_READ:        return("READ");
  475.     case ACTION_WRITE:        return("WRITE");
  476.     case ACTION_CLOSE:        return("CLOSE");
  477.     case ACTION_SEEK:        return("SEEK");
  478.     case ACTION_EXAMINE_NEXT:    return("EXAMINE NEXT");
  479.     case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
  480.     case ACTION_INFO:        return("INFO");
  481.     case ACTION_DISK_INFO:    return("DISK INFO");
  482.     case ACTION_PARENT:     return("PARENTDIR");
  483.     case ACTION_DELETE_OBJECT:    return("DELETE");
  484.     case ACTION_CREATE_DIR:    return("CREATEDIR");
  485.     case ACTION_LOCATE_OBJECT:    return("LOCK");
  486.     case ACTION_COPY_DIR:    return("DUPLOCK");
  487.     case ACTION_FREE_LOCK:    return("FREELOCK");
  488.     case ACTION_SET_PROTECT:    return("SETPROTECT");
  489.     case ACTION_SET_COMMENT:    return("SETCOMMENT");
  490.     case ACTION_RENAME_OBJECT:    return("RENAME");
  491.     case ACTION_INHIBIT:    return("INHIBIT");
  492.     case ACTION_RENAME_DISK:    return("RENAME DISK");
  493.     case ACTION_MORECACHE:    return("MORE CACHE");
  494.     case ACTION_WAIT_CHAR:    return("WAIT FOR CHAR");
  495.     case ACTION_FLUSH:        return("FLUSH");
  496.     case ACTION_RAWMODE:    return("RAWMODE");
  497.     default:            return("---------UNKNOWN-------");
  498.     }
  499. }
  500.  
  501.