+ yaffsfs_Lock();
+ if (!dev)
+ dev = yaffsfs_FindDevice(path, &dummy);
+ if (dev && dev->is_mounted) {
+ retVal = yaffs_get_n_free_chunks(dev);
+ retVal *= dev->data_bytes_per_chunk;
+
+ } else
+ yaffsfs_SetError(-EINVAL);
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+Y_LOFF_T yaffs_freespace_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_freespace_common(dev, NULL);
+}
+
+Y_LOFF_T yaffs_freespace(const YCHAR *path)
+{
+ return yaffs_freespace_common(NULL, path);
+}
+
+Y_LOFF_T yaffs_totalspace_common(struct yaffs_dev *dev, const YCHAR *path)
+{
+ Y_LOFF_T retVal = -1;
+ YCHAR *dummy;
+
+ if (!dev) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+ }
+
+ yaffsfs_Lock();
+ if (!dev)
+ dev = yaffsfs_FindDevice(path, &dummy);
+ if (dev && dev->is_mounted) {
+ retVal = (dev->param.end_block - dev->param.start_block + 1) -
+ dev->param.n_reserved_blocks;
+ retVal *= dev->param.chunks_per_block;
+ retVal *= dev->data_bytes_per_chunk;
+
+ } else
+ yaffsfs_SetError(-EINVAL);
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+Y_LOFF_T yaffs_totalspace_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_totalspace_common(dev, NULL);
+}
+
+Y_LOFF_T yaffs_totalspace(const YCHAR *path)
+{
+ return yaffs_totalspace_common(NULL, path);
+}
+
+int yaffs_inodecount_common(struct yaffs_dev *dev, const YCHAR *path)
+{
+ Y_LOFF_T retVal = -1;
+ YCHAR *dummy;
+
+ if (!dev) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+ }
+
+ yaffsfs_Lock();
+ if (!dev)
+ dev = yaffsfs_FindDevice(path, &dummy);
+ if (dev && dev->is_mounted) {
+ int n_obj = dev->n_obj;
+ if (n_obj > dev->n_hardlinks)
+ retVal = n_obj - dev->n_hardlinks;
+ }
+
+ if (retVal < 0)
+ yaffsfs_SetError(-EINVAL);
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+int yaffs_inodecount_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_inodecount_common(dev, NULL);
+}
+
+int yaffs_inodecount(const YCHAR *path)
+{
+ return yaffs_inodecount_common(NULL, path);
+}
+
+void yaffs_add_device(struct yaffs_dev *dev)
+{
+ struct list_head *cfg;
+ /* First check that the device is not in the list. */
+
+ list_for_each(cfg, &yaffsfs_deviceList) {
+ if (dev == list_entry(cfg, struct yaffs_dev, dev_list))
+ return;
+ }
+
+ dev->is_mounted = 0;
+ dev->param.remove_obj_fn = yaffsfs_RemoveObjectCallback;
+
+ if (!dev->dev_list.next)
+ INIT_LIST_HEAD(&dev->dev_list);
+
+ list_add(&dev->dev_list, &yaffsfs_deviceList);
+
+
+}
+
+void yaffs_remove_device(struct yaffs_dev *dev)
+{
+ list_del_init(&dev->dev_list);
+}
+
+/* Functions to iterate through devices. NB Use with extreme care! */
+
+static struct list_head *dev_iterator;
+void yaffs_dev_rewind(void)
+{
+ dev_iterator = yaffsfs_deviceList.next;
+}
+
+struct yaffs_dev *yaffs_next_dev(void)
+{
+ struct yaffs_dev *retval;
+
+ if (!dev_iterator)
+ return NULL;
+ if (dev_iterator == &yaffsfs_deviceList)
+ return NULL;
+
+ retval = list_entry(dev_iterator, struct yaffs_dev, dev_list);
+ dev_iterator = dev_iterator->next;
+ return retval;
+}
+
+/* Directory search stuff. */
+
+static struct list_head search_contexts;
+
+static void yaffsfs_SetDirRewound(struct yaffsfs_DirSearchContext *dsc)
+{
+ if (dsc &&
+ dsc->dirObj &&
+ dsc->dirObj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) {
+
+ dsc->offset = 0;
+
+ if (list_empty(&dsc->dirObj->variant.dir_variant.children))
+ dsc->nextReturn = NULL;
+ else
+ dsc->nextReturn =
+ list_entry(dsc->dirObj->variant.dir_variant.
+ children.next, struct yaffs_obj,
+ siblings);
+ } else {