/* * $Log: /806a01/RCFS/RCFS1.C $ * * 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:28 Sven_Goethel * *** empty log message *** * Revision 1.1 1996/03/05 14:14:47 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 /* RC-FS : LEVEL 0 */ unsigned char Calc8BitCRC(const unsigned char *buffer, unsigned short size) { unsigned char checksumme; int i; checksumme = 0; for (i = 0; i < size; i++) { checksumme += buffer[i]; } checksumme = 0 - checksumme; return checksumme; } unsigned long Calc32BitCRC(const unsigned char *buffer, unsigned short size) { unsigned long checksumme; int i; checksumme = 0; for (i = 0; i < size; i++) { checksumme += ( 0x000000FF & buffer[i] ); } checksumme = 0 - checksumme; return checksumme; } unsigned char _rcfs_status=0; unsigned char *_rcfs_blk_buff=NULL; unsigned short _rcfs_blk_sz=0; unsigned char *_rcfs_inode_bmp=NULL; unsigned char *_rcfs_zone_bmp=NULL; unsigned short _rcfs_inode_bmp_blks=0; unsigned short _rcfs_zone_bmp_blks=0; bool _rcfs_write_back=false; /* -> write_through */ rc_sb _rcfs_sb; unsigned short _rcfs_inumber; bool _rcfs_mounted=false; static char *bmp_signature=NULL; static rc_state init_glob_data(const rc_sb *sb, bool erase_bmp) { /* calculate the symetrie of the media, and initilize the global bitmaps */ static char ____ff[]=";blk_sz; if(&_rcfs_sb!=sb) _rcfs_sb=*sb; if(_rcfs_blk_buff) free(_rcfs_blk_buff); _rcfs_blk_buff=calloc(1, _rcfs_blk_sz); if(!_rcfs_blk_buff) return RCFS_NO_MORE_MEM; _rcfs_zone_bmp_blks=(sb->zone_number/8+1)/_rcfs_blk_sz+1; _rcfs_inode_bmp_blks=(sb->inode_number/8+1)/_rcfs_blk_sz+1; if(_rcfs_zone_bmp) free(_rcfs_zone_bmp); _rcfs_zone_bmp=calloc(1,_rcfs_zone_bmp_blks*_rcfs_blk_sz); if(!_rcfs_zone_bmp) { free(_rcfs_blk_buff); _rcfs_blk_buff=0; return RCFS_NO_MORE_MEM; } if(_rcfs_inode_bmp) free(_rcfs_inode_bmp); _rcfs_inode_bmp=calloc(1,_rcfs_inode_bmp_blks*_rcfs_blk_sz); if(!_rcfs_inode_bmp) { free(_rcfs_zone_bmp); _rcfs_zone_bmp=0; free(_rcfs_blk_buff); _rcfs_blk_buff=0; return RCFS_NO_MORE_MEM; } for(i=0; i<_rcfs_zone_bmp_blks; i++) { if(erase_bmp==false) { _rcfs_status = rc_blk_read ( MAGIC_SB_BLOCK_NUMBER+1+_rcfs_inode_bmp_blks+i, _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; assert(i*_rcfs_blk_sz+_rcfs_blk_sz<= _rcfs_zone_bmp_blks*_rcfs_blk_sz); memcpy(_rcfs_zone_bmp+i*_rcfs_blk_sz, _rcfs_blk_buff, _rcfs_blk_sz); } else { _rcfs_status = rc_blk_write ( MAGIC_SB_BLOCK_NUMBER+1+_rcfs_inode_bmp_blks+i, _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } } for(i=0; i<_rcfs_inode_bmp_blks; i++) { if(erase_bmp==false) { _rcfs_status = rc_blk_read ( MAGIC_SB_BLOCK_NUMBER+1+i, _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; assert(i*_rcfs_blk_sz+_rcfs_blk_sz<= _rcfs_inode_bmp_blks*_rcfs_blk_sz); memcpy(_rcfs_inode_bmp+i*_rcfs_blk_sz, _rcfs_blk_buff, _rcfs_blk_sz); } else { _rcfs_status = rc_blk_write ( MAGIC_SB_BLOCK_NUMBER+1+i, _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } } return RCFS_OK; } rc_state rc_sync() { int i, l, j; long sum; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; l=strlen(bmp_signature); for(j=0, sum=0; j> 8); } unsigned short get_ushort(const unsigned char *src) { return ((unsigned short)(*(src+1)) << 8) | ((unsigned short)(*src)) ; } void put_ushort_array(unsigned char *buffer, const unsigned short *usa, unsigned short usa_sz ) { int i; for(i=0; i> 8) ); *(dest+2) = (unsigned char)(0x000000FF & (val >> 16) ); *(dest+3) = (unsigned char)(0x000000FF & (val >> 24) ); } unsigned long get_ulong(const unsigned char *src) { return ((unsigned long)(*(src+3)) << 24) | ((unsigned long)(*(src+2)) << 16) | ((unsigned long)(*(src+1)) << 8) | ((unsigned long)(*src)) ; } /* GetBmpPos calculates from the bit-number, the following values, which ranges from [0..max[ : number : INPUT the relative zone ore inode number blkoffset : OUTPUT the block-offset of _rcfs_zone_bmp or _rcfs_inode_bmp byteoffset : OUTPUT the byte-offset of _rcfs_sb->blk_udata_start the RETURNVALUE is the bitmask of the corresponding bit-number, blkoffset and byteoffset */ static unsigned char GetBmpPos(unsigned short *byteoffset, unsigned short *blkoffset, unsigned short number ) { unsigned char bitmask=128; *byteoffset=number/8; *blkoffset=*byteoffset/_rcfs_blk_sz; return bitmask >> number%8; } /* action : 0 - bval := actual value 1 - mark, bval := true 2 - unmark, bval := false 3 - test, bval := marked == true, unmarked == false if bval is NULL, no value will be set there ! number is a valid relative-blk-number or inode-number and must range from [0..max[ */ static rc_state rc_dobmp(unsigned short number, bool zone_bmp, char action, bool *bval) { unsigned char bit_msk, b; unsigned char *pbmp=NULL; unsigned short byte_offset; unsigned short blk_offset; unsigned short bmp_blk_offset=MAGIC_SB_BLOCK_NUMBER+1; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(zone_bmp) { bmp_blk_offset+=_rcfs_sb.inode_bmp_blks; if(number>=_rcfs_sb.zone_number) return RCFS_WRONG_ZONE_NO; pbmp=_rcfs_zone_bmp; number-=_rcfs_sb.first_zone; } else { if(number>=_rcfs_sb.inode_number) return RCFS_WRONG_INODE_NO; pbmp=_rcfs_inode_bmp; } bit_msk = GetBmpPos(&byte_offset, &blk_offset, number); assert( ( zone_bmp && byte_offset<_rcfs_sb.zone_bmp_blks*_rcfs_blk_sz ) || ( !zone_bmp && byte_offset<_rcfs_sb.inode_bmp_blks*_rcfs_blk_sz ) ); assert( ( zone_bmp && blk_offset<_rcfs_sb.zone_bmp_blks ) || ( !zone_bmp && blk_offset<_rcfs_sb.inode_bmp_blks ) ); assert( ( zone_bmp && bmp_blk_offset==_rcfs_sb.first_inode -_rcfs_sb.zone_bmp_blks ) || ( !zone_bmp && bmp_blk_offset==_rcfs_sb.first_inode -_rcfs_sb.zone_bmp_blks -_rcfs_sb.inode_bmp_blks ) ); assert( ( zone_bmp && bmp_blk_offset+blk_offset<_rcfs_sb.first_inode ) || ( !zone_bmp && bmp_blk_offset+blk_offset<_rcfs_sb.first_inode -_rcfs_sb.zone_bmp_blks ) ); b=*(pbmp+byte_offset); if(action==1) { if(bval) *bval=true; if((b&bit_msk)!=0) { if(zone_bmp) return RCFS_ZONE_USED; else return RCFS_INODE_USED; } *(pbmp+byte_offset)=b|bit_msk; } else if(action==2) { if(bval) *bval=false; if((b&bit_msk)==0) { if(zone_bmp) return RCFS_ZONE_UNUSED; else return RCFS_INODE_UNUSED; } *(pbmp+byte_offset)=b&(~bit_msk); } else if(action==3 && bval) { *bval=b&bit_msk; } if( (action==1 || action==2) && !_rcfs_write_back ) { _rcfs_status = rc_blk_write ( bmp_blk_offset+blk_offset, pbmp+blk_offset*_rcfs_blk_sz, byte_offset%_rcfs_blk_sz+1 ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; return RCFS_OK; } rc_state rc_getfreeblknumber( bool zone_bmp, unsigned short *number ) { unsigned char bit_msk, b; unsigned char *pbmp=NULL; unsigned short byte_offset, blk_offset; unsigned short j, max; rc_state rs= RCFS_OK; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!number) INT_ERR(__LINE__); if(zone_bmp) { max=_rcfs_sb.zone_number; pbmp=_rcfs_zone_bmp; } else { max=_rcfs_sb.inode_number; pbmp=_rcfs_inode_bmp; } *number=0; for(j=0; j reload bitmaps !*/ rs=RCFS_DISK_FULL; init_glob_data(&_rcfs_sb, false); for(i=0; imagic_number); i=2; put_ushort(_rcfs_blk_buff+i, sb->blk_sz); i+=2; put_ulong(_rcfs_blk_buff+i, sb->rc_sz); i+=4; put_ushort(_rcfs_blk_buff+i, sb->inode_number); i+=2; put_ushort(_rcfs_blk_buff+i, sb->zone_number); i+=2; put_ushort(_rcfs_blk_buff+i, sb->root_inode); i+=2; put_ushort(_rcfs_blk_buff+i, sb->inode_bmp_blks); i+=2; put_ushort(_rcfs_blk_buff+i, sb->zone_bmp_blks); i+=2; put_ushort(_rcfs_blk_buff+i, sb->first_inode); i+=2; put_ushort(_rcfs_blk_buff+i, sb->first_zone); i+=2; put_ushort(_rcfs_blk_buff+i, sb->states); i+=2; put_ushort(_rcfs_blk_buff+i, sb->uid); i+=2; put_ushort(_rcfs_blk_buff+i, sb->magic_signature); i+=2; put_ushort_array(_rcfs_blk_buff+i, sb->xtensions, sizeof(sb->xtensions)/sizeof(sb->xtensions[0]) ); i+=sizeof(sb->xtensions); strncpy(_rcfs_blk_buff+i, sb->version, sizeof(sb->version)); i+=sizeof(sb->version); if(i!=sizeof(rc_sb)) INT_ERR(__LINE__); } _rcfs_status=rc_blk_write(MAGIC_SB_BLOCK_NUMBER, _rcfs_blk_buff, sizeof(rc_sb)); return IS_RC_ERR(_rcfs_status)?RCFS_BLK_ERR:RCFS_OK; } rc_state rc_readsb(rc_sb *sb) { int i,j; unsigned char blk_buff[MAGIC_MIN_BLCK_SIZE]; if(_rcfs_mounted) return RCFS_MOUNTED; if(!sb) INT_ERR(__LINE__); _rcfs_status=rc_blk_read(MAGIC_SB_BLOCK_NUMBER, blk_buff, MAGIC_MIN_BLCK_SIZE); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; /* seek the sb-start with search for magic number */ for(i=0; imagic_number=get_ushort(blk_buff+i); if(sb->magic_number==RC_MAGIC) { j=i; break; } } if(sb->magic_number!=RC_MAGIC) return RCFS_WRONG_FS; i+=2; sb->blk_sz=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->rc_sz=get_ulong(blk_buff+i); i+=4; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->inode_number=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->zone_number=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->root_inode=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->inode_bmp_blks=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->zone_bmp_blks=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->first_inode=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->first_zone=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->states=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->uid=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; sb->magic_signature=get_ushort(blk_buff+i); i+=2; if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; if(sb->magic_signature==RC_MAGIC_SIGNATURE) { get_ushort_array(blk_buff+i, sb->xtensions, sizeof(sb->xtensions)/sizeof(sb->xtensions[0]) ); } i+=sizeof(sb->xtensions); if(i>=sb->blk_sz-1) return RCFS_INVALID_SB; if(sb->magic_signature==RC_MAGIC_SIGNATURE) { strncpy(sb->version, blk_buff+i, sizeof(sb->version)); } i+=sizeof(sb->version); if(i-j!=sizeof(rc_sb)) INT_ERR(__LINE__); return RCFS_OK; } rc_state rc_writeinode(rc_inode *inode, unsigned short inumber) { #ifndef _C166_ time_t timer; struct tm *tblock; #endif rc_state rs=RCFS_OK; bool flag; int i; unsigned short byteofs, blkofs; unsigned char ibuff[sizeof(rc_inode)+1]; unsigned short inodes_p_blk = _rcfs_blk_sz / sizeof(rc_inode) ; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!inode) INT_ERR(__LINE__); if(inumber>_rcfs_sb.inode_number) return RCFS_WRONG_INODE_NO; rs = rc_dobmp(inumber, false /* no zone */, 3 /* test */, &flag); if(rs!=RCFS_OK) return rs; if(flag==false) return RCFS_WRONG_INODE_NO; #ifndef _C166_ /* gets time of day */ timer = time(NULL); /* converts date/time to a structure */ tblock = localtime(&timer); /* modification time */ inode->msec=tblock->tm_sec+tblock->tm_min*60+tblock->tm_hour*60*60; inode->mday_mmonth=tblock->tm_mday+(tblock->tm_mon+1)*100; inode->myear=tblock->tm_year+1900; /* modification time */ #endif i=0; put_ushort(ibuff+i, inode->user); i+=2; put_ushort(ibuff+i, inode->group); i+=2; put_ulong(ibuff+i, inode->size); i+=4; put_ushort(ibuff+i, inode->csec); i+=2; put_ushort(ibuff+i, inode->cday_cmonth); i+=2; put_ushort(ibuff+i, inode->cyear); i+=2; put_ushort(ibuff+i, inode->msec); i+=2; put_ushort(ibuff+i, inode->mday_mmonth); i+=2; put_ushort(ibuff+i, inode->myear); i+=2; put_ushort(ibuff+i, inode->uid); i+=2; put_ushort_array(ibuff+i, inode->zone_ptr, IZPTR); i+=IZPTR*sizeof(unsigned short); put_ushort(ibuff+i, inode->zone_ptrptr); i+=2; put_ulong(ibuff+i, inode->crc32bit); i+=4; if(i!=sizeof(rc_inode)) INT_ERR(__LINE__); blkofs=inumber/inodes_p_blk; byteofs=sizeof(rc_inode)*(inumber%inodes_p_blk); _rcfs_status=rc_blk_read(_rcfs_sb.first_inode+blkofs, _rcfs_blk_buff, byteofs); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; assert(byteofs+sizeof(rc_inode)<=_rcfs_blk_sz); memcpy(_rcfs_blk_buff+byteofs, ibuff, sizeof(rc_inode)); _rcfs_status=rc_blk_write(_rcfs_sb.first_inode+blkofs, _rcfs_blk_buff, byteofs+sizeof(rc_inode)); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; return RCFS_OK; } rc_state rc_readinode(rc_inode *inode, unsigned short inumber) { rc_state rs=RCFS_OK; bool flag; int i; unsigned short byteofs, blkofs; unsigned char ibuff[sizeof(rc_inode)+1]; unsigned short inodes_p_blk = _rcfs_blk_sz / sizeof(rc_inode) ; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!inode) INT_ERR(__LINE__); if(inumber>_rcfs_sb.inode_number) return RCFS_WRONG_INODE_NO; rs = rc_dobmp(inumber, false /* no zone */, 3 /* test */, &flag); if(rs!=RCFS_OK) return rs; if(flag==false) return RCFS_WRONG_INODE_NO; blkofs=inumber/inodes_p_blk; byteofs=sizeof(rc_inode)*(inumber%inodes_p_blk); _rcfs_status=rc_blk_read(_rcfs_sb.first_inode+blkofs, _rcfs_blk_buff, byteofs+sizeof(rc_inode)); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; memcpy(ibuff, _rcfs_blk_buff+byteofs, sizeof(rc_inode)); i=0; inode->user = get_ushort(ibuff+i); i+=2; inode->group = get_ushort(ibuff+i); i+=2; inode->size = get_ulong(ibuff+i); i+=4; inode->csec = get_ushort(ibuff+i); i+=2; inode->cday_cmonth = get_ushort(ibuff+i); i+=2; inode->cyear = get_ushort(ibuff+i); i+=2; inode->msec = get_ushort(ibuff+i); i+=2; inode->mday_mmonth = get_ushort(ibuff+i); i+=2; inode->myear = get_ushort(ibuff+i); i+=2; inode->uid = get_ushort(ibuff+i); i+=2; get_ushort_array(ibuff+i, inode->zone_ptr, IZPTR); i+=IZPTR*sizeof(unsigned short); inode->zone_ptrptr = get_ushort(ibuff+i); i+=2; inode->crc32bit = get_ulong(ibuff+i); i+=4; if(i!=sizeof(rc_inode)) INT_ERR(__LINE__); return RCFS_OK; } /* RC-FS : LEVEL 1 */ /* arguments : inode - the information node to work around ibidx - the blk index ranges from [0..mbn-1], where mbn is the inodes maximum number of blk's. action- this work around function supports several features to save CODE-MEMORY and to support only one BIG-BUG-SOURCE :-) !!!!!!!!!!!!!!!!!!!! blk_idx_fld - a array/field of hopefully created or found blk pointer fld_sz- the size of the blk_idx_fld blks - the actual number of blk's return value after inode-working /* action : 0 - get a number of 'fld_sz' pointer of blk's in the field 'blk_idx' from the inode-blk index 'ibidx' upto 'ibidx'+'fld_sz'-1 or the inodes maximum blk number. ([0..blks-1]) ========================================================= NORMAL ACTION: =============== - blks refer the last entry in the field blkidx - blk_idx-pointer array refer to the blocks from ibidx upto blks ERROR ACTION: =============== - RCFS_WRONG_IBLK_NO will be returned, if the inode has fewer blocks than ibidx, means that ibidx could not refer a valid blk. - blks is set to number of got blk's 1 - append a number of 'fldsz' new blocks at the inode ======================================================= NORMAL ACTION: =============== o blks is set to number of new blk's o blk_idx array will refer the new (fld_sz number) blk's o the new block will be marked in the zone map. ERROR ACTION: =============== o RCFS_INODE_FULL will be returned, if the inode is full o blks will be set to the inodes maximum !!! 2 - remove 'fld_sz' blk's of the inode from ibidx ================================================== NORMAL ACTION: =============== - the deleted blk' will be unmarked in the zone map. - blks is set to number of deleted blk's ERROR ACTION: =============== - see above actions number 1 3 - just return the number of blocks in blcks, the inode does reference if fld_sz is greater than zero, the last blk_idx's will be inserted in the first entry of blk_idx_fld !!! ======================================================== NORMAL ACTION: =============== - blks is set to the maximum of the inode's blk's ERROR ACTION: =============== - none */ static rc_state rc_doinodeblk(rc_inode *inode, unsigned short ibidx, char action, unsigned short *blk_idx_fld, unsigned short fld_sz, unsigned short *blks) { int i, j; bool end=false; unsigned short d_idrptr[IZPTRPTR]; unsigned short idrptrblk[IZPTRBLK]; unsigned short * ptrblkidx=NULL; unsigned short absblknum=0; rc_state rs=RCFS_OK; bool flag; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!inode) INT_ERR(__LINE__); if(action==1) { if(!blk_idx_fld) INT_ERR(__LINE__); rs= rc_getfreeblk( true /* zone_bmp */, blk_idx_fld, fld_sz, false /* do not erase */ ); } else if(blk_idx_fld) memset(blk_idx_fld, 0, fld_sz*sizeof(unsigned short)); /* i := double indirect index ( with i<0 => use inode->zone_ptr else loop through d_idrptr ) j := double indirect index for the loaded double indirect blk heap k := indirect ptr-table index */ /* for all possibles double indirected blocks */ /* the first double indirected block is the inode->zone_ptr array */ for(*blks=0, i=-1; rs==RCFS_OK && !end && i=0) { if(inode->zone_ptrptr==0) { if(action==1) { assert(i==0); rs= rc_getfreeblk( true /* zone_bmp */, &(inode->zone_ptrptr), 1, true /* erase */ ); if(rs!=RCFS_OK) return rs; } else { end=true; break; } } if(i%IZPTRPTR==0) { /* load new heap of double indirected blk pointer */ assert(sizeof(unsigned short)==2); _rcfs_status = rc_blk_read ( inode->zone_ptrptr, _rcfs_blk_buff, IZPTRPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; get_ushort_array(_rcfs_blk_buff+i*sizeof(unsigned short), d_idrptr, IZPTRPTR ); } /* check if new heap of indirected blk pointer should be added */ if(d_idrptr[i%IZPTRPTR]==0 && action==1 ) { rs= rc_getfreeblk( true /* zone_bmp */, &(d_idrptr[i%IZPTRPTR]), 1, true /* erase */ ); if(rs!=RCFS_OK) return rs; _rcfs_status = rc_blk_read ( inode->zone_ptrptr, _rcfs_blk_buff, IZPTRPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; put_ushort(_rcfs_blk_buff+i*sizeof(unsigned short), d_idrptr[i%IZPTRPTR] ); _rcfs_status = rc_blk_write ( inode->zone_ptrptr, _rcfs_blk_buff, IZPTRPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } /* load indirected blk pointer */ if(d_idrptr[i%IZPTRPTR]==0) { end=true; break; } _rcfs_status = rc_blk_read ( d_idrptr[i%IZPTRPTR], _rcfs_blk_buff, IZPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; get_ushort_array(_rcfs_blk_buff, idrptrblk, IZPTRBLK); ptrblkidx=idrptrblk; } else ptrblkidx=inode->zone_ptr; /* for all possibles indirected blocks */ for(j=0; rs==RCFS_OK && !end && ( (i<0 && j=0 && j=0) absblknum=IZPTRBLK*i+IZPTR; else absblknum=0; absblknum+=j; if(ptrblkidx[j]==0) { if(action==1) { ptrblkidx[j]=blk_idx_fld[*blks]; *blks+=1; if(*blks==fld_sz) { end=true; } /* if indirected blk is modified -> write when indirected blk ends */ if( i>=0 && ( end==true || j==IZPTRBLK-1 ) ) { assert((void *)ptrblkidx==(void *)idrptrblk); put_ushort_array(_rcfs_blk_buff, idrptrblk, IZPTRBLK); _rcfs_status = rc_blk_write ( d_idrptr[i%IZPTRPTR], _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } } else { end=true; break; } } else { if(action==0) { if(ibidx<=absblknum && absblknum=ibidx+fld_sz) { end=true; INT_ERR(__LINE__); } } else if(action==2) { if( (ibidx<=absblknum && absblknum write when indirected blk ends */ if( i>=0 && ( end==true || j==IZPTRBLK-1 ) ) { assert((void *)ptrblkidx==(void *)idrptrblk); if(ptrblkidx[0]==0) { rs = rc_unmarkzone(d_idrptr[i%IZPTRPTR]); if(rs!=RCFS_OK) return rs; d_idrptr[i%IZPTRPTR]=0; assert(sizeof(unsigned short)==2); _rcfs_status = rc_blk_read ( inode->zone_ptrptr, _rcfs_blk_buff, IZPTRPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; put_ushort_array(_rcfs_blk_buff+i*sizeof(unsigned short), d_idrptr, IZPTRPTR ); _rcfs_status = rc_blk_write ( inode->zone_ptrptr, _rcfs_blk_buff, IZPTRPTRBLK*sizeof(unsigned short) ); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } else { put_ushort_array(_rcfs_blk_buff, idrptrblk, IZPTRBLK); _rcfs_status = rc_blk_write ( d_idrptr[i%IZPTRPTR], _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; } if(inode->zone_ptr[0]==0) { rs = rc_unmarkzone(inode->zone_ptrptr); inode->zone_ptrptr=0; } } } else if(absblknum>=ibidx+fld_sz ) { end=true; INT_ERR(__LINE__); } } else if(action==3) { /* store the last block in the first field entry, if possible ! */ if(fld_sz>0&&blk_idx_fld!=NULL) blk_idx_fld[0]=ptrblkidx[j]; *blks+=1; } /* set action */ } /* set or unset block */ } /* for all poss. indirected blocks */ } /* for all poss. indirected blocks and double-indirected blocks */ if(rs==RCFS_OK && i>=IZPTRPTRBLK) rs=RCFS_DISK_FULL; return rs; } rc_state rc_addblks(const unsigned char *buffer, unsigned short sz, rc_inode *inode) { unsigned short last_blk_free_pos, blks_needed, blks_soll, blks_ist, i, j; rc_state rs=RCFS_OK; unsigned short blks[256]; unsigned short help, org_sz, bufferofs; unsigned long crc_add; org_sz=sz; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!inode) INT_ERR(__LINE__); if(!buffer) INT_ERR(__LINE__); crc_add = Calc32BitCRC(buffer, sz); /* calc the last-blk free space */ last_blk_free_pos=inode->size%_rcfs_blk_sz; bufferofs=0; /* fill up the last blk */ if(last_blk_free_pos>0) { help=_rcfs_blk_sz-last_blk_free_pos; if(help>sz) help=sz; rs = rc_doinodeblk(inode, 0 /* dummy */, 3 /* get max blk numb. */, blks, 1, &blks_ist); if(rs!=RCFS_OK) return rs; _rcfs_status = rc_blk_read ( blks[0], _rcfs_blk_buff, last_blk_free_pos); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; assert(last_blk_free_pos+help<=_rcfs_blk_sz); assert(help<=org_sz); memcpy(_rcfs_blk_buff+last_blk_free_pos, buffer, help); last_blk_free_pos+=help; _rcfs_status = rc_blk_write ( blks[0], _rcfs_blk_buff, last_blk_free_pos); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; inode->size += 0x0000FFFF & (unsigned long)(help); sz-=help; bufferofs+=help; } /* calc the new blk, which should be appended */ blks_needed=sz/_rcfs_blk_sz; if(sz%_rcfs_blk_sz) blks_needed++; for(i=0; rs==RCFS_OK && i0); help=_rcfs_blk_sz; if(szsize += 0x0000FFFF & (unsigned long)(help); } } if(rs==RCFS_OK) { inode->crc32bit += crc_add; } return rs; } rc_state rc_getblks(unsigned char *buffer, unsigned short sz, rc_inode *inode, unsigned long byteofs) { unsigned short blks_needed, blks_soll, blks_ist, i, j; rc_state rs=RCFS_OK; unsigned short blks[256]; unsigned short help, org_sz, bufferofs; unsigned short number, byteremain; org_sz=sz; if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!inode) INT_ERR(__LINE__); if(!buffer) INT_ERR(__LINE__); number=byteofs/_rcfs_blk_sz; byteofs=byteofs%_rcfs_blk_sz; if(byteofs>0) byteremain=_rcfs_blk_sz-byteofs; else byteremain=0; bufferofs=0; /* calc the blks, which should be read */ if(sz0); rs = rc_doinodeblk(inode, number+i*256 /* 1st blk */, 0 /* action get */, blks, blks_soll, &blks_ist); if(rs!=RCFS_OK) break; assert(blks_soll==blks_ist); for(j=0; rs==RCFS_OK && j0) help=byteremain; else help=_rcfs_blk_sz; if(szsize; for(i=0; rs==RCFS_OK && i=blks_ist) return RCFS_WRONG_IBLK_NO; blkidxdel=blktrunc; blksdel=blks_ist-blktrunc; if(byteofs>0) { blksdel--; blkidxdel++; } blks_soll=blks_ist-blksdel; rs = rc_doinodeblk(inode, blkidxdel /* 1st blk */, 2 /* action delete */, NULL, blksdel /* number to delete */, &blks_ist); if(rs!=RCFS_OK) return rs; assert(blksdel==blks_ist); inode->size = 0x0000FFFF & (unsigned long)(blks_soll*_rcfs_blk_sz); /* truncate the last blk */ if(byteofs>0) { rs = rc_doinodeblk(inode, blktrunc, 0 /* get blk-idx */, &blkidxdel, 1, &blks_ist); if(rs!=RCFS_OK) return rs; _rcfs_status = rc_blk_read ( blkidxdel, _rcfs_blk_buff, byteofs); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; assert(byteremain<=_rcfs_blk_sz); memset(_rcfs_blk_buff+(unsigned short)byteofs, 0, byteremain); assert(byteofs+byteremain==_rcfs_blk_sz); _rcfs_status = rc_blk_write ( blkidxdel, _rcfs_blk_buff, _rcfs_blk_sz); if(IS_RC_ERR(_rcfs_status)) return RCFS_BLK_ERR; inode->size -= 0x0000FFFF & (unsigned long)(byteremain); } if(rs==RCFS_OK) rs=rc_calc_crc32(inode, &(inode->crc32bit)); return rs; } static rc_state rc_cginode(int action, rc_inode *inode, unsigned short *inumber, unsigned short user, unsigned short group, unsigned short uid) { #ifndef _C166_ time_t timer; struct tm *tblock; #endif rc_state rs=RCFS_OK; bool flag; assert(action==0||action==1||action==2); if(!_rcfs_mounted) return RCFS_NOT_MOUNTED; if(!inode) INT_ERR(__LINE__); if(action==0) rs = rc_getfreeblk( false /* no zone_bmp */, inumber, 1 /* one inode */, false /* do not erase */ ); if(rs==RCFS_OK) { rs = rc_dobmp(*inumber, false /* no zone */, 3 /* test */, &flag); if(rs==RCFS_OK && flag==false) rs=RCFS_WRONG_INODE_NO; } if(rs==RCFS_OK) { if(action==0) { memset(inode, 0, sizeof(rc_inode)); #ifndef _C166_ /* gets time of day */ timer = time(NULL); /* converts date/time to a structure */ tblock = localtime(&timer); /* creation time */ inode->csec=tblock->tm_sec+tblock->tm_min*60+tblock->tm_hour*60*60; inode->cday_cmonth=tblock->tm_mday+(tblock->tm_mon+1)*100; inode->cyear=tblock->tm_year+1900; /* creation time */ #endif inode->user=user; inode->group=group; inode->uid=uid; } if(action==0||action==2) { rs = rc_writeinode(inode, *inumber); } else { rs = rc_readinode(inode, *inumber); } } return rs; } rc_state rc_createinode(unsigned short *inumber, unsigned short user, unsigned short group, unsigned short uid) { rc_inode mem_inode; return rc_cginode(0 /*create*/, &mem_inode, inumber, user, group, uid); } rc_state rc_getinode(rc_inode *inode, unsigned short inumber) { return rc_cginode(1 /*get*/, inode, &inumber, 0, 0, 0); } rc_state rc_putinode(rc_inode *inode, unsigned short inumber) { return rc_cginode(2 /*put*/, inode, &inumber, 0, 0, 0); } rc_state rc_rminode(unsigned short inumber) { rc_state rs=RCFS_OK ; rc_inode inode; rs = rc_getinode(&inode, inumber); if(rs==RCFS_OK) rs = rc_truncateblks(&inode, 0); if(rs==RCFS_OK) rs=rc_unmarkinode(inumber); return rs; } /* RC-FS : LEVEL 2 */ #ifndef _C166_ unsigned short rc_getuid(const char *str) { unsigned int i, uid; unsigned int l=strlen(str); for(i=0, uid=0; iuid; if((mode&RC_READ)!=0) { /* test for read */ if ( (uid&RC_ALL_RD)==0 ) { if( ( (uid&RC_GRP_RD)==0 ) || ( (uid&RC_GRP_RD)!=0 && inode->group!=group ) ) { if( ( (uid&RC_OWN_RD)==0 ) || ( (uid&RC_OWN_RD)!=0 && inode->user!=user ) ) { flag=false; } } } } if( flag==true && (mode&RC_WRITE)!=0 ) { /* test for write */ if ( (uid&RC_ALL_WR)==0 ) { if( ( (uid&RC_GRP_WR)==0 ) || ( (uid&RC_GRP_WR)!=0 && inode->group!=group ) ) { if( ( (uid&RC_OWN_WR)==0 ) || ( (uid&RC_OWN_WR)!=0 && inode->user!=user ) ) { flag=false; } } } } if( flag==true && (mode&RC_EXE)!=0 ) { /* test for exe */ if ( (uid&RC_ALL_EX)==0 ) { if( ( (uid&RC_GRP_EX)==0 ) || ( (uid&RC_GRP_EX)!=0 && inode->group!=group ) ) { if( ( (uid&RC_OWN_EX)==0 ) || ( (uid&RC_OWN_EX)!=0 && inode->user!=user ) ) { flag=false; } } } } #ifndef NDEBUG if(flag==false) { ErrorOut("Permission Failed\n\rinode.uid :'%s'\n\rinode.user %u\n\rinode.group %u\n\ruser %u, group %u\n\r", rc_getuidstr(inode->uid), inode->user, inode->group, user, group); } #endif return flag; } void rc_translatedirdata(bool FromDisk, unsigned char *buffer, unsigned short sz) { rc_dir_entry *pdir=NULL; int i; if(!buffer) INT_ERR(__LINE__); if(FromDisk==false) { /* translate to fixed disk byte arrangement */ for(i=0; iinode)), pdir->inode); } } else /* FromDisk == true */ { /* translate from fixed disk byte arrangement */ for(i=0; iinode= get_ushort(buffer+i); } } } rc_state rc_mkdirinode(unsigned short *new_inumber, unsigned short dir_inumber, const char *name, unsigned short user, unsigned short group, unsigned short uid) { rc_state rs=RCFS_OK; rc_dir_entry new_dir_entry[2]; rc_inode dir_inode; unsigned short freenumber, sollnumber; assert(new_inumber!=NULL); if(name==NULL || strlen(name)>FNAMESZ) return RCFS_INVALID_FILENAME; rs = rc_getinode(&dir_inode, dir_inumber); if(rs!=RCFS_OK) return rs; if(!TestPermission(&dir_inode, user, group, RC_RDWR)) return RCFS_WRONG_PERMISSION; rs = rc_getdirinode(new_inumber, dir_inumber, user, group, name); if(rs==RCFS_FILE_NOT_FOUND) rs=RCFS_OK; else return RCFS_FILE_EXIST; if(dir_inode.size%sizeof(rc_dir_entry)) return RCFS_INVALID_DIR; rs = rc_getfreeblknumber( true /* zone_bmp */, &freenumber ); if(rs!=RCFS_OK) return rs; sollnumber=dir_inode.size%_rcfs_blk_sz; if(_rcfs_blk_sz-sollnumber DISK */, (unsigned char *)(&(new_dir_entry[0])), sizeof(rc_dir_entry)); rs = rc_addblks( (unsigned char *)(&(new_dir_entry[0])), sizeof(rc_dir_entry), &dir_inode ); if(rs!=RCFS_OK) return rs; rs = rc_putinode(&dir_inode, dir_inumber); if(rs!=RCFS_OK) return rs; if((uid&RC_DIR)!=0) { /* create general files ('.' and '..' for dir-inode ) */ strcpy(new_dir_entry[0].fname, "."); new_dir_entry[0].inode=*new_inumber; strcpy(new_dir_entry[1].fname, ".."); new_dir_entry[1].inode=dir_inumber; rc_translatedirdata(false /* -> DISK */, (unsigned char *)(&(new_dir_entry[0])), 2*sizeof(rc_dir_entry)); rs = rc_getinode(&dir_inode, *new_inumber); if(rs!=RCFS_OK) return rs; rs = rc_addblks( (unsigned char *)(&(new_dir_entry[0])), 2*sizeof(rc_dir_entry), &dir_inode ); if(rs!=RCFS_OK) return rs; assert(dir_inode.size%sizeof(rc_dir_entry)==0); rs = rc_putinode(&dir_inode, *new_inumber); if(rs!=RCFS_OK) return rs; } return rs; } /* if name==NULL, the first entry will be received ... */ rc_state rc_getdirinode(unsigned short *inumber, unsigned short dir_inumber, unsigned short user, unsigned short group, const char *name ) { rc_dir_entry dir_buffer[100]; rc_state rs=RCFS_OK; int i,dirs, dir_heap; rc_inode dir_inode; bool found=false; assert(inumber!=NULL); rs = rc_getinode(&dir_inode, dir_inumber); if(rs!=RCFS_OK) return rs; if(!TestPermission(&dir_inode, user, group, RC_READ)) return RCFS_WRONG_PERMISSION; if(dir_inode.size%sizeof(rc_dir_entry)) return RCFS_INVALID_DIR; dirs=(int)(dir_inode.size/sizeof(rc_dir_entry)); assert(dirs>=2); for(i=0; i100)?100:dirs-i; rs = rc_getblks( (unsigned char *)(dir_buffer), dir_heap*sizeof(rc_dir_entry), &dir_inode, i*sizeof(rc_dir_entry) ); if(rs!=RCFS_OK) return rs; rc_translatedirdata( true /* <- DISK */, (unsigned char *)(dir_buffer), dir_heap*sizeof(rc_dir_entry) ); } if(name==NULL || strcmp(dir_buffer[i%100].fname,name)==0 ) { found=true; *inumber=dir_buffer[i%100].inode; } } /* search the name for all blk's */ if(found==false && rs==RCFS_OK) rs=RCFS_FILE_NOT_FOUND; return rs; } /* if name equals zero, all inodes in the parent one will be deleted */ /* if it is non recursiv and name is an directory, it cant be deleted ! */ rc_state rc_rmdirinode(unsigned short dir_inumber, const char *name, unsigned short user, unsigned short group, bool recursiv ) { rc_dir_entry *dir_buffer=NULL; rc_inode dir_inode, inode; unsigned short inumber; rc_state rs=RCFS_OK; int i,j, dirs; bool deleted=false, validinode; if(name) { if ( strcmp(name,"..")==0 || strcmp(name,".")==0 ) { return RCFS_WRONG_PERMISSION; } } rs = rc_getinode(&dir_inode, dir_inumber); if(rs!=RCFS_OK) return rs; if(!TestPermission(&dir_inode, user, group, RC_RDWR)) return RCFS_WRONG_PERMISSION; if(dir_inode.size%sizeof(rc_dir_entry)) return RCFS_INVALID_DIR; dirs=(int)(dir_inode.size/sizeof(rc_dir_entry)); assert(dirs>=2); i=2; while(i DISK */, (unsigned char *)(dir_buffer), dirs*sizeof(rc_dir_entry) ); rs = rc_addblks((unsigned char *)(dir_buffer), dirs*sizeof(rc_dir_entry), &dir_inode); } if(rs==RCFS_OK) { rs = rc_putinode(&dir_inode, dir_inumber); } /* remove the non dir, or the directory entry itself */ if(rs==RCFS_OK) rs=rc_rminode(inumber); } else { if(name!=NULL) rs=RCFS_FILE_IS_DIR ; else i++; /* next dir entry */ } } else rs=RCFS_WRONG_PERMISSION; } else i++; /* next dir entry */ } /* search the name for all blk's */ if(dir_buffer!=NULL) free(dir_buffer); if(name!=NULL && deleted==false && rs==RCFS_OK) rs=RCFS_FILE_NOT_FOUND; return rs; } #ifndef _C166_ rc_state rc_changedirinode(unsigned short NewUid, unsigned short NewUser, unsigned short NewGroup, unsigned short dir_inumber, const char *name, unsigned short user, unsigned short group, bool ch4own, bool ch4grp, bool ch4all, bool ChangeUserGroup, bool recursiv ) { rc_dir_entry *dir_buffer=NULL; rc_inode dir_inode, inode; unsigned short inumber, uid; rc_state rs=RCFS_OK; int i,j, dirs; bool changed=false, validinode; if(name) { if ( strcmp(name,"..")==0 || strcmp(name,".")==0 ) { return RCFS_WRONG_PERMISSION; } } rs = rc_getinode(&dir_inode, dir_inumber); if(rs!=RCFS_OK) return rs; if(!TestPermission(&dir_inode, user, group, RC_RDWR)) return RCFS_WRONG_PERMISSION; if(dir_inode.size%sizeof(rc_dir_entry)) return RCFS_INVALID_DIR; dirs=(int)(dir_inode.size/sizeof(rc_dir_entry)); assert(dirs>=2); for(i=2; i0 && rs!=RCFS_OK) { _rcfs_status = rc_blk_open(); if(IS_RC_ERR(_rcfs_status)) rs = RCFS_BLK_ERR; else rs = RCFS_OK; } #else _rcfs_status = rc_blk_open(); if(IS_RC_ERR(_rcfs_status)) rs = RCFS_BLK_ERR; #endif } if(rs==RCFS_OK) rs=rc_readsb(&_rcfs_sb); if(rs==RCFS_OK) rs=init_glob_data(&_rcfs_sb, false /* dont erase bmp */ ); if(rs==RCFS_OK) { // bmp ok ? l=strlen(bmp_signature); for(j=0, sum=0; j