- for (i = lastDel; i >= startDel; i--) {
- /* NB this could be optimised somewhat,
- * eg. could retrieve the tags and write them without
- * using yaffs_DeleteChunk
- */
-
- chunkId = yaffs_FindAndDeleteChunkInFile(in, i, NULL);
- if (chunkId > 0) {
- if (chunkId <
- (dev->internalStartBlock * dev->nChunksPerBlock)
- || chunkId >=
- ((dev->internalEndBlock +
- 1) * dev->nChunksPerBlock)) {
- T(YAFFS_TRACE_ALWAYS,
- (TSTR("Found daft chunkId %d for %d" TENDSTR),
- chunkId, i));
- } else {
- in->nDataChunks--;
- yaffs_DeleteChunk(dev, chunkId, 1, __LINE__);
- }
- }
- }
-
-}
-
-int yaffs_ResizeFile(yaffs_Object * in, int newSize)
-{
-
- int oldFileSize = in->variant.fileVariant.fileSize;
- int sizeOfPartialChunk;
- yaffs_Device *dev = in->myDev;
-
- sizeOfPartialChunk = newSize % dev->nBytesPerChunk;
-
- yaffs_FlushFilesChunkCache(in);
- yaffs_InvalidateWholeChunkCache(in);
-
- yaffs_CheckGarbageCollection(dev);
-
- if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
- return yaffs_GetFileSize(in);
- }
-
- if (newSize == oldFileSize) {
- return oldFileSize;
- }
-
- if (newSize < oldFileSize) {
-
- yaffs_PruneResizedChunks(in, newSize);
-
- if (sizeOfPartialChunk != 0) {
- int lastChunk = 1 + newSize / dev->nBytesPerChunk;
- __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
-
- /* Got to read and rewrite the last chunk with its new size and zero pad */
- yaffs_ReadChunkDataFromObject(in, lastChunk,
- localBuffer);
-
- memset(localBuffer + sizeOfPartialChunk, 0,
- dev->nBytesPerChunk - sizeOfPartialChunk);
-
- yaffs_WriteChunkDataToObject(in, lastChunk, localBuffer,
- sizeOfPartialChunk, 1);
-
- yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
- }
-
- in->variant.fileVariant.fileSize = newSize;
-
- yaffs_PruneFileStructure(dev, &in->variant.fileVariant);
- }
- /* Write a new object header.
- * show we've shrunk the file, if need be
- * Do this only if the file is not in the deleted directories.
- */
- if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
- in->parent->objectId != YAFFS_OBJECTID_DELETED) {
- yaffs_UpdateObjectHeader(in, NULL, 0,
- (newSize < oldFileSize) ? 1 : 0, 0);
- }
-
- return newSize;
-}
-
-loff_t yaffs_GetFileSize(yaffs_Object * obj)
-{
- obj = yaffs_GetEquivalentObject(obj);
-
- switch (obj->variantType) {
- case YAFFS_OBJECT_TYPE_FILE:
- return obj->variant.fileVariant.fileSize;
- case YAFFS_OBJECT_TYPE_SYMLINK:
- return yaffs_strlen(obj->variant.symLinkVariant.alias);
- default:
- return 0;
- }
-}
-
-
-
-int yaffs_FlushFile(yaffs_Object * in, int updateTime)
-{
- int retVal;
- if (in->dirty) {
- yaffs_FlushFilesChunkCache(in);
- if (updateTime) {
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_WinFileTimeNow(in->win_mtime);
-#else
-
- in->yst_mtime = Y_CURRENT_TIME;
-
-#endif
- }
-
- retVal =
- (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >=
- 0) ? YAFFS_OK : YAFFS_FAIL;
- } else {
- retVal = YAFFS_OK;
- }
-
- return retVal;
-
-}
-
-static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
-{
-
- /* First off, invalidate the file's data in the cache, without flushing. */
- yaffs_InvalidateWholeChunkCache(in);
-
- if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
- /* Move to the unlinked directory so we have a record that it was deleted. */
- yaffs_ChangeObjectName(in, in->myDev->deletedDir, NULL, 0, 0);
-
- }
-
- yaffs_RemoveObjectFromDirectory(in);
- yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
- in->chunkId = -1;
-
- yaffs_FreeObject(in);
- return YAFFS_OK;
-
-}
-
-/* yaffs_DeleteFile deletes the whole file data
- * and the inode associated with the file.
- * It does not delete the links associated with the file.
- */
-static int yaffs_UnlinkFile(yaffs_Object * in)
-{
-
- int retVal;
- int immediateDeletion = 0;
-
- if (1) {
-#ifdef __KERNEL__
- if (!in->myInode) {
- immediateDeletion = 1;
-
- }
-#else
- if (in->inUse <= 0) {
- immediateDeletion = 1;
-
- }
-#endif
- if (immediateDeletion) {
- retVal =
- yaffs_ChangeObjectName(in, in->myDev->deletedDir,
- NULL, 0, 0);
- T(YAFFS_TRACE_TRACING,
- (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
- in->objectId));
- in->deleted = 1;
- in->myDev->nDeletedFiles++;
- if (0 && in->myDev->isYaffs2) {
- yaffs_ResizeFile(in, 0);
- }
- yaffs_SoftDeleteFile(in);
- } else {
- retVal =
- yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
- NULL, 0, 0);
- }
-
- }
- return retVal;
-}
-
-int yaffs_DeleteFile(yaffs_Object * in)
-{
- int retVal = YAFFS_OK;
-
- if (in->nDataChunks > 0) {
- /* Use soft deletion if there is data in the file */
- if (!in->unlinked) {
- retVal = yaffs_UnlinkFile(in);
- }
- if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
- in->deleted = 1;
- in->myDev->nDeletedFiles++;
- yaffs_SoftDeleteFile(in);
- }
- return in->deleted ? YAFFS_OK : YAFFS_FAIL;
- } else {
- /* The file has no data chunks so we toss it immediately */
- yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
- in->variant.fileVariant.top = NULL;
- yaffs_DoGenericObjectDeletion(in);
-
- return YAFFS_OK;
- }
-}
-
-static int yaffs_DeleteDirectory(yaffs_Object * in)
-{
- /* First check that the directory is empty. */
- if (list_empty(&in->variant.directoryVariant.children)) {
- return yaffs_DoGenericObjectDeletion(in);
- }
-
- return YAFFS_FAIL;
-
-}
-
-static int yaffs_DeleteSymLink(yaffs_Object * in)
-{
- YFREE(in->variant.symLinkVariant.alias);
-
- return yaffs_DoGenericObjectDeletion(in);
-}
-
-static int yaffs_DeleteHardLink(yaffs_Object * in)
-{
- /* remove this hardlink from the list assocaited with the equivalent
- * object
- */
- list_del(&in->hardLinks);
- return yaffs_DoGenericObjectDeletion(in);
-}
-
-static void yaffs_DestroyObject(yaffs_Object * obj)
-{
- switch (obj->variantType) {
- case YAFFS_OBJECT_TYPE_FILE:
- yaffs_DeleteFile(obj);
- break;
- case YAFFS_OBJECT_TYPE_DIRECTORY:
- yaffs_DeleteDirectory(obj);
- break;
- case YAFFS_OBJECT_TYPE_SYMLINK:
- yaffs_DeleteSymLink(obj);
- break;
- case YAFFS_OBJECT_TYPE_HARDLINK:
- yaffs_DeleteHardLink(obj);
- break;
- case YAFFS_OBJECT_TYPE_SPECIAL:
- yaffs_DoGenericObjectDeletion(obj);
- break;
- case YAFFS_OBJECT_TYPE_UNKNOWN:
- break; /* should not happen. */
- }
-}
-
-static int yaffs_UnlinkWorker(yaffs_Object * obj)
-{
-
- if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
- return yaffs_DeleteHardLink(obj);
- } else if (!list_empty(&obj->hardLinks)) {
- /* Curve ball: We're unlinking an object that has a hardlink.
- *
- * This problem arises because we are not strictly following
- * The Linux link/inode model.
- *
- * We can't really delete the object.
- * Instead, we do the following:
- * - Select a hardlink.
- * - Unhook it from the hard links
- * - Unhook it from its parent directory (so that the rename can work)
- * - Rename the object to the hardlink's name.
- * - Delete the hardlink
- */
-
- yaffs_Object *hl;
- int retVal;
- YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
-
- hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
-
- list_del_init(&hl->hardLinks);
- list_del_init(&hl->siblings);
-
- yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
-
- retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
-
- if (retVal == YAFFS_OK) {
- retVal = yaffs_DoGenericObjectDeletion(hl);
- }
- return retVal;
-
- } else {
- switch (obj->variantType) {
- case YAFFS_OBJECT_TYPE_FILE:
- return yaffs_UnlinkFile(obj);
- break;
- case YAFFS_OBJECT_TYPE_DIRECTORY:
- return yaffs_DeleteDirectory(obj);
- break;
- case YAFFS_OBJECT_TYPE_SYMLINK:
- return yaffs_DeleteSymLink(obj);
- break;
- case YAFFS_OBJECT_TYPE_SPECIAL:
- return yaffs_DoGenericObjectDeletion(obj);
- break;
- case YAFFS_OBJECT_TYPE_HARDLINK:
- case YAFFS_OBJECT_TYPE_UNKNOWN:
- default:
- return YAFFS_FAIL;
- }
- }
-}
-
-
-static int yaffs_UnlinkObject( yaffs_Object *obj)
-{
-
- if (obj && obj->unlinkAllowed) {
- return yaffs_UnlinkWorker(obj);
- }
-
- return YAFFS_FAIL;
-
-}
-int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name)
-{
- yaffs_Object *obj;
-
- obj = yaffs_FindObjectByName(dir, name);
- return yaffs_UnlinkObject(obj);
-}
-
-/*----------------------- Initialisation Scanning ---------------------- */
-
-static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,
- int backwardScanning)
-{
- yaffs_Object *obj;
-
- if (!backwardScanning) {
- /* Handle YAFFS1 forward scanning case
- * For YAFFS1 we always do the deletion
- */
-
- } else {
- /* Handle YAFFS2 case (backward scanning)
- * If the shadowed object exists then ignore.
- */
- if (yaffs_FindObjectByNumber(dev, objId)) {
- return;
- }
- }
-
- /* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc.
- * We put it in unlinked dir to be cleaned up after the scanning
- */
- obj =
- yaffs_FindOrCreateObjectByNumber(dev, objId,
- YAFFS_OBJECT_TYPE_FILE);
- yaffs_AddObjectToDirectory(dev->unlinkedDir, obj);
- obj->variant.fileVariant.shrinkSize = 0;
- obj->valid = 1; /* So that we don't read any other info for this file */
-
-}
-
-typedef struct {
- int seq;
- int block;
-} yaffs_BlockIndex;
-
-
-static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)
-{
- yaffs_Object *hl;
- yaffs_Object *in;
-
- while (hardList) {
- hl = hardList;
- hardList = (yaffs_Object *) (hardList->hardLinks.next);
-
- in = yaffs_FindObjectByNumber(dev,
- hl->variant.hardLinkVariant.
- equivalentObjectId);
-
- if (in) {
- /* Add the hardlink pointers */
- hl->variant.hardLinkVariant.equivalentObject = in;
- list_add(&hl->hardLinks, &in->hardLinks);
- } else {
- /* Todo Need to report/handle this better.
- * Got a problem... hardlink to a non-existant object
- */
- hl->variant.hardLinkVariant.equivalentObject = NULL;
- INIT_LIST_HEAD(&hl->hardLinks);
-
- }
-
- }
-
-}
-
-
-
-
-
-static int yaffs_Scan(yaffs_Device * dev)
-{
- yaffs_ExtendedTags tags;
- int blk;
- int blockIterator;
- int startIterator;
- int endIterator;
- int nBlocksToScan = 0;
-
- int chunk;
- int c;
- int deleted;
- yaffs_BlockState state;
- yaffs_Object *hardList = NULL;
- yaffs_Object *hl;
- yaffs_BlockInfo *bi;
- int sequenceNumber;
- yaffs_ObjectHeader *oh;
- yaffs_Object *in;
- yaffs_Object *parent;
- int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
-
- __u8 *chunkData;
-
- yaffs_BlockIndex *blockIndex = NULL;
-
- T(YAFFS_TRACE_SCAN,
- (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR),
- dev->internalStartBlock, dev->internalEndBlock));
-
- chunkData = yaffs_GetTempBuffer(dev, __LINE__);
-
- dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
-
- if (dev->isYaffs2) {
- blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
- }
-
- /* Scan all the blocks to determine their state */
- for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
- bi = yaffs_GetBlockInfo(dev, blk);
- yaffs_ClearChunkBits(dev, blk);
- bi->pagesInUse = 0;
- bi->softDeletions = 0;
-
- yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
-
- bi->blockState = state;
- bi->sequenceNumber = sequenceNumber;
-
- T(YAFFS_TRACE_SCAN_DEBUG,
- (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
- state, sequenceNumber));
-
- if (state == YAFFS_BLOCK_STATE_DEAD) {
- T(YAFFS_TRACE_BAD_BLOCKS,
- (TSTR("block %d is bad" TENDSTR), blk));
- } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
- T(YAFFS_TRACE_SCAN_DEBUG,
- (TSTR("Block empty " TENDSTR)));
- dev->nErasedBlocks++;
- dev->nFreeChunks += dev->nChunksPerBlock;
- } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
-
- /* Determine the highest sequence number */
- if (dev->isYaffs2 &&
- sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
- sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
-
- blockIndex[nBlocksToScan].seq = sequenceNumber;
- blockIndex[nBlocksToScan].block = blk;
-
- nBlocksToScan++;
-
- if (sequenceNumber >= dev->sequenceNumber) {
- dev->sequenceNumber = sequenceNumber;
- }
- } else if (dev->isYaffs2) {
- /* TODO: Nasty sequence number! */
- T(YAFFS_TRACE_SCAN,
- (TSTR
- ("Block scanning block %d has bad sequence number %d"
- TENDSTR), blk, sequenceNumber));
-
- }
- }
- }
-
- /* Sort the blocks
- * Dungy old bubble sort for now...
- */
- if (dev->isYaffs2) {
- yaffs_BlockIndex temp;
- int i;
- int j;
-
- for (i = 0; i < nBlocksToScan; i++)
- for (j = i + 1; j < nBlocksToScan; j++)
- if (blockIndex[i].seq > blockIndex[j].seq) {
- temp = blockIndex[j];
- blockIndex[j] = blockIndex[i];
- blockIndex[i] = temp;
- }
- }
-
- /* Now scan the blocks looking at the data. */
- if (dev->isYaffs2) {
- startIterator = 0;
- endIterator = nBlocksToScan - 1;
- T(YAFFS_TRACE_SCAN_DEBUG,
- (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
- } else {
- startIterator = dev->internalStartBlock;
- endIterator = dev->internalEndBlock;
- }
-
- /* For each block.... */
- for (blockIterator = startIterator; blockIterator <= endIterator;
- blockIterator++) {
-
- if (dev->isYaffs2) {
- /* get the block to scan in the correct order */
- blk = blockIndex[blockIterator].block;
- } else {
- blk = blockIterator;
- }
-
- bi = yaffs_GetBlockInfo(dev, blk);
- state = bi->blockState;
-
- deleted = 0;
-
- /* For each chunk in each block that needs scanning....*/
- for (c = 0; c < dev->nChunksPerBlock &&
- state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {
- /* Read the tags and decide what to do */
- chunk = blk * dev->nChunksPerBlock + c;
-
- yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
- &tags);
-
- /* Let's have a good look at this chunk... */
-
- if (!dev->isYaffs2 && tags.chunkDeleted) {
- /* YAFFS1 only...
- * A deleted chunk
- */
- deleted++;
- dev->nFreeChunks++;
- /*T((" %d %d deleted\n",blk,c)); */
- } else if (!tags.chunkUsed) {
- /* An unassigned chunk in the block
- * This means that either the block is empty or
- * this is the one being allocated from
- */
-
- if (c == 0) {
- /* We're looking at the first chunk in the block so the block is unused */
- state = YAFFS_BLOCK_STATE_EMPTY;
- dev->nErasedBlocks++;
- } else {
- /* this is the block being allocated from */
- T(YAFFS_TRACE_SCAN,
- (TSTR
- (" Allocating from %d %d" TENDSTR),
- blk, c));
- state = YAFFS_BLOCK_STATE_ALLOCATING;
- dev->allocationBlock = blk;
- dev->allocationPage = c;
- dev->allocationBlockFinder = blk;
- /* Set it to here to encourage the allocator to go forth from here. */
-
- /* Yaffs2 sanity check:
- * This should be the one with the highest sequence number
- */
- if (dev->isYaffs2
- && (dev->sequenceNumber !=
- bi->sequenceNumber)) {
- T(YAFFS_TRACE_ALWAYS,
- (TSTR
- ("yaffs: Allocation block %d was not highest sequence id:"
- " block seq = %d, dev seq = %d"
- TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
- }
- }
-
- dev->nFreeChunks += (dev->nChunksPerBlock - c);
- } else if (tags.chunkId > 0) {
- /* chunkId > 0 so it is a data chunk... */
- unsigned int endpos;
-
- yaffs_SetChunkBit(dev, blk, c);
- bi->pagesInUse++;
-
- in = yaffs_FindOrCreateObjectByNumber(dev,
- tags.
- objectId,
- YAFFS_OBJECT_TYPE_FILE);
- /* PutChunkIntoFile checks for a clash (two data chunks with
- * the same chunkId).
- */
- yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,
- 1);
- endpos =
- (tags.chunkId - 1) * dev->nBytesPerChunk +
- tags.byteCount;
- if (in->variantType == YAFFS_OBJECT_TYPE_FILE
- && in->variant.fileVariant.scannedFileSize <
- endpos) {
- in->variant.fileVariant.
- scannedFileSize = endpos;
- if (!dev->useHeaderFileSize) {
- in->variant.fileVariant.
- fileSize =
- in->variant.fileVariant.
- scannedFileSize;
- }
-
- }
- /* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); */
- } else {
- /* chunkId == 0, so it is an ObjectHeader.
- * Thus, we read in the object header and make the object
- */
- yaffs_SetChunkBit(dev, blk, c);
- bi->pagesInUse++;
-
- yaffs_ReadChunkWithTagsFromNAND(dev, chunk,
- chunkData,
- NULL);
-
- oh = (yaffs_ObjectHeader *) chunkData;
-
- in = yaffs_FindObjectByNumber(dev,
- tags.objectId);
- if (in && in->variantType != oh->type) {
- /* This should not happen, but somehow
- * Wev'e ended up with an objectId that has been reused but not yet
- * deleted, and worse still it has changed type. Delete the old object.
- */
-
- yaffs_DestroyObject(in);
-
- in = 0;
- }
-
- in = yaffs_FindOrCreateObjectByNumber(dev,
- tags.
- objectId,
- oh->type);
-
- if (oh->shadowsObject > 0) {
- yaffs_HandleShadowedObject(dev,
- oh->
- shadowsObject,
- 0);
- }
-
- if (in->valid) {
- /* We have already filled this one. We have a duplicate and need to resolve it. */
-
- unsigned existingSerial = in->serial;
- unsigned newSerial = tags.serialNumber;
-
- if (dev->isYaffs2 ||
- ((existingSerial + 1) & 3) ==
- newSerial) {
- /* Use new one - destroy the exisiting one */
- yaffs_DeleteChunk(dev,
- in->chunkId,
- 1, __LINE__);
- in->valid = 0;
- } else {
- /* Use existing - destroy this one. */
- yaffs_DeleteChunk(dev, chunk, 1,
- __LINE__);
- }
- }
-
- if (!in->valid &&
- (tags.objectId == YAFFS_OBJECTID_ROOT ||
- tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) {
- /* We only load some info, don't fiddle with directory structure */
- in->valid = 1;
- in->variantType = oh->type;
-
- in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
-#else
- in->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
-#endif
- in->chunkId = chunk;
-
- } else if (!in->valid) {
- /* we need to load this info */
-
- in->valid = 1;
- in->variantType = oh->type;
-
- in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
-#else
- in->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
-#endif
- in->chunkId = chunk;
-
- yaffs_SetObjectName(in, oh->name);
- in->dirty = 0;
-
- /* directory stuff...
- * hook up to parent
- */
-
- parent =
- yaffs_FindOrCreateObjectByNumber
- (dev, oh->parentObjectId,
- YAFFS_OBJECT_TYPE_DIRECTORY);
- if (parent->variantType ==
- YAFFS_OBJECT_TYPE_UNKNOWN) {
- /* Set up as a directory */
- parent->variantType =
- YAFFS_OBJECT_TYPE_DIRECTORY;
- INIT_LIST_HEAD(&parent->variant.
- directoryVariant.
- children);
- } else if (parent->variantType !=
- YAFFS_OBJECT_TYPE_DIRECTORY)
- {
- /* Hoosterman, another problem....
- * We're trying to use a non-directory as a directory
- */
-
- T(YAFFS_TRACE_ERROR,
- (TSTR
- ("yaffs tragedy: attempting to use non-directory as"
- " a directory in scan. Put in lost+found."
- TENDSTR)));
- parent = dev->lostNFoundDir;
- }
-
- yaffs_AddObjectToDirectory(parent, in);
-
- if (0 && (parent == dev->deletedDir ||
- parent == dev->unlinkedDir)) {
- in->deleted = 1; /* If it is unlinked at start up then it wants deleting */
- dev->nDeletedFiles++;
- }
- /* Note re hardlinks.
- * Since we might scan a hardlink before its equivalent object is scanned
- * we put them all in a list.
- * After scanning is complete, we should have all the objects, so we run through this
- * list and fix up all the chains.
- */
-
- switch (in->variantType) {
- case YAFFS_OBJECT_TYPE_UNKNOWN:
- /* Todo got a problem */
- break;
- case YAFFS_OBJECT_TYPE_FILE:
- if (dev->isYaffs2
- && oh->isShrink) {
- /* Prune back the shrunken chunks */
- yaffs_PruneResizedChunks
- (in, oh->fileSize);
- /* Mark the block as having a shrinkHeader */
- bi->hasShrinkHeader = 1;
- }
-
- if (dev->useHeaderFileSize)
-
- in->variant.fileVariant.
- fileSize =
- oh->fileSize;
-
- break;
- case YAFFS_OBJECT_TYPE_HARDLINK:
- in->variant.hardLinkVariant.
- equivalentObjectId =
- oh->equivalentObjectId;
- in->hardLinks.next =
- (struct list_head *)
- hardList;
- hardList = in;
- break;
- case YAFFS_OBJECT_TYPE_DIRECTORY:
- /* Do nothing */
- break;
- case YAFFS_OBJECT_TYPE_SPECIAL:
- /* Do nothing */
- break;
- case YAFFS_OBJECT_TYPE_SYMLINK:
- in->variant.symLinkVariant.
- alias =
- yaffs_CloneString(oh->alias);
- break;
- }
-
- if (parent == dev->deletedDir) {
- yaffs_DestroyObject(in);
- bi->hasShrinkHeader = 1;
- }
- }
- }
- }
-
- if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
- /* If we got this far while scanning, then the block is fully allocated.*/
- state = YAFFS_BLOCK_STATE_FULL;
- }
-
- bi->blockState = state;
-
- /* Now let's see if it was dirty */
- if (bi->pagesInUse == 0 &&
- !bi->hasShrinkHeader &&
- bi->blockState == YAFFS_BLOCK_STATE_FULL) {
- yaffs_BlockBecameDirty(dev, blk);
- }
-
- }
-
- if (blockIndex) {
- YFREE(blockIndex);
- }
-
-
- /* Ok, we've done all the scanning.
- * Fix up the hard link chains.
- * We should now have scanned all the objects, now it's time to add these
- * hardlinks.
- */
-
- yaffs_HardlinkFixup(dev,hardList);
-
- /* Handle the unlinked files. Since they were left in an unlinked state we should
- * just delete them.
- */
- {
- struct list_head *i;
- struct list_head *n;
-
- yaffs_Object *l;
- /* Soft delete all the unlinked files */
- list_for_each_safe(i, n,
- &dev->unlinkedDir->variant.directoryVariant.
- children) {
- if (i) {
- l = list_entry(i, yaffs_Object, siblings);
- yaffs_DestroyObject(l);
- }
- }
- }
-
- yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
-
- T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
-
- return YAFFS_OK;
-}
-
-static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
-{
- __u8 *chunkData;
- yaffs_ObjectHeader *oh;
- yaffs_Device *dev = in->myDev;
-
- if(in->lazyLoaded){
- in->lazyLoaded = 0;
- chunkData = yaffs_GetTempBuffer(dev, __LINE__);
-
- yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,NULL);
- oh = (yaffs_ObjectHeader *) chunkData;
-
- in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
-#else
- in->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
-