|
1
|
1 /* |
|
|
2 * YAFFS: Yet another FFS. A NAND-flash specific file system. |
|
|
3 * yaffsfs.c The interface functions for using YAFFS via a "direct" interface. |
|
|
4 * |
|
|
5 * Copyright (C) 2002 Aleph One Ltd. |
|
|
6 * |
|
|
7 * Created by Charles Manning <charles@aleph1.co.uk> |
|
|
8 * |
|
|
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. |
|
|
12 * |
|
|
13 */ |
|
|
14 |
|
|
15 #include "yaffsfs.h" |
|
|
16 #include "yaffs_guts.h" |
|
|
17 #include "yaffscfg.h" |
|
|
18 #include <string.h> // for memset |
|
|
19 #include "yportenv.h" |
|
|
20 |
|
|
21 #define YAFFSFS_MAX_SYMLINK_DEREFERENCES 5 |
|
|
22 |
|
|
23 #ifndef NULL |
|
|
24 #define NULL ((void *)0) |
|
|
25 #endif |
|
|
26 |
|
|
27 |
|
11
|
28 const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.3 2005-04-24 09:18:52 charles Exp $"; |
|
1
|
29 |
|
|
30 // configurationList is the list of devices that are supported |
|
|
31 static yaffsfs_DeviceConfiguration *yaffsfs_configurationList; |
|
|
32 |
|
|
33 |
|
|
34 // |
|
|
35 // Directory search context |
|
|
36 // |
|
|
37 // NB this is an opaque structure. |
|
|
38 |
|
|
39 struct yaffsfs_ObjectListEntry |
|
|
40 { |
|
|
41 int objectId; |
|
|
42 struct yaffsfs_ObjectListEntry *next; |
|
|
43 }; |
|
|
44 |
|
|
45 |
|
|
46 typedef struct |
|
|
47 { |
|
|
48 __u32 magic; |
|
|
49 yaffs_dirent de; |
|
|
50 struct yaffsfs_ObjectListEntry *list; |
|
|
51 char name[NAME_MAX+1]; |
|
|
52 |
|
|
53 } yaffsfs_DirectorySearchContext; |
|
|
54 |
|
|
55 |
|
|
56 // Handle management. |
|
|
57 // |
|
|
58 |
|
|
59 typedef struct |
|
|
60 { |
|
|
61 __u8 inUse:1; // this handle is in use |
|
|
62 __u8 readOnly:1; // this handle is read only |
|
|
63 __u8 append:1; // append only |
|
|
64 __u8 exclusive:1; // exclusive |
|
|
65 __u32 position; // current position in file |
|
|
66 yaffs_Object *obj; // the object |
|
|
67 }yaffsfs_Handle; |
|
|
68 |
|
|
69 |
|
|
70 static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path, int symDepth); |
|
|
71 |
|
|
72 |
|
|
73 |
|
|
74 static yaffsfs_Handle yaffsfs_handle[YAFFSFS_N_HANDLES]; |
|
|
75 |
|
|
76 // yaffsfs_InitHandle |
|
|
77 /// Inilitalise handles on start-up. |
|
|
78 // |
|
|
79 static int yaffsfs_InitHandles(void) |
|
|
80 { |
|
|
81 int i; |
|
|
82 for(i = 0; i < YAFFSFS_N_HANDLES; i++) |
|
|
83 { |
|
|
84 yaffsfs_handle[i].inUse = 0; |
|
|
85 yaffsfs_handle[i].obj = NULL; |
|
|
86 } |
|
|
87 return 0; |
|
|
88 } |
|
|
89 |
|
|
90 yaffsfs_Handle *yaffsfs_GetHandlePointer(int h) |
|
|
91 { |
|
|
92 if(h < 0 || h >= YAFFSFS_N_HANDLES) |
|
|
93 { |
|
|
94 return NULL; |
|
|
95 } |
|
|
96 |
|
|
97 return &yaffsfs_handle[h]; |
|
|
98 } |
|
|
99 |
|
|
100 yaffs_Object *yaffsfs_GetHandleObject(int handle) |
|
|
101 { |
|
|
102 yaffsfs_Handle *h = yaffsfs_GetHandlePointer(handle); |
|
|
103 |
|
|
104 if(h && h->inUse) |
|
|
105 { |
|
|
106 return h->obj; |
|
|
107 } |
|
|
108 |
|
|
109 return NULL; |
|
|
110 } |
|
|
111 |
|
|
112 |
|
|
113 //yaffsfs_GetHandle |
|
|
114 // Grab a handle (when opening a file) |
|
|
115 // |
|
|
116 |
|
|
117 static int yaffsfs_GetHandle(void) |
|
|
118 { |
|
|
119 int i; |
|
|
120 yaffsfs_Handle *h; |
|
|
121 |
|
|
122 for(i = 0; i < YAFFSFS_N_HANDLES; i++) |
|
|
123 { |
|
|
124 h = yaffsfs_GetHandlePointer(i); |
|
|
125 if(!h) |
|
|
126 { |
|
|
127 // todo bug: should never happen |
|
|
128 } |
|
|
129 if(!h->inUse) |
|
|
130 { |
|
|
131 memset(h,0,sizeof(yaffsfs_Handle)); |
|
|
132 h->inUse=1; |
|
|
133 return i; |
|
|
134 } |
|
|
135 } |
|
|
136 return -1; |
|
|
137 } |
|
|
138 |
|
|
139 // yaffs_PutHandle |
|
|
140 // Let go of a handle (when closing a file) |
|
|
141 // |
|
|
142 static int yaffsfs_PutHandle(int handle) |
|
|
143 { |
|
|
144 yaffsfs_Handle *h = yaffsfs_GetHandlePointer(handle); |
|
|
145 |
|
|
146 if(h) |
|
|
147 { |
|
|
148 h->inUse = 0; |
|
|
149 h->obj = NULL; |
|
|
150 } |
|
|
151 return 0; |
|
|
152 } |
|
|
153 |
|
|
154 |
|
|
155 |
|
|
156 // Stuff to search for a directory from a path |
|
|
157 |
|
|
158 |
|
|
159 int yaffsfs_Match(char a, char b) |
|
|
160 { |
|
|
161 // case sensitive |
|
|
162 return (a == b); |
|
|
163 } |
|
|
164 |
|
|
165 // yaffsfs_FindDevice |
|
|
166 // yaffsfs_FindRoot |
|
|
167 // Scan the configuration list to find the root. |
|
|
168 static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) |
|
|
169 { |
|
|
170 yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList; |
|
|
171 const char *leftOver; |
|
|
172 const char *p; |
|
|
173 |
|
|
174 while(cfg && cfg->prefix && cfg->dev) |
|
|
175 { |
|
|
176 leftOver = path; |
|
|
177 p = cfg->prefix; |
|
|
178 while(*p && *leftOver && yaffsfs_Match(*p,*leftOver)) |
|
|
179 { |
|
|
180 p++; |
|
|
181 leftOver++; |
|
|
182 } |
|
6
|
183 if(!*p && (!*leftOver || *leftOver == '/')) |
|
1
|
184 { |
|
|
185 // Matched prefix |
|
|
186 *restOfPath = (char *)leftOver; |
|
|
187 return cfg->dev; |
|
|
188 } |
|
|
189 cfg++; |
|
|
190 } |
|
|
191 return NULL; |
|
|
192 } |
|
|
193 |
|
|
194 static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath) |
|
|
195 { |
|
|
196 |
|
|
197 yaffs_Device *dev; |
|
|
198 |
|
|
199 dev= yaffsfs_FindDevice(path,restOfPath); |
|
|
200 if(dev && dev->isMounted) |
|
|
201 { |
|
|
202 return dev->rootDir; |
|
|
203 } |
|
|
204 return NULL; |
|
|
205 } |
|
|
206 |
|
|
207 static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth) |
|
|
208 { |
|
|
209 |
|
|
210 while(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) |
|
|
211 { |
|
|
212 char *alias = obj->variant.symLinkVariant.alias; |
|
|
213 |
|
|
214 if(*alias == '/') |
|
|
215 { |
|
|
216 // Starts with a /, need to scan from root up |
|
|
217 obj = yaffsfs_FindObject(NULL,alias,symDepth++); |
|
|
218 } |
|
|
219 else |
|
|
220 { |
|
|
221 // Relative to here, so use the parent of the symlink as a start |
|
|
222 obj = yaffsfs_FindObject(obj->parent,alias,symDepth++); |
|
|
223 } |
|
|
224 } |
|
|
225 return obj; |
|
|
226 } |
|
|
227 |
|
|
228 |
|
|
229 // yaffsfs_FindDirectory |
|
|
230 // Parse a path to determine the directory and the name within the directory. |
|
|
231 // |
|
|
232 // eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx" |
|
|
233 static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *path,char **name,int symDepth) |
|
|
234 { |
|
|
235 yaffs_Object *dir; |
|
|
236 char *restOfPath; |
|
|
237 char str[YAFFS_MAX_NAME_LENGTH+1]; |
|
|
238 int i; |
|
|
239 |
|
|
240 if(symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES) |
|
|
241 { |
|
|
242 return NULL; |
|
|
243 } |
|
|
244 |
|
|
245 if(startDir) |
|
|
246 { |
|
|
247 dir = startDir; |
|
|
248 restOfPath = (char *)path; |
|
|
249 } |
|
|
250 else |
|
|
251 { |
|
|
252 dir = yaffsfs_FindRoot(path,&restOfPath); |
|
|
253 } |
|
|
254 |
|
|
255 while(dir) |
|
|
256 { |
|
|
257 // parse off /. |
|
|
258 // curve ball: also throw away surplus '/' |
|
|
259 // eg. "/ram/x////ff" gets treated the same as "/ram/x/ff" |
|
|
260 while(*restOfPath == '/') |
|
|
261 { |
|
|
262 restOfPath++; // get rid of '/' |
|
|
263 } |
|
|
264 |
|
|
265 *name = restOfPath; |
|
|
266 i = 0; |
|
|
267 |
|
|
268 while(*restOfPath && *restOfPath != '/') |
|
|
269 { |
|
|
270 if (i < YAFFS_MAX_NAME_LENGTH) |
|
|
271 { |
|
|
272 str[i] = *restOfPath; |
|
|
273 str[i+1] = '\0'; |
|
|
274 i++; |
|
|
275 } |
|
|
276 restOfPath++; |
|
|
277 } |
|
|
278 |
|
|
279 if(!*restOfPath) |
|
|
280 { |
|
|
281 // got to the end of the string |
|
|
282 return dir; |
|
|
283 } |
|
|
284 else |
|
|
285 { |
|
|
286 if(strcmp(str,".") == 0) |
|
|
287 { |
|
|
288 // Do nothing |
|
|
289 } |
|
|
290 else if(strcmp(str,"..") == 0) |
|
|
291 { |
|
|
292 dir = dir->parent; |
|
|
293 } |
|
|
294 else |
|
|
295 { |
|
|
296 dir = yaffs_FindObjectByName(dir,str); |
|
|
297 |
|
|
298 while(dir && dir->variantType == YAFFS_OBJECT_TYPE_SYMLINK) |
|
|
299 { |
|
|
300 |
|
|
301 dir = yaffsfs_FollowLink(dir,symDepth); |
|
|
302 |
|
|
303 } |
|
|
304 |
|
|
305 if(dir && dir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
306 { |
|
|
307 dir = NULL; |
|
|
308 } |
|
|
309 } |
|
|
310 } |
|
|
311 } |
|
|
312 // directory did not exist. |
|
|
313 return NULL; |
|
|
314 } |
|
|
315 |
|
|
316 static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const char *path,char **name,int symDepth) |
|
|
317 { |
|
|
318 return yaffsfs_DoFindDirectory(relativeDirectory,path,name,symDepth); |
|
|
319 } |
|
|
320 |
|
|
321 // yaffsfs_FindObject turns a path for an existing object into the object |
|
|
322 // |
|
|
323 static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path,int symDepth) |
|
|
324 { |
|
|
325 yaffs_Object *dir; |
|
|
326 char *name; |
|
|
327 |
|
|
328 dir = yaffsfs_FindDirectory(relativeDirectory,path,&name,symDepth); |
|
|
329 |
|
|
330 if(dir && *name) |
|
|
331 { |
|
|
332 return yaffs_FindObjectByName(dir,name); |
|
|
333 } |
|
|
334 |
|
|
335 return dir; |
|
|
336 } |
|
|
337 |
|
|
338 |
|
|
339 |
|
|
340 int yaffs_open(const char *path, int oflag, int mode) |
|
|
341 { |
|
|
342 yaffs_Object *obj = NULL; |
|
|
343 yaffs_Object *dir = NULL; |
|
|
344 char *name; |
|
|
345 int handle = -1; |
|
|
346 yaffsfs_Handle *h = NULL; |
|
|
347 int alreadyOpen = 0; |
|
|
348 int alreadyExclusive = 0; |
|
|
349 int openDenied = 0; |
|
|
350 int symDepth = 0; |
|
|
351 int errorReported = 0; |
|
|
352 |
|
|
353 int i; |
|
|
354 |
|
|
355 |
|
|
356 // todo sanity check oflag (eg. can't have O_TRUNC without WRONLY or RDWR |
|
|
357 |
|
|
358 |
|
|
359 yaffsfs_Lock(); |
|
|
360 |
|
|
361 handle = yaffsfs_GetHandle(); |
|
|
362 |
|
|
363 if(handle >= 0) |
|
|
364 { |
|
|
365 |
|
|
366 h = yaffsfs_GetHandlePointer(handle); |
|
|
367 |
|
|
368 |
|
|
369 // try to find the exisiting object |
|
|
370 obj = yaffsfs_FindObject(NULL,path,0); |
|
|
371 |
|
|
372 if(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) |
|
|
373 { |
|
|
374 |
|
|
375 obj = yaffsfs_FollowLink(obj,symDepth++); |
|
|
376 } |
|
|
377 |
|
|
378 if(obj) |
|
|
379 { |
|
|
380 // Check if the object is already in use |
|
|
381 alreadyOpen = alreadyExclusive = 0; |
|
|
382 |
|
|
383 for(i = 0; i <= YAFFSFS_N_HANDLES; i++) |
|
|
384 { |
|
|
385 |
|
|
386 if(i != handle && |
|
|
387 yaffsfs_handle[i].inUse && |
|
|
388 obj == yaffsfs_handle[i].obj) |
|
|
389 { |
|
|
390 alreadyOpen = 1; |
|
|
391 if(yaffsfs_handle[i].exclusive) |
|
|
392 { |
|
|
393 alreadyExclusive = 1; |
|
|
394 } |
|
|
395 } |
|
|
396 } |
|
|
397 |
|
|
398 if(((oflag & O_EXCL) && alreadyOpen) || alreadyExclusive) |
|
|
399 { |
|
|
400 openDenied = 1; |
|
|
401 } |
|
|
402 |
|
|
403 // Open should fail if O_CREAT and O_EXCL are specified |
|
|
404 if((oflag & O_EXCL) && (oflag & O_CREAT)) |
|
|
405 { |
|
|
406 openDenied = 1; |
|
|
407 yaffsfs_SetError(-EEXIST); |
|
|
408 errorReported = 1; |
|
|
409 } |
|
|
410 |
|
|
411 // Check file permissions |
|
|
412 if( (oflag & (O_RDWR | O_WRONLY)) == 0 && // ie O_RDONLY |
|
|
413 !(obj->st_mode & S_IREAD)) |
|
|
414 { |
|
|
415 openDenied = 1; |
|
|
416 } |
|
|
417 |
|
|
418 if( (oflag & O_RDWR) && |
|
|
419 !(obj->st_mode & S_IREAD)) |
|
|
420 { |
|
|
421 openDenied = 1; |
|
|
422 } |
|
|
423 |
|
|
424 if( (oflag & (O_RDWR | O_WRONLY)) && |
|
|
425 !(obj->st_mode & S_IWRITE)) |
|
|
426 { |
|
|
427 openDenied = 1; |
|
|
428 } |
|
|
429 |
|
|
430 } |
|
|
431 |
|
|
432 else if((oflag & O_CREAT)) |
|
|
433 { |
|
|
434 // Let's see if we can create this file |
|
|
435 dir = yaffsfs_FindDirectory(NULL,path,&name,0); |
|
|
436 if(dir) |
|
|
437 { |
|
|
438 obj = yaffs_MknodFile(dir,name,mode,0,0); |
|
|
439 } |
|
|
440 else |
|
|
441 { |
|
|
442 yaffsfs_SetError(-ENOTDIR); |
|
|
443 } |
|
|
444 } |
|
|
445 |
|
|
446 if(obj && !openDenied) |
|
|
447 { |
|
|
448 h->obj = obj; |
|
|
449 h->inUse = 1; |
|
|
450 h->readOnly = (oflag & (O_WRONLY | O_RDWR)) ? 0 : 1; |
|
|
451 h->append = (oflag & O_APPEND) ? 1 : 0; |
|
|
452 h->exclusive = (oflag & O_EXCL) ? 1 : 0; |
|
|
453 h->position = 0; |
|
|
454 |
|
|
455 obj->inUse++; |
|
|
456 if((oflag & O_TRUNC) && !h->readOnly) |
|
|
457 { |
|
|
458 //todo truncate |
|
|
459 yaffs_ResizeFile(obj,0); |
|
|
460 } |
|
|
461 |
|
|
462 } |
|
|
463 else |
|
|
464 { |
|
|
465 yaffsfs_PutHandle(handle); |
|
|
466 if(!errorReported) |
|
|
467 { |
|
|
468 yaffsfs_SetError(-EACCESS); |
|
|
469 errorReported = 1; |
|
|
470 } |
|
|
471 handle = -1; |
|
|
472 } |
|
|
473 |
|
|
474 } |
|
|
475 |
|
|
476 yaffsfs_Unlock(); |
|
|
477 |
|
|
478 return handle; |
|
|
479 } |
|
|
480 |
|
|
481 int yaffs_close(int fd) |
|
|
482 { |
|
|
483 yaffsfs_Handle *h = NULL; |
|
|
484 int retVal = 0; |
|
|
485 |
|
|
486 yaffsfs_Lock(); |
|
|
487 |
|
|
488 h = yaffsfs_GetHandlePointer(fd); |
|
|
489 |
|
|
490 if(h && h->inUse) |
|
|
491 { |
|
|
492 // clean up |
|
|
493 yaffs_FlushFile(h->obj,1); |
|
|
494 h->obj->inUse--; |
|
|
495 if(h->obj->inUse <= 0 && h->obj->unlinked) |
|
|
496 { |
|
|
497 yaffs_DeleteFile(h->obj); |
|
|
498 } |
|
|
499 yaffsfs_PutHandle(fd); |
|
|
500 retVal = 0; |
|
|
501 } |
|
|
502 else |
|
|
503 { |
|
|
504 // bad handle |
|
|
505 yaffsfs_SetError(-EBADF); |
|
|
506 retVal = -1; |
|
|
507 } |
|
|
508 |
|
|
509 yaffsfs_Unlock(); |
|
|
510 |
|
|
511 return retVal; |
|
|
512 } |
|
|
513 |
|
|
514 int yaffs_read(int fd, void *buf, unsigned int nbyte) |
|
|
515 { |
|
|
516 yaffsfs_Handle *h = NULL; |
|
|
517 yaffs_Object *obj = NULL; |
|
|
518 int pos = 0; |
|
|
519 int nRead = -1; |
|
|
520 int maxRead; |
|
|
521 |
|
|
522 yaffsfs_Lock(); |
|
|
523 h = yaffsfs_GetHandlePointer(fd); |
|
|
524 obj = yaffsfs_GetHandleObject(fd); |
|
|
525 |
|
|
526 if(!h || !obj) |
|
|
527 { |
|
|
528 // bad handle |
|
|
529 yaffsfs_SetError(-EBADF); |
|
|
530 } |
|
|
531 else if( h && obj) |
|
|
532 { |
|
|
533 pos= h->position; |
|
|
534 if(yaffs_GetObjectFileLength(obj) > pos) |
|
|
535 { |
|
|
536 maxRead = yaffs_GetObjectFileLength(obj) - pos; |
|
|
537 } |
|
|
538 else |
|
|
539 { |
|
|
540 maxRead = 0; |
|
|
541 } |
|
|
542 |
|
|
543 if(nbyte > maxRead) |
|
|
544 { |
|
|
545 nbyte = maxRead; |
|
|
546 } |
|
|
547 |
|
|
548 |
|
|
549 if(nbyte > 0) |
|
|
550 { |
|
|
551 nRead = yaffs_ReadDataFromFile(obj,buf,pos,nbyte); |
|
|
552 if(nRead >= 0) |
|
|
553 { |
|
|
554 h->position = pos + nRead; |
|
|
555 } |
|
|
556 else |
|
|
557 { |
|
|
558 //todo error |
|
|
559 } |
|
|
560 } |
|
|
561 else |
|
|
562 { |
|
|
563 nRead = 0; |
|
|
564 } |
|
|
565 |
|
|
566 } |
|
|
567 |
|
|
568 yaffsfs_Unlock(); |
|
|
569 |
|
|
570 |
|
|
571 return (nRead >= 0) ? nRead : -1; |
|
|
572 |
|
|
573 } |
|
|
574 |
|
|
575 int yaffs_write(int fd, const void *buf, unsigned int nbyte) |
|
|
576 { |
|
|
577 yaffsfs_Handle *h = NULL; |
|
|
578 yaffs_Object *obj = NULL; |
|
|
579 int pos = 0; |
|
|
580 int nWritten = -1; |
|
|
581 |
|
|
582 yaffsfs_Lock(); |
|
|
583 h = yaffsfs_GetHandlePointer(fd); |
|
|
584 obj = yaffsfs_GetHandleObject(fd); |
|
|
585 |
|
|
586 if(!h || !obj) |
|
|
587 { |
|
|
588 // bad handle |
|
|
589 yaffsfs_SetError(-EBADF); |
|
|
590 } |
|
|
591 else if( h && obj && h->readOnly) |
|
|
592 { |
|
|
593 // todo error |
|
|
594 } |
|
|
595 else if( h && obj) |
|
|
596 { |
|
|
597 if(h->append) |
|
|
598 { |
|
|
599 pos = yaffs_GetObjectFileLength(obj); |
|
|
600 } |
|
|
601 else |
|
|
602 { |
|
|
603 pos = h->position; |
|
|
604 } |
|
|
605 |
|
|
606 nWritten = yaffs_WriteDataToFile(obj,buf,pos,nbyte); |
|
|
607 |
|
|
608 if(nWritten >= 0) |
|
|
609 { |
|
|
610 h->position = pos + nWritten; |
|
|
611 } |
|
|
612 else |
|
|
613 { |
|
|
614 //todo error |
|
|
615 } |
|
|
616 |
|
|
617 } |
|
|
618 |
|
|
619 yaffsfs_Unlock(); |
|
|
620 |
|
|
621 |
|
|
622 return (nWritten >= 0) ? nWritten : -1; |
|
|
623 |
|
|
624 } |
|
|
625 |
|
|
626 int yaffs_truncate(int fd, unsigned int newSize) |
|
|
627 { |
|
|
628 yaffsfs_Handle *h = NULL; |
|
|
629 yaffs_Object *obj = NULL; |
|
|
630 int result = 0; |
|
|
631 |
|
|
632 yaffsfs_Lock(); |
|
|
633 h = yaffsfs_GetHandlePointer(fd); |
|
|
634 obj = yaffsfs_GetHandleObject(fd); |
|
|
635 |
|
|
636 if(!h || !obj) |
|
|
637 { |
|
|
638 // bad handle |
|
|
639 yaffsfs_SetError(-EBADF); |
|
|
640 } |
|
|
641 else |
|
|
642 { |
|
|
643 // resize the file |
|
|
644 result = yaffs_ResizeFile(obj,newSize); |
|
|
645 } |
|
|
646 yaffsfs_Unlock(); |
|
|
647 |
|
|
648 |
|
|
649 return (result) ? 0 : -1; |
|
|
650 |
|
|
651 } |
|
|
652 |
|
|
653 off_t yaffs_lseek(int fd, off_t offset, int whence) |
|
|
654 { |
|
|
655 yaffsfs_Handle *h = NULL; |
|
|
656 yaffs_Object *obj = NULL; |
|
|
657 int pos = -1; |
|
|
658 int fSize = -1; |
|
|
659 |
|
|
660 yaffsfs_Lock(); |
|
|
661 h = yaffsfs_GetHandlePointer(fd); |
|
|
662 obj = yaffsfs_GetHandleObject(fd); |
|
|
663 |
|
|
664 if(!h || !obj) |
|
|
665 { |
|
|
666 // bad handle |
|
|
667 yaffsfs_SetError(-EBADF); |
|
|
668 } |
|
|
669 else if(whence == SEEK_SET) |
|
|
670 { |
|
|
671 if(offset >= 0) |
|
|
672 { |
|
|
673 pos = offset; |
|
|
674 } |
|
|
675 } |
|
|
676 else if(whence == SEEK_CUR) |
|
|
677 { |
|
|
678 if( (h->position + offset) >= 0) |
|
|
679 { |
|
|
680 pos = (h->position + offset); |
|
|
681 } |
|
|
682 } |
|
|
683 else if(whence == SEEK_END) |
|
|
684 { |
|
|
685 fSize = yaffs_GetObjectFileLength(obj); |
|
|
686 if(fSize >= 0 && (fSize + offset) >= 0) |
|
|
687 { |
|
|
688 pos = fSize + offset; |
|
|
689 } |
|
|
690 } |
|
|
691 |
|
|
692 if(pos >= 0) |
|
|
693 { |
|
|
694 h->position = pos; |
|
|
695 } |
|
|
696 else |
|
|
697 { |
|
|
698 // todo error |
|
|
699 } |
|
|
700 |
|
|
701 |
|
|
702 yaffsfs_Unlock(); |
|
|
703 |
|
|
704 return pos; |
|
|
705 } |
|
|
706 |
|
|
707 |
|
|
708 int yaffsfs_DoUnlink(const char *path,int isDirectory) |
|
|
709 { |
|
|
710 yaffs_Object *dir = NULL; |
|
|
711 yaffs_Object *obj = NULL; |
|
|
712 char *name; |
|
|
713 int result = YAFFS_FAIL; |
|
|
714 |
|
|
715 yaffsfs_Lock(); |
|
|
716 |
|
|
717 obj = yaffsfs_FindObject(NULL,path,0); |
|
|
718 dir = yaffsfs_FindDirectory(NULL,path,&name,0); |
|
|
719 if(!dir) |
|
|
720 { |
|
|
721 yaffsfs_SetError(-ENOTDIR); |
|
|
722 } |
|
|
723 else if(!obj) |
|
|
724 { |
|
|
725 yaffsfs_SetError(-ENOENT); |
|
|
726 } |
|
|
727 else if(!isDirectory && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
728 { |
|
|
729 yaffsfs_SetError(-EISDIR); |
|
|
730 } |
|
|
731 else if(isDirectory && obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
732 { |
|
|
733 yaffsfs_SetError(-ENOTDIR); |
|
|
734 } |
|
|
735 else if(isDirectory && obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
736 { |
|
|
737 yaffsfs_SetError(-ENOTDIR); |
|
|
738 } |
|
|
739 else |
|
|
740 { |
|
|
741 result = yaffs_Unlink(dir,name); |
|
|
742 |
|
|
743 if(result == YAFFS_FAIL && isDirectory) |
|
|
744 { |
|
|
745 yaffsfs_SetError(-ENOTEMPTY); |
|
|
746 } |
|
|
747 } |
|
|
748 |
|
|
749 yaffsfs_Unlock(); |
|
|
750 |
|
|
751 // todo error |
|
|
752 |
|
|
753 return (result == YAFFS_FAIL) ? -1 : 0; |
|
|
754 } |
|
|
755 int yaffs_rmdir(const char *path) |
|
|
756 { |
|
|
757 return yaffsfs_DoUnlink(path,1); |
|
|
758 } |
|
|
759 |
|
|
760 int yaffs_unlink(const char *path) |
|
|
761 { |
|
|
762 return yaffsfs_DoUnlink(path,0); |
|
|
763 } |
|
|
764 |
|
|
765 int yaffs_rename(const char *oldPath, const char *newPath) |
|
|
766 { |
|
|
767 yaffs_Object *olddir = NULL; |
|
|
768 yaffs_Object *newdir = NULL; |
|
|
769 yaffs_Object *obj = NULL; |
|
|
770 char *oldname; |
|
|
771 char *newname; |
|
|
772 int result= YAFFS_FAIL; |
|
|
773 int renameAllowed = 1; |
|
|
774 |
|
|
775 yaffsfs_Lock(); |
|
|
776 |
|
|
777 olddir = yaffsfs_FindDirectory(NULL,oldPath,&oldname,0); |
|
|
778 newdir = yaffsfs_FindDirectory(NULL,newPath,&newname,0); |
|
|
779 obj = yaffsfs_FindObject(NULL,oldPath,0); |
|
|
780 |
|
|
781 if(!olddir || !newdir || !obj) |
|
|
782 { |
|
|
783 // bad file |
|
|
784 yaffsfs_SetError(-EBADF); |
|
|
785 renameAllowed = 0; |
|
|
786 } |
|
|
787 else if(olddir->myDev != newdir->myDev) |
|
|
788 { |
|
|
789 // oops must be on same device |
|
|
790 // todo error |
|
|
791 yaffsfs_SetError(-EXDEV); |
|
|
792 renameAllowed = 0; |
|
|
793 } |
|
|
794 else if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
795 { |
|
|
796 // It is a directory, check that it is not being renamed to |
|
|
797 // being its own decendent. |
|
|
798 // Do this by tracing from the new directory back to the root, checking for obj |
|
|
799 |
|
|
800 yaffs_Object *xx = newdir; |
|
|
801 |
|
|
802 while( renameAllowed && xx) |
|
|
803 { |
|
|
804 if(xx == obj) |
|
|
805 { |
|
|
806 renameAllowed = 0; |
|
|
807 } |
|
|
808 xx = xx->parent; |
|
|
809 } |
|
|
810 if(!renameAllowed) yaffsfs_SetError(-EACCESS); |
|
|
811 } |
|
|
812 |
|
|
813 if(renameAllowed) |
|
|
814 { |
|
|
815 result = yaffs_RenameObject(olddir,oldname,newdir,newname); |
|
|
816 } |
|
|
817 |
|
|
818 yaffsfs_Unlock(); |
|
|
819 |
|
|
820 return (result == YAFFS_FAIL) ? -1 : 0; |
|
|
821 } |
|
|
822 |
|
|
823 |
|
|
824 static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf) |
|
|
825 { |
|
|
826 int retVal = -1; |
|
|
827 |
|
|
828 if(obj) |
|
|
829 { |
|
|
830 obj = yaffs_GetEquivalentObject(obj); |
|
|
831 } |
|
|
832 |
|
|
833 if(obj && buf) |
|
|
834 { |
|
|
835 buf->st_dev = (int)obj->myDev->genericDevice; |
|
|
836 buf->st_ino = obj->objectId; |
|
|
837 buf->st_mode = obj->st_mode & ~S_IFMT; // clear out file type bits |
|
|
838 |
|
|
839 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
840 { |
|
|
841 buf->st_mode |= S_IFDIR; |
|
|
842 } |
|
|
843 else if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) |
|
|
844 { |
|
|
845 buf->st_mode |= S_IFLNK; |
|
|
846 } |
|
|
847 else if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) |
|
|
848 { |
|
|
849 buf->st_mode |= S_IFREG; |
|
|
850 } |
|
|
851 |
|
|
852 buf->st_nlink = yaffs_GetObjectLinkCount(obj); |
|
|
853 buf->st_uid = 0; |
|
|
854 buf->st_gid = 0;; |
|
|
855 buf->st_rdev = obj->st_rdev; |
|
|
856 buf->st_size = yaffs_GetObjectFileLength(obj); |
|
|
857 buf->st_blksize = obj->myDev->nBytesPerChunk; |
|
|
858 buf->st_blocks = (buf->st_size + buf->st_blksize -1)/buf->st_blksize; |
|
|
859 buf->st_atime = obj->st_atime; |
|
|
860 buf->st_ctime = obj->st_ctime; |
|
|
861 buf->st_mtime = obj->st_mtime; |
|
|
862 retVal = 0; |
|
|
863 } |
|
|
864 return retVal; |
|
|
865 } |
|
|
866 |
|
|
867 static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int doLStat) |
|
|
868 { |
|
|
869 yaffs_Object *obj; |
|
|
870 |
|
|
871 int retVal = -1; |
|
|
872 |
|
|
873 yaffsfs_Lock(); |
|
|
874 obj = yaffsfs_FindObject(NULL,path,0); |
|
|
875 |
|
|
876 if(!doLStat && obj) |
|
|
877 { |
|
|
878 obj = yaffsfs_FollowLink(obj,0); |
|
|
879 } |
|
|
880 |
|
|
881 if(obj) |
|
|
882 { |
|
|
883 retVal = yaffsfs_DoStat(obj,buf); |
|
|
884 } |
|
|
885 else |
|
|
886 { |
|
|
887 // todo error not found |
|
|
888 yaffsfs_SetError(-ENOENT); |
|
|
889 } |
|
|
890 |
|
|
891 yaffsfs_Unlock(); |
|
|
892 |
|
|
893 return retVal; |
|
|
894 |
|
|
895 } |
|
|
896 |
|
|
897 int yaffs_stat(const char *path, struct yaffs_stat *buf) |
|
|
898 { |
|
|
899 return yaffsfs_DoStatOrLStat(path,buf,0); |
|
|
900 } |
|
|
901 |
|
|
902 int yaffs_lstat(const char *path, struct yaffs_stat *buf) |
|
|
903 { |
|
|
904 return yaffsfs_DoStatOrLStat(path,buf,1); |
|
|
905 } |
|
|
906 |
|
|
907 int yaffs_fstat(int fd, struct yaffs_stat *buf) |
|
|
908 { |
|
|
909 yaffs_Object *obj; |
|
|
910 |
|
|
911 int retVal = -1; |
|
|
912 |
|
|
913 yaffsfs_Lock(); |
|
|
914 obj = yaffsfs_GetHandleObject(fd); |
|
|
915 |
|
|
916 if(obj) |
|
|
917 { |
|
|
918 retVal = yaffsfs_DoStat(obj,buf); |
|
|
919 } |
|
|
920 else |
|
|
921 { |
|
|
922 // bad handle |
|
|
923 yaffsfs_SetError(-EBADF); |
|
|
924 } |
|
|
925 |
|
|
926 yaffsfs_Unlock(); |
|
|
927 |
|
|
928 return retVal; |
|
|
929 } |
|
|
930 |
|
|
931 static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode) |
|
|
932 { |
|
|
933 int result; |
|
|
934 |
|
|
935 if(obj) |
|
|
936 { |
|
|
937 obj = yaffs_GetEquivalentObject(obj); |
|
|
938 } |
|
|
939 |
|
|
940 if(obj) |
|
|
941 { |
|
|
942 obj->st_mode = mode; |
|
|
943 obj->dirty = 1; |
|
|
944 result = yaffs_FlushFile(obj,0); |
|
|
945 } |
|
|
946 |
|
|
947 return result == YAFFS_OK ? 0 : -1; |
|
|
948 } |
|
|
949 |
|
|
950 |
|
|
951 int yaffs_chmod(const char *path, mode_t mode) |
|
|
952 { |
|
|
953 yaffs_Object *obj; |
|
|
954 |
|
|
955 int retVal = -1; |
|
|
956 |
|
|
957 yaffsfs_Lock(); |
|
|
958 obj = yaffsfs_FindObject(NULL,path,0); |
|
|
959 |
|
|
960 if(obj) |
|
|
961 { |
|
|
962 retVal = yaffsfs_DoChMod(obj,mode); |
|
|
963 } |
|
|
964 else |
|
|
965 { |
|
|
966 // todo error not found |
|
|
967 yaffsfs_SetError(-ENOENT); |
|
|
968 } |
|
|
969 |
|
|
970 yaffsfs_Unlock(); |
|
|
971 |
|
|
972 return retVal; |
|
|
973 |
|
|
974 } |
|
|
975 |
|
|
976 |
|
|
977 int yaffs_fchmod(int fd, mode_t mode) |
|
|
978 { |
|
|
979 yaffs_Object *obj; |
|
|
980 |
|
|
981 int retVal = -1; |
|
|
982 |
|
|
983 yaffsfs_Lock(); |
|
|
984 obj = yaffsfs_GetHandleObject(fd); |
|
|
985 |
|
|
986 if(obj) |
|
|
987 { |
|
|
988 retVal = yaffsfs_DoChMod(obj,mode); |
|
|
989 } |
|
|
990 else |
|
|
991 { |
|
|
992 // bad handle |
|
|
993 yaffsfs_SetError(-EBADF); |
|
|
994 } |
|
|
995 |
|
|
996 yaffsfs_Unlock(); |
|
|
997 |
|
|
998 return retVal; |
|
|
999 } |
|
|
1000 |
|
|
1001 |
|
|
1002 int yaffs_mkdir(const char *path, mode_t mode) |
|
|
1003 { |
|
|
1004 yaffs_Object *parent = NULL; |
|
|
1005 yaffs_Object *dir; |
|
|
1006 char *name; |
|
|
1007 int retVal= -1; |
|
|
1008 |
|
|
1009 yaffsfs_Lock(); |
|
|
1010 parent = yaffsfs_FindDirectory(NULL,path,&name,0); |
|
|
1011 dir = yaffs_MknodDirectory(parent,name,mode,0,0); |
|
|
1012 if(dir) |
|
|
1013 { |
|
|
1014 retVal = 0; |
|
|
1015 } |
|
|
1016 else |
|
|
1017 { |
|
|
1018 yaffsfs_SetError(-ENOSPC); // just assume no space for now |
|
|
1019 retVal = -1; |
|
|
1020 } |
|
|
1021 |
|
|
1022 yaffsfs_Unlock(); |
|
|
1023 |
|
|
1024 return retVal; |
|
|
1025 } |
|
|
1026 |
|
|
1027 int yaffs_mount(const char *path) |
|
|
1028 { |
|
|
1029 int retVal=-1; |
|
|
1030 int result=YAFFS_FAIL; |
|
|
1031 yaffs_Device *dev=NULL; |
|
|
1032 char *dummy; |
|
|
1033 |
|
|
1034 T(YAFFS_TRACE_ALWAYS,("yaffs: Mounting %s\n",path)); |
|
|
1035 |
|
|
1036 yaffsfs_Lock(); |
|
|
1037 dev = yaffsfs_FindDevice(path,&dummy); |
|
|
1038 if(dev) |
|
|
1039 { |
|
|
1040 if(!dev->isMounted) |
|
|
1041 { |
|
|
1042 result = yaffs_GutsInitialise(dev); |
|
|
1043 if(result == YAFFS_FAIL) |
|
|
1044 { |
|
|
1045 // todo error - mount failed |
|
|
1046 yaffsfs_SetError(-ENOMEM); |
|
|
1047 } |
|
|
1048 retVal = result ? 0 : -1; |
|
|
1049 |
|
|
1050 } |
|
|
1051 else |
|
|
1052 { |
|
|
1053 //todo error - already mounted. |
|
|
1054 yaffsfs_SetError(-EBUSY); |
|
|
1055 } |
|
|
1056 } |
|
|
1057 else |
|
|
1058 { |
|
|
1059 // todo error - no device |
|
|
1060 yaffsfs_SetError(-ENODEV); |
|
|
1061 } |
|
|
1062 yaffsfs_Unlock(); |
|
|
1063 return retVal; |
|
|
1064 |
|
|
1065 } |
|
|
1066 |
|
|
1067 int yaffs_unmount(const char *path) |
|
|
1068 { |
|
|
1069 int retVal=-1; |
|
|
1070 yaffs_Device *dev=NULL; |
|
|
1071 char *dummy; |
|
|
1072 |
|
|
1073 yaffsfs_Lock(); |
|
|
1074 dev = yaffsfs_FindDevice(path,&dummy); |
|
|
1075 if(dev) |
|
|
1076 { |
|
|
1077 if(dev->isMounted) |
|
|
1078 { |
|
|
1079 int i; |
|
|
1080 int inUse; |
|
|
1081 for(i = inUse = 0; i < YAFFSFS_N_HANDLES && !inUse; i++) |
|
|
1082 { |
|
|
1083 if(yaffsfs_handle[i].inUse && yaffsfs_handle[i].obj->myDev == dev) |
|
|
1084 { |
|
|
1085 inUse = 1; // the device is in use, can't unmount |
|
|
1086 } |
|
|
1087 } |
|
|
1088 |
|
|
1089 if(!inUse) |
|
|
1090 { |
|
|
1091 yaffs_Deinitialise(dev); |
|
|
1092 |
|
|
1093 retVal = 0; |
|
|
1094 } |
|
|
1095 else |
|
|
1096 { |
|
|
1097 // todo error can't unmount as files are open |
|
|
1098 yaffsfs_SetError(-EBUSY); |
|
|
1099 } |
|
|
1100 |
|
|
1101 } |
|
|
1102 else |
|
|
1103 { |
|
|
1104 //todo error - not mounted. |
|
|
1105 yaffsfs_SetError(-EINVAL); |
|
|
1106 |
|
|
1107 } |
|
|
1108 } |
|
|
1109 else |
|
|
1110 { |
|
|
1111 // todo error - no device |
|
|
1112 yaffsfs_SetError(-ENODEV); |
|
|
1113 } |
|
|
1114 yaffsfs_Unlock(); |
|
|
1115 return retVal; |
|
|
1116 |
|
|
1117 } |
|
|
1118 |
|
|
1119 off_t yaffs_freespace(const char *path) |
|
|
1120 { |
|
|
1121 off_t retVal=-1; |
|
|
1122 yaffs_Device *dev=NULL; |
|
|
1123 char *dummy; |
|
|
1124 |
|
|
1125 yaffsfs_Lock(); |
|
|
1126 dev = yaffsfs_FindDevice(path,&dummy); |
|
11
|
1127 if(dev && dev->isMounted) |
|
1
|
1128 { |
|
|
1129 retVal = yaffs_GetNumberOfFreeChunks(dev); |
|
|
1130 retVal *= dev->nBytesPerChunk; |
|
|
1131 |
|
|
1132 } |
|
|
1133 else |
|
|
1134 { |
|
|
1135 yaffsfs_SetError(-EINVAL); |
|
|
1136 } |
|
|
1137 |
|
|
1138 yaffsfs_Unlock(); |
|
|
1139 return retVal; |
|
|
1140 } |
|
|
1141 |
|
|
1142 void yaffs_initialise(yaffsfs_DeviceConfiguration *cfgList) |
|
|
1143 { |
|
|
1144 |
|
|
1145 yaffsfs_DeviceConfiguration *cfg; |
|
|
1146 |
|
|
1147 yaffsfs_configurationList = cfgList; |
|
|
1148 |
|
|
1149 yaffsfs_InitHandles(); |
|
|
1150 |
|
|
1151 cfg = yaffsfs_configurationList; |
|
|
1152 |
|
|
1153 while(cfg && cfg->prefix && cfg->dev) |
|
|
1154 { |
|
|
1155 cfg->dev->isMounted = 0; |
|
|
1156 cfg++; |
|
|
1157 } |
|
|
1158 |
|
|
1159 |
|
|
1160 } |
|
|
1161 |
|
|
1162 |
|
|
1163 // |
|
|
1164 // Directory search stuff. |
|
|
1165 |
|
|
1166 yaffs_DIR *yaffs_opendir(const char *dirname) |
|
|
1167 { |
|
|
1168 yaffs_DIR *dir = NULL; |
|
|
1169 yaffs_Object *obj = NULL; |
|
|
1170 yaffsfs_DirectorySearchContext *dsc = NULL; |
|
|
1171 |
|
|
1172 yaffsfs_Lock(); |
|
|
1173 |
|
|
1174 obj = yaffsfs_FindObject(NULL,dirname,0); |
|
|
1175 |
|
|
1176 if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
1177 { |
|
|
1178 |
|
|
1179 dsc = YMALLOC(sizeof(yaffsfs_DirectorySearchContext)); |
|
|
1180 dir = (yaffs_DIR *)dsc; |
|
|
1181 if(dsc) |
|
|
1182 { |
|
|
1183 dsc->magic = YAFFS_MAGIC; |
|
|
1184 dsc->list = NULL; |
|
|
1185 memset(dsc->name,0,NAME_MAX+1); |
|
|
1186 strncpy(dsc->name,dirname,NAME_MAX); |
|
|
1187 } |
|
|
1188 |
|
|
1189 } |
|
|
1190 |
|
|
1191 yaffsfs_Unlock(); |
|
|
1192 |
|
|
1193 return dir; |
|
|
1194 } |
|
|
1195 |
|
|
1196 struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) |
|
|
1197 { |
|
|
1198 yaffsfs_DirectorySearchContext *dsc = (yaffsfs_DirectorySearchContext *)dirp; |
|
|
1199 struct yaffs_dirent *retVal = NULL; |
|
|
1200 struct list_head *i; |
|
|
1201 yaffs_Object *entry = NULL; |
|
|
1202 int offset; |
|
|
1203 yaffs_Object *obj = NULL; |
|
|
1204 struct yaffsfs_ObjectListEntry *list = NULL; |
|
|
1205 int inList = 0; |
|
|
1206 |
|
|
1207 yaffsfs_Lock(); |
|
|
1208 |
|
|
1209 offset = -1; |
|
|
1210 |
|
|
1211 if(dsc && dsc->magic == YAFFS_MAGIC) |
|
|
1212 { |
|
|
1213 yaffsfs_SetError(0); |
|
|
1214 |
|
|
1215 obj = yaffsfs_FindObject(NULL,dsc->name,0); |
|
|
1216 |
|
|
1217 if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) |
|
|
1218 { |
|
|
1219 |
|
|
1220 list_for_each(i,&obj->variant.directoryVariant.children) |
|
|
1221 { |
|
|
1222 offset++; |
|
|
1223 entry = (i) ? list_entry(i, yaffs_Object,siblings) : NULL; |
|
|
1224 |
|
|
1225 if(entry) |
|
|
1226 { |
|
|
1227 list = dsc->list; |
|
|
1228 inList = 0; |
|
|
1229 while(list && !inList) |
|
|
1230 { |
|
|
1231 if(list->objectId == entry->objectId) |
|
|
1232 { |
|
|
1233 inList = 1; |
|
|
1234 } |
|
|
1235 list = list->next; |
|
|
1236 } |
|
|
1237 |
|
|
1238 if(!inList) goto foundNew; |
|
|
1239 } |
|
|
1240 |
|
|
1241 } |
|
|
1242 |
|
|
1243 foundNew: |
|
|
1244 |
|
|
1245 if(!inList && entry) |
|
|
1246 { |
|
|
1247 //This is the entry we're going to return; |
|
|
1248 struct yaffsfs_ObjectListEntry *le; |
|
|
1249 |
|
|
1250 le = YMALLOC(sizeof(struct yaffsfs_ObjectListEntry)); |
|
|
1251 |
|
|
1252 if(le) |
|
|
1253 { |
|
|
1254 le->next = dsc->list; |
|
|
1255 le->objectId = entry->objectId; |
|
|
1256 dsc->list = le; |
|
|
1257 |
|
|
1258 dsc->de.d_ino = yaffs_GetEquivalentObject(entry)->objectId; |
|
|
1259 dsc->de.d_off = offset; |
|
|
1260 yaffs_GetObjectName(entry,dsc->de.d_name,NAME_MAX+1); |
|
|
1261 dsc->de.d_reclen = sizeof(struct yaffs_dirent); |
|
|
1262 |
|
|
1263 retVal = &dsc->de; |
|
|
1264 } |
|
|
1265 |
|
|
1266 } |
|
|
1267 } |
|
|
1268 |
|
|
1269 } |
|
|
1270 else |
|
|
1271 { |
|
|
1272 yaffsfs_SetError(-EBADF); |
|
|
1273 } |
|
|
1274 |
|
|
1275 yaffsfs_Unlock(); |
|
|
1276 |
|
|
1277 return retVal; |
|
|
1278 |
|
|
1279 } |
|
|
1280 |
|
|
1281 void yaffsfs_ListClear(yaffsfs_DirectorySearchContext *dsc) |
|
|
1282 { |
|
|
1283 |
|
|
1284 struct yaffsfs_ObjectListEntry *le; |
|
|
1285 |
|
|
1286 if(dsc && dsc->magic == YAFFS_MAGIC) |
|
|
1287 { |
|
|
1288 while(dsc->list) |
|
|
1289 { |
|
|
1290 le = dsc->list; |
|
|
1291 dsc->list = dsc->list->next; |
|
|
1292 YFREE(le); |
|
|
1293 } |
|
|
1294 } |
|
|
1295 |
|
|
1296 } |
|
|
1297 |
|
|
1298 void yaffs_rewinddir(yaffs_DIR *dirp) |
|
|
1299 { |
|
|
1300 yaffsfs_DirectorySearchContext *dsc = (yaffsfs_DirectorySearchContext *)dirp; |
|
|
1301 |
|
|
1302 yaffsfs_Lock(); |
|
|
1303 yaffsfs_ListClear(dsc); |
|
|
1304 yaffsfs_Unlock(); |
|
|
1305 } |
|
|
1306 |
|
|
1307 |
|
|
1308 int yaffs_closedir(yaffs_DIR *dirp) |
|
|
1309 { |
|
|
1310 yaffsfs_DirectorySearchContext *dsc = (yaffsfs_DirectorySearchContext *)dirp; |
|
|
1311 |
|
|
1312 yaffsfs_Lock(); |
|
|
1313 yaffsfs_ListClear(dsc); |
|
|
1314 dsc->magic = 0; |
|
|
1315 YFREE(dsc); |
|
|
1316 yaffsfs_Unlock(); |
|
|
1317 return 0; |
|
|
1318 } |
|
|
1319 |
|
|
1320 |
|
|
1321 |
|
|
1322 int yaffs_symlink(const char *oldpath, const char *newpath) |
|
|
1323 { |
|
|
1324 yaffs_Object *parent = NULL; |
|
|
1325 yaffs_Object *obj; |
|
|
1326 char *name; |
|
|
1327 int retVal= -1; |
|
|
1328 int mode = 0; // ignore for now |
|
|
1329 |
|
|
1330 yaffsfs_Lock(); |
|
|
1331 parent = yaffsfs_FindDirectory(NULL,newpath,&name,0); |
|
|
1332 obj = yaffs_MknodSymLink(parent,name,mode,0,0,oldpath); |
|
|
1333 if(obj) |
|
|
1334 { |
|
|
1335 retVal = 0; |
|
|
1336 } |
|
|
1337 else |
|
|
1338 { |
|
|
1339 yaffsfs_SetError(-ENOSPC); // just assume no space for now |
|
|
1340 retVal = -1; |
|
|
1341 } |
|
|
1342 |
|
|
1343 yaffsfs_Unlock(); |
|
|
1344 |
|
|
1345 return retVal; |
|
|
1346 |
|
|
1347 } |
|
|
1348 |
|
|
1349 int yaffs_readlink(const char *path, char *buf, int bufsiz) |
|
|
1350 { |
|
|
1351 yaffs_Object *obj = NULL; |
|
|
1352 int retVal; |
|
|
1353 |
|
|
1354 |
|
|
1355 yaffsfs_Lock(); |
|
|
1356 |
|
|
1357 obj = yaffsfs_FindObject(NULL,path,0); |
|
|
1358 |
|
|
1359 if(!obj) |
|
|
1360 { |
|
|
1361 yaffsfs_SetError(-ENOENT); |
|
|
1362 retVal = -1; |
|
|
1363 } |
|
|
1364 else if(obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK) |
|
|
1365 { |
|
|
1366 yaffsfs_SetError(-EINVAL); |
|
|
1367 retVal = -1; |
|
|
1368 } |
|
|
1369 else |
|
|
1370 { |
|
|
1371 char *alias = obj->variant.symLinkVariant.alias; |
|
|
1372 memset(buf,0,bufsiz); |
|
|
1373 strncpy(buf,alias,bufsiz - 1); |
|
|
1374 retVal = 0; |
|
|
1375 } |
|
|
1376 yaffsfs_Unlock(); |
|
|
1377 return retVal; |
|
|
1378 } |
|
|
1379 |
|
|
1380 int yaffs_link(const char *oldpath, const char *newpath); |
|
|
1381 int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev); |
|
|
1382 |
|
|
1383 int yaffs_DumpDevStruct(const char *path) |
|
|
1384 { |
|
|
1385 char *rest; |
|
|
1386 |
|
|
1387 yaffs_Object *obj = yaffsfs_FindRoot(path,&rest); |
|
|
1388 |
|
|
1389 if(obj) |
|
|
1390 { |
|
|
1391 yaffs_Device *dev = obj->myDev; |
|
|
1392 |
|
|
1393 printf("\n" |
|
|
1394 "nPageWrites.......... %d\n" |
|
|
1395 "nPageReads........... %d\n" |
|
|
1396 "nBlockErasures....... %d\n" |
|
|
1397 "nGCCopies............ %d\n" |
|
|
1398 "garbageCollections... %d\n" |
|
|
1399 "passiveGarbageColl'ns %d\n" |
|
|
1400 "\n", |
|
|
1401 dev->nPageWrites, |
|
|
1402 dev->nPageReads, |
|
|
1403 dev->nBlockErasures, |
|
|
1404 dev->nGCCopies, |
|
|
1405 dev->garbageCollections, |
|
|
1406 dev->passiveGarbageCollections |
|
|
1407 ); |
|
|
1408 |
|
|
1409 } |
|
|
1410 return 0; |
|
|
1411 } |
|
|
1412 |