// Sets 'blockpos' to point to the next block segment for the inode (and moves onto the // next block descriptor inode if necessary) int blockSeekNextSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos) { pfs_cache_t *nextSegment; int result=0; if (blockpos->byte_offset) { printf("ps2fs: Panic: This is a bug!\n"); return -1; } // If we're at the end of the block descriptor array for the current // inode, then move onto the next inode if (fixIndex(blockpos->block_segment+1)==0) { if ((nextSegment=blockGetNextSegment(cacheUsedAdd(blockpos->inode), &result)) == NULL) return result; cacheAdd(blockpos->inode); blockpos->inode=nextSegment; if (clink->u.inode->number_data-1 == ++blockpos->block_segment) return -EINVAL; } blockpos->block_offset=0; blockpos->block_segment++; return result; }
int blockInitPos(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u64 position) { blockpos->inode=cacheUsedAdd(clink); blockpos->byte_offset=0; if (clink->u.inode->size) { blockpos->block_segment=1; blockpos->block_offset=0; }else{ blockpos->block_segment=0; blockpos->block_offset=1; } return inodeSync(blockpos, position, clink->u.inode->number_data); }
// Gets a dir entry from the inode specified by clink pfs_cache_t *getDentry(pfs_cache_t *clink, char *path, pfs_dentry **dentry, u32 *size, int option) { pfs_blockpos_t block_pos; u32 result; pfs_dentry *d; u16 aLen; pfs_dentry *d2; pfs_cache_t *dentCache; u32 dentryLen=0; int len=0; if (path) { len = strlen(path); dentryLen = (len+8+3) &~4; } *size = 0; block_pos.inode = cacheUsedAdd(clink); block_pos.block_segment = 1; block_pos.block_offset = 0; block_pos.byte_offset = 0; dentCache = getDentriesChunk(&block_pos, (int *)&result); if (dentCache) { d2=d=dentCache->u.dentry; while(*size < clink->u.inode->size) { // Read another dentry chunk if we need to if ((int)d2 >= ((int)dentCache->u.inode + metaSize)) { if (inodeSync(&block_pos, metaSize, clink->u.inode->number_data)) break; cacheAdd(dentCache); if ((dentCache=getDentriesChunk(&block_pos, (int *)&result))==0) break; d=dentCache->u.dentry; } for (d2=(pfs_dentry*)((int)d+512); d < d2; (int)d+=aLen) { aLen=(d->aLen & 0xFFF); if (aLen & 3){ printf("ps2fs: Error: dir-entry allocated length/4 != 0\n"); goto _exit; } if (aLen < ((d->pLen + 8 + 3) & 0x1FC)){ printf("ps2fs: Error: dir-entry is too small\n"); goto _exit; } if ((u32)d2 < ((u32)d + aLen)){ printf("ps2fs: Error: dir-entry across sectors\n"); goto _exit; } // decide if the current dentry meets the required criteria, based on 'option' switch(option) { case 0: // result = 1 when paths are equal result = (len==d->pLen) && (memcmp(path, d->path, d->pLen)==0); break; case 1: // hrm.. result = ((d->inode) || (aLen < dentryLen)) ? ((aLen - ((d->pLen + 8 + 3) & 0x1FC)) > dentryLen) : 1; break; case 2: // result = 1 when dir path is not empty, "." or ".." result = d->pLen && strcmp(d->path, ".") && strcmp(d->path, ".."); break; default: goto _exit; } if (result) { *dentry=d; cacheAdd(block_pos.inode); return dentCache; } *size+=aLen; } } _exit: cacheAdd(dentCache); } cacheAdd(block_pos.inode); return NULL; }
void ioctl2Free(pfs_cache_t *pfree) { pfs_blockinfo b; int result; pfs_mount_t *pfsMount = pfree->pfsMount; pfs_inode *inode = pfree->u.inode; u32 nextsegdesc = 1, limit = inode->number_data, i, j = 0, zones; pfs_blockinfo *bi; pfs_cache_t *clink; zones = inode->size / pfsMount->zsize; if(inode->size % pfsMount->zsize) zones++; if(inode->number_segdesg + zones == inode->number_blocks) return; j = zones; b.number = 0; clink = cacheUsedAdd(pfree); // iterate through each of the block segments used by the inode for (i = 1; i < limit && j; i++) { if(fixIndex(i) == 0) { if ((clink = blockGetNextSegment(clink, &result)) == 0) return; nextsegdesc++; } else if(j < clink->u.inode->data[fixIndex(i)].count) { clink->u.inode->data[fixIndex(i)].count -= j; b.subpart = clink->u.inode->data[fixIndex(i)].subpart; b.count = j; b.number = clink->u.inode->data[fixIndex(i)].number + clink->u.inode->data[fixIndex(i)].count; j = 0; clink->flags |= CACHE_FLAG_DIRTY; } else j -= clink->u.inode->data[fixIndex(i)].count; } pfree->u.inode->number_data = i; pfree->u.inode->number_blocks = zones + nextsegdesc; pfree->u.inode->number_segdesg = nextsegdesc; pfree->u.inode->last_segment.number = clink->u.inode->data[0].number; pfree->u.inode->last_segment.subpart= clink->u.inode->data[0].subpart; pfree->u.inode->last_segment.count = clink->u.inode->data[0].count; pfree->flags |= CACHE_FLAG_DIRTY; if (b.number) bitmapFreeBlockSegment(pfsMount, &b); while(i < limit) { if (fixIndex(i) == 0) { if((clink = blockGetNextSegment(clink, &result)) == 0) return; } bi = &clink->u.inode->data[fixIndex(i++)]; bitmapFreeBlockSegment(pfsMount, bi); cacheMarkClean(pfsMount, bi->subpart, bi->number<<pfsMount->inode_scale, (bi->number+bi->count)<<pfsMount->inode_scale); } cacheAdd(clink); }