+
+/*-----------------------------------------------------------------*/
+/* Directory search context allows us to unlock access to yaffs during
+ * filldir without causing problems with the directory being modified.
+ * This is similar to the tried and tested mechanism used in yaffs direct.
+ *
+ * A search context iterates along a doubly linked list of siblings in the
+ * directory. If the iterating object is deleted then this would corrupt
+ * the list iteration, likely causing a crash. The search context avoids
+ * this by using the removeObjectCallback to move the search context to the
+ * next object before the object is deleted.
+ *
+ * Many readdirs (and thus seach conexts) may be alive simulateously so
+ * each yaffs_Device has a list of these.
+ *
+ * A seach context lives for the duration of a readdir.
+ *
+ * All these functions must be called while yaffs is locked.
+ */
+
+struct yaffs_SearchContext {
+ yaffs_Device *dev;
+ yaffs_Object *dirObj;
+ yaffs_Object *nextReturn;
+ struct ylist_head others;
+};
+
+/*
+ * yaffs_NewSearch() creates a new search context, initialises it and
+ * adds it to the device's search context list.
+ *
+ * Called at start of readdir.
+ */
+static struct yaffs_SearchContext * yaffs_NewSearch(yaffs_Object *dir)
+{
+ yaffs_Device *dev = dir->myDev;
+ struct yaffs_SearchContext *sc = YMALLOC(sizeof(struct yaffs_SearchContext));
+ if(sc){
+ sc->dirObj = dir;
+ sc->dev = dev;
+ if( ylist_empty(&sc->dirObj->variant.directoryVariant.children))
+ sc->nextReturn = NULL;
+ else
+ sc->nextReturn = ylist_entry(
+ dir->variant.directoryVariant.children.next,
+ yaffs_Object,siblings);
+ YINIT_LIST_HEAD(&sc->others);
+ ylist_add(&sc->others,&dev->searchContexts);
+ }
+ return sc;
+}
+
+/*
+ * yaffs_EndSearch() disposes of a search context and cleans up.
+ */
+static void yaffs_EndSearch(struct yaffs_SearchContext * sc)
+{
+ if(sc){
+ ylist_del(&sc->others);
+ YFREE(sc);
+ }