2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2007 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.
19 #include "yaffs_guts.h"
25 #include <string.h> // for memset
28 #define YAFFSFS_MAX_SYMLINK_DEREFERENCES 5
31 #define NULL ((void *)0)
35 const char *yaffsfs_c_version
="$Id: yaffsfs.c,v 1.18 2007/07/18 19:40:38 charles Exp $";
37 // configurationList is the list of devices that are supported
38 static yaffsfs_DeviceConfiguration
*yaffsfs_configurationList
;
41 /* Some forward references */
42 static yaffs_Object
*yaffsfs_FindObject(yaffs_Object
*relativeDirectory
, const char *path
, int symDepth
);
43 static void yaffsfs_RemoveObjectCallback(yaffs_Object
*obj
);
50 unsigned int yaffs_wr_attempts
;
54 __u8 inUse
:1; // this handle is in use
55 __u8 readOnly
:1; // this handle is read only
56 __u8 append
:1; // append only
57 __u8 exclusive
:1; // exclusive
58 __u32 position
; // current position in file
59 yaffs_Object
*obj
; // the object
63 static yaffsfs_Handle yaffsfs_handle
[YAFFSFS_N_HANDLES
];
66 /// Inilitalise handles on start-up.
68 static int yaffsfs_InitHandles(void)
71 for(i
= 0; i
< YAFFSFS_N_HANDLES
; i
++)
73 yaffsfs_handle
[i
].inUse
= 0;
74 yaffsfs_handle
[i
].obj
= NULL
;
79 yaffsfs_Handle
*yaffsfs_GetHandlePointer(int h
)
81 if(h
< 0 || h
>= YAFFSFS_N_HANDLES
)
86 return &yaffsfs_handle
[h
];
89 yaffs_Object
*yaffsfs_GetHandleObject(int handle
)
91 yaffsfs_Handle
*h
= yaffsfs_GetHandlePointer(handle
);
103 // Grab a handle (when opening a file)
106 static int yaffsfs_GetHandle(void)
111 for(i
= 0; i
< YAFFSFS_N_HANDLES
; i
++)
113 h
= yaffsfs_GetHandlePointer(i
);
116 // todo bug: should never happen
120 memset(h
,0,sizeof(yaffsfs_Handle
));
129 // Let go of a handle (when closing a file)
131 static int yaffsfs_PutHandle(int handle
)
133 yaffsfs_Handle
*h
= yaffsfs_GetHandlePointer(handle
);
145 // Stuff to search for a directory from a path
148 int yaffsfs_Match(char a
, char b
)
154 // yaffsfs_FindDevice
156 // Scan the configuration list to find the root.
157 // Curveballs: Should match paths that end in '/' too
158 // Curveball2 Might have "/x/ and "/x/y". Need to return the longest match
159 static yaffs_Device
*yaffsfs_FindDevice(const char *path
, char **restOfPath
)
161 yaffsfs_DeviceConfiguration
*cfg
= yaffsfs_configurationList
;
162 const char *leftOver
;
164 yaffs_Device
*retval
= NULL
;
166 int longestMatch
= -1;
168 // Check all configs, choose the one that:
169 // 1) Actually matches a prefix (ie /a amd /abc will not match
170 // 2) Matches the longest.
171 while(cfg
&& cfg
->prefix
&& cfg
->dev
)
177 while(*p
&& //unmatched part of prefix
178 strcmp(p
,"/") && // the rest of the prefix is not / (to catch / at end)
180 yaffsfs_Match(*p
,*leftOver
))
186 if((!*p
|| strcmp(p
,"/") == 0) && // end of prefix
187 (!*leftOver
|| *leftOver
== '/') && // no more in this path name part
188 (thisMatchLength
> longestMatch
))
191 *restOfPath
= (char *)leftOver
;
193 longestMatch
= thisMatchLength
;
200 static yaffs_Object
*yaffsfs_FindRoot(const char *path
, char **restOfPath
)
205 dev
= yaffsfs_FindDevice(path
,restOfPath
);
206 if(dev
&& dev
->isMounted
)
213 static yaffs_Object
*yaffsfs_FollowLink(yaffs_Object
*obj
,int symDepth
)
216 while(obj
&& obj
->variantType
== YAFFS_OBJECT_TYPE_SYMLINK
)
218 char *alias
= obj
->variant
.symLinkVariant
.alias
;
222 // Starts with a /, need to scan from root up
223 obj
= yaffsfs_FindObject(NULL
,alias
,symDepth
++);
227 // Relative to here, so use the parent of the symlink as a start
228 obj
= yaffsfs_FindObject(obj
->parent
,alias
,symDepth
++);
235 // yaffsfs_FindDirectory
236 // Parse a path to determine the directory and the name within the directory.
238 // eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx"
239 static yaffs_Object
*yaffsfs_DoFindDirectory(yaffs_Object
*startDir
,const char *path
,char **name
,int symDepth
)
243 char str
[YAFFS_MAX_NAME_LENGTH
+1];
246 if(symDepth
> YAFFSFS_MAX_SYMLINK_DEREFERENCES
)
254 restOfPath
= (char *)path
;
258 dir
= yaffsfs_FindRoot(path
,&restOfPath
);
264 // curve ball: also throw away surplus '/'
265 // eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"
266 while(*restOfPath
== '/')
268 restOfPath
++; // get rid of '/'
274 while(*restOfPath
&& *restOfPath
!= '/')
276 if (i
< YAFFS_MAX_NAME_LENGTH
)
278 str
[i
] = *restOfPath
;
287 // got to the end of the string
292 if(strcmp(str
,".") == 0)
296 else if(strcmp(str
,"..") == 0)
302 dir
= yaffs_FindObjectByName(dir
,str
);
304 while(dir
&& dir
->variantType
== YAFFS_OBJECT_TYPE_SYMLINK
)
307 dir
= yaffsfs_FollowLink(dir
,symDepth
);
311 if(dir
&& dir
->variantType
!= YAFFS_OBJECT_TYPE_DIRECTORY
)
318 // directory did not exist.
322 static yaffs_Object
*yaffsfs_FindDirectory(yaffs_Object
*relativeDirectory
,const char *path
,char **name
,int symDepth
)
324 return yaffsfs_DoFindDirectory(relativeDirectory
,path
,name
,symDepth
);
327 // yaffsfs_FindObject turns a path for an existing object into the object
329 static yaffs_Object
*yaffsfs_FindObject(yaffs_Object
*relativeDirectory
, const char *path
,int symDepth
)
334 dir
= yaffsfs_FindDirectory(relativeDirectory
,path
,&name
,symDepth
);
338 return yaffs_FindObjectByName(dir
,name
);
346 int yaffs_open(const char *path
, int oflag
, int mode
)
348 yaffs_Object
*obj
= NULL
;
349 yaffs_Object
*dir
= NULL
;
352 yaffsfs_Handle
*h
= NULL
;
354 int alreadyExclusive
= 0;
357 int errorReported
= 0;
362 // todo sanity check oflag (eg. can't have O_TRUNC without WRONLY or RDWR
367 handle
= yaffsfs_GetHandle();
372 h
= yaffsfs_GetHandlePointer(handle
);
375 // try to find the exisiting object
376 obj
= yaffsfs_FindObject(NULL
,path
,0);
378 if(obj
&& obj
->variantType
== YAFFS_OBJECT_TYPE_SYMLINK
)
381 obj
= yaffsfs_FollowLink(obj
,symDepth
++);
386 // Check if the object is already in use
387 alreadyOpen
= alreadyExclusive
= 0;
389 for(i
= 0; i
<= YAFFSFS_N_HANDLES
; i
++)
393 yaffsfs_handle
[i
].inUse
&&
394 obj
== yaffsfs_handle
[i
].obj
)
397 if(yaffsfs_handle
[i
].exclusive
)
399 alreadyExclusive
= 1;
404 if(((oflag
& O_EXCL
) && alreadyOpen
) || alreadyExclusive
)
409 // Open should fail if O_CREAT and O_EXCL are specified
410 if((oflag
& O_EXCL
) && (oflag
& O_CREAT
))
413 yaffsfs_SetError(-EEXIST
);
417 // Check file permissions
418 if( (oflag
& (O_RDWR
| O_WRONLY
)) == 0 && // ie O_RDONLY
419 !(obj
->yst_mode
& S_IREAD
))
424 if( (oflag
& O_RDWR
) &&
425 !(obj
->yst_mode
& S_IREAD
))
430 if( (oflag
& (O_RDWR
| O_WRONLY
)) &&
431 !(obj
->yst_mode
& S_IWRITE
))
438 else if((oflag
& O_CREAT
))
440 // Let's see if we can create this file
441 dir
= yaffsfs_FindDirectory(NULL
,path
,&name
,0);
444 obj
= yaffs_MknodFile(dir
,name
,mode
,0,0);
448 yaffsfs_SetError(-ENOTDIR
);
452 if(obj
&& !openDenied
)
456 h
->readOnly
= (oflag
& (O_WRONLY
| O_RDWR
)) ? 0 : 1;
457 h
->append
= (oflag
& O_APPEND
) ? 1 : 0;
458 h
->exclusive
= (oflag
& O_EXCL
) ? 1 : 0;
462 if((oflag
& O_TRUNC
) && !h
->readOnly
)
465 yaffs_ResizeFile(obj
,0);
471 yaffsfs_PutHandle(handle
);
474 yaffsfs_SetError(-EACCESS
);
487 int yaffs_close(int fd
)
489 yaffsfs_Handle
*h
= NULL
;
494 h
= yaffsfs_GetHandlePointer(fd
);
499 yaffs_FlushFile(h
->obj
,1);
501 if(h
->obj
->inUse
<= 0 && h
->obj
->unlinked
)
503 yaffs_DeleteFile(h
->obj
);
505 yaffsfs_PutHandle(fd
);
511 yaffsfs_SetError(-EBADF
);
520 int yaffs_read(int fd
, void *buf
, unsigned int nbyte
)
522 yaffsfs_Handle
*h
= NULL
;
523 yaffs_Object
*obj
= NULL
;
529 h
= yaffsfs_GetHandlePointer(fd
);
530 obj
= yaffsfs_GetHandleObject(fd
);
535 yaffsfs_SetError(-EBADF
);
540 if(yaffs_GetObjectFileLength(obj
) > pos
)
542 maxRead
= yaffs_GetObjectFileLength(obj
) - pos
;
557 nRead
= yaffs_ReadDataFromFile(obj
,buf
,pos
,nbyte
);
560 h
->position
= pos
+ nRead
;
577 return (nRead
>= 0) ? nRead
: -1;
581 int yaffs_write(int fd
, const void *buf
, unsigned int nbyte
)
583 yaffsfs_Handle
*h
= NULL
;
584 yaffs_Object
*obj
= NULL
;
587 int writeThrough
= 0;
590 h
= yaffsfs_GetHandlePointer(fd
);
591 obj
= yaffsfs_GetHandleObject(fd
);
596 yaffsfs_SetError(-EBADF
);
598 else if( h
&& obj
&& h
->readOnly
)
606 pos
= yaffs_GetObjectFileLength(obj
);
613 nWritten
= yaffs_WriteDataToFile(obj
,buf
,pos
,nbyte
,writeThrough
);
617 h
->position
= pos
+ nWritten
;
629 return (nWritten
>= 0) ? nWritten
: -1;
633 int yaffs_truncate(int fd
, off_t newSize
)
635 yaffsfs_Handle
*h
= NULL
;
636 yaffs_Object
*obj
= NULL
;
640 h
= yaffsfs_GetHandlePointer(fd
);
641 obj
= yaffsfs_GetHandleObject(fd
);
646 yaffsfs_SetError(-EBADF
);
651 result
= yaffs_ResizeFile(obj
,newSize
);
656 return (result
) ? 0 : -1;
660 off_t
yaffs_lseek(int fd
, off_t offset
, int whence
)
662 yaffsfs_Handle
*h
= NULL
;
663 yaffs_Object
*obj
= NULL
;
668 h
= yaffsfs_GetHandlePointer(fd
);
669 obj
= yaffsfs_GetHandleObject(fd
);
674 yaffsfs_SetError(-EBADF
);
676 else if(whence
== SEEK_SET
)
683 else if(whence
== SEEK_CUR
)
685 if( (h
->position
+ offset
) >= 0)
687 pos
= (h
->position
+ offset
);
690 else if(whence
== SEEK_END
)
692 fSize
= yaffs_GetObjectFileLength(obj
);
693 if(fSize
>= 0 && (fSize
+ offset
) >= 0)
695 pos
= fSize
+ offset
;
715 int yaffsfs_DoUnlink(const char *path
,int isDirectory
)
717 yaffs_Object
*dir
= NULL
;
718 yaffs_Object
*obj
= NULL
;
720 int result
= YAFFS_FAIL
;
724 obj
= yaffsfs_FindObject(NULL
,path
,0);
725 dir
= yaffsfs_FindDirectory(NULL
,path
,&name
,0);
728 yaffsfs_SetError(-ENOTDIR
);
732 yaffsfs_SetError(-ENOENT
);
734 else if(!isDirectory
&& obj
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
)
736 yaffsfs_SetError(-EISDIR
);
738 else if(isDirectory
&& obj
->variantType
!= YAFFS_OBJECT_TYPE_DIRECTORY
)
740 yaffsfs_SetError(-ENOTDIR
);
744 result
= yaffs_Unlink(dir
,name
);
746 if(result
== YAFFS_FAIL
&& isDirectory
)
748 yaffsfs_SetError(-ENOTEMPTY
);
756 return (result
== YAFFS_FAIL
) ? -1 : 0;
758 int yaffs_rmdir(const char *path
)
760 return yaffsfs_DoUnlink(path
,1);
763 int yaffs_unlink(const char *path
)
765 return yaffsfs_DoUnlink(path
,0);
768 int yaffs_rename(const char *oldPath
, const char *newPath
)
770 yaffs_Object
*olddir
= NULL
;
771 yaffs_Object
*newdir
= NULL
;
772 yaffs_Object
*obj
= NULL
;
775 int result
= YAFFS_FAIL
;
776 int renameAllowed
= 1;
780 olddir
= yaffsfs_FindDirectory(NULL
,oldPath
,&oldname
,0);
781 newdir
= yaffsfs_FindDirectory(NULL
,newPath
,&newname
,0);
782 obj
= yaffsfs_FindObject(NULL
,oldPath
,0);
784 if(!olddir
|| !newdir
|| !obj
)
787 yaffsfs_SetError(-EBADF
);
790 else if(olddir
->myDev
!= newdir
->myDev
)
792 // oops must be on same device
794 yaffsfs_SetError(-EXDEV
);
797 else if(obj
&& obj
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
)
799 // It is a directory, check that it is not being renamed to
800 // being its own decendent.
801 // Do this by tracing from the new directory back to the root, checking for obj
803 yaffs_Object
*xx
= newdir
;
805 while( renameAllowed
&& xx
)
813 if(!renameAllowed
) yaffsfs_SetError(-EACCESS
);
818 result
= yaffs_RenameObject(olddir
,oldname
,newdir
,newname
);
823 return (result
== YAFFS_FAIL
) ? -1 : 0;
827 static int yaffsfs_DoStat(yaffs_Object
*obj
,struct yaffs_stat
*buf
)
833 obj
= yaffs_GetEquivalentObject(obj
);
838 buf
->st_dev
= (int)obj
->myDev
->genericDevice
;
839 buf
->st_ino
= obj
->objectId
;
840 buf
->st_mode
= obj
->yst_mode
& ~S_IFMT
; // clear out file type bits
842 if(obj
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
)
844 buf
->st_mode
|= S_IFDIR
;
846 else if(obj
->variantType
== YAFFS_OBJECT_TYPE_SYMLINK
)
848 buf
->st_mode
|= S_IFLNK
;
850 else if(obj
->variantType
== YAFFS_OBJECT_TYPE_FILE
)
852 buf
->st_mode
|= S_IFREG
;
855 buf
->st_nlink
= yaffs_GetObjectLinkCount(obj
);
858 buf
->st_rdev
= obj
->yst_rdev
;
859 buf
->st_size
= yaffs_GetObjectFileLength(obj
);
860 buf
->st_blksize
= obj
->myDev
->nDataBytesPerChunk
;
861 buf
->st_blocks
= (buf
->st_size
+ buf
->st_blksize
-1)/buf
->st_blksize
;
862 buf
->yst_atime
= obj
->yst_atime
;
863 buf
->yst_ctime
= obj
->yst_ctime
;
864 buf
->yst_mtime
= obj
->yst_mtime
;
870 static int yaffsfs_DoStatOrLStat(const char *path
, struct yaffs_stat
*buf
,int doLStat
)
877 obj
= yaffsfs_FindObject(NULL
,path
,0);
881 obj
= yaffsfs_FollowLink(obj
,0);
886 retVal
= yaffsfs_DoStat(obj
,buf
);
890 // todo error not found
891 yaffsfs_SetError(-ENOENT
);
900 int yaffs_stat(const char *path
, struct yaffs_stat
*buf
)
902 return yaffsfs_DoStatOrLStat(path
,buf
,0);
905 int yaffs_lstat(const char *path
, struct yaffs_stat
*buf
)
907 return yaffsfs_DoStatOrLStat(path
,buf
,1);
910 int yaffs_fstat(int fd
, struct yaffs_stat
*buf
)
917 obj
= yaffsfs_GetHandleObject(fd
);
921 retVal
= yaffsfs_DoStat(obj
,buf
);
926 yaffsfs_SetError(-EBADF
);
934 static int yaffsfs_DoChMod(yaffs_Object
*obj
,mode_t mode
)
936 int result
= YAFFS_FAIL
;
940 obj
= yaffs_GetEquivalentObject(obj
);
945 obj
->yst_mode
= mode
;
947 result
= yaffs_FlushFile(obj
,0);
950 return result
== YAFFS_OK
? 0 : -1;
954 int yaffs_chmod(const char *path
, mode_t mode
)
961 obj
= yaffsfs_FindObject(NULL
,path
,0);
965 retVal
= yaffsfs_DoChMod(obj
,mode
);
969 // todo error not found
970 yaffsfs_SetError(-ENOENT
);
980 int yaffs_fchmod(int fd
, mode_t mode
)
987 obj
= yaffsfs_GetHandleObject(fd
);
991 retVal
= yaffsfs_DoChMod(obj
,mode
);
996 yaffsfs_SetError(-EBADF
);
1005 int yaffs_mkdir(const char *path
, mode_t mode
)
1007 yaffs_Object
*parent
= NULL
;
1008 yaffs_Object
*dir
= NULL
;
1013 parent
= yaffsfs_FindDirectory(NULL
,path
,&name
,0);
1015 dir
= yaffs_MknodDirectory(parent
,name
,mode
,0,0);
1022 yaffsfs_SetError(-ENOSPC
); // just assume no space for now
1031 int yaffs_mount(const char *path
)
1034 int result
=YAFFS_FAIL
;
1035 yaffs_Device
*dev
=NULL
;
1038 T(YAFFS_TRACE_ALWAYS
,("yaffs: Mounting %s\n",path
));
1041 dev
= yaffsfs_FindDevice(path
,&dummy
);
1046 result
= yaffs_GutsInitialise(dev
);
1047 if(result
== YAFFS_FAIL
)
1049 // todo error - mount failed
1050 yaffsfs_SetError(-ENOMEM
);
1052 retVal
= result
? 0 : -1;
1057 //todo error - already mounted.
1058 yaffsfs_SetError(-EBUSY
);
1063 // todo error - no device
1064 yaffsfs_SetError(-ENODEV
);
1071 int yaffs_unmount(const char *path
)
1074 yaffs_Device
*dev
=NULL
;
1078 dev
= yaffsfs_FindDevice(path
,&dummy
);
1086 yaffs_FlushEntireDeviceCache(dev
);
1087 yaffs_CheckpointSave(dev
);
1089 for(i
= inUse
= 0; i
< YAFFSFS_N_HANDLES
&& !inUse
; i
++)
1091 if(yaffsfs_handle
[i
].inUse
&& yaffsfs_handle
[i
].obj
->myDev
== dev
)
1093 inUse
= 1; // the device is in use, can't unmount
1099 yaffs_Deinitialise(dev
);
1105 // todo error can't unmount as files are open
1106 yaffsfs_SetError(-EBUSY
);
1112 //todo error - not mounted.
1113 yaffsfs_SetError(-EINVAL
);
1119 // todo error - no device
1120 yaffsfs_SetError(-ENODEV
);
1127 loff_t
yaffs_freespace(const char *path
)
1130 yaffs_Device
*dev
=NULL
;
1134 dev
= yaffsfs_FindDevice(path
,&dummy
);
1135 if(dev
&& dev
->isMounted
)
1137 retVal
= yaffs_GetNumberOfFreeChunks(dev
);
1138 retVal
*= dev
->nDataBytesPerChunk
;
1143 yaffsfs_SetError(-EINVAL
);
1152 void yaffs_initialise(yaffsfs_DeviceConfiguration
*cfgList
)
1155 yaffsfs_DeviceConfiguration
*cfg
;
1157 yaffsfs_configurationList
= cfgList
;
1159 yaffsfs_InitHandles();
1161 cfg
= yaffsfs_configurationList
;
1163 while(cfg
&& cfg
->prefix
&& cfg
->dev
)
1165 cfg
->dev
->isMounted
= 0;
1166 cfg
->dev
->removeObjectCallback
= yaffsfs_RemoveObjectCallback
;
1173 // Directory search stuff.
1176 // Directory search context
1178 // NB this is an opaque structure.
1184 yaffs_dirent de
; /* directory entry being used by this dsc */
1185 char name
[NAME_MAX
+1]; /* name of directory being searched */
1186 yaffs_Object
*dirObj
; /* ptr to directory being searched */
1187 yaffs_Object
*nextReturn
; /* obj to be returned by next readddir */
1189 struct list_head others
;
1190 } yaffsfs_DirectorySearchContext
;
1194 static struct list_head search_contexts
;
1197 static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext
*dsc
)
1201 dsc
->dirObj
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
){
1205 if( list_empty(&dsc
->dirObj
->variant
.directoryVariant
.children
)){
1206 dsc
->nextReturn
= NULL
;
1208 dsc
->nextReturn
= list_entry(dsc
->dirObj
->variant
.directoryVariant
.children
.next
,
1209 yaffs_Object
,siblings
);
1212 /* Hey someone isn't playing nice! */
1216 static void yaffsfs_DirAdvance(yaffsfs_DirectorySearchContext
*dsc
)
1220 dsc
->dirObj
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
){
1222 if( dsc
->nextReturn
== NULL
||
1223 list_empty(&dsc
->dirObj
->variant
.directoryVariant
.children
)){
1224 dsc
->nextReturn
= NULL
;
1226 struct list_head
*next
= dsc
->nextReturn
->siblings
.next
;
1228 if( next
== &dsc
->dirObj
->variant
.directoryVariant
.children
)
1229 dsc
->nextReturn
= NULL
; /* end of list */
1231 dsc
->nextReturn
= list_entry(next
,yaffs_Object
,siblings
);
1234 /* Hey someone isn't playing nice! */
1238 static void yaffsfs_RemoveObjectCallback(yaffs_Object
*obj
)
1241 struct list_head
*i
;
1242 yaffsfs_DirectorySearchContext
*dsc
;
1244 /* if search contexts not initilised then skip */
1245 if(!search_contexts
.next
)
1248 /* Iteratethrough the directory search contexts.
1249 * If any are the one being removed, then advance the dsc to
1250 * the next one to prevent a hanging ptr.
1252 list_for_each(i
, &search_contexts
) {
1254 dsc
= list_entry(i
, yaffsfs_DirectorySearchContext
,others
);
1255 if(dsc
->nextReturn
== obj
)
1256 yaffsfs_DirAdvance(dsc
);
1262 yaffs_DIR
*yaffs_opendir(const char *dirname
)
1264 yaffs_DIR
*dir
= NULL
;
1265 yaffs_Object
*obj
= NULL
;
1266 yaffsfs_DirectorySearchContext
*dsc
= NULL
;
1270 obj
= yaffsfs_FindObject(NULL
,dirname
,0);
1272 if(obj
&& obj
->variantType
== YAFFS_OBJECT_TYPE_DIRECTORY
)
1275 dsc
= YMALLOC(sizeof(yaffsfs_DirectorySearchContext
));
1276 dir
= (yaffs_DIR
*)dsc
;
1279 memset(dsc
,0,sizeof(yaffsfs_DirectorySearchContext
));
1280 dsc
->magic
= YAFFS_MAGIC
;
1282 strncpy(dsc
->name
,dirname
,NAME_MAX
);
1283 INIT_LIST_HEAD(&dsc
->others
);
1285 if(!search_contexts
.next
)
1286 INIT_LIST_HEAD(&search_contexts
);
1288 list_add(&dsc
->others
,&search_contexts
);
1289 yaffsfs_SetDirRewound(dsc
); }
1298 struct yaffs_dirent
*yaffs_readdir(yaffs_DIR
*dirp
)
1300 yaffsfs_DirectorySearchContext
*dsc
= (yaffsfs_DirectorySearchContext
*)dirp
;
1301 struct yaffs_dirent
*retVal
= NULL
;
1305 if(dsc
&& dsc
->magic
== YAFFS_MAGIC
){
1306 yaffsfs_SetError(0);
1307 if(dsc
->nextReturn
){
1308 dsc
->de
.d_ino
= yaffs_GetEquivalentObject(dsc
->nextReturn
)->objectId
;
1309 dsc
->de
.d_dont_use
= (unsigned)dsc
->nextReturn
;
1310 dsc
->de
.d_off
= dsc
->offset
++;
1311 yaffs_GetObjectName(dsc
->nextReturn
,dsc
->de
.d_name
,NAME_MAX
);
1312 if(strlen(dsc
->de
.d_name
) == 0)
1314 // this should not happen!
1315 strcpy(dsc
->de
.d_name
,"zz");
1317 dsc
->de
.d_reclen
= sizeof(struct yaffs_dirent
);
1319 yaffsfs_DirAdvance(dsc
);
1325 yaffsfs_SetError(-EBADF
);
1335 void yaffs_rewinddir(yaffs_DIR
*dirp
)
1337 yaffsfs_DirectorySearchContext
*dsc
= (yaffsfs_DirectorySearchContext
*)dirp
;
1341 yaffsfs_SetDirRewound(dsc
);
1347 int yaffs_closedir(yaffs_DIR
*dirp
)
1349 yaffsfs_DirectorySearchContext
*dsc
= (yaffsfs_DirectorySearchContext
*)dirp
;
1353 list_del(&dsc
->others
); /* unhook from list */
1359 // end of directory stuff
1362 int yaffs_symlink(const char *oldpath
, const char *newpath
)
1364 yaffs_Object
*parent
= NULL
;
1368 int mode
= 0; // ignore for now
1371 parent
= yaffsfs_FindDirectory(NULL
,newpath
,&name
,0);
1372 obj
= yaffs_MknodSymLink(parent
,name
,mode
,0,0,oldpath
);
1379 yaffsfs_SetError(-ENOSPC
); // just assume no space for now
1389 int yaffs_readlink(const char *path
, char *buf
, int bufsiz
)
1391 yaffs_Object
*obj
= NULL
;
1397 obj
= yaffsfs_FindObject(NULL
,path
,0);
1401 yaffsfs_SetError(-ENOENT
);
1404 else if(obj
->variantType
!= YAFFS_OBJECT_TYPE_SYMLINK
)
1406 yaffsfs_SetError(-EINVAL
);
1411 char *alias
= obj
->variant
.symLinkVariant
.alias
;
1412 memset(buf
,0,bufsiz
);
1413 strncpy(buf
,alias
,bufsiz
- 1);
1420 int yaffs_link(const char *oldpath
, const char *newpath
)
1422 // Creates a link called newpath to existing oldpath
1423 yaffs_Object
*obj
= NULL
;
1424 yaffs_Object
*target
= NULL
;
1430 obj
= yaffsfs_FindObject(NULL
,oldpath
,0);
1431 target
= yaffsfs_FindObject(NULL
,newpath
,0);
1435 yaffsfs_SetError(-ENOENT
);
1440 yaffsfs_SetError(-EEXIST
);
1445 yaffs_Object
*newdir
= NULL
;
1446 yaffs_Object
*link
= NULL
;
1450 newdir
= yaffsfs_FindDirectory(NULL
,newpath
,&newname
,0);
1454 yaffsfs_SetError(-ENOTDIR
);
1457 else if(newdir
->myDev
!= obj
->myDev
)
1459 yaffsfs_SetError(-EXDEV
);
1462 if(newdir
&& strlen(newname
) > 0)
1464 link
= yaffs_Link(newdir
,newname
,obj
);
1469 yaffsfs_SetError(-ENOSPC
);
1480 int yaffs_mknod(const char *pathname
, mode_t mode
, dev_t dev
);
1482 int yaffs_DumpDevStruct(const char *path
)
1486 yaffs_Object
*obj
= yaffsfs_FindRoot(path
,&rest
);
1490 yaffs_Device
*dev
= obj
->myDev
;
1493 "nPageWrites.......... %d\n"
1494 "nPageReads........... %d\n"
1495 "nBlockErasures....... %d\n"
1496 "nGCCopies............ %d\n"
1497 "garbageCollections... %d\n"
1498 "passiveGarbageColl'ns %d\n"
1502 dev
->nBlockErasures
,
1504 dev
->garbageCollections
,
1505 dev
->passiveGarbageCollections