home *** CD-ROM | disk | FTP | other *** search
- /* dosfunc.c - packet implementations of standard dos functions
- with variations to suit the XFH filing 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 <exec/ports.h>
-
- #include <string.h>
-
- #include <dossupport.h>
-
-
-
- /* Lock a file. Passed a parent-lock, a file name, and a mode. */
-
- struct FileLock *xLock(glb glob, struct FileLock *parent,
- char *name, LONG mode){
- struct MsgPort *procid;
- LONG res1;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_LOCATE_OBJECT, 3,
- c2b(parent), cstr2b(name,glob->stringbuf), mode );
- return (struct FileLock *) b2c( res1 );
- }
-
-
- /* Test whether a given file/dir exists. ASSUMES a Lock() on a non-existing
- * object will return ERROR_OBJECT_NOT_FOUND (so if this returns FALSE, one
- * can be pretty sure that the file does not exist).
- * Ceveat: because of race conditions, the returned value cannot be
- * guaranteed to be correct.
- */
- BOOL xExists1(glb glob, struct FileLock *parent, char *name){
- struct FileLock *tmplock = xLock(glob, parent, name, ACCESS_READ);
- if(tmplock){
- xUnLock(glob, tmplock);
- return TRUE;
- }else{
- return (BOOL) ((glob->ioerr == ERROR_OBJECT_NOT_FOUND) ? FALSE : TRUE);
- }
- }
-
-
- BOOL xExamine(glb glob, struct FileLock *lock, struct FileInfoBlock *fib){
- struct MsgPort *procid;
- LONG res1;
-
- procid = lock ? lock->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_EXAMINE_OBJECT, 2,
- c2b(lock), c2b(fib) );
-
- /* Convert bcpl string to c-strings. */
- bstr2cinplace( &fib->fib_FileName[0] );
- bstr2cinplace( &fib->fib_Comment[0] );
-
- return (BOOL) res1;
- }
-
-
- BOOL xExamineNext(glb glob, struct FileLock *lock, struct FileInfoBlock *fib){
- struct MsgPort *procid;
- LONG res1;
-
- /* Convert c-strings to bcpl strings.
- * According to specs, this is not nessesary for the comment. However,
- * 'better safe that sorry'.
- * However, care must be taken to handle the case where the comment is
- * not a valid BSTR. For example, dos.library messes it up in Examine()
- * and ExNext() (converting it to a CSTR and not converting back).
- */
- cstr2binplace(&fib->fib_FileName[0]);
- safecstr2binplace(&fib->fib_Comment[0], 80);
-
- procid = lock ? lock->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_EXAMINE_NEXT, 2,
- c2b(lock), c2b(fib) );
-
- /* Convert bcpl string to c-strings. */
- bstr2cinplace( &fib->fib_FileName[0] );
- bstr2cinplace( &fib->fib_Comment[0] );
-
- return (BOOL) res1;
- }
-
-
- struct FileLock *xCreateDir(glb glob, struct FileLock *parent, char *name){
- struct MsgPort *procid;
- LONG res1;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_CREATE_DIR, 2,
- c2b(parent), cstr2b(name,glob->stringbuf) );
- return (struct FileLock *) b2c( res1 );
- }
-
-
- BOOL xDeleteFile(glb glob, struct FileLock *parent, char *name){
- struct MsgPort *procid;
- BOOL res1;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_DELETE_OBJECT, 2,
- c2b(parent), cstr2b(name,glob->stringbuf) );
- return res1;
- }
-
-
- BOOL xRename(glb glob, struct FileLock *parent1, char *name1,
- struct FileLock *parent2, char *name2){
- struct MsgPort *procid1, *procid2;
- BOOL res1;
-
- procid1 = parent1 ? parent1->fl_Task : glob->xprocid;
- procid2 = parent2 ? parent2->fl_Task : glob->xprocid;
- if( procid1 != procid2 ){
- debug(("ERROR: xRename() across devices.\n"));
- glob->ioerr = ERROR_RENAME_ACROSS_DEVICES;
- return DOSFALSE;
- }
- res1 = dopkt( &glob->iopkt, procid1, glob->ioport, &glob->ioerr,
- ACTION_RENAME_OBJECT, 4,
- c2b(parent1), cstr2b(name1,glob->stringbuf),
- c2b(parent2), cstr2b(name2,glob->stringbuf2) );
- return res1;
- }
-
-
- struct FileLock *xParentDir(glb glob, struct FileLock *lock){
- struct MsgPort *procid;
- LONG res1;
-
- procid = lock ? lock->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_PARENT, 1,
- c2b(lock) );
- return (struct FileLock *) b2c( res1 );
- }
-
-
- struct FileLock *xParentFH(glb glob, struct FileHandle *fh){
- LONG res1;
-
- if ( !fh ) return NULL;
-
- res1 = dopkt( &glob->iopkt, fh->fh_Type, glob->ioport, &glob->ioerr,
- ACTION_PARENT_FH, 1,
- fh->fh_Args );
- return (struct FileLock *) b2c( res1 );
- }
-
-
- BOOL xSetProtection(glb glob, struct FileLock *parent, char *name, LONG bits){
- struct MsgPort *procid;
- BOOL res1;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_SET_PROTECT, 4,
- 0L, c2b(parent), cstr2b(name,glob->stringbuf), bits );
- return res1;
- }
-
-
- BOOL xSetComment(glb glob, struct FileLock *parent, char *name, char *comment){
- struct MsgPort *procid;
- BOOL res1;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_SET_COMMENT, 4,
- 0L, c2b(parent), cstr2b(name,glob->stringbuf),
- cstr2b(comment,glob->stringbuf2) );
- return res1;
- }
-
-
- BOOL xSetFileDate(glb glob, struct FileLock *parent, char *name, struct DateStamp *ds){
- struct MsgPort *procid;
- BOOL res1;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_SET_DATE, 4,
- 0L, c2b(parent), cstr2b(name,glob->stringbuf), ds );
- return res1;
- }
-
-
- struct FileLock *xDupLock(glb glob, struct FileLock *lock){
- struct MsgPort *procid;
- LONG res1;
-
- procid = lock ? lock->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_COPY_DIR, 1,
- c2b(lock) );
- return (struct FileLock *) b2c( res1 );
- }
-
-
- BOOL xUnLock(glb glob, struct FileLock *lock){
- struct MsgPort *procid;
- LONG res1;
-
- procid = lock ? lock->fl_Task : glob->xprocid;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_FREE_LOCK, 1,
- c2b(lock) );
- return (BOOL) res1;
- }
-
-
- /* NOTE: Do NOT call xOpen() with a bogus mode!!! */
- struct FileHandle *xOpen(glb glob, struct FileLock *parent,
- char *name, LONG mode){
- struct MsgPort *procid;
- LONG res1;
- struct FileHandle *fh;
-
- procid = parent ? parent->fl_Task : glob->xprocid;
- if( !dalloc(fh) ){
- OUTOFMEM;
- return NULL;
- }
- fh->fh_Pos=fh->fh_End=-1L;
- fh->fh_Type=procid;
-
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- mode, 3,
- c2b(fh), c2b(parent), cstr2b(name,glob->stringbuf) );
- if( res1 ){
- return fh;
- }else{
- dfree( fh );
- return NULL;
- }
- }
-
-
- struct FileHandle *xOpenFromLock( glb glob, struct FileLock *lock ){
- struct MsgPort *procid;
- LONG res1;
- struct FileHandle *fh;
-
- procid = lock ? lock->fl_Task : glob->xprocid;
- if( !dalloc(fh) ){
- OUTOFMEM;
- return NULL;
- }
- fh->fh_Pos=fh->fh_End=-1L;
- fh->fh_Type=procid;
-
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_FH_FROM_LOCK, 2,
- c2b(fh), c2b(lock) );
- if( res1 ){
- return fh;
- }else{
- dfree( fh );
- /* Attemp to open file with Open(lock,""). */
- if( fh = xOpen( glob, lock, "", MODE_OLDFILE ) ){
- xUnLock( glob, lock );
- return fh;
- }else{
- struct FileLock *parent;
- struct FileInfoBlock *fib;
-
- /* Attemp to open file with Open(ParentDir(lock),name). */
- if( !dalloc(fib) ){
- OUTOFMEM;
- return NULL;
- }
- if( !xExamine( glob, lock, fib ) ){
- dfree(fib);
- return NULL;
- }
- if( !(parent = xParentDir( glob, lock )) ){
- dfree(fib);
- return NULL;
- }
- if( fh = xOpen( glob, parent, fib->fib_FileName, MODE_OLDFILE )){
- xUnLock( glob, parent );
- xUnLock( glob, lock );
- dfree(fib);
- return fh;
- }
- xUnLock( glob, parent );
- dfree(fib);
- return NULL;
- }
- }
- }
-
-
- struct FileHandle *xOpenFromCopyOfLock( glb glob, struct FileLock *lock ){
- struct FileLock *lock2;
- struct FileHandle *fh;
-
- if( !(lock2 = xDupLock( glob, lock )) ){
- return NULL;
- }
- if( !(fh = xOpenFromLock( glob, lock2 )) ){
- xUnLock( glob, lock2 );
- return NULL;
- }
- return fh;
- }
-
-
- BOOL xClose(glb glob, struct FileHandle *fh){
- struct MsgPort *procid;
- LONG res1;
-
- if( !fh ) return DOSTRUE;
- procid = fh->fh_Type;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_END, 1,
- fh->fh_Arg1 );
- if( res1 ) dfree( fh );
- return (BOOL) res1;
- }
-
-
- LONG xRead(glb glob, struct FileHandle *fh, void *buf, LONG len){
- struct MsgPort *procid;
- LONG res1;
-
- if( !fh ) return 0L;
- procid = fh->fh_Type;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_READ, 3,
- fh->fh_Arg1, (LONG)buf, len );
- return res1;
- }
-
-
- LONG xWrite(glb glob, struct FileHandle *fh, void *buf, LONG len){
- struct MsgPort *procid;
- LONG res1;
-
- if( !fh ) return 0L;
- procid = fh->fh_Type;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_WRITE, 3,
- fh->fh_Arg1, (LONG)buf, len );
- return res1;
- }
-
-
- LONG xSeek(glb glob, struct FileHandle *fh, LONG pos, LONG offset){
- struct MsgPort *procid;
- LONG res1;
-
- if( !fh ) return -1L;
- procid = fh->fh_Type;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_SEEK, 3,
- fh->fh_Arg1, pos, offset );
- return res1;
- }
-
-
- LONG xSetFileSize(glb glob, struct FileHandle *fh, LONG pos, LONG offset){
- struct MsgPort *procid;
- LONG res1;
-
- if( !fh ) return -1L;
- procid = fh->fh_Type;
- /* ToDo: NOTE: The docs say that this call takes the *file handle* in
- * Arg1 (and not the usual fh->fh_arg1). This should be tested! */
- debug(("xSetFileSize: Sending packet..."));
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_SET_FILE_SIZE, 3,
- c2b(fh), pos, offset );
- debug(("returned! with %ld (ioerr=%ld).\n",res1,glob->ioerr));
- return res1;
- }
-
-
- BOOL xChangeMode(glb glob, ULONG type, void *obj, ULONG mode){
- struct MsgPort *procid;
- BOOL res1;
-
- if(!obj) return FALSE;
- switch(type){
- case CHANGE_FH:
- procid = ((struct FileHandle *)obj)->fh_Type;
- break;
- case CHANGE_LOCK:
- procid = ((struct FileLock *)obj)->fl_Task;
- break;
- default:
- debug(("Error: xChangeMode(): Bad type value %ld.\n",type));
- glob->ioerr = ERROR_OBJECT_WRONG_TYPE;
- return FALSE;
- }
- res1 = dopkt(&glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_CHANGE_MODE, 3,
- type, c2b(obj), mode);
- return res1;
- }
-
-
- BOOL xInfo(glb glob, struct FileLock *lock, struct InfoData *info){
- struct MsgPort *procid;
- LONG res1;
-
- if( !info ) return DOSFALSE;
- if( !lock ) lock = glob->xrootlock;
- procid = lock->fl_Task;
- res1 = dopkt( &glob->iopkt, procid, glob->ioport, &glob->ioerr,
- ACTION_INFO, 2,
- c2b(lock), c2b(info) );
- return (BOOL) res1;
- }
-
-
-
- /* ToDo: Must search for doc. on correct behavior in case of a NULL lock. */
- /* For now, a null lock is different from a lock to the root dir. */
- LONG xSameLock( glb glob, struct FileLock *l1, struct FileLock *l2 ){
- BOOL res1;
- struct MsgPort *prcid1, *prcid2;
- BPTR vol1,vol2;
-
- /* debug(("xSameLock(%lx,%lx) ",l1,l2)); */
- prcid1 = l1 ? l1->fl_Task : glob->xprocid;
- prcid2 = l2 ? l2->fl_Task : glob->xprocid;
- if( !l1 || !l2 ) /* Test for a NULL lock. */
- return l1==l2 ? LOCK_SAME :
- prcid1==prcid2 ? LOCK_SAME_HANDLER : LOCK_DIFFERENT;
- vol1 = l1->fl_Volume;
- vol2 = l2->fl_Volume;
- if( vol1 != vol2 || prcid1 != prcid2 ) return LOCK_DIFFERENT;
- res1 = dopkt( &glob->iopkt, prcid1, glob->ioport, &glob->ioerr,
- ACTION_SAME_LOCK, 2,
- c2b(l1), c2b(l2) );
- if( !res1 && glob->ioerr == ERROR_ACTION_NOT_KNOWN ){
- /* Klugde to support pre-2.0 file systems that cannot handle the
- * SameLock() function. To simulate it, the full paths for both locks
- * are obtained and compared.
- */
- if( !xgetpath( glob, l1, &glob->stringbuf[0], MAXSTRING-1 ) )
- res1 = FALSE;
- else if( !xgetpath( glob, l2, &glob->stringbuf2[0], MAXSTRING-1 ) )
- res1 = FALSE;
- else{
- res1 = !strcmp(&glob->stringbuf[0],&glob->stringbuf2[0]);
- debug(("xSameLock(): '%s' '%s' -> %ld\n",
- &glob->stringbuf[0],&glob->stringbuf2[0],res1));
- }
- }
- /* debug((": result %ld\n",res1)); */
- return res1 ? LOCK_SAME : LOCK_SAME_HANDLER;
- }
-
-
- /* A strncat() that allows zero or negative max length. */
- static char *mystrncat(char *d,char *s,int num){
- if(num>0) return strncat(d,s,num);
- else return d;
- }
-
-
- /* The recursion part of the xgetpath() function (see below). */
- static BOOL xgetpath1(glb glob, struct FileLock *Lock,char *f,
- struct FileInfoBlock *finfo,int max){
- char fname[31];
- LONG type;
- struct FileLock *parent;
- BOOL result;
-
- if( !xExamine( glob, Lock, finfo) ) return FALSE;
- fname[30]='\0';
- strncpy(fname,finfo->fib_FileName,30);
- type = finfo->fib_DirEntryType;
- if( parent = xParentDir(glob, Lock) ){
- result = xgetpath1( glob, parent, f, finfo, max );
- xUnLock( glob, parent );
- if(!result) return result;
- }
- mystrncat( f, fname, max-strlen(f) );
- if(type>0) mystrncat( f, parent ? "/" : ":",max-strlen(f) );
- return TRUE;
- }
-
-
- /* Get the full path name of an xlock in the buffer 'f' with lenght max.
- * Returns TRUE if succesfull, FALSE if an error occured.
- */
- BOOL xgetpath(glb glob, struct FileLock *Lock, char *f, int max){
- struct FileInfoBlock *finfo;
- BOOL err;
-
- if( !dalloc(finfo) ) return FALSE;
- strcpy(f,"");
- err = xgetpath1( glob, Lock, f, finfo, max);
- dfree(finfo);
- return err;
- }
-
-
- /* Generation of temporary file names.
- * Called with a buffer of at least TMPNAMEMAXSIZE bytes.
- */
- static void NewTmpFile(glb glob, char *name){
- sprintf(name,TMPNAMETEMPLATE,glob->mytask,glob->tmpfilecount++);
- }
-
-
- /* Clone protection flags etc. of file (or dir). */
- BOOL CloneFile2File(glb glob, struct FileLock *parent1, char *name1,
- struct FileLock *parent2, char *name2){
- struct FileLock *lock;
-
- if(!(lock = xLock(glob, parent1, name1, ACCESS_READ))){
- debug(("Error: CloneFile2File(): cannot lock file: %ld.\n",glob->ioerr));
- return FALSE;
- }
- if(!xExamine(glob, lock, &glob->fib2)){
- SAVEIOERR;
- debug(("Error: CloneFile2File(): couldn't xExamine(): %ld.\n",glob->ioerr));
- xUnLock(glob, lock);
- RESTIOERR;
- return FALSE;
- }
- xUnLock(glob, lock);
- if(!xSetFileDate(glob, parent2, name2, &glob->fib2.fib_Date)){
- debug(("Error: CloneFile2File(): xSetFileDate / %ld.\n",glob->ioerr));
- return FALSE;
- }
- if(!xSetComment(glob, parent2, name2, &glob->fib2.fib_Comment[0])){
- debug(("Error: CloneFile2File(): xSetComment / %ld.\n",glob->ioerr));
- return FALSE;
- }
- if(!xSetProtection(glob, parent2, name2, glob->fib2.fib_Protection)){
- debug(("Error: CloneFile2File(): xSetProtection / %ld.\n",glob->ioerr));
- return FALSE;
- }
- return TRUE;
- }
-
-
- /* Transforming a file handle (see TranformFile(), below for details).
- * NOTE BIEN: this function will close the file handle.
- */
- BOOL TransformXFH(glb glob, struct FileHandle *srcfh,
- struct FileLock *parent, char *name,
- BOOL (*f)(glb, struct FileHandle *, struct FileHandle *, void *),
- void *userdata){
- char tmp1[TMPNAMEMAXSIZE], tmp2[TMPNAMEMAXSIZE];
- struct FileHandle *dstfh;
- BOOL res;
- DECLIOERR;
-
- NewTmpFile(glob, tmp1);
- if(!(dstfh = xOpen(glob, parent, tmp1, MODE_NEWFILE))){
- debug(("Error: TransFormFile: Cannot open destination '%s': %ld.\n",tmp1,glob->ioerr));
- PUTIOERR;
- goto cleanup_src;
- }
- /* Now do the magic stuff. */
- res = (*f)(glob, srcfh, dstfh, userdata);
- if(!res){
- debug(("Error: TransFormFile: User func returned error: %ld.\n",glob->ioerr));
- PUTIOERR;
- goto cleanup_src_dst;
- }
- if(!xClose(glob, dstfh)){
- /* We can't close the new file - play it safe and keep the old
- * file as it is. */
- debug(("Error: TransFormFile: Error closing new file: %ld.\n",glob->ioerr));
- PUTIOERR;
- goto cleanup_delete_dst;
- }
- /* If we can't close the old file, we'll just have to hope for the
- * best... (it's a read handle, after all). */
- xClose(glob, srcfh);
-
- /* Now copy the protection flags etc. from the source file. */
- if(!CloneFile2File(glob, parent, name, parent, tmp1)){
- debug(("Error: TransFormFile(): Error cloning file: %ld.\n",glob->ioerr));
- goto failexit;
- }
-
- /* Rename the original file (to make room for the new one). */
- NewTmpFile(glob, tmp2);
- if(!xRename(glob, parent, name, parent, tmp2)){
- /* Something went wrong moving the old file. Better carry on,
- * however, in case the file did move (if it did not we'll fail
- * trying to replace it with the new one).
- */
- debug(("Error: TransFormFile: Couldn't rename the old file: %ld.\n",glob->ioerr));
- }
- if(!xRename(glob, parent, tmp1, parent, name)){
- /* Here comes trouble... we've got the old file away, and the new
- * one won't fall in place. We'll just try to save as much as
- * possible. */
- PUTIOERR;
- if(xRename(glob, parent, tmp2, parent, name)){
- /* We only delete the new file if we are "sure" that the old one
- * is OK. We might end up with two files this way, but it's safer.
- */
- xDeleteFile(glob, parent, tmp1);
- }
- RESTIOERR;
- return FALSE;
- }
-
- /* Great! The new file is well and in place. Let's delete the old
- * one and return (we return succes even if the old file wouldn't go
- * away. */
- xDeleteFile(glob, parent, tmp2);
- return TRUE;
- /*-----------------------------------------------------------------------*/
-
- /* Common clean-up code in error case. Remember to set RESTIOERR. */
- cleanup_src_dst:
- /* Now clean up the mess. Any of these calls may fail; we'll just
- * have to make the best of it. */
-
- /* We try to truncate the file to save flushing buffers. */
- /* This call is switchable, since the docs are dubious... */
- if(glob->truncateonpack){
- xSetFileSize(glob, dstfh, 0L, OFFSET_BEGINNING);
- }else{
- debug(("File truncation not requested... skipping.\n"));
- }
- xClose(glob, dstfh);
- cleanup_delete_dst:
- xDeleteFile(glob, parent, tmp1);
- cleanup_src:
- xClose(glob, srcfh); /* Leave the file as it was. */
- RESTIOERR;
- failexit:
- return FALSE;
- }
-
-
- /* The main function for transforming files (typically for packing a
- * file after ACTION_END). Arguments 'parent' and 'name' refer to the
- * file to be transformed. Additionally, a function and data pointer
- * is passed. The function will receive source and destination file
- * handles for it to do its magic on.
- */
- BOOL TransformFile(glb glob, struct FileLock *parent, char *name,
- BOOL (*f)(glb, struct FileHandle *, struct FileHandle *, void *),
- void *userdata){
- struct FileHandle *srcfh;
-
- if(!(srcfh = xOpen(glob, parent, name, MODE_OLDFILE))){
- debug(("Error: TransFormFile: Cannot open source: %ld.\n",glob->ioerr));
- return FALSE;
- }
- return TransformXFH(glob, srcfh, parent, name, f, userdata);
- }
-
-
- /* Get the size of an open file. Returns size or -1L if error.
- * Currently, in case of error, the file position may change.
- */
- LONG xGetFileSize(glb glob, struct FileHandle *fh){
- LONG oldpos,size;
-
- /* Todo: Should first try Examine_FH() (and perhaps even try
- * SetFileSize(..,0,OFFSET_END) ). */
- oldpos = xSeek(glob, fh, 0L, OFFSET_END);
- if(oldpos==-1L) return oldpos;
- size = xSeek(glob, fh, oldpos, OFFSET_BEGINNING);
- return size;
- }
-
-
- /* Write string to output file, returning success / failure. */
- BOOL xWriteStr(glb glob, struct FileHandle *fh, char *str){
- LONG len = strlen(str);
-
- if(len != xWrite(glob, fh, str, len)){
- debug(("Error: xWriteStr(): xWrite(): %ld.\n",glob->ioerr));
- return FALSE;
- }
- return TRUE;
- }
-
-
- /* End of dosfunc.h */
-