/* * $Log: /806a01/RCFS/RCFS2.C $ * * 3 31.07.96 7:16 Goethel * Aenderungen Menuoberflaeche und Ablauf * Fehlerbehebung ETERNA KL806II.DOC * * 2 28.06.96 11:27 Goethel * Eterna Prototyp plus Aenderungen * * 1 11.06.96 2:42 Goethel * Revision 1.2 1996/03/05 14:39:32 Sven_Goethel * *** empty log message *** * Revision 1.1 1996/03/05 14:14:59 Sven_Goethel * Initial revision * Revision 1.2 1996/02/15 22:23:43 Sven_Goethel * now the fs is checked for pc<->KL806 Terminal and C166<->Terminal * the duperblock contains a version string and an xtensions short array. * (superblock) * works fine and fast. * Revision 1.1 1996/02/13 06:35:37 Sven_Goethel * Initial revision */ #include "rcfs.h" #ifndef _C166_ #include #include #endif extern unsigned char _rcfs_status; extern unsigned char *_rcfs_blk_buff; extern unsigned short _rcfs_blk_sz; extern unsigned char *_rcfs_inode_bmp; extern unsigned char *_rcfs_zone_bmp; extern unsigned short _rcfs_inode_bmp_blks; extern unsigned short _rcfs_zone_bmp_blks; extern bool _rcfs_write_back; extern rc_sb _rcfs_sb; extern unsigned short _rcfs_inumber; extern bool _rcfs_mounted; /* RC-FS : LEVEL 3 -- USER LEVEL */ /* -- to provide file permissions, you will need the permssn.c/h module !!!!!!!!!!!!!!!!!!! */ #ifndef _C166_ static void __umount(void) { unsigned char __rcfs_status=_rcfs_status; if(_rcfs_mounted) rc_umount(); _rcfs_status=__rcfs_status; } rc_state rc_format(unsigned short blk_sz, double inode_pct, unsigned short uid ) { rc_state rs=RCFS_OK; rc_sb sb; rc_dir_entry new_dir_entry[2]; unsigned short root_inumber, dummy; unsigned long rc_sz; rc_inode root_inode; unsigned short max_blks ; unsigned short inode_number ; unsigned short inodes_p_blk ; unsigned short inodes_blks ; unsigned short zone_blks ; unsigned short inode_bmp_sz ; unsigned short inode_bmp_blks; unsigned short zone_bmp_sz ; unsigned short zone_bmp_blks; unsigned char buffer[100]; if(_rcfs_mounted) return RCFS_MOUNTED; _rcfs_status = rc_blk_format(blk_sz, 0 /* no need to zero blocks (SECURITY?) */ ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; /* validate low level superblock on ramcard */ _rcfs_status = rc_blk_open(); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; memset(buffer, 0xff, 100); _rcfs_status = rc_blk_read(0, buffer, 30); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; dummy=get_ushort(buffer+19); /* block size */ if(dummy!=blk_sz) return RCFS_BLK_ERR; /* get ramcard size */ rc_sz=(unsigned long)(get_ushort(buffer+21))*(unsigned long)(blk_sz); #ifdef __KL806_BF1_3e__ /* lets hava the restriction because of the bug in BF1.3e */ if(rc_sz>65024L) rc_sz=65024L; #endif max_blks = (unsigned short)(rc_sz / blk_sz) - 1 - 1; inode_number = (max_blks - 2)*inode_pct; inodes_p_blk = blk_sz / sizeof(rc_inode); inodes_blks = inode_number / inodes_p_blk ; zone_blks = max_blks - 2 - inodes_blks ; inode_bmp_sz = inode_number / 8 + 1 ; inode_bmp_blks = inode_bmp_sz / blk_sz + 1 ; zone_bmp_sz = zone_blks / 8 + 1 ; zone_bmp_blks = zone_bmp_sz / blk_sz + 1; zone_blks = zone_blks - zone_bmp_blks - inode_bmp_blks + 2 ; sb.magic_number = (unsigned short )RC_MAGIC; sb.blk_sz = blk_sz; sb.rc_sz = rc_sz; sb.inode_number = inode_number; sb.zone_number = zone_blks; sb.root_inode = MAGIC_INODE_NUMBER_ROOT ; sb.inode_bmp_blks = inode_bmp_blks ; sb.zone_bmp_blks = zone_bmp_blks ; sb.first_inode = MAGIC_SB_BLOCK_NUMBER+1+inode_bmp_blks+zone_bmp_blks; sb.first_zone = sb.first_inode + inodes_blks; sb.states = RC_RDWR|RC_EXE ; sb.uid = uid; sb.magic_signature = RC_MAGIC_SIGNATURE; strncpy(sb.version, RCFS_VERSION_STRING, sizeof(sb.version)); rs = rc_writesb(&sb, true /* erase bmp's */ ) ; if(rs!=RCFS_OK) return rs; _rcfs_status = rc_blk_close(); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; if(rc_sz/blk_sz>9999) { _rcfs_status=RC_BLK_INVALID_BLK_NUM; return RCFS_BLK_ERR; } if(blk_sz>9999) { _rcfs_status=RC_BLK_INVALID_BLK_SZ; return RCFS_BLK_ERR; } rs = rc_mount ( true /* write back */ ); if(rs!=RCFS_OK) return rs; /* root directory */ uid = (unsigned short)RC_OWN_RDWR | (unsigned short)RC_OWN_EX | (unsigned short)RC_GRP_RDWR | (unsigned short)RC_GRP_EX | (unsigned short)RC_ALL_RDWR | (unsigned short)RC_ALL_EX | (unsigned short)RC_DIR /* std root dir uid */ ; rs = rc_createinode(&root_inumber, 0, 0 /* usr and grp are root */, uid ); if(rs!=RCFS_OK) { __umount(); return rs; } if(root_inumber!=MAGIC_INODE_NUMBER_ROOT) { __umount(); return RCFS_WRONG_INODE_NO; } /* create general files ('.' and '..' for dir-inode ) */ strcpy(new_dir_entry[0].fname, "."); new_dir_entry[0].inode=MAGIC_INODE_NUMBER_ROOT; strcpy(new_dir_entry[1].fname, ".."); new_dir_entry[1].inode=MAGIC_INODE_NUMBER_ROOT; rc_translatedirdata(false /* -> DISK */, (unsigned char *)(&(new_dir_entry[0])), 2*sizeof(rc_dir_entry)); rs = rc_getinode(&root_inode, root_inumber); if(rs!=RCFS_OK) { __umount(); return rs; } rs = rc_addblks( (unsigned char *)(&(new_dir_entry[0])), 2*sizeof(rc_dir_entry), &root_inode ); if(rs!=RCFS_OK) { __umount(); return rs; } rs = rc_putinode(&root_inode, root_inumber); if(rs!=RCFS_OK) { __umount(); return rs; } rs = rc_umount (); if(rs!=RCFS_OK) return rs; return rs; } #endif static rc_state rc_goto_dir(unsigned short *inumber, const char *name, unsigned short user, unsigned short group, const char **last_fname, bool *last_dir, bool *last_parent_dir ) { int i,j,k,l; rc_state rs=RCFS_OK; char _name[FNAMESZ+1]; unsigned short new_inumber; rc_inode new_inode; *last_dir=false; *last_parent_dir=false; if(inumber==NULL) INT_ERR(__LINE__); if(name==NULL) { *inumber=MAGIC_INODE_NUMBER_ROOT; return RCFS_OK; } /* parse the directory string */ l=strlen(name); i=0; *last_fname=0; while(i file-seperator */ for(j=i; name[j]!=0 && name[j]!='/' && name[j]!='\\' ; j++) ; k=j-i; if(k>FNAMESZ) return RCFS_INVALID_FILENAME; if(j==0) { *inumber=MAGIC_INODE_NUMBER_ROOT; } else { strncpy(_name, &(name[i]), k); _name[k]=0; rs=rc_getdirinode(&new_inumber, *inumber, user, group, _name ); if(rs==RCFS_FILE_NOT_FOUND) { if(j0 && fname[i-1]!='/' && fname[i-1]!='\\'; i--) ; if(i>0) { buffer=(char *)calloc(i, 1); if(!buffer) return RCFS_NO_MORE_MEM; strncpy(buffer, fname, i-1); buffer[i]=0; rs = rc_goto_dir(&inumber, buffer, user, group, &last_fname, &last_dir, &last_parent_dir ); free(buffer); if(rs!=RCFS_OK) return rs; if(last_fname!=NULL||last_dir||last_parent_dir) return RCFS_FILE_NOT_FOUND; } rs = rc_changedirinode(uid, 0, 0, inumber, &(fname[i]), user, group, ch4own, ch4grp, ch4all, false, recursiv); return rs; } #endif /* static globals to save stack-memory for recursiv directory dump */ static char __buffer[100]; static char __buffer2[100]; static unsigned short __h, __m, __s, __time; static unsigned short __user, __group; static unsigned short __level=0; static unsigned short __dest_len; static rc_dir_entry * __pdir = 0; unsigned short __inumber; unsigned short __parent_inumber; unsigned long __entrys; unsigned long __size_used; static rc_state __rc_dir(char *dest, unsigned short dest_sz, char *prefix, bool recursiv, bool flong) { rc_state rs=RCFS_OK; unsigned short inumber, i, j, dirs; rc_inode inode, inode_b; bool corrupt=false; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(dest==0) INT_ERR(__LINE__); if(dest_sz==0) return RCFS_OK; inumber=__inumber; rs = rc_getinode(&inode, inumber); if(rs!=RCFS_OK) return rs; /* skip if no permission */ if(!TestPermission(&inode, __user, __group, RC_READ)) return RCFS_WRONG_PERMISSION; if(inode.size%sizeof(rc_dir_entry)) return RCFS_INVALID_DIR; dirs=inode.size/sizeof(rc_dir_entry); if(dirs<2) return RCFS_INVALID_DIR; for(i=0; i=2) { if(prefix && (j=strlen(prefix))>0) { if( ( strlen(__pdir[i].fname)>=j && strcmp(&(__pdir[i].fname[strlen(__pdir[i].fname)-j]), prefix )==0 ) ) { /* ok */ } else continue; } __size_used+=inode_b.size; if((inode_b.uid&RC_DIR)!=0) strcat(__buffer,"/"); } else if(!corrupt && rs==RCFS_OK) { strcat(__buffer,"/"); inode_b=inode; inode_b.size=0; /* verkettung null laenge */ inode_b.uid&=~RC_DIR; /* dir ausmaskieren, da nicht zu rekursieren */ } if(!corrupt && rs==RCFS_OK && flong) { strcat(__buffer,__buffer2); if((inode_b.uid&RC_DIR)!=0) sprintf(__buffer2,"%5.5lu", 0L); else sprintf(__buffer2,"%5.5lu", inode_b.size); strcat(__buffer, __buffer2); __time=inode_b.csec; __h=__time/60/60; __time-=__h*60*60; __m=__time/60; __time-=__m*60; __s=__time; sprintf(__buffer2," %2.2u:%2.2u:%2.2u %2.2u/%2.2u/%4.4u", __h, __m, __s, inode_b.cday_cmonth/100, inode_b.cday_cmonth%100, inode_b.cyear); strcat(__buffer, __buffer2); __time=inode_b.msec; __h=__time/60/60; __time-=__h*60*60; __m=__time/60; __time-=__m*60; __s=__time; sprintf(__buffer2," %2.2u:%2.2u:%2.2u %2.2u/%2.2u/%4.4u", __h, __m, __s, inode_b.mday_mmonth/100, inode_b.mday_mmonth%100, inode_b.myear); strcat(__buffer, __buffer2); sprintf(__buffer2," %u %u", inode_b.user, inode_b.group); strcat(__buffer, __buffer2); } strcat(__buffer, "\n"); if(__dest_len+strlen(__buffer)=2); /* verkettung sollte ausmaskiert sein */ __parent_inumber=inumber; __inumber=__pdir[i].inode; if(__pdir) free(__pdir); __pdir=0; __level++; rs = __rc_dir(dest, dest_sz, prefix, recursiv, flong); __level--; __inumber=inumber; if(rs!=RCFS_OK) return rs; } } } if(__level==0 && flong) { rs=rc_getfreeblknumber( false /* inode_bmp */, &i ); if(rs!=RCFS_OK) return rs; rs=rc_getfreeblknumber( true /* zone_bmp */, &j ); if(rs!=RCFS_OK) return rs; sprintf(__buffer, " %lu Files %lu Bytes used\n %lu Bytes free\n %u zone free, %u inodes free\n", __entrys, __size_used, (unsigned long)j*(unsigned long)_rcfs_blk_sz, j, i ); if(__dest_len+strlen(__buffer)_rcfs_sb.inode_number) { *corrupt=true; return RCFS_OK; } rs = rc_markinode(inumber); if(rs!=RCFS_OK) { *corrupt=true; return rs; } rs = rc_readinode(&inode, inumber); if(rs!=RCFS_OK) { *corrupt=true; return rs; } for(done=false, i=-1; !done && i=0) { if(i==0) { if(inode.zone_ptrptr==0) { done=true; break; } rs = rc_markzone(inode.zone_ptrptr); if(rs!=RCFS_OK) { done=true; break; } _rcfs_status = rc_blk_read ( inode.zone_ptrptr, _rcfs_blk_buff, IZPTRPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) { rs=RCFS_BLK_ERR; done=true; break; } get_ushort_array(_rcfs_blk_buff, d_idrblk, IZPTRPTRBLK); } /* load indirected blk pointer */ if(d_idrblk[i]==0) { done=true; break; } rs = rc_markzone(d_idrblk[i]); if(rs!=RCFS_OK) { done=true; break; } _rcfs_status = rc_blk_read ( d_idrblk[i], _rcfs_blk_buff, IZPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) { rs=RCFS_BLK_ERR; done=true; break; } get_ushort_array(_rcfs_blk_buff, idrblk, IZPTRBLK); idrblkptr=idrblk; } else idrblkptr=inode.zone_ptr; for(k=0; !done && (i>=0 && k=2) { if(verbose) { #ifndef _C166_ printf("test inode Number %u, File %s\n", __pdir[i].inode, __pdir[i].fname ); #else printf("test inode Number %u, File %s\n\r", __pdir[i].inode, __pdir[i].fname ); #endif } rs=__rc_rebuildbmp(__pdir[i].inode, false /* dont erase */, &corrupt); if(corrupt) { #ifndef _C166_ printf("!!!! Inode Number %u, File %s, corrupt and deleted\n", __pdir[i].inode, __pdir[i].fname ); #else ErrorOut("!!!! Inode Number %u, File %s,\n\r corrupt and deleted\n\r", __pdir[i].inode, __pdir[i].fname ); #endif } if(!corrupt && rs==RCFS_OK) rs = rc_getinode(&inode_b, __pdir[i].inode); if(rs!=RCFS_OK||corrupt) { if(rs==RCFS_WRONG_INODE_NO) { #ifndef _C166_ printf("!!!! unreferenced inode number %u\n (entry '%s' deleted)!\n", __pdir[i].inode, __pdir[i].fname); #else ErrorOut("!!!! unreferenced inode number %u\n\r (entry '%s' deleted)!\n\r", __pdir[i].inode, __pdir[i].fname); #endif } if(rs==RCFS_WRONG_INODE_NO||corrupt) { for(j=i+1; j DISK */, (unsigned char *)(__pdir), dirs*sizeof(rc_dir_entry)); rs = rc_addblks((unsigned char *)(__pdir), dirs*sizeof(rc_dir_entry), &inode); } if(rs==RCFS_OK) { rs = rc_putinode(&inode, inumber); } fixed=0; } if(rs==RCFS_OK && (inode_b.uid&RC_DIR)!=0 && inumber!=__pdir[i].inode) { __parent_inumber=inumber; __inumber=__pdir[i].inode; if(__pdir) free(__pdir); __pdir=0; __level++; rs = __rc_checkfs(verbose, __fixed); __level--; __inumber=inumber; if(rs!=RCFS_OK) return rs; } } if(__pdir) free(__pdir); __pdir=0; return rs; } rc_state rc_checkfs(bool verbose) { bool fixed; rc_state rs=RCFS_OK; if(_rcfs_mounted) return RCFS_MOUNTED; __level=0; rs = rc_mount ( false /* write through */ ); if(rs!=RCFS_OK) return rs; do { rs = __rc_checkfs(verbose, &fixed); if( fixed && rs==RCFS_OK) { #ifndef _C166_ printf("!!!! CheckFs again, because of modification ...\n"); #else ErrorOut("!!!! CheckFs again, because of modification ...\n\r"); #endif } } while (fixed && rs==RCFS_OK); rc_umount(); return rs; } rc_state rc_rm(const char *fname, bool recursiv) { rc_state rs=RCFS_OK; unsigned short inumber; unsigned short user, group; char *last_fname=NULL; char *buffer=NULL; bool last_dir, last_parent_dir; int i; if(fname==NULL) INT_ERR(__LINE__); user = getuid(); group= getgid(); inumber=_rcfs_inumber; /* SEEK FOR A PATHNAME BEFORE THE FILENAME/PATH TO DELETE */ for(i=strlen(fname); i>=0 && fname[i]!='/' && fname[i]!='\\'; i--) ; if( i>=0 && ( fname[i]=='/' || fname[i]=='\\' ) ) { buffer=(char *)calloc( i + 2 /* index and EOS */, 1); if(!buffer) return RCFS_NO_MORE_MEM; strncpy(buffer, fname, i+1); buffer[i+1]=0; rs = rc_goto_dir(&inumber, buffer, user, group, &last_fname, &last_dir, &last_parent_dir ); free(buffer); if(rs!=RCFS_OK) return rs; if(last_fname!=NULL||last_dir||last_parent_dir) return RCFS_FILE_NOT_FOUND; } rs = rc_rmdirinode(inumber, &(fname[i+1]), user, group, recursiv); return rs; } rc_state rc_remove(const char *fname) { return rc_rm(fname, false); } static rc_state _rc_ischecks(const char *name, bool *isdir, bool *isthere) { unsigned short inumber; const char *last_fname; rc_state rs; bool last_dir, last_parent_dir; if(name==NULL) INT_ERR(__LINE__); if(isdir==NULL) INT_ERR(__LINE__); if(isthere==NULL) INT_ERR(__LINE__); *isthere=false; *isdir=false; inumber=_rcfs_inumber; rs = rc_goto_dir(&inumber, name, 0,0, &last_fname, &last_dir, &last_parent_dir ); if(rs==RCFS_FILE_IS_NOT_DIR && last_fname==0) { *isthere=true; *isdir=false; return RCFS_OK; } if(rs!=RCFS_OK) return rs; if(last_fname!=NULL) { *isthere=false; *isdir=last_dir||last_parent_dir; } else { *isthere=true; *isdir=true; } return rs; } rc_state rc_IsExistFile (const char *name, bool *flag) { rc_state rs; bool isdir, isthere; if(flag==NULL) INT_ERR(__LINE__); rs = _rc_ischecks(name, &isdir, &isthere); if(rs==RCFS_OK) { *flag=isthere && !isdir; } return rs; } rc_state rc_IsExistDir (const char *name, bool *flag) { rc_state rs; bool isdir, isthere; if(flag==NULL) INT_ERR(__LINE__); rs = _rc_ischecks(name, &isdir, &isthere); if(rs==RCFS_OK) { *flag=isthere && isdir; } return rs; } rc_state rc_IsExist (const char *name, bool *flag) { rc_state rs; bool isdir, isthere; if(flag==NULL) INT_ERR(__LINE__); rs = _rc_ischecks(name, &isdir, &isthere); if(rs==RCFS_OK) { *flag=isthere; } return rs; } unsigned short __file_buffer_size__ = RC_DEF_FILE_BUFFER_SZ; static rc_state __rs=RCFS_OK; void rc_set_fbuffer_sz(unsigned short sz) { __file_buffer_size__=sz; } rc_handle * rc_open(const char *fname, unsigned short mode) { rc_state rs=RCFS_OK; unsigned short user, group, uid; char *last_fname=NULL; rc_inode inode; rc_handle *hdle=0; bool last_dir, last_parent_dir; if(fname==NULL) { __rs=RCFS_WRONG_HANDLE; return NULL; } hdle=(rc_handle *)calloc(1, sizeof(rc_handle)); if(hdle==NULL) { __rs=RCFS_NO_MORE_MEM; return NULL; } hdle->open_mode=mode; hdle->mode=mode; hdle->byte_pos=0; hdle->inumber=_rcfs_inumber; hdle->eof=false; hdle->bufferidx=0; hdle->buffersz=__file_buffer_size__; if(__file_buffer_size__) { hdle->buffer=malloc(__file_buffer_size__); if(!hdle->buffer) { free(hdle); __rs=RCFS_NO_MORE_MEM; return NULL; } } else hdle->buffer=NULL; /* check file */ __rs=RCFS_OK; user = getuid(); group= getgid(); rs = rc_goto_dir(&(hdle->inumber), fname, user, group, &last_fname, &last_dir, &last_parent_dir ); /* file exist, but is directory ?? */ if(rs==RCFS_OK && last_fname==NULL) { free(hdle); __rs=RCFS_FILE_IS_DIR; return NULL; } /* file does not exist, but it is a directory ?? */ if(last_fname!=NULL && (last_dir || last_parent_dir) ) { free(hdle); __rs=RCFS_FILE_IS_DIR; return NULL; } /* file exist, and is not a directory !! */ if(rs==RCFS_FILE_IS_NOT_DIR) rs=RCFS_OK; if(last_fname==NULL) rs = rc_getinode(&inode, hdle->inumber); if(rs!=RCFS_OK) { free(hdle); __rs=rs; return NULL; } if(last_fname==NULL && (inode.uid&RC_DIR)!=0) { free(hdle); __rs=RCFS_FILE_IS_DIR; return NULL; } if(last_fname==NULL) { /* file exist and is no directroy */ /* skip if no permission */ if(!TestPermission(&inode, user, group, hdle->open_mode)) { free(hdle); __rs=RCFS_WRONG_PERMISSION; return NULL; } if((mode&RC_WRITE)!=0) { if((mode&RC_APPEND)!=0) { hdle->byte_pos=inode.size; } else { free(hdle); __rs=RCFS_WRONG_OPEN_MODE; return NULL; } } #ifdef _HANDLE_WITH_INODE_ hdle->inode=inode; #endif } else { /* file does not exist */ if((mode&RC_CREATE)!=0) { uid = RC_OWN_RDWR | RC_OWN_EX | RC_GRP_RDWR | RC_GRP_EX | RC_ALL_RD | RC_ALL_EX ; rs = rc_mkdirinode(&(hdle->inumber), hdle->inumber, last_fname, user, group, uid ); if(rs!=RCFS_OK) { free(hdle); __rs=rs; return NULL; } #ifdef _HANDLE_WITH_INODE_ __rs = rc_getinode(&(hdle->inode), hdle->inumber); if(__rs!=RCFS_OK) { free(hdle); return NULL; } #endif } else { free(hdle); __rs=RCFS_WRONG_OPEN_MODE; return NULL; } } return hdle; } rc_state rc_flush(rc_handle *hdle) { rc_state rs=RCFS_OK; #ifndef _HANDLE_WITH_INODE_ rc_inode inode; #endif rc_inode *pinode; if(hdle==NULL) return RCFS_WRONG_HANDLE; #ifndef _HANDLE_WITH_INODE_ rs = rc_getinode(&inode, hdle->inumber); pinode=&inode; #else pinode=&(hdle->inode); #endif assert(hdle->buffersz==0 || hdle->bufferidx<=hdle->buffersz); if(rs==RCFS_OK && (hdle->mode&RC_WRITE)!=0 && hdle->bufferidx>0) { assert(hdle->buffer); rs=rc_addblks(hdle->buffer, hdle->bufferidx, pinode); if(rs==RCFS_OK) rs = rc_putinode(pinode, hdle->inumber); } hdle->bufferidx=0; return rs; } rc_state rc_close(rc_handle *hdle) { rc_state rs; rs=rc_flush(hdle); if(hdle) { if(hdle->buffer) { assert(hdle->buffersz); free(hdle->buffer); } free(hdle); } return rs; } rc_state rc_rewind(rc_handle *hdle) { rc_state rs; if((rs=rc_flush(hdle))!=RCFS_OK) return rs; hdle->byte_pos=0; hdle->mode=hdle->open_mode; hdle->eof=false; return RCFS_OK; } rc_state rc_geterr(void) { rc_state rs=__rs; __rs=RCFS_OK; return rs; } int rc_eof(rc_handle *hdle) { if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return -1; } return hdle->eof; } unsigned short rc_write(rc_handle *hdle, const unsigned char *mem, unsigned short size) { #ifndef _HANDLE_WITH_INODE_ rc_inode inode; #else bool blksadd=false; #endif rc_inode *pinode; unsigned short help, memidx, orgsize; if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return 0; } if((hdle->mode&RC_WRITE)==0) { __rs=RCFS_WRONG_OPEN_MODE; return 0; } hdle->mode&=~RC_READ; /* no more read access until rewind */ #ifndef _HANDLE_WITH_INODE_ __rs=rc_getinode(&inode, hdle->inumber); if(__rs!=RCFS_OK) return 0; pinode=&inode; #else pinode=&(hdle->inode); #endif orgsize=size; memidx=0; while(size>0 && __rs==RCFS_OK) { assert(hdle->buffersz==0 || hdle->bufferidx<=hdle->buffersz); if(hdle->buffersz) help = size/hdle->buffersz; else help = size; if(hdle->bufferidx==0 && help>0) { help *= hdle->buffersz; __rs=rc_addblks(mem+memidx, help, pinode); #ifdef _HANDLE_WITH_INODE_ blksadd=true; #endif } else if(hdle->bufferidxbuffersz) { assert(hdle->buffer); help = hdle->buffersz-hdle->bufferidx; if(help>size) help=size; assert(help!=0); memcpy(hdle->buffer+hdle->bufferidx, mem+memidx, help); hdle->bufferidx+=help; if(hdle->bufferidx==hdle->buffersz) { __rs=rc_addblks(hdle->buffer, hdle->buffersz, pinode); #ifdef _HANDLE_WITH_INODE_ blksadd=true; #endif hdle->bufferidx=0; } } else INT_ERR(__LINE__); if(__rs==RCFS_OK) { hdle->byte_pos+=help; memidx+=help; size-=help; } } #ifdef _HANDLE_WITH_INODE_ if( __rs==RCFS_OK && blksadd==true ) #else if( __rs==RCFS_OK ) #endif __rs = rc_putinode(pinode, hdle->inumber); if(__rs!=RCFS_OK) { #ifdef _HANDLE_WITH_INODE_ rc_getinode(&(hdle->inode), hdle->inumber); #endif return 0; } return orgsize-size; } unsigned long rc_ftell(rc_handle *hdle) { if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return EOF; } return hdle->byte_pos; } int rc_fseek(rc_handle *hdle, long offset, int whence) { #ifndef _HANDLE_WITH_INODE_ rc_inode inode; #endif rc_inode *pinode; unsigned long cur; if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return EOF; } #ifndef _HANDLE_WITH_INODE_ __rs=rc_getinode(&inode, hdle->inumber); if(__rs!=RCFS_OK) return EOF; pinode=&inode; #else pinode=&(hdle->inode); #endif if(whence==0) { if(offset>=pinode->size) hdle->eof=true; else hdle->eof=false; __rs=rc_rewind(hdle); if(__rs!=RCFS_OK) return EOF; hdle->byte_pos=offset; } else if(whence==1) { cur=hdle->byte_pos; if(cur+offset>=pinode->size) hdle->eof=true; else hdle->eof=false; __rs=rc_rewind(hdle); if(__rs!=RCFS_OK) return EOF; hdle->byte_pos=cur+offset; } else if(whence==2) { cur=pinode->size; if(cur-offset>=pinode->size) hdle->eof=true; else hdle->eof=false; __rs=rc_rewind(hdle); if(__rs!=RCFS_OK) return EOF; hdle->byte_pos=cur-offset; } else return EOF; return 0; } unsigned short rc_read(rc_handle *hdle, unsigned char *mem, unsigned short size) { #ifndef _HANDLE_WITH_INODE_ rc_inode inode; #endif rc_inode *pinode; unsigned short help, memidx, orgsize; if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return 0; } if((hdle->mode&RC_READ)==0) { __rs=RCFS_WRONG_OPEN_MODE; return 0; } hdle->mode&=~RC_WRITE; /* no more write access until rewind */ #ifndef _HANDLE_WITH_INODE_ __rs=rc_getinode(&inode, hdle->inumber); if(__rs!=RCFS_OK) return 0; pinode=&inode; #else pinode=&(hdle->inode); #endif orgsize=size; memidx=0; while(size>0 && __rs==RCFS_OK && hdle->eof==false) { assert(hdle->buffersz==0 || hdle->bufferidx<=hdle->buffersz); if(hdle->buffersz) help = size/hdle->buffersz; else help = size; if(hdle->bufferidx==0 && help>0) { if(hdle->buffersz) help *= hdle->buffersz; if( (hdle->eof = help > pinode->size-hdle->byte_pos)==false ) { __rs=rc_getblks(mem+memidx, help, pinode, hdle->byte_pos); if(__rs!=RCFS_OK) break; } } else if(hdle->bufferidxbuffersz) { assert(hdle->buffer); if(hdle->bufferidx==0) { help=pinode->size-hdle->byte_pos; if(help>hdle->buffersz) help=hdle->buffersz; __rs=rc_getblks(hdle->buffer, help, pinode, hdle->byte_pos); if(__rs!=RCFS_OK) break; } assert(size>0); help = hdle->buffersz - hdle->bufferidx ; if(help>size) help=size; if( (hdle->eof = help > pinode->size-hdle->byte_pos)==false ) { memcpy(mem+memidx, hdle->buffer+hdle->bufferidx, help); hdle->bufferidx= (hdle->bufferidx+help)%hdle->buffersz; } } else INT_ERR(__LINE__); if( hdle->eof == false && __rs==RCFS_OK) { hdle->byte_pos+=help; memidx+=help; size-=help; } } if(hdle->byte_pos==pinode->size) hdle->eof=true; return orgsize-size; } int rc_printf(rc_handle *hdle, const char *fmt, ... ) { va_list va; char Buffer[512]; int result; if(!hdle) INT_ERR(__LINE__); va_start(va, fmt); vsprintf(Buffer, fmt, va); result = rc_write(hdle, Buffer, strlen(Buffer)); va_end(va); return result; } int rc_getc(rc_handle *hdle) { char c=0; unsigned short result; if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return 0; } result = rc_read(hdle, &c, 1); if(result==1) { return c; } else return EOF; } int rc_putc(char c, rc_handle *hdle) { unsigned short result; if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return 0; } result = rc_write(hdle, &c, 1); if(result==1) { return c; } else return EOF; } char * rc_gets(char *str, int n, rc_handle *hdle) { int l; int c; if(hdle==NULL) { __rs=RCFS_WRONG_HANDLE; return 0; } if(str==NULL) return 0; l=0; while(lRCFS_LAST_ERROR) { result= errors[RCFS_LAST_ERROR+1]; } else { result= errors[state]; } return result; }