2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2011 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
15 #include "yaffs_guts.h"
18 #include "yaffs_trace.h"
22 #define YAFFSFS_MAX_SYMLINK_DEREFERENCES 5
25 #define NULL ((void *)0)
28 /* YAFFSFS_RW_SIZE must be a power of 2 */
29 #define YAFFSFS_RW_SHIFT (13)
30 #define YAFFSFS_RW_SIZE (1<<YAFFSFS_RW_SHIFT)
32 /* Some forward references */
33 static struct yaffs_obj *yaffsfs_FindObject(struct yaffs_obj *relativeDirectory,
35 int symDepth, int getEquiv,
36 struct yaffs_obj **dirOut,
37 int *notDir, int *loop);
39 static void yaffsfs_RemoveObjectCallback(struct yaffs_obj *obj);
40 static yaffs_DIR *yaffsfs_opendir_no_lock(const YCHAR *dirname);
41 static int yaffsfs_closedir_no_lock(yaffs_DIR *dirent);
43 unsigned int yaffs_wr_attempts;
47 * There are open inodes in struct yaffsfs_Inode.
48 * There are open file descriptors in yaffsfs_FileDes.
49 * There are open handles in yaffsfs_FileDes.
51 * Things are structured this way to be like the Linux VFS model
52 * so that interactions with the yaffs guts calls are similar.
53 * That means more common code paths and less special code.
54 * That means better testing etc.
56 * We have 3 layers because:
57 * A handle is different than an fd because you can use dup()
58 * to create a new handle that accesses the *same* fd. The two
59 * handles will use the same offset (part of the fd). We only close
60 * down the fd when there are no more handles accessing it.
62 * More than one fd can currently access one file, but each fd
63 * has its own permsiions and offset.
66 struct yaffsfs_Inode {
67 int count; /* Number of handles accessing this inode */
68 struct yaffs_obj *iObj;
72 struct yaffsfs_DirSearchContext {
73 struct yaffs_dirent de; /* directory entry */
74 YCHAR name[NAME_MAX + 1]; /* name of directory being searched */
75 struct yaffs_obj *dirObj; /* ptr to directory being searched */
76 struct yaffs_obj *nextReturn; /* obj returned by next readddir */
77 struct list_head others;
82 struct yaffsfs_FileDes {
83 u8 isDir:1; /* This s a directory */
89 int inodeId:12; /* Index to corresponding yaffsfs_Inode */
90 int handleCount:10; /* Number of handles for this fd */
92 Y_LOFF_T position; /* current position in file */
97 struct yaffsfs_Handle {
103 static struct yaffsfs_DirSearchContext yaffsfs_dsc[YAFFSFS_N_DSC];
104 static struct yaffsfs_Inode yaffsfs_inode[YAFFSFS_N_HANDLES];
105 static struct yaffsfs_FileDes yaffsfs_fd[YAFFSFS_N_HANDLES];
106 static struct yaffsfs_Handle yaffsfs_handle[YAFFSFS_N_HANDLES];
108 static int yaffsfs_handlesInitialised;
110 unsigned yaffs_set_trace(unsigned tm)
112 yaffs_trace_mask = tm;
113 return yaffs_trace_mask;
116 unsigned yaffs_get_trace(void)
118 return yaffs_trace_mask;
123 * Inilitalise handle management on start-up.
126 static void yaffsfs_InitHandles(void)
129 if (yaffsfs_handlesInitialised)
132 yaffsfs_handlesInitialised = 1;
134 memset(yaffsfs_inode, 0, sizeof(yaffsfs_inode));
135 memset(yaffsfs_fd, 0, sizeof(yaffsfs_fd));
136 memset(yaffsfs_handle, 0, sizeof(yaffsfs_handle));
137 memset(yaffsfs_dsc, 0, sizeof(yaffsfs_dsc));
139 for (i = 0; i < YAFFSFS_N_HANDLES; i++)
140 yaffsfs_fd[i].inodeId = -1;
141 for (i = 0; i < YAFFSFS_N_HANDLES; i++)
142 yaffsfs_handle[i].fdId = -1;
145 static struct yaffsfs_Handle *yaffsfs_HandleToPointer(int h)
147 if (h >= 0 && h < YAFFSFS_N_HANDLES)
148 return &yaffsfs_handle[h];
152 static struct yaffsfs_FileDes *yaffsfs_HandleToFileDes(int handle)
154 struct yaffsfs_Handle *h = yaffsfs_HandleToPointer(handle);
156 if (h && h->useCount > 0 && h->fdId >= 0 && h->fdId < YAFFSFS_N_HANDLES)
157 return &yaffsfs_fd[h->fdId];
162 static struct yaffsfs_Inode *yaffsfs_HandleToInode(int handle)
164 struct yaffsfs_FileDes *fd = yaffsfs_HandleToFileDes(handle);
166 if (fd && fd->handleCount > 0 &&
167 fd->inodeId >= 0 && fd->inodeId < YAFFSFS_N_HANDLES)
168 return &yaffsfs_inode[fd->inodeId];
173 static struct yaffs_obj *yaffsfs_HandleToObject(int handle)
175 struct yaffsfs_Inode *in = yaffsfs_HandleToInode(handle);
184 * yaffsfs_FindInodeIdForObject
185 * Find the inode entry for an object, if it exists.
188 static int yaffsfs_FindInodeIdForObject(struct yaffs_obj *obj)
194 obj = yaffs_get_equivalent_obj(obj);
196 /* Look for it in open inode table */
197 for (i = 0; i < YAFFSFS_N_HANDLES && ret < 0; i++) {
198 if (yaffsfs_inode[i].iObj == obj)
205 * yaffsfs_GetInodeIdForObject
206 * Grab an inode entry when opening a new inode.
208 static int yaffsfs_GetInodeIdForObject(struct yaffs_obj *obj)
212 struct yaffsfs_Inode *in = NULL;
215 obj = yaffs_get_equivalent_obj(obj);
217 ret = yaffsfs_FindInodeIdForObject(obj);
219 for (i = 0; i < YAFFSFS_N_HANDLES && ret < 0; i++) {
220 if (!yaffsfs_inode[i].iObj)
225 in = &yaffsfs_inode[ret];
235 static int yaffsfs_CountHandles(struct yaffs_obj *obj)
237 int i = yaffsfs_FindInodeIdForObject(obj);
240 return yaffsfs_inode[i].count;
245 static void yaffsfs_ReleaseInode(struct yaffsfs_Inode *in)
247 struct yaffs_obj *obj;
254 obj->my_inode = NULL;
259 static void yaffsfs_PutInode(int inodeId)
261 if (inodeId >= 0 && inodeId < YAFFSFS_N_HANDLES) {
262 struct yaffsfs_Inode *in = &yaffsfs_inode[inodeId];
264 if (in->count <= 0) {
265 yaffsfs_ReleaseInode(in);
271 static int yaffsfs_NewHandle(struct yaffsfs_Handle **hptr)
274 struct yaffsfs_Handle *h;
276 for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
277 h = &yaffsfs_handle[i];
278 if (h->useCount < 1) {
279 memset(h, 0, sizeof(struct yaffsfs_Handle));
290 static int yaffsfs_NewHandleAndFileDes(void)
293 struct yaffsfs_FileDes *fd;
294 struct yaffsfs_Handle *h = NULL;
295 int handle = yaffsfs_NewHandle(&h);
300 for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
302 if (fd->handleCount < 1) {
303 memset(fd, 0, sizeof(struct yaffsfs_FileDes));
311 /* Dump the handle because we could not get a fd */
318 * Increase use of handle when reading/writing a file
319 * Also gets the file descriptor.
322 static int yaffsfs_GetHandle(int handle)
324 struct yaffsfs_Handle *h = yaffsfs_HandleToPointer(handle);
326 if (h && h->useCount > 0) {
335 * Let go of a handle when closing a file or aborting an open or
336 * ending a read or write.
339 static int yaffsfs_PutFileDes(int fdId)
341 struct yaffsfs_FileDes *fd;
343 if (fdId >= 0 && fdId < YAFFSFS_N_HANDLES) {
344 fd = &yaffsfs_fd[fdId];
346 if (fd->handleCount < 1) {
348 yaffsfs_closedir_no_lock(fd->v.dir);
349 if (fd->inodeId >= 0) {
350 yaffsfs_PutInode(fd->inodeId);
358 static int yaffsfs_PutHandle(int handle)
360 struct yaffsfs_Handle *h = yaffsfs_HandleToPointer(handle);
362 if (h && h->useCount > 0) {
364 if (h->useCount < 1) {
365 yaffsfs_PutFileDes(h->fdId);
373 static void yaffsfs_BreakDeviceHandles(struct yaffs_dev *dev)
375 struct yaffsfs_FileDes *fd;
376 struct yaffsfs_Handle *h;
377 struct yaffs_obj *obj;
379 for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
380 h = yaffsfs_HandleToPointer(i);
381 fd = yaffsfs_HandleToFileDes(i);
382 obj = yaffsfs_HandleToObject(i);
383 if (h && h->useCount > 0) {
387 if (fd && fd->handleCount > 0 && obj && obj->my_dev == dev) {
389 yaffsfs_PutInode(fd->inodeId);
396 * Stuff to handle names.
398 #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
400 static int yaffs_toupper(YCHAR a)
402 if (a >= 'a' && a <= 'z')
403 return (a - 'a') + 'A';
408 static int yaffsfs_Match(YCHAR a, YCHAR b)
410 return (yaffs_toupper(a) == yaffs_toupper(b));
413 static int yaffsfs_Match(YCHAR a, YCHAR b)
420 static int yaffsfs_IsPathDivider(YCHAR ch)
422 const YCHAR *str = YAFFS_PATH_DIVIDERS;
433 static int yaffsfs_CheckNameLength(const char *name)
437 int nameLength = yaffs_strnlen(name, YAFFS_MAX_NAME_LENGTH + 1);
439 if (nameLength == 0) {
440 yaffsfs_SetError(-ENOENT);
442 } else if (nameLength > YAFFS_MAX_NAME_LENGTH) {
443 yaffsfs_SetError(-ENAMETOOLONG);
450 static int yaffsfs_alt_dir_path(const YCHAR *path, YCHAR **ret_path)
452 YCHAR *alt_path = NULL;
457 * We don't have a definition for max path length.
458 * We will use 3 * max name length instead.
461 path_length = yaffs_strnlen(path, (YAFFS_MAX_NAME_LENGTH + 1) * 3 + 1);
463 /* If the last character is a path divider, then we need to
464 * trim it back so that the name look-up works properly.
465 * eg. /foo/new_dir/ -> /foo/newdir
466 * Curveball: Need to handle multiple path dividers:
467 * eg. /foof/sdfse///// -> /foo/sdfse
469 if (path_length > 0 && yaffsfs_IsPathDivider(path[path_length - 1])) {
470 alt_path = kmalloc(path_length + 1, 0);
473 yaffs_strcpy(alt_path, path);
474 for (i = path_length - 1;
475 i >= 0 && yaffsfs_IsPathDivider(alt_path[i]); i--)
476 alt_path[i] = (YCHAR) 0;
478 *ret_path = alt_path;
482 LIST_HEAD(yaffsfs_deviceList);
487 * Scan the configuration list to find the device
488 * Curveballs: Should match paths that end in '/' too
489 * Curveball2 Might have "/x/ and "/x/y". Need to return the longest match
491 static struct yaffs_dev *yaffsfs_FindDevice(const YCHAR *path,
494 struct list_head *cfg;
495 const YCHAR *leftOver;
497 struct yaffs_dev *retval = NULL;
498 struct yaffs_dev *dev = NULL;
500 int longestMatch = -1;
504 * Check all configs, choose the one that:
505 * 1) Actually matches a prefix (ie /a amd /abc will not match
506 * 2) Matches the longest.
508 list_for_each(cfg, &yaffsfs_deviceList) {
509 dev = list_entry(cfg, struct yaffs_dev, dev_list);
518 while (matching && *p && *leftOver) {
519 /* Skip over any /s */
520 while (yaffsfs_IsPathDivider(*p))
523 /* Skip over any /s */
524 while (yaffsfs_IsPathDivider(*leftOver))
527 /* Now match the text part */
529 *p && !yaffsfs_IsPathDivider(*p) &&
530 *leftOver && !yaffsfs_IsPathDivider(*leftOver)) {
531 if (yaffsfs_Match(*p, *leftOver)) {
541 /* Skip over any /s in leftOver */
542 while (yaffsfs_IsPathDivider(*leftOver))
545 /*Skip over any /s in p */
546 while (yaffsfs_IsPathDivider(*p))
549 /* p should now be at the end of the string if fully matched */
553 if (matching && (thisMatchLength > longestMatch)) {
555 *restOfPath = (YCHAR *) leftOver;
557 longestMatch = thisMatchLength;
564 static int yaffsfs_CheckPath(const YCHAR *path)
569 while (*path && n < YAFFS_MAX_NAME_LENGTH && divs < 100) {
570 if (yaffsfs_IsPathDivider(*path)) {
578 return (*path) ? -1 : 0;
581 /* FindMountPoint only returns a dev entry if the path is a mount point */
582 static struct yaffs_dev *yaffsfs_FindMountPoint(const YCHAR *path)
584 struct yaffs_dev *dev;
585 YCHAR *restOfPath = NULL;
587 dev = yaffsfs_FindDevice(path, &restOfPath);
588 if (dev && restOfPath && *restOfPath)
593 static struct yaffs_obj *yaffsfs_FindRoot(const YCHAR *path,
596 struct yaffs_dev *dev;
598 dev = yaffsfs_FindDevice(path, restOfPath);
599 if (dev && dev->is_mounted)
600 return dev->root_dir;
605 static struct yaffs_obj *yaffsfs_FollowLink(struct yaffs_obj *obj,
606 int symDepth, int *loop)
610 obj = yaffs_get_equivalent_obj(obj);
612 while (obj && obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
613 YCHAR *alias = obj->variant.symlink_variant.alias;
615 if (yaffsfs_IsPathDivider(*alias))
616 /* Starts with a /, need to scan from root up */
617 obj = yaffsfs_FindObject(NULL, alias, symDepth++,
618 1, NULL, NULL, loop);
621 * Relative to here so use the parent of the
624 obj = yaffsfs_FindObject(obj->parent, alias, symDepth++,
625 1, NULL, NULL, loop);
631 * yaffsfs_FindDirectory
632 * Parse a path to determine the directory and the name within the directory.
634 * eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx"
636 static struct yaffs_obj *yaffsfs_DoFindDirectory(struct yaffs_obj *startDir,
638 YCHAR **name, int symDepth,
639 int *notDir, int *loop)
641 struct yaffs_obj *dir;
643 YCHAR str[YAFFS_MAX_NAME_LENGTH + 1];
646 if (symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES) {
654 restOfPath = (YCHAR *) path;
656 dir = yaffsfs_FindRoot(path, &restOfPath);
661 * curve ball: also throw away surplus '/'
662 * eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"
664 while (yaffsfs_IsPathDivider(*restOfPath))
665 restOfPath++; /* get rid of '/' */
670 while (*restOfPath && !yaffsfs_IsPathDivider(*restOfPath)) {
671 if (i < YAFFS_MAX_NAME_LENGTH) {
672 str[i] = *restOfPath;
680 /* got to the end of the string */
683 if (yaffs_strcmp(str, _Y(".")) == 0) {
685 } else if (yaffs_strcmp(str, _Y("..")) == 0) {
688 dir = yaffs_find_by_name(dir, str);
690 dir = yaffsfs_FollowLink(dir, symDepth, loop);
692 if (dir && dir->variant_type !=
693 YAFFS_OBJECT_TYPE_DIRECTORY) {
702 /* directory did not exist. */
706 static struct yaffs_obj *yaffsfs_FindDirectory(struct yaffs_obj *relDir,
710 int *notDir, int *loop)
712 return yaffsfs_DoFindDirectory(relDir, path, name, symDepth, notDir,
717 * yaffsfs_FindObject turns a path for an existing object into the object
719 static struct yaffs_obj *yaffsfs_FindObject(struct yaffs_obj *relDir,
720 const YCHAR *path, int symDepth,
722 struct yaffs_obj **dirOut,
723 int *notDir, int *loop)
725 struct yaffs_obj *dir;
726 struct yaffs_obj *obj;
730 yaffsfs_FindDirectory(relDir, path, &name, symDepth, notDir, loop);
736 obj = yaffs_find_by_name(dir, name);
741 obj = yaffs_get_equivalent_obj(obj);
746 /*************************************************************************
747 * Start of yaffsfs visible functions.
748 *************************************************************************/
750 int yaffs_dup(int handle)
752 int newHandleNumber = -1;
753 struct yaffsfs_FileDes *existingFD = NULL;
754 struct yaffsfs_Handle *existingHandle = NULL;
755 struct yaffsfs_Handle *newHandle = NULL;
758 existingHandle = yaffsfs_HandleToPointer(handle);
759 existingFD = yaffsfs_HandleToFileDes(handle);
761 newHandleNumber = yaffsfs_NewHandle(&newHandle);
763 newHandle->fdId = existingHandle->fdId;
764 existingFD->handleCount++;
770 yaffsfs_SetError(-EBADF);
772 yaffsfs_SetError(-ENOMEM);
774 return newHandleNumber;
778 static int yaffsfs_TooManyObjects(struct yaffs_dev *dev)
780 int current_objects = dev->n_obj - dev->n_deleted_files;
782 if (dev->param.max_objects && current_objects > dev->param.max_objects)
788 int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
790 struct yaffs_obj *obj = NULL;
791 struct yaffs_obj *dir = NULL;
794 struct yaffsfs_FileDes *fd = NULL;
797 int errorReported = 0;
798 int rwflags = oflag & (O_RDWR | O_RDONLY | O_WRONLY);
799 u8 shareRead = (sharing & YAFFS_SHARE_READ) ? 1 : 0;
800 u8 shareWrite = (sharing & YAFFS_SHARE_WRITE) ? 1 : 0;
801 u8 sharedReadAllowed;
802 u8 sharedWriteAllowed;
812 if (yaffsfs_CheckMemRegion(path, 0, 0)< 0) {
813 yaffsfs_SetError(-EFAULT);
817 if (yaffsfs_CheckPath(path) < 0) {
818 yaffsfs_SetError(-ENAMETOOLONG);
822 /* O_EXCL only has meaning if O_CREAT is specified */
823 if (!(oflag & O_CREAT))
826 /* O_TRUNC has no meaning if (O_CREAT | O_EXCL) is specified */
827 if ((oflag & O_CREAT) & (oflag & O_EXCL))
830 /* Todo: Are there any more flag combos to sanitise ? */
832 /* Figure out if reading or writing is requested */
834 readRequested = (rwflags == O_RDWR || rwflags == O_RDONLY) ? 1 : 0;
835 writeRequested = (rwflags == O_RDWR || rwflags == O_WRONLY) ? 1 : 0;
839 handle = yaffsfs_NewHandleAndFileDes();
842 yaffsfs_SetError(-ENFILE);
846 fd = yaffsfs_HandleToFileDes(handle);
848 /* try to find the exisiting object */
849 obj = yaffsfs_FindObject(NULL, path, 0, 1, NULL, NULL, NULL);
851 obj = yaffsfs_FollowLink(obj, symDepth++, &loop);
854 obj->variant_type != YAFFS_OBJECT_TYPE_FILE &&
855 obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
860 /* The file already exists or it might be a directory */
861 is_dir = (obj->variant_type ==
862 YAFFS_OBJECT_TYPE_DIRECTORY);
864 /* A directory can't be opened except for read */
866 (writeRequested || !readRequested ||
867 (oflag & ~O_RDONLY))) {
869 yaffsfs_SetError(-EISDIR);
874 dsc = yaffsfs_opendir_no_lock(path);
877 yaffsfs_SetError(-ENFILE);
882 /* Open should fail if O_CREAT and O_EXCL are specified
883 * for a file that exists.
885 if (!errorReported &&
886 (oflag & O_EXCL) && (oflag & O_CREAT)) {
888 yaffsfs_SetError(-EEXIST);
892 /* Check file permissions */
893 if (readRequested && !(obj->yst_mode & S_IREAD))
896 if (writeRequested && !(obj->yst_mode & S_IWRITE))
899 if (!errorReported && writeRequested &&
900 obj->my_dev->read_only) {
902 yaffsfs_SetError(-EROFS);
906 if (openDenied && !errorReported) {
907 yaffsfs_SetError(-EACCES);
911 /* Check sharing of an existing object. */
913 struct yaffsfs_FileDes *fdx;
916 sharedReadAllowed = 1;
917 sharedWriteAllowed = 1;
920 for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
921 fdx = &yaffsfs_fd[i];
922 if (fdx->handleCount > 0 &&
924 yaffsfs_inode[fdx->inodeId].iObj
927 sharedReadAllowed = 0;
928 if (!fdx->shareWrite)
929 sharedWriteAllowed = 0;
937 if ((!sharedReadAllowed && readRequested) ||
938 (!shareRead && alreadyReading) ||
939 (!sharedWriteAllowed && writeRequested) ||
940 (!shareWrite && alreadyWriting)) {
942 yaffsfs_SetError(-EBUSY);
949 /* If we could not open an existing object, then let's see if
950 * the directory exists. If not, error.
952 if (!obj && !errorReported) {
953 dir = yaffsfs_FindDirectory(NULL, path, &name, 0,
955 if (!dir && notDir) {
956 yaffsfs_SetError(-ENOTDIR);
959 yaffsfs_SetError(-ELOOP);
962 yaffsfs_SetError(-ENOENT);
967 if (!obj && dir && !errorReported && (oflag & O_CREAT)) {
968 /* Let's see if we can create this file */
969 if (dir->my_dev->read_only) {
970 yaffsfs_SetError(-EROFS);
972 } else if (yaffsfs_TooManyObjects(dir->my_dev)) {
973 yaffsfs_SetError(-ENFILE);
976 obj = yaffs_create_file(dir, name, mode, 0, 0);
978 if (!obj && !errorReported) {
979 yaffsfs_SetError(-ENOSPC);
984 if (!obj && dir && !errorReported && !(oflag & O_CREAT)) {
985 yaffsfs_SetError(-ENOENT);
989 if (obj && !openDenied) {
990 int inodeId = yaffsfs_GetInodeIdForObject(obj);
994 * Todo: Fix any problem if inodes run out,
995 * That can't happen if the number of inode
996 * items >= number of handles.
1000 fd->inodeId = inodeId;
1001 fd->reading = readRequested;
1002 fd->writing = writeRequested;
1003 fd->append = (oflag & O_APPEND) ? 1 : 0;
1004 fd->shareRead = shareRead;
1005 fd->shareWrite = shareWrite;
1013 /* Hook inode to object */
1014 obj->my_inode = (void *)&yaffsfs_inode[inodeId];
1016 if (!is_dir && (oflag & O_TRUNC) && fd->writing)
1017 yaffs_resize_file(obj, 0);
1019 yaffsfs_PutHandle(handle);
1021 yaffsfs_SetError(0); /* Problem */
1031 int yaffs_open(const YCHAR *path, int oflag, int mode)
1033 return yaffs_open_sharing(path, oflag, mode,
1034 YAFFS_SHARE_READ | YAFFS_SHARE_WRITE);
1037 static int yaffs_Dofsync(int handle, int datasync)
1040 struct yaffs_obj *obj;
1044 obj = yaffsfs_HandleToObject(handle);
1047 yaffsfs_SetError(-EBADF);
1048 else if (obj->my_dev->read_only)
1049 yaffsfs_SetError(-EROFS);
1051 yaffs_flush_file(obj, 1, datasync);
1060 int yaffs_fsync(int handle)
1062 return yaffs_Dofsync(handle, 0);
1065 int yaffs_flush(int handle)
1067 return yaffs_fsync(handle);
1070 int yaffs_fdatasync(int handle)
1072 return yaffs_Dofsync(handle, 1);
1075 int yaffs_close(int handle)
1077 struct yaffsfs_Handle *h = NULL;
1078 struct yaffsfs_FileDes *f;
1079 struct yaffs_obj *obj = NULL;
1084 h = yaffsfs_HandleToPointer(handle);
1085 f = yaffsfs_HandleToFileDes(handle);
1086 obj = yaffsfs_HandleToObject(handle);
1088 if (!h || !obj || !f)
1089 yaffsfs_SetError(-EBADF);
1093 yaffs_flush_file(obj, 1, 0);
1094 yaffsfs_PutHandle(handle);
1103 static int yaffsfs_do_read(int handle, void *vbuf, unsigned int nbyte,
1104 int isPread, Y_LOFF_T offset)
1106 struct yaffsfs_FileDes *fd = NULL;
1107 struct yaffs_obj *obj = NULL;
1109 Y_LOFF_T startPos = 0;
1110 Y_LOFF_T endPos = 0;
1115 u8 *buf = (u8 *) vbuf;
1117 if (yaffsfs_CheckMemRegion(vbuf, nbyte, 1) < 0) {
1118 yaffsfs_SetError(-EFAULT);
1123 fd = yaffsfs_HandleToFileDes(handle);
1124 obj = yaffsfs_HandleToObject(handle);
1128 yaffsfs_SetError(-EBADF);
1130 } else if (!fd->reading) {
1131 /* Not a reading handle */
1132 yaffsfs_SetError(-EINVAL);
1134 } else if (nbyte > YAFFS_MAX_FILE_SIZE) {
1135 yaffsfs_SetError(-EINVAL);
1141 startPos = fd->v.position;
1145 if (yaffs_get_obj_length(obj) > pos)
1146 maxRead = yaffs_get_obj_length(obj) - pos;
1150 if (nbyte > maxRead)
1153 yaffsfs_GetHandle(handle);
1155 endPos = pos + nbyte;
1157 if (pos < 0 || pos > YAFFS_MAX_FILE_SIZE ||
1158 nbyte > YAFFS_MAX_FILE_SIZE ||
1159 endPos < 0 || endPos > YAFFS_MAX_FILE_SIZE) {
1165 nToRead = YAFFSFS_RW_SIZE -
1166 (pos & (YAFFSFS_RW_SIZE - 1));
1167 if (nToRead > nbyte)
1171 * Need to reverify object in case the device was
1172 * unmounted in another thread.
1174 obj = yaffsfs_HandleToObject(handle);
1178 nRead = yaffs_file_rd(obj, buf, pos, nToRead);
1186 if (nRead == nToRead)
1189 nbyte = 0; /* no more to read */
1198 yaffsfs_PutHandle(handle);
1202 fd->v.position = startPos + totalRead;
1204 yaffsfs_SetError(-EINVAL);
1211 return (totalRead >= 0) ? totalRead : -1;
1215 int yaffs_read(int handle, void *buf, unsigned int nbyte)
1217 return yaffsfs_do_read(handle, buf, nbyte, 0, 0);
1220 int yaffs_pread(int handle, void *buf, unsigned int nbyte, Y_LOFF_T offset)
1222 return yaffsfs_do_read(handle, buf, nbyte, 1, offset);
1225 static int yaffsfs_do_write(int handle, const void *vbuf, unsigned int nbyte,
1226 int isPwrite, Y_LOFF_T offset)
1228 struct yaffsfs_FileDes *fd = NULL;
1229 struct yaffs_obj *obj = NULL;
1231 Y_LOFF_T startPos = 0;
1234 int totalWritten = 0;
1235 int write_trhrough = 0;
1237 const u8 *buf = (const u8 *)vbuf;
1239 if (yaffsfs_CheckMemRegion(vbuf, nbyte, 0) < 0) {
1240 yaffsfs_SetError(-EFAULT);
1245 fd = yaffsfs_HandleToFileDes(handle);
1246 obj = yaffsfs_HandleToObject(handle);
1250 yaffsfs_SetError(-EBADF);
1252 } else if (!fd->writing) {
1253 yaffsfs_SetError(-EINVAL);
1255 } else if (obj->my_dev->read_only) {
1256 yaffsfs_SetError(-EROFS);
1260 startPos = yaffs_get_obj_length(obj);
1264 startPos = fd->v.position;
1266 yaffsfs_GetHandle(handle);
1268 endPos = pos + nbyte;
1270 if (pos < 0 || pos > YAFFS_MAX_FILE_SIZE ||
1271 nbyte > YAFFS_MAX_FILE_SIZE ||
1272 endPos < 0 || endPos > YAFFS_MAX_FILE_SIZE) {
1279 nToWrite = YAFFSFS_RW_SIZE -
1280 (pos & (YAFFSFS_RW_SIZE - 1));
1281 if (nToWrite > nbyte)
1285 * Need to reverify object in case the device was
1286 * remounted or unmounted in another thread.
1288 obj = yaffsfs_HandleToObject(handle);
1289 if (!obj || obj->my_dev->read_only)
1293 yaffs_wr_file(obj, buf, pos, nToWrite,
1296 totalWritten += nWritten;
1301 if (nWritten == nToWrite)
1306 if (nWritten < 1 && totalWritten < 1) {
1307 yaffsfs_SetError(-ENOSPC);
1317 yaffsfs_PutHandle(handle);
1320 if (totalWritten > 0)
1321 fd->v.position = startPos + totalWritten;
1323 yaffsfs_SetError(-EINVAL);
1329 return (totalWritten >= 0) ? totalWritten : -1;
1332 int yaffs_write(int fd, const void *buf, unsigned int nbyte)
1334 return yaffsfs_do_write(fd, buf, nbyte, 0, 0);
1337 int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, Y_LOFF_T offset)
1339 return yaffsfs_do_write(fd, buf, nbyte, 1, offset);
1342 int yaffs_truncate(const YCHAR *path, Y_LOFF_T new_size)
1344 struct yaffs_obj *obj = NULL;
1345 struct yaffs_obj *dir = NULL;
1346 int result = YAFFS_FAIL;
1350 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
1351 yaffsfs_SetError(-EFAULT);
1355 if (yaffsfs_CheckPath(path) < 0) {
1356 yaffsfs_SetError(-ENAMETOOLONG);
1362 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
1363 obj = yaffsfs_FollowLink(obj, 0, &loop);
1366 yaffsfs_SetError(-ENOTDIR);
1368 yaffsfs_SetError(-ELOOP);
1369 else if (!dir || !obj)
1370 yaffsfs_SetError(-ENOENT);
1371 else if (obj->my_dev->read_only)
1372 yaffsfs_SetError(-EROFS);
1373 else if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
1374 yaffsfs_SetError(-EISDIR);
1375 else if (obj->my_dev->read_only)
1376 yaffsfs_SetError(-EROFS);
1377 else if (new_size < 0 || new_size > YAFFS_MAX_FILE_SIZE)
1378 yaffsfs_SetError(-EINVAL);
1380 result = yaffs_resize_file(obj, new_size);
1384 return (result) ? 0 : -1;
1387 int yaffs_ftruncate(int handle, Y_LOFF_T new_size)
1389 struct yaffsfs_FileDes *fd = NULL;
1390 struct yaffs_obj *obj = NULL;
1394 fd = yaffsfs_HandleToFileDes(handle);
1395 obj = yaffsfs_HandleToObject(handle);
1399 yaffsfs_SetError(-EBADF);
1400 else if (!fd->writing)
1401 yaffsfs_SetError(-EINVAL);
1402 else if (obj->my_dev->read_only)
1403 yaffsfs_SetError(-EROFS);
1404 else if (new_size < 0 || new_size > YAFFS_MAX_FILE_SIZE)
1405 yaffsfs_SetError(-EINVAL);
1407 /* resize the file */
1408 result = yaffs_resize_file(obj, new_size);
1411 return (result) ? 0 : -1;
1415 Y_LOFF_T yaffs_lseek(int handle, Y_LOFF_T offset, int whence)
1417 struct yaffsfs_FileDes *fd = NULL;
1418 struct yaffs_obj *obj = NULL;
1420 Y_LOFF_T fSize = -1;
1423 fd = yaffsfs_HandleToFileDes(handle);
1424 obj = yaffsfs_HandleToObject(handle);
1427 yaffsfs_SetError(-EBADF);
1428 else if (offset > YAFFS_MAX_FILE_SIZE)
1429 yaffsfs_SetError(-EINVAL);
1431 if (whence == SEEK_SET) {
1434 } else if (whence == SEEK_CUR) {
1435 if ((fd->v.position + offset) >= 0)
1436 pos = (fd->v.position + offset);
1437 } else if (whence == SEEK_END) {
1438 fSize = yaffs_get_obj_length(obj);
1439 if (fSize >= 0 && (fSize + offset) >= 0)
1440 pos = fSize + offset;
1443 if (pos >= 0 && pos <= YAFFS_MAX_FILE_SIZE)
1444 fd->v.position = pos;
1446 yaffsfs_SetError(-EINVAL);
1456 static int yaffsfs_DoUnlink(const YCHAR *path, int isDirectory)
1458 struct yaffs_obj *dir = NULL;
1459 struct yaffs_obj *obj = NULL;
1461 int result = YAFFS_FAIL;
1465 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
1466 yaffsfs_SetError(-EFAULT);
1470 if (yaffsfs_CheckPath(path) < 0) {
1471 yaffsfs_SetError(-ENAMETOOLONG);
1477 obj = yaffsfs_FindObject(NULL, path, 0, 0, NULL, NULL, NULL);
1478 dir = yaffsfs_FindDirectory(NULL, path, &name, 0, ¬Dir, &loop);
1481 yaffsfs_SetError(-ENOTDIR);
1483 yaffsfs_SetError(-ELOOP);
1485 yaffsfs_SetError(-ENOENT);
1486 else if (yaffs_strncmp(name, _Y("."), 2) == 0)
1487 yaffsfs_SetError(-EINVAL);
1489 yaffsfs_SetError(-ENOENT);
1490 else if (obj->my_dev->read_only)
1491 yaffsfs_SetError(-EROFS);
1492 else if (!isDirectory &&
1493 obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
1494 yaffsfs_SetError(-EISDIR);
1495 else if (isDirectory &&
1496 obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
1497 yaffsfs_SetError(-ENOTDIR);
1498 else if (isDirectory && obj == obj->my_dev->root_dir)
1499 yaffsfs_SetError(-EBUSY); /* Can't rmdir a root */
1501 result = yaffs_unlinker(dir, name);
1503 if (result == YAFFS_FAIL && isDirectory)
1504 yaffsfs_SetError(-ENOTEMPTY);
1509 return (result == YAFFS_FAIL) ? -1 : 0;
1512 int yaffs_unlink(const YCHAR *path)
1514 return yaffsfs_DoUnlink(path, 0);
1517 static int rename_file_over_dir(struct yaffs_obj *obj, struct yaffs_obj *newobj)
1519 if (obj && obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY &&
1520 newobj && newobj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
1526 static int rename_dir_over_file(struct yaffs_obj *obj, struct yaffs_obj *newobj)
1528 if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
1529 newobj && newobj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
1535 int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath)
1537 struct yaffs_obj *olddir = NULL;
1538 struct yaffs_obj *newdir = NULL;
1539 struct yaffs_obj *obj = NULL;
1540 struct yaffs_obj *newobj = NULL;
1543 int result = YAFFS_FAIL;
1544 int rename_allowed = 1;
1550 YCHAR *alt_newpath = NULL;
1552 if (yaffsfs_CheckMemRegion(oldPath, 0, 0) < 0 ||
1553 yaffsfs_CheckMemRegion(newPath, 0, 0) < 0) {
1554 yaffsfs_SetError(-EFAULT);
1558 if (yaffsfs_CheckPath(oldPath) < 0 || yaffsfs_CheckPath(newPath) < 0) {
1559 yaffsfs_SetError(-ENAMETOOLONG);
1563 if (yaffsfs_alt_dir_path(newPath, &alt_newpath) < 0) {
1564 yaffsfs_SetError(-ENOMEM);
1568 newPath = alt_newpath;
1572 olddir = yaffsfs_FindDirectory(NULL, oldPath, &oldname, 0,
1573 ¬OldDir, &oldLoop);
1574 newdir = yaffsfs_FindDirectory(NULL, newPath, &newname, 0,
1575 ¬NewDir, &newLoop);
1576 obj = yaffsfs_FindObject(NULL, oldPath, 0, 0, NULL, NULL, NULL);
1577 newobj = yaffsfs_FindObject(NULL, newPath, 0, 0, NULL, NULL, NULL);
1579 /* If the object being renamed is a directory and the
1580 * path ended with a "/" then the olddir == obj.
1581 * We pass through NULL for the old name to tell the lower layers
1582 * to use olddir as the object.
1588 if ((!olddir && notOldDir) || (!newdir && notNewDir)) {
1589 yaffsfs_SetError(-ENOTDIR);
1591 } else if (oldLoop || newLoop) {
1592 yaffsfs_SetError(-ELOOP);
1594 } else if (olddir && oldname &&
1595 yaffs_strncmp(oldname, _Y("."), 2) == 0) {
1596 yaffsfs_SetError(-EINVAL);
1598 } else if (!olddir || !newdir || !obj) {
1599 yaffsfs_SetError(-ENOENT);
1601 } else if (obj->my_dev->read_only) {
1602 yaffsfs_SetError(-EROFS);
1604 } else if (rename_file_over_dir(obj, newobj)) {
1605 yaffsfs_SetError(-EISDIR);
1607 } else if (rename_dir_over_file(obj, newobj)) {
1608 yaffsfs_SetError(-ENOTDIR);
1610 } else if (yaffs_is_non_empty_dir(newobj)) {
1611 yaffsfs_SetError(-ENOTEMPTY);
1613 } else if (olddir->my_dev != newdir->my_dev) {
1614 /* Rename must be on same device */
1615 yaffsfs_SetError(-EXDEV);
1617 } else if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) {
1619 * It is a directory, check that it is not being renamed to
1620 * being its own decendent.
1621 * Do this by tracing from the new directory back to the root,
1625 struct yaffs_obj *xx = newdir;
1627 while (rename_allowed && xx) {
1632 if (!rename_allowed)
1633 yaffsfs_SetError(-EINVAL);
1637 result = yaffs_rename_obj(olddir, oldname, newdir, newname);
1643 return (result == YAFFS_FAIL) ? -1 : 0;
1646 static int yaffsfs_DoStat(struct yaffs_obj *obj, struct yaffs_stat *buf)
1650 obj = yaffs_get_equivalent_obj(obj);
1653 buf->st_dev = (int)obj->my_dev->os_context;
1654 buf->st_ino = obj->obj_id;
1655 buf->st_mode = obj->yst_mode & ~S_IFMT;
1657 if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
1658 buf->st_mode |= S_IFDIR;
1659 else if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
1660 buf->st_mode |= S_IFLNK;
1661 else if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
1662 buf->st_mode |= S_IFREG;
1664 buf->st_nlink = yaffs_get_obj_link_count(obj);
1667 buf->st_rdev = obj->yst_rdev;
1668 buf->st_size = yaffs_get_obj_length(obj);
1669 buf->st_blksize = obj->my_dev->data_bytes_per_chunk;
1670 buf->st_blocks = (buf->st_size + buf->st_blksize - 1) /
1672 #if CONFIG_YAFFS_WINCE
1673 buf->yst_wince_atime[0] = obj->win_atime[0];
1674 buf->yst_wince_atime[1] = obj->win_atime[1];
1675 buf->yst_wince_ctime[0] = obj->win_ctime[0];
1676 buf->yst_wince_ctime[1] = obj->win_ctime[1];
1677 buf->yst_wince_mtime[0] = obj->win_mtime[0];
1678 buf->yst_wince_mtime[1] = obj->win_mtime[1];
1680 buf->yst_atime = obj->yst_atime;
1681 buf->yst_ctime = obj->yst_ctime;
1682 buf->yst_mtime = obj->yst_mtime;
1689 static int yaffsfs_DoStatOrLStat(const YCHAR *path,
1690 struct yaffs_stat *buf, int doLStat)
1692 struct yaffs_obj *obj = NULL;
1693 struct yaffs_obj *dir = NULL;
1698 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
1699 yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) {
1700 yaffsfs_SetError(-EFAULT);
1704 if (yaffsfs_CheckPath(path) < 0) {
1705 yaffsfs_SetError(-ENAMETOOLONG);
1711 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
1713 if (!doLStat && obj)
1714 obj = yaffsfs_FollowLink(obj, 0, &loop);
1717 yaffsfs_SetError(-ENOTDIR);
1719 yaffsfs_SetError(-ELOOP);
1720 else if (!dir || !obj)
1721 yaffsfs_SetError(-ENOENT);
1723 retVal = yaffsfs_DoStat(obj, buf);
1731 int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf)
1733 return yaffsfs_DoStatOrLStat(path, buf, 0);
1736 int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf)
1738 return yaffsfs_DoStatOrLStat(path, buf, 1);
1741 int yaffs_fstat(int fd, struct yaffs_stat *buf)
1743 struct yaffs_obj *obj;
1747 if (yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) {
1748 yaffsfs_SetError(-EFAULT);
1753 obj = yaffsfs_HandleToObject(fd);
1756 retVal = yaffsfs_DoStat(obj, buf);
1759 yaffsfs_SetError(-EBADF);
1766 static int yaffsfs_DoUtime(struct yaffs_obj *obj,
1767 const struct yaffs_utimbuf *buf)
1772 struct yaffs_utimbuf local;
1774 obj = yaffs_get_equivalent_obj(obj);
1776 if (obj && obj->my_dev->read_only) {
1777 yaffsfs_SetError(-EROFS);
1782 local.actime = Y_CURRENT_TIME;
1783 local.modtime = local.actime;
1788 obj->yst_atime = buf->actime;
1789 obj->yst_mtime = buf->modtime;
1791 result = yaffs_flush_file(obj, 0, 0);
1792 retVal = result == YAFFS_OK ? 0 : -1;
1798 int yaffs_utime(const YCHAR *path, const struct yaffs_utimbuf *buf)
1800 struct yaffs_obj *obj = NULL;
1801 struct yaffs_obj *dir = NULL;
1807 yaffsfs_SetError(-EFAULT);
1811 if (yaffsfs_CheckPath(path) < 0) {
1812 yaffsfs_SetError(-ENAMETOOLONG);
1818 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
1821 yaffsfs_SetError(-ENOTDIR);
1823 yaffsfs_SetError(-ELOOP);
1824 else if (!dir || !obj)
1825 yaffsfs_SetError(-ENOENT);
1827 retVal = yaffsfs_DoUtime(obj, buf);
1835 int yaffs_futime(int fd, const struct yaffs_utimbuf *buf)
1837 struct yaffs_obj *obj;
1842 obj = yaffsfs_HandleToObject(fd);
1845 retVal = yaffsfs_DoUtime(obj, buf);
1848 yaffsfs_SetError(-EBADF);
1855 #ifndef CONFIG_YAFFS_WINCE
1856 /* xattrib functions */
1858 static int yaffs_do_setxattr(const YCHAR *path, const char *name,
1859 const void *data, int size, int flags, int follow)
1861 struct yaffs_obj *obj;
1862 struct yaffs_obj *dir;
1868 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
1869 yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
1870 yaffsfs_CheckMemRegion(data, size, 0) < 0) {
1871 yaffsfs_SetError(-EFAULT);
1875 if (yaffsfs_CheckPath(path) < 0) {
1876 yaffsfs_SetError(-ENAMETOOLONG);
1882 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
1885 obj = yaffsfs_FollowLink(obj, 0, &loop);
1888 yaffsfs_SetError(-ENOTDIR);
1890 yaffsfs_SetError(-ELOOP);
1891 else if (!dir || !obj)
1892 yaffsfs_SetError(-ENOENT);
1894 retVal = yaffs_set_xattrib(obj, name, data, size, flags);
1896 yaffsfs_SetError(retVal);
1907 int yaffs_setxattr(const YCHAR *path, const char *name,
1908 const void *data, int size, int flags)
1910 return yaffs_do_setxattr(path, name, data, size, flags, 1);
1913 int yaffs_lsetxattr(const YCHAR *path, const char *name,
1914 const void *data, int size, int flags)
1916 return yaffs_do_setxattr(path, name, data, size, flags, 0);
1919 int yaffs_fsetxattr(int fd, const char *name,
1920 const void *data, int size, int flags)
1922 struct yaffs_obj *obj;
1926 if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
1927 yaffsfs_CheckMemRegion(data, size, 0) < 0) {
1928 yaffsfs_SetError(-EFAULT);
1933 obj = yaffsfs_HandleToObject(fd);
1936 yaffsfs_SetError(-EBADF);
1938 retVal = yaffs_set_xattrib(obj, name, data, size, flags);
1940 yaffsfs_SetError(retVal);
1950 static int yaffs_do_getxattr(const YCHAR *path, const char *name,
1951 void *data, int size, int follow)
1953 struct yaffs_obj *obj;
1954 struct yaffs_obj *dir;
1959 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
1960 yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
1961 yaffsfs_CheckMemRegion(data, size, 1) < 0) {
1962 yaffsfs_SetError(-EFAULT);
1966 if (yaffsfs_CheckPath(path) < 0) {
1967 yaffsfs_SetError(-ENAMETOOLONG);
1973 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
1976 obj = yaffsfs_FollowLink(obj, 0, &loop);
1979 yaffsfs_SetError(-ENOTDIR);
1981 yaffsfs_SetError(-ELOOP);
1982 else if (!dir || !obj)
1983 yaffsfs_SetError(-ENOENT);
1985 retVal = yaffs_get_xattrib(obj, name, data, size);
1987 yaffsfs_SetError(retVal);
1997 int yaffs_getxattr(const YCHAR *path, const char *name, void *data, int size)
1999 return yaffs_do_getxattr(path, name, data, size, 1);
2002 int yaffs_lgetxattr(const YCHAR *path, const char *name, void *data, int size)
2004 return yaffs_do_getxattr(path, name, data, size, 0);
2007 int yaffs_fgetxattr(int fd, const char *name, void *data, int size)
2009 struct yaffs_obj *obj;
2013 if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
2014 yaffsfs_CheckMemRegion(data, size, 1) < 0) {
2015 yaffsfs_SetError(-EFAULT);
2020 obj = yaffsfs_HandleToObject(fd);
2023 retVal = yaffs_get_xattrib(obj, name, data, size);
2025 yaffsfs_SetError(retVal);
2030 yaffsfs_SetError(-EBADF);
2037 static int yaffs_do_listxattr(const YCHAR *path, char *data,
2038 int size, int follow)
2040 struct yaffs_obj *obj = NULL;
2041 struct yaffs_obj *dir = NULL;
2046 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
2047 yaffsfs_CheckMemRegion(data, size, 1) < 0) {
2048 yaffsfs_SetError(-EFAULT);
2052 if (yaffsfs_CheckPath(path) < 0) {
2053 yaffsfs_SetError(-ENAMETOOLONG);
2059 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
2062 obj = yaffsfs_FollowLink(obj, 0, &loop);
2065 yaffsfs_SetError(-ENOTDIR);
2067 yaffsfs_SetError(-ELOOP);
2068 else if (!dir || !obj)
2069 yaffsfs_SetError(-ENOENT);
2071 retVal = yaffs_list_xattrib(obj, data, size);
2073 yaffsfs_SetError(retVal);
2084 int yaffs_listxattr(const YCHAR *path, char *data, int size)
2086 return yaffs_do_listxattr(path, data, size, 1);
2089 int yaffs_llistxattr(const YCHAR *path, char *data, int size)
2091 return yaffs_do_listxattr(path, data, size, 0);
2094 int yaffs_flistxattr(int fd, char *data, int size)
2096 struct yaffs_obj *obj;
2100 if (yaffsfs_CheckMemRegion(data, size, 1) < 0) {
2101 yaffsfs_SetError(-EFAULT);
2106 obj = yaffsfs_HandleToObject(fd);
2109 retVal = yaffs_list_xattrib(obj, data, size);
2111 yaffsfs_SetError(retVal);
2116 yaffsfs_SetError(-EBADF);
2123 static int yaffs_do_removexattr(const YCHAR *path, const char *name,
2126 struct yaffs_obj *obj = NULL;
2127 struct yaffs_obj *dir = NULL;
2132 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
2133 yaffsfs_CheckMemRegion(name, 0, 0) < 0) {
2134 yaffsfs_SetError(-EFAULT);
2138 if (yaffsfs_CheckPath(path) < 0) {
2139 yaffsfs_SetError(-ENAMETOOLONG);
2145 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
2148 obj = yaffsfs_FollowLink(obj, 0, &loop);
2151 yaffsfs_SetError(-ENOTDIR);
2153 yaffsfs_SetError(-ELOOP);
2154 else if (!dir || !obj)
2155 yaffsfs_SetError(-ENOENT);
2157 retVal = yaffs_remove_xattrib(obj, name);
2159 yaffsfs_SetError(retVal);
2170 int yaffs_removexattr(const YCHAR *path, const char *name)
2172 return yaffs_do_removexattr(path, name, 1);
2175 int yaffs_lremovexattr(const YCHAR *path, const char *name)
2177 return yaffs_do_removexattr(path, name, 0);
2180 int yaffs_fremovexattr(int fd, const char *name)
2182 struct yaffs_obj *obj;
2186 if (yaffsfs_CheckMemRegion(name, 0, 0) < 0) {
2187 yaffsfs_SetError(-EFAULT);
2192 obj = yaffsfs_HandleToObject(fd);
2195 retVal = yaffs_remove_xattrib(obj, name);
2197 yaffsfs_SetError(retVal);
2202 yaffsfs_SetError(-EBADF);
2210 #ifdef CONFIG_YAFFS_WINCE
2211 int yaffs_get_wince_times(int fd, unsigned *wctime,
2212 unsigned *watime, unsigned *wmtime)
2214 struct yaffs_obj *obj;
2219 obj = yaffsfs_HandleToObject(fd);
2224 wctime[0] = obj->win_ctime[0];
2225 wctime[1] = obj->win_ctime[1];
2228 watime[0] = obj->win_atime[0];
2229 watime[1] = obj->win_atime[1];
2232 wmtime[0] = obj->win_mtime[0];
2233 wmtime[1] = obj->win_mtime[1];
2239 yaffsfs_SetError(-EBADF);
2246 int yaffs_set_wince_times(int fd,
2247 const unsigned *wctime,
2248 const unsigned *watime, const unsigned *wmtime)
2250 struct yaffs_obj *obj;
2255 obj = yaffsfs_HandleToObject(fd);
2260 obj->win_ctime[0] = wctime[0];
2261 obj->win_ctime[1] = wctime[1];
2264 obj->win_atime[0] = watime[0];
2265 obj->win_atime[1] = watime[1];
2268 obj->win_mtime[0] = wmtime[0];
2269 obj->win_mtime[1] = wmtime[1];
2273 result = yaffs_flush_file(obj, 0, 0);
2277 yaffsfs_SetError(-EBADF);
2286 static int yaffsfs_DoChMod(struct yaffs_obj *obj, mode_t mode)
2291 obj = yaffs_get_equivalent_obj(obj);
2294 obj->yst_mode = mode;
2296 result = yaffs_flush_file(obj, 0, 0);
2299 return result == YAFFS_OK ? 0 : -1;
2302 int yaffs_access(const YCHAR *path, int amode)
2304 struct yaffs_obj *obj = NULL;
2305 struct yaffs_obj *dir = NULL;
2310 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2311 yaffsfs_SetError(-EFAULT);
2315 if (yaffsfs_CheckPath(path) < 0) {
2316 yaffsfs_SetError(-ENAMETOOLONG);
2320 if (amode & ~(R_OK | W_OK | X_OK)) {
2321 yaffsfs_SetError(-EINVAL);
2327 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
2328 obj = yaffsfs_FollowLink(obj, 0, &loop);
2331 yaffsfs_SetError(-ENOTDIR);
2333 yaffsfs_SetError(-ELOOP);
2334 else if (!dir || !obj)
2335 yaffsfs_SetError(-ENOENT);
2336 else if ((amode & W_OK) && obj->my_dev->read_only)
2337 yaffsfs_SetError(-EROFS);
2341 if ((amode & R_OK) && !(obj->yst_mode & S_IREAD))
2343 if ((amode & W_OK) && !(obj->yst_mode & S_IWRITE))
2345 if ((amode & X_OK) && !(obj->yst_mode & S_IEXEC))
2349 yaffsfs_SetError(-EACCES);
2360 int yaffs_chmod(const YCHAR *path, mode_t mode)
2362 struct yaffs_obj *obj = NULL;
2363 struct yaffs_obj *dir = NULL;
2368 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2369 yaffsfs_SetError(-EFAULT);
2373 if (yaffsfs_CheckPath(path) < 0) {
2374 yaffsfs_SetError(-ENAMETOOLONG);
2378 if (mode & ~(0777)) {
2379 yaffsfs_SetError(-EINVAL);
2385 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
2386 obj = yaffsfs_FollowLink(obj, 0, &loop);
2389 yaffsfs_SetError(-ENOTDIR);
2391 yaffsfs_SetError(-ELOOP);
2392 else if (!dir || !obj)
2393 yaffsfs_SetError(-ENOENT);
2394 else if (obj->my_dev->read_only)
2395 yaffsfs_SetError(-EROFS);
2397 retVal = yaffsfs_DoChMod(obj, mode);
2405 int yaffs_fchmod(int fd, mode_t mode)
2407 struct yaffs_obj *obj;
2410 if (mode & ~(0777)) {
2411 yaffsfs_SetError(-EINVAL);
2416 obj = yaffsfs_HandleToObject(fd);
2419 yaffsfs_SetError(-EBADF);
2420 else if (obj->my_dev->read_only)
2421 yaffsfs_SetError(-EROFS);
2423 retVal = yaffsfs_DoChMod(obj, mode);
2430 int yaffs_mkdir(const YCHAR *path, mode_t mode)
2432 struct yaffs_obj *parent = NULL;
2433 struct yaffs_obj *dir = NULL;
2435 YCHAR *alt_path = NULL;
2440 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2441 yaffsfs_SetError(-EFAULT);
2445 if (yaffsfs_CheckPath(path) < 0) {
2446 yaffsfs_SetError(-ENAMETOOLONG);
2450 if (yaffsfs_alt_dir_path(path, &alt_path) < 0) {
2451 yaffsfs_SetError(-ENOMEM);
2458 parent = yaffsfs_FindDirectory(NULL, path, &name, 0, ¬Dir, &loop);
2459 if (!parent && notDir)
2460 yaffsfs_SetError(-ENOTDIR);
2462 yaffsfs_SetError(-ELOOP);
2464 yaffsfs_SetError(-ENOENT);
2465 else if (yaffsfs_TooManyObjects(parent->my_dev))
2466 yaffsfs_SetError(-ENFILE);
2467 else if (yaffs_strnlen(name, 5) == 0) {
2468 /* Trying to make the root itself */
2469 yaffsfs_SetError(-EEXIST);
2470 } else if (parent->my_dev->read_only)
2471 yaffsfs_SetError(-EROFS);
2473 dir = yaffs_create_dir(parent, name, mode, 0, 0);
2476 else if (yaffs_find_by_name(parent, name))
2477 yaffsfs_SetError(-EEXIST); /* name exists */
2479 yaffsfs_SetError(-ENOSPC); /* assume no space */
2489 int yaffs_rmdir(const YCHAR *path)
2494 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2495 yaffsfs_SetError(-EFAULT);
2499 if (yaffsfs_CheckPath(path) < 0) {
2500 yaffsfs_SetError(-ENAMETOOLONG);
2504 if (yaffsfs_alt_dir_path(path, &alt_path) < 0) {
2505 yaffsfs_SetError(-ENOMEM);
2510 result = yaffsfs_DoUnlink(path, 1);
2517 void *yaffs_getdev(const YCHAR *path)
2519 struct yaffs_dev *dev = NULL;
2521 dev = yaffsfs_FindDevice(path, &dummy);
2525 int yaffs_mount_common(const YCHAR *path, int read_only, int skip_checkpt)
2528 int result = YAFFS_FAIL;
2529 struct yaffs_dev *dev = NULL;
2531 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2532 yaffsfs_SetError(-EFAULT);
2536 yaffs_trace(YAFFS_TRACE_MOUNT, "yaffs: Mounting %s", path);
2538 if (yaffsfs_CheckPath(path) < 0) {
2539 yaffsfs_SetError(-ENAMETOOLONG);
2545 yaffsfs_InitHandles();
2547 dev = yaffsfs_FindMountPoint(path);
2549 if (!dev->is_mounted) {
2550 dev->read_only = read_only ? 1 : 0;
2552 u8 skip = dev->param.skip_checkpt_rd;
2553 dev->param.skip_checkpt_rd = 1;
2554 result = yaffs_guts_initialise(dev);
2555 dev->param.skip_checkpt_rd = skip;
2557 result = yaffs_guts_initialise(dev);
2560 if (result == YAFFS_FAIL)
2561 yaffsfs_SetError(-ENOMEM);
2562 retVal = result ? 0 : -1;
2565 yaffsfs_SetError(-EBUSY);
2567 yaffsfs_SetError(-ENODEV);
2574 int yaffs_mount2(const YCHAR *path, int readonly)
2576 return yaffs_mount_common(path, readonly, 0);
2579 int yaffs_mount(const YCHAR *path)
2581 return yaffs_mount_common(path, 0, 0);
2584 int yaffs_sync(const YCHAR *path)
2587 struct yaffs_dev *dev = NULL;
2590 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2591 yaffsfs_SetError(-EFAULT);
2595 if (yaffsfs_CheckPath(path) < 0) {
2596 yaffsfs_SetError(-ENAMETOOLONG);
2601 dev = yaffsfs_FindDevice(path, &dummy);
2603 if (!dev->is_mounted)
2604 yaffsfs_SetError(-EINVAL);
2605 else if (dev->read_only)
2606 yaffsfs_SetError(-EROFS);
2609 yaffs_flush_whole_cache(dev);
2610 yaffs_checkpoint_save(dev);
2615 yaffsfs_SetError(-ENODEV);
2621 static int yaffsfs_IsDevBusy(struct yaffs_dev *dev)
2624 struct yaffs_obj *obj;
2626 for (i = 0; i < YAFFSFS_N_HANDLES; i++) {
2627 obj = yaffsfs_HandleToObject(i);
2628 if (obj && obj->my_dev == dev)
2634 int yaffs_remount(const YCHAR *path, int force, int read_only)
2637 struct yaffs_dev *dev = NULL;
2639 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2640 yaffsfs_SetError(-EFAULT);
2644 if (yaffsfs_CheckPath(path) < 0) {
2645 yaffsfs_SetError(-ENAMETOOLONG);
2650 dev = yaffsfs_FindMountPoint(path);
2652 if (dev->is_mounted) {
2653 yaffs_flush_whole_cache(dev);
2655 if (force || !yaffsfs_IsDevBusy(dev)) {
2657 yaffs_checkpoint_save(dev);
2658 dev->read_only = read_only ? 1 : 0;
2661 yaffsfs_SetError(-EBUSY);
2664 yaffsfs_SetError(-EINVAL);
2667 yaffsfs_SetError(-ENODEV);
2674 int yaffs_unmount2(const YCHAR *path, int force)
2677 struct yaffs_dev *dev = NULL;
2679 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2680 yaffsfs_SetError(-EFAULT);
2684 if (yaffsfs_CheckPath(path) < 0) {
2685 yaffsfs_SetError(-ENAMETOOLONG);
2690 dev = yaffsfs_FindMountPoint(path);
2692 if (dev->is_mounted) {
2694 yaffs_flush_whole_cache(dev);
2695 yaffs_checkpoint_save(dev);
2696 inUse = yaffsfs_IsDevBusy(dev);
2697 if (!inUse || force) {
2699 yaffsfs_BreakDeviceHandles(dev);
2700 yaffs_deinitialise(dev);
2704 yaffsfs_SetError(-EBUSY);
2707 yaffsfs_SetError(-EINVAL);
2710 yaffsfs_SetError(-ENODEV);
2717 int yaffs_unmount(const YCHAR *path)
2719 return yaffs_unmount2(path, 0);
2722 int yaffs_format(const YCHAR *path,
2724 int force_unmount_flag,
2728 struct yaffs_dev *dev = NULL;
2732 yaffsfs_SetError(-EFAULT);
2736 if (yaffsfs_CheckPath(path) < 0) {
2737 yaffsfs_SetError(-ENAMETOOLONG);
2742 dev = yaffsfs_FindMountPoint(path);
2745 int was_mounted = dev->is_mounted;
2747 if (dev->is_mounted && unmount_flag) {
2749 yaffs_flush_whole_cache(dev);
2750 yaffs_checkpoint_save(dev);
2751 inUse = yaffsfs_IsDevBusy(dev);
2752 if (!inUse || force_unmount_flag) {
2754 yaffsfs_BreakDeviceHandles(dev);
2755 yaffs_deinitialise(dev);
2759 if(dev->is_mounted) {
2760 yaffsfs_SetError(-EBUSY);
2763 yaffs_format_dev(dev);
2764 if(was_mounted && remount_flag) {
2765 result = yaffs_guts_initialise(dev);
2766 if (result == YAFFS_FAIL) {
2767 yaffsfs_SetError(-ENOMEM);
2773 yaffsfs_SetError(-ENODEV);
2783 Y_LOFF_T yaffs_freespace(const YCHAR *path)
2785 Y_LOFF_T retVal = -1;
2786 struct yaffs_dev *dev = NULL;
2789 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2790 yaffsfs_SetError(-EFAULT);
2794 if (yaffsfs_CheckPath(path) < 0) {
2795 yaffsfs_SetError(-ENAMETOOLONG);
2800 dev = yaffsfs_FindDevice(path, &dummy);
2801 if (dev && dev->is_mounted) {
2802 retVal = yaffs_get_n_free_chunks(dev);
2803 retVal *= dev->data_bytes_per_chunk;
2806 yaffsfs_SetError(-EINVAL);
2812 Y_LOFF_T yaffs_totalspace(const YCHAR *path)
2814 Y_LOFF_T retVal = -1;
2815 struct yaffs_dev *dev = NULL;
2818 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2819 yaffsfs_SetError(-EFAULT);
2823 if (yaffsfs_CheckPath(path) < 0) {
2824 yaffsfs_SetError(-ENAMETOOLONG);
2829 dev = yaffsfs_FindDevice(path, &dummy);
2830 if (dev && dev->is_mounted) {
2831 retVal = (dev->param.end_block - dev->param.start_block + 1) -
2832 dev->param.n_reserved_blocks;
2833 retVal *= dev->param.chunks_per_block;
2834 retVal *= dev->data_bytes_per_chunk;
2837 yaffsfs_SetError(-EINVAL);
2843 int yaffs_inodecount(const YCHAR *path)
2845 Y_LOFF_T retVal = -1;
2846 struct yaffs_dev *dev = NULL;
2849 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
2850 yaffsfs_SetError(-EFAULT);
2854 if (yaffsfs_CheckPath(path) < 0) {
2855 yaffsfs_SetError(-ENAMETOOLONG);
2860 dev = yaffsfs_FindDevice(path, &dummy);
2861 if (dev && dev->is_mounted) {
2862 int n_obj = dev->n_obj;
2863 if (n_obj > dev->n_hardlinks)
2864 retVal = n_obj - dev->n_hardlinks;
2868 yaffsfs_SetError(-EINVAL);
2874 void yaffs_add_device(struct yaffs_dev *dev)
2876 struct list_head *cfg;
2877 /* First check that the device is not in the list. */
2879 list_for_each(cfg, &yaffsfs_deviceList) {
2880 if (dev == list_entry(cfg, struct yaffs_dev, dev_list))
2884 dev->is_mounted = 0;
2885 dev->param.remove_obj_fn = yaffsfs_RemoveObjectCallback;
2887 if (!dev->dev_list.next)
2888 INIT_LIST_HEAD(&dev->dev_list);
2890 list_add(&dev->dev_list, &yaffsfs_deviceList);
2895 void yaffs_remove_device(struct yaffs_dev *dev)
2897 list_del_init(&dev->dev_list);
2900 /* Functions to iterate through devices. NB Use with extreme care! */
2902 static struct list_head *dev_iterator;
2903 void yaffs_dev_rewind(void)
2905 dev_iterator = yaffsfs_deviceList.next;
2908 struct yaffs_dev *yaffs_next_dev(void)
2910 struct yaffs_dev *retval;
2914 if (dev_iterator == &yaffsfs_deviceList)
2917 retval = list_entry(dev_iterator, struct yaffs_dev, dev_list);
2918 dev_iterator = dev_iterator->next;
2922 /* Directory search stuff. */
2924 static struct list_head search_contexts;
2926 static void yaffsfs_SetDirRewound(struct yaffsfs_DirSearchContext *dsc)
2930 dsc->dirObj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) {
2934 if (list_empty(&dsc->dirObj->variant.dir_variant.children))
2935 dsc->nextReturn = NULL;
2938 list_entry(dsc->dirObj->variant.dir_variant.
2939 children.next, struct yaffs_obj,
2942 /* Hey someone isn't playing nice! */
2946 static void yaffsfs_DirAdvance(struct yaffsfs_DirSearchContext *dsc)
2950 dsc->dirObj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) {
2952 if (dsc->nextReturn == NULL ||
2953 list_empty(&dsc->dirObj->variant.dir_variant.children))
2954 dsc->nextReturn = NULL;
2956 struct list_head *next = dsc->nextReturn->siblings.next;
2958 if (next == &dsc->dirObj->variant.dir_variant.children)
2959 dsc->nextReturn = NULL; /* end of list */
2961 dsc->nextReturn = list_entry(next,
2966 /* Hey someone isn't playing nice! */
2970 static void yaffsfs_RemoveObjectCallback(struct yaffs_obj *obj)
2973 struct list_head *i;
2974 struct yaffsfs_DirSearchContext *dsc;
2976 /* if search contexts not initilised then skip */
2977 if (!search_contexts.next)
2980 /* Iterate through the directory search contexts.
2981 * If any are the one being removed, then advance the dsc to
2982 * the next one to prevent a hanging ptr.
2984 list_for_each(i, &search_contexts) {
2986 dsc = list_entry(i, struct yaffsfs_DirSearchContext,
2988 if (dsc->nextReturn == obj)
2989 yaffsfs_DirAdvance(dsc);
2995 static yaffs_DIR *yaffsfs_opendir_no_lock(const YCHAR *dirname)
2997 yaffs_DIR *dir = NULL;
2998 struct yaffs_obj *obj = NULL;
2999 struct yaffsfs_DirSearchContext *dsc = NULL;
3003 if (yaffsfs_CheckMemRegion(dirname, 0, 0) < 0) {
3004 yaffsfs_SetError(-EFAULT);
3008 if (yaffsfs_CheckPath(dirname) < 0) {
3009 yaffsfs_SetError(-ENAMETOOLONG);
3013 obj = yaffsfs_FindObject(NULL, dirname, 0, 1, NULL, ¬Dir, &loop);
3016 yaffsfs_SetError(-ENOTDIR);
3018 yaffsfs_SetError(-ELOOP);
3020 yaffsfs_SetError(-ENOENT);
3021 else if (obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
3022 yaffsfs_SetError(-ENOTDIR);
3026 for (i = 0, dsc = NULL; i < YAFFSFS_N_DSC && !dsc; i++) {
3027 if (!yaffsfs_dsc[i].inUse)
3028 dsc = &yaffsfs_dsc[i];
3031 dir = (yaffs_DIR *) dsc;
3034 memset(dsc, 0, sizeof(struct yaffsfs_DirSearchContext));
3037 yaffs_strncpy(dsc->name, dirname, NAME_MAX);
3038 INIT_LIST_HEAD(&dsc->others);
3040 if (!search_contexts.next)
3041 INIT_LIST_HEAD(&search_contexts);
3043 list_add(&dsc->others, &search_contexts);
3044 yaffsfs_SetDirRewound(dsc);
3050 yaffs_DIR *yaffs_opendir(const YCHAR *dirname)
3055 ret = yaffsfs_opendir_no_lock(dirname);
3060 struct yaffs_dirent *yaffsfs_readdir_no_lock(yaffs_DIR * dirp)
3062 struct yaffsfs_DirSearchContext *dsc;
3063 struct yaffs_dirent *retVal = NULL;
3065 dsc = (struct yaffsfs_DirSearchContext *) dirp;
3068 if (dsc && dsc->inUse) {
3069 yaffsfs_SetError(0);
3070 if (dsc->nextReturn) {
3072 yaffs_get_equivalent_obj(dsc->nextReturn)->obj_id;
3073 dsc->de.d_dont_use = (unsigned)dsc->nextReturn;
3074 dsc->de.d_off = dsc->offset++;
3075 yaffs_get_obj_name(dsc->nextReturn,
3076 dsc->de.d_name, NAME_MAX);
3077 if (yaffs_strnlen(dsc->de.d_name, NAME_MAX + 1) == 0) {
3078 /* this should not happen! */
3079 yaffs_strcpy(dsc->de.d_name, _Y("zz"));
3081 dsc->de.d_reclen = sizeof(struct yaffs_dirent);
3083 yaffsfs_DirAdvance(dsc);
3087 yaffsfs_SetError(-EBADF);
3092 struct yaffs_dirent *yaffs_readdir(yaffs_DIR * dirp)
3094 struct yaffs_dirent *ret;
3097 ret = yaffsfs_readdir_no_lock(dirp);
3102 static void yaffsfs_rewinddir_no_lock(yaffs_DIR *dirp)
3104 struct yaffsfs_DirSearchContext *dsc;
3106 dsc = (struct yaffsfs_DirSearchContext *) dirp;
3108 if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0)
3111 yaffsfs_SetDirRewound(dsc);
3115 void yaffs_rewinddir(yaffs_DIR *dirp)
3118 yaffsfs_rewinddir_no_lock(dirp);
3122 struct yaffs_dirent *yaffs_readdir_fd(int fd)
3124 struct yaffs_dirent *ret = NULL;
3125 struct yaffsfs_FileDes *f;
3128 f = yaffsfs_HandleToFileDes(fd);
3130 ret = yaffsfs_readdir_no_lock(f->v.dir);
3135 void yaffs_rewinddir_fd(int fd)
3137 struct yaffsfs_FileDes *f;
3140 f = yaffsfs_HandleToFileDes(fd);
3142 yaffsfs_rewinddir_no_lock(f->v.dir);
3147 static int yaffsfs_closedir_no_lock(yaffs_DIR *dirp)
3149 struct yaffsfs_DirSearchContext *dsc;
3151 dsc = (struct yaffsfs_DirSearchContext *) dirp;
3153 if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0) {
3154 yaffsfs_SetError(-EFAULT);
3159 list_del(&dsc->others); /* unhook from list */
3163 int yaffs_closedir(yaffs_DIR *dirp)
3168 ret = yaffsfs_closedir_no_lock(dirp);
3173 /* End of directory stuff */
3175 int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath)
3177 struct yaffs_obj *parent = NULL;
3178 struct yaffs_obj *obj;
3181 int mode = 0; /* ignore for now */
3185 if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 ||
3186 yaffsfs_CheckMemRegion(newpath, 0, 0) < 0) {
3187 yaffsfs_SetError(-EFAULT);
3191 if (yaffsfs_CheckPath(newpath) < 0 || yaffsfs_CheckPath(oldpath) < 0) {
3192 yaffsfs_SetError(-ENAMETOOLONG);
3197 parent = yaffsfs_FindDirectory(NULL, newpath, &name, 0, ¬Dir, &loop);
3198 if (!parent && notDir)
3199 yaffsfs_SetError(-ENOTDIR);
3201 yaffsfs_SetError(-ELOOP);
3202 else if (!parent || yaffs_strnlen(name, 5) < 1)
3203 yaffsfs_SetError(-ENOENT);
3204 else if (yaffsfs_TooManyObjects(parent->my_dev))
3205 yaffsfs_SetError(-ENFILE);
3206 else if (parent->my_dev->read_only)
3207 yaffsfs_SetError(-EROFS);
3209 obj = yaffs_create_symlink(parent, name, mode, 0, 0, oldpath);
3212 else if (yaffsfs_FindObject
3213 (NULL, newpath, 0, 0, NULL, NULL, NULL))
3214 yaffsfs_SetError(-EEXIST);
3216 yaffsfs_SetError(-ENOSPC);
3225 int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz)
3227 struct yaffs_obj *obj = NULL;
3228 struct yaffs_obj *dir = NULL;
3233 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
3234 yaffsfs_CheckMemRegion(buf, bufsiz, 1) < 0) {
3235 yaffsfs_SetError(-EFAULT);
3241 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop);
3244 yaffsfs_SetError(-ENOTDIR);
3246 yaffsfs_SetError(-ELOOP);
3247 else if (!dir || !obj)
3248 yaffsfs_SetError(-ENOENT);
3249 else if (obj->variant_type != YAFFS_OBJECT_TYPE_SYMLINK)
3250 yaffsfs_SetError(-EINVAL);
3252 YCHAR *alias = obj->variant.symlink_variant.alias;
3253 memset(buf, 0, bufsiz);
3254 yaffs_strncpy(buf, alias, bufsiz - 1);
3261 int yaffs_link(const YCHAR *oldpath, const YCHAR *linkpath)
3263 /* Creates a link called newpath to existing oldpath */
3264 struct yaffs_obj *obj = NULL;
3265 struct yaffs_obj *lnk = NULL;
3266 struct yaffs_obj *obj_dir = NULL;
3267 struct yaffs_obj *lnk_dir = NULL;
3275 if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 ||
3276 yaffsfs_CheckMemRegion(linkpath, 0, 0) < 0) {
3277 yaffsfs_SetError(-EFAULT);
3281 if (yaffsfs_CheckPath(linkpath) < 0 || yaffsfs_CheckPath(oldpath) < 0) {
3282 yaffsfs_SetError(-ENAMETOOLONG);
3288 obj = yaffsfs_FindObject(NULL, oldpath, 0, 1,
3289 &obj_dir, ¬DirObj, &objLoop);
3290 lnk = yaffsfs_FindObject(NULL, linkpath, 0, 0, NULL, NULL, NULL);
3291 lnk_dir = yaffsfs_FindDirectory(NULL, linkpath, &newname,
3292 0, ¬DirLnk, &lnkLoop);
3294 if ((!obj_dir && notDirObj) || (!lnk_dir && notDirLnk))
3295 yaffsfs_SetError(-ENOTDIR);
3296 else if (objLoop || lnkLoop)
3297 yaffsfs_SetError(-ELOOP);
3298 else if (!obj_dir || !lnk_dir || !obj)
3299 yaffsfs_SetError(-ENOENT);
3300 else if (obj->my_dev->read_only)
3301 yaffsfs_SetError(-EROFS);
3302 else if (yaffsfs_TooManyObjects(obj->my_dev))
3303 yaffsfs_SetError(-ENFILE);
3305 yaffsfs_SetError(-EEXIST);
3306 else if (lnk_dir->my_dev != obj->my_dev)
3307 yaffsfs_SetError(-EXDEV);
3309 retVal = yaffsfs_CheckNameLength(newname);
3312 lnk = yaffs_link_obj(lnk_dir, newname, obj);
3316 yaffsfs_SetError(-ENOSPC);
3326 int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev)
3332 yaffsfs_SetError(-EINVAL);
3337 * D E B U G F U N C T I O N S
3342 * Returns number of handles attached to the object
3344 int yaffs_n_handles(const YCHAR *path)
3346 struct yaffs_obj *obj;
3348 if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
3349 yaffsfs_SetError(-EFAULT);
3353 if (yaffsfs_CheckPath(path) < 0) {
3354 yaffsfs_SetError(-ENAMETOOLONG);
3358 obj = yaffsfs_FindObject(NULL, path, 0, 1, NULL, NULL, NULL);
3361 return yaffsfs_CountHandles(obj);
3366 int yaffs_get_error(void)
3368 return yaffsfs_GetLastError();
3371 int yaffs_set_error(int error)
3373 yaffsfs_SetError(error);
3377 int yaffs_dump_dev(const YCHAR *path)
3384 struct yaffs_obj *obj = yaffsfs_FindRoot(path, &rest);
3387 struct yaffs_dev *dev = obj->my_dev;
3390 "n_page_writes.......... %d\n"
3391 "n_page_reads........... %d\n"
3392 "n_erasures....... %d\n"
3393 "n_gc_copies............ %d\n"
3394 "garbageCollections... %d\n"
3395 "passiveGarbageColl'ns %d\n"
3401 dev->garbageCollections, dev->passiveGarbageCollections);