home *** CD-ROM | disk | FTP | other *** search
- /* xobj.c - 'wrapper' calls for directing requests through to
- the underlying file system.
- Copyright (C) 1991, 1992, 1993 Kristian Nielsen.
-
- This file is part of XFH, the compressing file system handler.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "CFS.h"
-
- #include <dossupport.h>
-
- LONG XObjClose( glb glob, struct CFSFH *fh ){
- LONG res;
-
- if(!(res=xClose(glob, fh->xfh))){
- return res; /* Dare not free the file handle. */
- }
- fh->xfh = NULL;
-
- /* Check whether we need to compress the file (signified by a non-NULL
- * fh->filename field). */
- if(fh->filename){
- debug(("Attempting to compress file '%s'...",fh->filename));
- #ifdef DEBUG
- res=TransformFile(glob,fh->parent->xlock,fh->filename,PackFile2File,NULL);
- debug(("result: %ld (ioerr=%ld).\n",res,glob->ioerr));
- #else
- (void)TransformFile(glob,fh->parent->xlock,fh->filename,PackFile2File,NULL);
- #endif
- /* Even if the compressing fails, we still have the file intact. */
- }
- XObjFreeFH(glob, fh);
- return DOSTRUE;
- }
-
-
- LONG XObjRead( glb glob, struct CFSFH *fh, UBYTE *buf, LONG len ){
- return xRead( glob, fh->xfh, buf, len );
- }
-
-
- LONG XObjWrite( glb glob, struct CFSFH *fh, UBYTE *buf, LONG len ){
- return xWrite( glob, fh->xfh, buf, len );
- }
-
-
- LONG XObjSeek( glb glob, struct CFSFH *fh, LONG pos, LONG offset ){
- return xSeek( glob, fh->xfh, pos, offset );
- }
-
-
- /* Allocate and partly initialise a struct CFSFH (should ONLY be called
- * from XObjCreateFH()!).
- */
- static struct CFSFH *XObjAllocFH(glb glob, struct FileHandle *xfh, LONG mode){
- struct CFSFH *newfh;
-
- if( !dalloc(newfh) ){
- debug(("Error: XObjAllocFH(): No memory for file handle.\n"));
- OUTOFMEM;
- return NULL;
- }
-
- newfh->objtype = XOBJECT;
- newfh->mode = mode;
- newfh->xfh = xfh;
- newfh->f = &Xfunc;
- /* Other fields are NULL by default. */
- return newfh;
- }
-
-
- /* This function is needed to convert from XpkFH to CFSFH in Xpk_Write(). */
- void XObjStealXpkFH(glb glob, struct CFSFH *fh){
- fh->objtype = XOBJECT;
- fh->f = &Xfunc;
- }
-
-
- /* Stuff the filename / parentdir thingies into a CFSFH file handle. Must
- * be 'undone' with XObjUnStuffFH().
- */
- BOOL XObjStuffFH(glb glob, struct CFSFH *fh, char *name,
- struct CFSLock *parent){
-
- debug(("Setting up fields in fh for autocompressing at Close().\n"));
- if(!(fh->filename = copystr(name))){
- debug(("Error: XObjStuffFH(): No memory for file name.\n"));
- OUTOFMEM;
- return FALSE;
- }
- if(!(fh->parent = CFSDupLock(glob, parent))){
- /* Couldn't DupLock() it, so just hold a reference. */
- debug(("XObjStuffFH(): Couldn't DupLock() parent, adding reference.\n"));
- XObjAddReferenceToLock(glob, parent);
- fh->parent = parent;
- /* NOTE: We now have a dangerous double reference to the
- * lock. Notably, the lock will be CFSUnLock()'ed two
- * times.
- */
- }
- return TRUE;
- }
-
-
- void XObjUnStuffFH(glb glob, struct CFSFH *fh){
- if(fh->filename){
- freestr(fh->filename);
- CFSUnLock(glob, fh->parent);
- fh->filename = NULL;
- fh->parent = NULL;
- }
- }
-
-
- /* Free CFSFH allocated with XObjCreateFH() (will not close the file handle).*/
- void XObjFreeFH(glb glob, struct CFSFH *fh){
- XObjUnStuffFH(glob, fh);
- dfree(fh);
- }
-
-
- /* Create a file handle to an xObj file. If 'name' is non-NULL,
- * and autocompression is ON, will prepare filehandle for autocompression
- * at Close() time (assuming 'parent' to be a lock on the parentdir of
- * the file).
- */
- struct CFSFH *XObjCreateFH(glb glob, struct FileHandle *xfh, LONG mode,
- char *name,struct CFSLock *parent){
- struct CFSFH *newfh;
-
- if( !( newfh = XObjAllocFH(glob, xfh, mode) ) ){
- return NULL;
- }
-
- /* Prepare for compressing the file at Close() time if needed. */
- if(glob->autocompress && name){
- if(!XObjStuffFH(glob, newfh, name, parent)){
- SAVEIOERR;
- XObjFreeFH(glob, newfh);
- RESTIOERR;
- return NULL;
- }
- }
- return newfh;
- }
-
-
- /* Wraps a CFSLock around an xLock. */
- struct CFSLock *XObjMakeLock( glb glob, struct FileLock *xlock, LONG mode ){
- struct CFSLock *newlock;
-
- if( !dalloc(newlock) ){
- OUTOFMEM;
- return NULL;
- }
- debug(("XObjMakeLock(): xlock=%lx, procid=%lx.\n",xlock,xlock->fl_Task));
- newlock->objtype = XOBJECT;
- newlock->mode = mode;
- newlock->xlock = xlock;
- newlock->f = &Xfunc;
- newlock->refcount = 0;
- return newlock;
- }
-
- struct CFSLock *XObjDupLock( glb glob, struct CFSLock *lock ){
- struct CFSLock *newlock;
-
- /* XOBJECT locks have their xLocks xDupLock'ed, and the rest of
- * the fields are just copied vanilla.
- * Special case for the refcount; it must be set to 0 in the new lock.
- */
- if( !dalloc(newlock) ){
- OUTOFMEM;
- return 0L;
- }
- *newlock = *lock;
- newlock->refcount = 0; /* IMPORTANT!!! */
- if( !(newlock->xlock = xDupLock(glob, lock->xlock)) ){
- dfree(newlock);
- return 0L;
- }
- return newlock;
- }
-
- /* This nasty function adds a reference to a CFSLock. FOR EACH CALL TO
- * THIS FUNCTION THERE MUST BE A CORRESPONDING CALL TO XObjUnLock(), as
- * well as a final one to match the original XObjLock(), XObjDupLock() or
- * whatever.
- */
- void XObjAddReferenceToLock(glb glob, struct CFSLock *lock){
- lock->refcount++;
- }
-
-
- struct CFSLock *XObjParentDir( glb glob, struct CFSLock *lock ){
- struct FileLock *xlock;
- struct CFSLock *newlock;
-
- if( xSameLock(glob, glob->xrootlock, lock->xlock) == LOCK_SAME ){
- debug(("- ParentDir() of root lock. -"));
- glob->ioerr = 0L;
- return NULL;
- }
- if( !(xlock = xParentDir(glob, lock->xlock)) ){
- return 0L;
- }
- newlock = XObjMakeLock( glob, xlock, ACCESS_READ );
- if( !newlock ){
- LONG saveioerr = glob->ioerr;
- xUnLock(glob, xlock);
- glob->ioerr = saveioerr;
- }
- return newlock;
- }
-
-
- struct CFSLock *XObjParentFH( glb glob, struct CFSFH *fh ){
- struct FileLock *xlock;
- struct CFSLock *newlock;
-
- if( !(xlock = xParentFH(glob, fh->xfh)) ){
- return 0L;
- }
- newlock = XObjMakeLock( glob, xlock, ACCESS_READ );
- if( !newlock ){
- LONG saveioerr = glob->ioerr;
- xUnLock(glob, xlock);
- glob->ioerr = saveioerr;
- }
- return newlock;
- }
-
-
- BOOL XObjUnLock( glb glob, struct CFSLock *lock ){
- BOOL err;
-
- /* Have to check if there are outstanding references to the lock. */
- if(lock->refcount){
- debug(("XObjUnLock: Just decrementing the refcount (%ld).\n",lock->refcount));
- lock->refcount--;
- return DOSTRUE;
- }
-
- err = xUnLock(glob, lock->xlock);
-
- /* Now, what if the UnLock fails? I guess it's best to return FALSE
- * and let the lock live.
- */
- if(!err) return DOSFALSE;
- dfree(lock);
- return DOSTRUE;
- }
-
-
- BOOL XObjSameLock(glb glob, struct CFSLock *l1, struct CFSLock *l2 ){
- return (BOOL) (xSameLock( glob, l1->xlock, l2->xlock ) == LOCK_SAME);
- }
-
-
- BOOL XObjExamine( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib ){
- BOOL err, fix=FALSE;
-
- if(xSameLock(glob, glob->xrootlock, lock->xlock) == LOCK_SAME) fix=TRUE;
- err = xExamine(glob, lock->xlock, fib);
- debug(("XObjExamine(): %ld,'%s'\n",err,fib->fib_FileName));
-
- /* Check if Examine()'ing the root dir (if so, fix name). */
- if(fix){
- /* ARRGHH! Nasty BCPL stuff around... */
- bstr2c(glob->volnode->dl_Name, &fib->fib_FileName[0]);
- debug(("XObjExamine(): Changing name in FIB to '%s'.\n",
- &fib->fib_FileName[0]));
- }
- return err;
- }
-
- BOOL XObjExNext( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib ){
- BOOL err, err2;
-
- err = xExamineNext(glob, lock->xlock, fib);
- debug(("CFSExamineNext(): %ld,'%s'\n",err,fib->fib_FileName));
- if( !err ) return err;
- err2 = ModifyFIB( glob, lock, fib );
- if(!glob->FailOnExNext){
- /* The error return from ModifyFIB is discarded. This way, a directory
- * scan won't fail in flaky programs that don't test IOERR for
- * ERROR_NO_MORE_ENTRIES.
- */
- }else{
- err = err2;
- }
- return err;
- }
-
-
- BOOL ModifyFIB( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib ){
- LONG saveioerr;
-
- if( fib->fib_DirEntryType < 0 ){
- LONG filetype;
- struct FileHandle *xfh;
- BOOL err;
-
- if ( XpkFastModifyFIB(fib) ) return DOSTRUE;
-
- /* A plain file. This needs a closer look.*/
- xfh = xOpen( glob, lock->xlock, fib->fib_FileName, MODE_OLDFILE );
- if( !xfh ){
- debug(("Error: ModifyFIB(): Couldn't open file: %ld\n",glob->ioerr));
- return DOSFALSE;
- }
- filetype = xFileType( glob, xfh );
- err = ModifyFIB_type( glob, filetype, lock, fib, xfh );
- if( !err ) saveioerr = glob->ioerr;
- xClose(glob, xfh);
- if( !err ) glob->ioerr = saveioerr;
- return err;
- }else{
- /* Do nothing for a directory.*/
- return DOSTRUE;
- }
- }
-
- /* XObjModifyFIB() is just a NO-OP.*/
- BOOL XObjModifyFIB( glb glob, struct CFSLock *lock,struct FileInfoBlock *fib, struct FileHandle *xfh ){
- return DOSTRUE;
- }
-
-
- struct CFSLock *XObjCreateDir( glb glob, struct CFSLock *parentlock, char *name ){
- struct CFSLock *newlock;
- struct FileLock *xlock;
-
- if( !(xlock = xCreateDir(glob, parentlock->xlock, name)) ){
- return 0L;
- }
- newlock = XObjMakeLock( glob, xlock, xlock->fl_Access );
- if( !newlock ){
- LONG saveioerr = glob->ioerr;
-
- /* Oh No! We're left with a dangling directory...
- * Try to remove it before returning.
- */
- debug(("XObjCreateDir(): Trying to delete dangling directory..."));
- xUnLock(glob, xlock);
- if( CFSDeleteFile( glob, parentlock, name ) )
- debug(("Succes!\n"));
- else
- debug(("Failure...\n"));
- glob->ioerr = saveioerr;
- }
- return newlock;
- }
-
-
- BOOL XObjSetProtection(glb glob, struct CFSLock *parent, char *name, LONG mask){
- BOOL err;
-
- err = xSetProtection(glob, parent->xlock, name, mask);
- return err;
- }
-
- BOOL XObjSetComment(glb glob, struct CFSLock *parent, char *name, char *comment){
- BOOL err;
-
- err = xSetComment(glob, parent->xlock, name, comment);
- return err;
- }
-
- BOOL XObjSetFileDate(glb glob, struct CFSLock *parent, char *name, struct DateStamp *ds){
- BOOL err;
-
- err = xSetFileDate(glob, parent->xlock, name, ds);
- return err;
- }
-
-
- BOOL XObjDeleteFile(glb glob, struct CFSLock *parent, char *name){
- BOOL err;
-
- err = xDeleteFile(glob, parent->xlock, name);
- return err;
- }
-
-
- BOOL XObjRename(glb glob, struct CFSLock *p1, char *n1, struct CFSLock *p2, char *n2){
- BOOL err;
-
- if(p2->objtype != XOBJECT){
- debug(("XObjRename(): Error: rename to lock of type %ld\n",p2->objtype));
- glob->ioerr = ERROR_RENAME_ACROSS_DEVICES;
- return DOSFALSE;
- }else{
- err = xRename(glob, p1->xlock, n1, p2->xlock, n2);
- return err;
- }
- }
-
-
- /* End of xobj.c */
-