+ retVal = yaffsfs_DoChMod(obj, mode);
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+int yaffs_mkdir_reldir(struct yaffs_obj *reldir, const YCHAR *path, mode_t mode)
+{
+ struct yaffs_obj *parent = NULL;
+ struct yaffs_obj *dir = NULL;
+ YCHAR *name;
+ YCHAR *alt_path = NULL;
+ int retVal = -1;
+ int notDir = 0;
+ int loop = 0;
+
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+
+ if (yaffsfs_alt_dir_path(path, &alt_path) < 0) {
+ yaffsfs_SetError(-ENOMEM);
+ return -1;
+ }
+ if (alt_path)
+ path = alt_path;
+
+ yaffsfs_Lock();
+ parent = yaffsfs_FindDirectory(reldir, path, &name, 0, ¬Dir, &loop);
+ if (!parent && notDir)
+ yaffsfs_SetError(-ENOTDIR);
+ else if (loop)
+ yaffsfs_SetError(-ELOOP);
+ else if (!parent)
+ yaffsfs_SetError(-ENOENT);
+ else if (yaffsfs_TooManyObjects(parent->my_dev))
+ yaffsfs_SetError(-ENFILE);
+ else if (yaffs_strnlen(name, 5) == 0) {
+ /* Trying to make the root itself */
+ yaffsfs_SetError(-EEXIST);
+ } else if (parent->my_dev->read_only)
+ yaffsfs_SetError(-EROFS);
+ else {
+ dir = yaffs_create_dir(parent, name, mode, 0, 0);
+ if (dir)
+ retVal = 0;
+ else if (yaffs_find_by_name(parent, name))
+ yaffsfs_SetError(-EEXIST); /* name exists */
+ else
+ yaffsfs_SetError(-ENOSPC); /* assume no space */
+ }
+
+ yaffsfs_Unlock();
+
+ kfree(alt_path);
+
+ return retVal;
+}
+
+int yaffs_mkdir_reldev(struct yaffs_dev *dev, const YCHAR *path, mode_t mode)
+{
+ return yaffs_mkdir_reldir(ROOT_DIR(dev), path, mode);
+}
+
+int yaffs_mkdir(const YCHAR *path, mode_t mode)
+{
+ return yaffs_mkdir_reldir(NULL, path, mode);
+}
+
+int yaffs_rmdir_reldir(struct yaffs_obj *reldir, const YCHAR *path)
+{
+ int result;
+ YCHAR *alt_path;
+
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+
+ if (yaffsfs_alt_dir_path(path, &alt_path) < 0) {
+ yaffsfs_SetError(-ENOMEM);
+ return -1;
+ }
+ if (alt_path)
+ path = alt_path;
+ result = yaffsfs_DoUnlink_reldir(reldir, path, 1);
+
+ kfree(alt_path);
+
+ return result;
+}
+
+int yaffs_rmdir_reldev(struct yaffs_dev *dev, const YCHAR *path)
+{
+ return yaffs_rmdir_reldir(ROOT_DIR(dev), path);
+}
+
+int yaffs_rmdir(const YCHAR *path)
+{
+ return yaffs_rmdir_reldir(NULL, path);
+}
+
+/*
+ * The mount/unmount/sync functions act on devices rather than reldirs.
+ */
+void *yaffs_getdev(const YCHAR *path)
+{
+ struct yaffs_dev *dev = NULL;
+ YCHAR *dummy;
+ dev = yaffsfs_FindDevice(path, &dummy);
+ return (void *)dev;
+}
+
+int yaffs_mount_common(struct yaffs_dev *dev, const YCHAR *path,
+ int read_only, int skip_checkpt)
+{
+ int retVal = -1;
+ int result = YAFFS_FAIL;
+
+ if (!dev) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ yaffs_trace(YAFFS_TRACE_MOUNT, "yaffs: Mounting %s", path);
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+ }
+
+ yaffsfs_Lock();
+
+ yaffsfs_InitHandles();
+
+ if (!dev)
+ dev = yaffsfs_FindMountPoint(path);
+
+ if (dev) {
+ if (!dev->is_mounted) {
+ dev->read_only = read_only ? 1 : 0;
+ if (skip_checkpt) {
+ u8 skip = dev->param.skip_checkpt_rd;
+ dev->param.skip_checkpt_rd = 1;
+ result = yaffs_guts_initialise(dev);
+ dev->param.skip_checkpt_rd = skip;
+ } else {
+ result = yaffs_guts_initialise(dev);
+ }
+
+ if (result == YAFFS_FAIL)
+ yaffsfs_SetError(-ENOMEM);
+ retVal = result ? 0 : -1;
+
+ } else
+ yaffsfs_SetError(-EBUSY);
+ } else
+ yaffsfs_SetError(-ENODEV);
+
+ yaffsfs_Unlock();
+ return retVal;
+
+}
+
+int yaffs_mount3_reldev(struct yaffs_dev *dev, int read_only, int skip_checkpt)
+{
+ return yaffs_mount_common(dev, NULL, read_only, skip_checkpt);
+}
+
+int yaffs_mount3(const YCHAR *path, int read_only, int skip_checkpt)
+{
+ return yaffs_mount_common(NULL, path, read_only, skip_checkpt);
+}
+
+int yaffs_mount2_reldev(struct yaffs_dev *dev, int readonly)
+{
+ return yaffs_mount_common(dev, NULL, readonly, 0);
+}
+
+int yaffs_mount2(const YCHAR *path, int readonly)
+{
+ return yaffs_mount_common(NULL, path, readonly, 0);
+}
+
+int yaffs_mount_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_mount_common(dev, NULL, 0, 0);
+}
+
+int yaffs_mount(const YCHAR *path)
+{
+ return yaffs_mount_common(NULL, path, 0, 0);
+}
+
+static int yaffs_sync_common(struct yaffs_dev *dev,
+ const YCHAR *path,
+ int do_checkpt)
+{
+ int 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) {
+ if (!dev->is_mounted)
+ yaffsfs_SetError(-EINVAL);
+ else if (dev->read_only)
+ yaffsfs_SetError(-EROFS);
+ else {
+
+ yaffs_flush_whole_cache(dev, 0);
+ if (do_checkpt)
+ yaffs_checkpoint_save(dev);
+ retVal = 0;
+
+ }
+ } else
+ yaffsfs_SetError(-ENODEV);
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+int yaffs_sync_files_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_sync_common(dev, NULL, 0);
+}
+
+int yaffs_sync_files(const YCHAR *path)
+{
+ return yaffs_sync_common(NULL, path, 0);
+}
+
+int yaffs_sync_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_sync_common(dev, NULL, 1);
+}
+
+int yaffs_sync(const YCHAR *path)
+{
+ return yaffs_sync_common(NULL, path, 1);
+}
+
+
+static int yaffsfs_bg_gc_common(struct yaffs_dev *dev,
+ const YCHAR *path,
+ int urgency)
+{
+ int 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) {
+ if (!dev->is_mounted)
+ yaffsfs_SetError(-EINVAL);
+ else
+ retVal = yaffs_bg_gc(dev, urgency);
+ } else
+ yaffsfs_SetError(-ENODEV);
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+/* Background gc functions.
+ * These return 0 when bg done or greater than 0 when gc has been
+ * done and there is still a lot of garbage to be cleaned up.
+ */
+
+int yaffs_do_background_gc(const YCHAR *path, int urgency)
+{
+ return yaffsfs_bg_gc_common(NULL, path, urgency);
+}
+
+int yaffs_do_background_gc_reldev(struct yaffs_dev *dev, int urgency)
+{
+ return yaffsfs_bg_gc_common(dev, NULL, urgency);
+}
+
+static int yaffsfs_IsDevBusy(struct yaffs_dev *dev)
+{
+ int i;
+ struct yaffs_obj *obj;
+
+ for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
+ obj = yaffsfs_HandleToObject(i);
+ if (obj && obj->my_dev == dev)
+ return 1;
+ }
+ return 0;
+}
+
+int yaffs_remount_common(struct yaffs_dev *dev, const YCHAR *path,
+ int force, int read_only)
+{
+ int retVal = -1;
+ int was_read_only;
+
+ 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_FindMountPoint(path);
+
+ if (dev) {
+ if (dev->is_mounted) {
+ yaffs_flush_whole_cache(dev, 0);
+
+ if (force || !yaffsfs_IsDevBusy(dev)) {
+ if (read_only)
+ yaffs_checkpoint_save(dev);
+ was_read_only = dev->read_only;
+ dev->read_only = read_only ? 1 : 0;
+ if (was_read_only && !read_only) {
+ yaffs_guts_cleanup(dev);
+ }
+ retVal = 0;
+ } else
+ yaffsfs_SetError(-EBUSY);
+
+ } else
+ yaffsfs_SetError(-EINVAL);
+
+ } else
+ yaffsfs_SetError(-ENODEV);
+
+ yaffsfs_Unlock();
+ return retVal;
+
+}
+
+int yaffs_remount_reldev(struct yaffs_dev *dev, int force, int read_only)
+{
+ return yaffs_remount_common(dev, NULL, force, read_only);
+}
+int yaffs_remount(const YCHAR *path, int force, int read_only)
+{
+ return yaffs_remount_common(NULL, path, force, read_only);
+}
+
+int yaffs_unmount2_common(struct yaffs_dev *dev, const YCHAR *path, int force)
+{
+ int retVal = -1;
+
+
+ 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_FindMountPoint(path);
+
+ if (dev) {
+ if (dev->is_mounted) {
+ int inUse;
+ yaffs_flush_whole_cache(dev, 0);
+ yaffs_checkpoint_save(dev);
+ inUse = yaffsfs_IsDevBusy(dev);
+ if (!inUse || force) {
+ if (inUse)
+ yaffsfs_BreakDeviceHandles(dev);
+ yaffs_deinitialise(dev);
+
+ retVal = 0;
+ } else
+ yaffsfs_SetError(-EBUSY);
+
+ } else
+ yaffsfs_SetError(-EINVAL);
+
+ } else
+ yaffsfs_SetError(-ENODEV);
+
+ yaffsfs_Unlock();
+ return retVal;
+
+}
+
+int yaffs_unmount2_reldev(struct yaffs_dev *dev, int force)
+{
+ return yaffs_unmount2_common(dev, NULL, force);
+}
+
+int yaffs_unmount2(const YCHAR *path, int force)
+{
+ return yaffs_unmount2_common(NULL, path, force);
+}
+
+int yaffs_unmount_reldev(struct yaffs_dev *dev)
+{
+ return yaffs_unmount2_reldev(dev, 0);
+}
+
+int yaffs_unmount(const YCHAR *path)
+{
+ return yaffs_unmount2(path, 0);
+}
+
+int yaffs_format_common(struct yaffs_dev *dev,
+ const YCHAR *path,
+ int unmount_flag,
+ int force_unmount_flag,
+ int remount_flag)
+{
+ int retVal = 0;
+ int result;
+
+ if (!dev) {
+ if (!path) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
+ }
+
+ yaffsfs_Lock();
+ if (!dev)
+ dev = yaffsfs_FindMountPoint(path);
+
+ if (dev) {
+ int was_mounted = dev->is_mounted;
+
+ if (dev->is_mounted && unmount_flag) {
+ int inUse;
+ yaffs_flush_whole_cache(dev, 0);
+ yaffs_checkpoint_save(dev);
+ inUse = yaffsfs_IsDevBusy(dev);
+ if (!inUse || force_unmount_flag) {
+ if (inUse)
+ yaffsfs_BreakDeviceHandles(dev);
+ yaffs_deinitialise(dev);
+ }
+ }
+
+ if(dev->is_mounted) {
+ yaffsfs_SetError(-EBUSY);
+ retVal = -1;
+ } else {
+ yaffs_guts_format_dev(dev);
+ if(was_mounted && remount_flag) {
+ result = yaffs_guts_initialise(dev);
+ if (result == YAFFS_FAIL) {
+ yaffsfs_SetError(-ENOMEM);
+ retVal = -1;
+ }
+ }
+ }
+ } else {