home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / compress / xfh132.lzh / XFH / src / xobj.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  11KB  |  398 lines

  1. /* xobj.c - 'wrapper' calls for directing requests through to
  2.    the underlying file system. 
  3.    Copyright (C) 1991, 1992, 1993 Kristian Nielsen.
  4.  
  5.    This file is part of XFH, the compressing file system handler.
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */
  20.  
  21. /* $Log:    xobj.c,v $
  22.  * Revision 1.2  93/01/14  15:29:49  Kristian
  23.  * Added RCS keywords.
  24.  * 
  25.  */
  26.  
  27. #include "CFS.h"
  28.  
  29. #include <dossupport.h>
  30.  
  31. LONG XObjClose( glb glob, struct CFSFH *fh ){
  32.   LONG res;
  33.   
  34.   if(!(res=xClose(glob, fh->xfh))){
  35.     return res;  /* Dare not free the file handle. */
  36.   }
  37.   fh->xfh = NULL;
  38.   
  39.   /* Check whether we need to compress the file (signified by a non-NULL
  40.    * fh->filename field). */
  41.   if(fh->filename){
  42.     debug(("Attempting to compress file '%s'...",fh->filename));
  43.     res=TransformFile(glob,fh->parent->xlock,fh->filename,PackFile2File,NULL);
  44.     debug(("result: %ld (ioerr=%ld).\n",res,glob->ioerr));
  45.     /* Even if the compressing fails, we still have the file intact. */
  46.   }
  47.   XObjFreeFH(glob, fh);
  48.   return DOSTRUE;
  49. }
  50.  
  51.  
  52. LONG XObjRead( glb glob, struct CFSFH *fh, UBYTE *buf, LONG len ){
  53.    return xRead( glob, fh->xfh, buf, len );
  54. }
  55.  
  56.  
  57. LONG XObjWrite( glb glob, struct CFSFH *fh, UBYTE *buf, LONG len ){
  58.    return xWrite( glob, fh->xfh, buf, len );
  59. }
  60.  
  61.  
  62. LONG XObjSeek( glb glob, struct CFSFH *fh, LONG pos, LONG offset ){
  63.    return xSeek( glob, fh->xfh, pos, offset );
  64. }
  65.  
  66.  
  67. /* Allocate and partly initialise a struct CFSFH (should ONLY be called
  68.  * from XObjCreateFH()!).
  69.  */
  70. static struct CFSFH *XObjAllocFH(glb glob, struct FileHandle *xfh, LONG mode){
  71.    struct CFSFH *newfh;
  72.  
  73.    if( !dalloc(newfh) ){
  74.       debug(("Error: XObjAllocFH(): No memory for file handle.\n"));
  75.       OUTOFMEM;
  76.       return NULL;
  77.    }
  78.  
  79.    newfh->objtype = XOBJECT;
  80.    newfh->mode = mode;
  81.    newfh->xfh = xfh;
  82.    newfh->f = &Xfunc;
  83.    /* Other fields are NULL by default. */
  84.    return newfh;
  85. }
  86.  
  87.  
  88. /* This function is needed to convert from XpkFH to CFSFH in Xpk_Write(). */
  89. void XObjStealXpkFH(glb glob, struct CFSFH *fh){
  90.   fh->objtype = XOBJECT;
  91.   fh->f = &Xfunc;
  92. }  
  93.  
  94.  
  95. /* Stuff the filename / parentdir thingies into a CFSFH file handle. Must
  96.  * be 'undone' with XObjUnStuffFH().
  97.  */
  98. BOOL XObjStuffFH(glb glob, struct CFSFH *fh, char *name,
  99.          struct CFSLock *parent){
  100.  
  101.   debug(("Setting up fields in fh for autocompressing at Close().\n"));
  102.   if(!(fh->filename = copystr(name))){
  103.     debug(("Error: XObjStuffFH(): No memory for file name.\n"));
  104.     OUTOFMEM;
  105.     return FALSE;
  106.   }
  107.   if(!(fh->parent = CFSDupLock(glob, parent))){
  108.     /* Couldn't DupLock() it, so just hold a reference. */
  109.     debug(("XObjStuffFH(): Couldn't DupLock() parent, adding reference.\n"));
  110.     XObjAddReferenceToLock(glob, parent);
  111.     fh->parent = parent;
  112.     /* NOTE: We now have a dangerous double reference to the
  113.      * lock. Notably, the lock will be CFSUnLock()'ed two
  114.      * times.
  115.      */
  116.   }
  117.   return TRUE;
  118. }
  119.  
  120.  
  121. void XObjUnStuffFH(glb glob, struct CFSFH *fh){
  122.   if(fh->filename){
  123.     freestr(fh->filename);
  124.     CFSUnLock(glob, fh->parent);
  125.     fh->filename = NULL;
  126.     fh->parent = NULL;
  127.   }
  128. }
  129.   
  130.  
  131. /* Free CFSFH allocated with XObjCreateFH() (will not close the file handle).*/
  132. void XObjFreeFH(glb glob, struct CFSFH *fh){
  133.   XObjUnStuffFH(glob, fh);
  134.   dfree(fh);
  135. }
  136.  
  137.  
  138. /* Create a file handle to an xObj file. If 'name' is non-NULL,
  139.  * and autocompression is ON, will prepare filehandle for autocompression
  140.  * at Close() time (assuming 'parent' to be a lock on the parentdir of
  141.  * the file).
  142.  */
  143. struct CFSFH *XObjCreateFH(glb glob, struct FileHandle *xfh, LONG mode,
  144.                                  char *name,struct CFSLock *parent){
  145.   struct CFSFH *newfh;
  146.  
  147.   if( !( newfh = XObjAllocFH(glob, xfh, mode) ) ){
  148.     return NULL;
  149.   }
  150.  
  151.   /* Prepare for compressing the file at Close() time if needed. */
  152.   if(glob->autocompress && name){
  153.     if(!XObjStuffFH(glob, newfh, name, parent)){
  154.       SAVEIOERR;
  155.       XObjFreeFH(glob, newfh);
  156.       RESTIOERR;
  157.       return NULL;
  158.     }
  159.   }
  160.   return newfh;
  161. }
  162.  
  163.  
  164. /* Wraps a CFSLock around an xLock. */
  165. struct CFSLock *XObjMakeLock( glb glob, struct FileLock *xlock, LONG mode ){
  166.    struct CFSLock *newlock;
  167.  
  168.    if( !dalloc(newlock) ){
  169.       OUTOFMEM;
  170.       return NULL;
  171.    }
  172. debug(("XObjMakeLock(): xlock=%lx, procid=%lx.\n",xlock,xlock->fl_Task));
  173.    newlock->objtype = XOBJECT;
  174.    newlock->mode = mode;
  175.    newlock->xlock = xlock;
  176.    newlock->f = &Xfunc;
  177.    newlock->refcount = 0;
  178.    return newlock;
  179. }
  180.  
  181. struct CFSLock *XObjDupLock( glb glob, struct CFSLock *lock ){
  182.    struct CFSLock *newlock;
  183.  
  184.    /* XOBJECT locks have their xLocks xDupLock'ed, and the rest of
  185.     * the fields are just copied vanilla.
  186.     * Special case for the refcount; it must be set to 0 in the new lock.
  187.     */
  188.    if( !dalloc(newlock) ){
  189.       OUTOFMEM;
  190.       return 0L;
  191.    }
  192.    *newlock = *lock;
  193.    newlock->refcount = 0;   /* IMPORTANT!!! */
  194.    if( !(newlock->xlock = xDupLock(glob, lock->xlock)) ){
  195.       dfree(newlock);
  196.       return 0L;
  197.    }
  198.    return newlock;   
  199. }
  200.  
  201. /* This nasty function adds a reference to a CFSLock. FOR EACH CALL TO
  202.  * THIS FUNCTION THERE MUST BE A CORRESPONDING CALL TO XObjUnLock(), as
  203.  * well as a final one to match the original XObjLock(), XObjDupLock() or
  204.  * whatever.
  205.  */
  206. void XObjAddReferenceToLock(glb glob, struct CFSLock *lock){
  207.    lock->refcount++;
  208. }
  209.  
  210.  
  211. struct CFSLock *XObjParentDir( glb glob, struct CFSLock *lock ){
  212.     struct FileLock *xlock;
  213.     struct CFSLock *newlock;
  214.     
  215.     if( xSameLock(glob, glob->xrootlock, lock->xlock) == LOCK_SAME ){
  216.         debug(("- ParentDir() of root lock. -"));
  217.         glob->ioerr = 0L;
  218.         return NULL;
  219.     }
  220.     if( !(xlock = xParentDir(glob, lock->xlock)) ){
  221.         return 0L;
  222.     }
  223.     newlock = XObjMakeLock( glob, xlock, ACCESS_READ );
  224.     if( !newlock ){
  225.         LONG saveioerr = glob->ioerr;
  226.         xUnLock(glob, xlock);
  227.         glob->ioerr = saveioerr;
  228.     }
  229.     return newlock;
  230. }
  231.  
  232.  
  233. BOOL XObjUnLock( glb glob, struct CFSLock *lock ){
  234.     BOOL err;
  235.  
  236.    /* Have to check if there are outstanding references to the lock. */
  237.    if(lock->refcount){
  238.       debug(("XObjUnLock: Just decrementing the refcount (%ld).\n",lock->refcount));
  239.       lock->refcount--;
  240.       return DOSTRUE;
  241.    }
  242.    
  243.     err = xUnLock(glob, lock->xlock);
  244.       
  245.     /* Now, what if the UnLock fails? I guess it's best to return FALSE
  246.      * and let the lock live.
  247.      */
  248.     if(!err) return DOSFALSE;
  249.     dfree(lock);
  250.     return DOSTRUE;
  251. }
  252.  
  253.  
  254. BOOL XObjSameLock(glb glob, struct CFSLock *l1, struct CFSLock *l2 ){
  255.     return xSameLock( glob, l1->xlock, l2->xlock ) == LOCK_SAME;
  256. }
  257.  
  258.  
  259. BOOL XObjExamine( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib ){
  260.    BOOL err, fix=FALSE;
  261.    
  262.    if(xSameLock(glob, glob->xrootlock, lock->xlock) == LOCK_SAME) fix=TRUE;
  263.    err = xExamine(glob, lock->xlock, fib);
  264.    debug(("XObjExamine(): %ld,'%s'\n",err,fib->fib_FileName));
  265.    
  266.    /* Check if Examine()'ing the root dir (if so, fix name). */
  267.    if(fix){
  268.       /* ARRGHH! Nasty BCPL stuff around... */
  269.       bstr2c(glob->volnode->dl_Name, &fib->fib_FileName[0]);
  270.       debug(("XObjExamine(): Changing name in FIB to '%s'.\n",
  271.                                                  &fib->fib_FileName[0]));
  272.    }
  273.    return err;
  274. }
  275.  
  276. BOOL XObjExNext( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib ){
  277.    BOOL err, err2;
  278.    
  279.    err = xExamineNext(glob, lock->xlock, fib);
  280.    debug(("CFSExamineNext(): %ld,'%s'\n",err,fib->fib_FileName));
  281.    if( !err ) return err;
  282.    err2 = ModifyFIB( glob, lock, fib );
  283.    if(!glob->FailOnExNext){
  284.       /* The error return from ModifyFIB is discarded. This way, a directory
  285.        * scan won't fail in flaky programs that don't test IOERR for
  286.        * ERROR_NO_MORE_ENTRIES.
  287.        */
  288.    }else{
  289.       err = err2;
  290.    }
  291.    return err;
  292. }
  293.  
  294.  
  295. BOOL ModifyFIB( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib ){
  296.    LONG saveioerr;
  297.    
  298.    if( fib->fib_DirEntryType < 0 ){
  299.       LONG filetype;
  300.       struct FileHandle *xfh;
  301.       BOOL err;
  302.       
  303.       /* A plain file. This needs a closer look.*/
  304.       xfh = xOpen( glob, lock->xlock, fib->fib_FileName, MODE_OLDFILE );
  305.       if( !xfh ){
  306.          debug(("Error: ModifyFIB(): Couldn't open file: %ld\n",glob->ioerr));
  307.          return DOSFALSE;
  308.       }
  309.       filetype = xFileType( glob, xfh );
  310.       err = ModifyFIB_type( glob, filetype, lock, fib, xfh );
  311.       if( !err ) saveioerr = glob->ioerr;
  312.       xClose(glob, xfh);
  313.       if( !err ) glob->ioerr = saveioerr;
  314.       return err;
  315.    }else{
  316.       /* Do nothing for a directory.*/
  317.       return DOSTRUE;
  318.    }
  319. }
  320.  
  321. /* XObjModifyFIB() is just a NO-OP.*/
  322. BOOL XObjModifyFIB( glb glob, struct CFSLock *lock,struct FileInfoBlock *fib, struct FileHandle *xfh ){
  323.    return DOSTRUE;
  324. }
  325.  
  326.  
  327. struct CFSLock *XObjCreateDir( glb glob, struct CFSLock *parentlock, char *name ){
  328.    struct CFSLock *newlock;
  329.    struct FileLock *xlock;
  330.    
  331.    if( !(xlock = xCreateDir(glob, parentlock->xlock, name)) ){
  332.       return 0L;
  333.    }
  334.    newlock = XObjMakeLock( glob, xlock, xlock->fl_Access );
  335.    if( !newlock ){
  336.       LONG saveioerr = glob->ioerr;
  337.  
  338.       /* Oh No! We're left with a dangling directory...
  339.        * Try to remove it before returning.
  340.        */
  341.       debug(("XObjCreateDir(): Trying to delete dangling directory..."));
  342.       xUnLock(glob, xlock);
  343.       if( CFSDeleteFile( glob, parentlock, name ) )
  344.          debug(("Succes!\n"));
  345.       else
  346.          debug(("Failure...\n"));
  347.       glob->ioerr = saveioerr;
  348.    }
  349.    return newlock;
  350. }
  351.  
  352.  
  353. BOOL XObjSetProtection(glb glob, struct CFSLock *parent, char *name, LONG mask){
  354.    BOOL err;
  355.    
  356.    err = xSetProtection(glob, parent->xlock, name, mask);
  357.    return err;
  358. }
  359.  
  360. BOOL XObjSetComment(glb glob, struct CFSLock *parent, char *name, char *comment){
  361.    BOOL err;
  362.    
  363.    err = xSetComment(glob, parent->xlock, name, comment);
  364.    return err;
  365. }
  366.  
  367. BOOL XObjSetFileDate(glb glob, struct CFSLock *parent, char *name, struct DateStamp *ds){
  368.    BOOL err;
  369.    
  370.    err = xSetFileDate(glob, parent->xlock, name, ds);
  371.    return err;
  372. }
  373.  
  374.  
  375. BOOL XObjDeleteFile(glb glob, struct CFSLock *parent, char *name){
  376.    BOOL err;
  377.    
  378.    err = xDeleteFile(glob, parent->xlock, name);
  379.    return err;
  380. }
  381.  
  382.  
  383. BOOL XObjRename(glb glob, struct CFSLock *p1, char *n1, struct CFSLock *p2, char *n2){
  384.    BOOL err;
  385.    
  386.    if(p2->objtype != XOBJECT){
  387.       debug(("XObjRename(): Error: rename to lock of type %ld\n",p2->objtype));
  388.       glob->ioerr = ERROR_RENAME_ACROSS_DEVICES;
  389.       return DOSFALSE;
  390.    }else{
  391.       err = xRename(glob, p1->xlock, n1, p2->xlock, n2);
  392.       return err;
  393.    }
  394. }
  395.  
  396.  
  397. /* End of xobj.c */
  398.