- 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(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->st_mode = oh->st_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->st_uid = oh->st_uid;
- in->st_gid = oh->st_gid;
- in->st_atime = oh->st_atime;
- in->st_mtime = oh->st_mtime;
- in->st_ctime = oh->st_ctime;
- in->st_rdev = oh->st_rdev;
-#endif
- in->chunkId = chunk;
-
- }
- else if(!in->valid)
- {
- // we need to load this info
-
- in->valid = 1;
- in->variantType = oh->type;
-
- in->st_mode = oh->st_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->st_uid = oh->st_uid;
- in->st_gid = oh->st_gid;
- in->st_atime = oh->st_atime;
- in->st_mtime = oh->st_mtime;
- in->st_ctime = oh->st_ctime;
- in->st_rdev = oh->st_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: // Do nothing
- in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
- break;
- }
-
- if(parent == dev->deletedDir)
- {
- yaffs_DestroyObject(in);
- bi->hasShrinkHeader = 1;
- }
- //T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType));
- }
- }
- }
-
- 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.
- 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);
-