- * This code assumes that we don't ever change the current relationships between
- * directories:
- * rootDir->parent == unlinkedDir->parent == deletedDir->parent == NULL
- * lostNfound->parent == rootDir
- *
- * This fixes the problem where directories might have inadvertently been deleted
- * leaving the object "hanging" without being rooted in the directory tree.
- */
-
-static int yaffs_HasNULLParent(yaffs_Device *dev, yaffs_Object *obj)
-{
- return (obj == dev->deletedDir ||
- obj == dev->unlinkedDir||
- obj == dev->rootDir);
-}
-
-static void yaffs_FixHangingObjects(yaffs_Device *dev)
-{
- yaffs_Object *obj;
- yaffs_Object *parent;
- int i;
- struct ylist_head *lh;
- struct ylist_head *n;
- int depthLimit;
- int hanging;
-
-
- /* Iterate through the objects in each hash entry,
- * looking at each object.
- * Make sure it is rooted.
- */
-
- for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
- ylist_for_each_safe(lh, n, &dev->objectBucket[i].list) {
- if (lh) {
- obj = ylist_entry(lh, yaffs_Object, hashLink);
- parent= obj->parent;
-
- if(yaffs_HasNULLParent(dev,obj)){
- /* These directories are not hanging */
- hanging = 0;
- }
- else if(!parent || parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
- hanging = 1;
- else if(yaffs_HasNULLParent(dev,parent))
- hanging = 0;
- else {
- /*
- * Need to follow the parent chain to see if it is hanging.
- */
- hanging = 0;
- depthLimit=100;
-
- while(parent != dev->rootDir &&
- parent->parent &&
- parent->parent->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
- depthLimit > 0){
- parent = parent->parent;
- depthLimit--;
- }
- if(parent != dev->rootDir)
- hanging = 1;
- }
- if(hanging){
- T(YAFFS_TRACE_SCAN,
- (TSTR("Hanging object %d moved to lost and found" TENDSTR),
- obj->objectId));
- yaffs_AddObjectToDirectory(dev->lostNFoundDir,obj);
- }
- }
- }
- }
-}
-
-
-/*
- * Delete directory contents for cleaning up lost and found.
- */
-static void yaffs_DeleteDirectoryContents(yaffs_Object *dir)
-{
- yaffs_Object *obj;
- struct ylist_head *lh;
- struct ylist_head *n;
-
- if(dir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
- YBUG();
-
- ylist_for_each_safe(lh, n, &dir->variant.directoryVariant.children) {
- if (lh) {
- obj = ylist_entry(lh, yaffs_Object, siblings);
- if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
- yaffs_DeleteDirectoryContents(obj);
-
- T(YAFFS_TRACE_SCAN,
- (TSTR("Deleting lost_found object %d" TENDSTR),
- obj->objectId));
-
- /* Need to use UnlinkObject since Delete would not handle
- * hardlinked objects correctly.
- */
- yaffs_UnlinkObject(obj);
- }
- }
-
-}
-
-static void yaffs_EmptyLostAndFound(yaffs_Device *dev)
-{
- yaffs_DeleteDirectoryContents(dev->lostNFoundDir);
-}
-
-static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
-{
- __u8 *chunkData;
- yaffs_ObjectHeader *oh;
- yaffs_Device *dev;
- yaffs_ExtendedTags tags;
- int result;
- int alloc_failed = 0;
-
- if (!in)
- return;
-
- dev = in->myDev;
-
-#if 0
- T(YAFFS_TRACE_SCAN, (TSTR("details for object %d %s loaded" TENDSTR),
- in->objectId,
- in->lazyLoaded ? "not yet" : "already"));
-#endif
-
- if (in->lazyLoaded && in->hdrChunk > 0) {
- in->lazyLoaded = 0;
- chunkData = yaffs_GetTempBuffer(dev, __LINE__);
-
- result = yaffs_ReadChunkWithTagsFromNAND(dev, in->hdrChunk, chunkData, &tags);
- 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;
-
-#endif
- yaffs_SetObjectName(in, oh->name);
-
- if (in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
- in->variant.symLinkVariant.alias =
- yaffs_CloneString(oh->alias);
- if (!in->variant.symLinkVariant.alias)
- alloc_failed = 1; /* Not returned to caller */
- }
-
- yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
- }
-}
-
-/*------------------------------ Directory Functions ----------------------------- */
-
-/*
- *yaffs_UpdateParent() handles fixing a directories mtime and ctime when a new
- * link (ie. name) is created or deleted in the directory.
- *
- * ie.
- * create dir/a : update dir's mtime/ctime
- * rm dir/a: update dir's mtime/ctime
- * modify dir/a: don't update dir's mtimme/ctime