1 /*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001-2003 Free Software Foundation, Inc.
5 *
6 * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com>
7 * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
8 *
9 * For licensing information, see the file 'LICENCE' in this directory.
10 *
11 * $Id: fs-ecos.c,v 1.44 2005/07/24 15:29:57 dedekind Exp $
12 *
13 */
14
15 #include <stdio.h> //prife for SEEK_SET SEEK_CUR SEEK_END
16 #include <linux/kernel.h>
17 #include <string.h>
18 #include <linux/pagemap.h>
19 #include <linux/semaphore.h>
20 #include <linux/delay.h>
21 #include "mtd_list.h"
22 #include "jffs2/nodelist.h"
23 #include "los_crc32.h"
24 #include "jffs2/compr.h"
25 #include "port/fcntl.h"
26 #include "porting.h"
27 #include "limits.h"
28 #include "los_process_pri.h"
29 #include "capability_type.h"
30 #include "capability_api.h"
31 #include "mtd_partition.h"
32 #include "vfs_jffs2.h"
33
34 // Filesystem operations
35 static int jffs2_mount(cyg_mtab_entry *mte, int partition_num);
36 static int jffs2_umount(cyg_mtab_entry *mte);
37 static int jffs2_open (cyg_mtab_entry *mte, const char *name, int flags,
38 int mode, cyg_file *fte);
39 static int jffs2_ops_unlink(cyg_mtab_entry *mte, const char *name);
40 static int jffs2_ops_mkdir(cyg_mtab_entry *mte, const char *name, int mode);
41 static int jffs2_ops_rmdir(cyg_mtab_entry *mte, const char *name);
42 static int jffs2_ops_rename(cyg_mtab_entry *mte, const char *name1, const char *name2);
43 static int jffs2_opendir(cyg_mtab_entry *mte, const char *name, cyg_file *fte);
44 static int jffs2_stat(cyg_mtab_entry *mte, const char *name, struct jffs2_stat *buf);
45 static int jffs2_fo_chattr(cyg_mtab_entry *mte, const char *name, iattr *attr);
46
47 // File operations
48 static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
49 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
50 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
51 static int jffs2_fo_close(struct CYG_FILE_TAG *fp);
52
53 // Directory operations
54 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
55 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence);
56
57 static int jffs2_read_inode (struct _inode *inode);
58 static void jffs2_clear_inode (struct _inode *inode);
59 static int jffs2_truncate_file (struct _inode *inode);
60 static int jffsfs_IsPathDivider(char ch);
61 static int jffs_check_path(const char *path);
62 static unsigned int CheckPermission(struct _inode *node, int accMode);
63 int jffs2_chattr (struct _inode *dir_i, const unsigned char *d_name, iattr *attr, struct _inode *node_old);
64
65
66 struct MtdNorDev jffs_part[CONFIG_MTD_PATTITION_NUM];
67 //==========================================================================
68 // STATIC VARIABLES !!!
69
70 static unsigned char gc_buffer[PAGE_CACHE_SIZE]; //avoids malloc when user may be under memory pressure
71 static unsigned char n_fs_mounted = 0; // a counter to track the number of jffs2 instances mounted
72
73 #define JFFS_PATH_DIVIDERS "/"
74 //==========================================================================
75 // Directory operations
76
77 struct jffs2_dirsearch {
78 struct _inode *dir; // directory to search
79 const unsigned char *path; // path to follow
80 struct _inode *node; // Node found
81 const unsigned char *name; // last name fragment used
82 int namelen; // name fragment length
83 int last; // last name in path?
84 int accMode; // access mode
85 };
86
87 typedef struct jffs2_dirsearch jffs2_dirsearch;
88
89 //==========================================================================
90 // Ref count and nlink management
91
92 // FIXME: This seems like real cruft. Wouldn't it be better just to do the
93 // right thing?
icache_evict(struct _inode * root_i,struct _inode * i)94 static void icache_evict(struct _inode *root_i, struct _inode *i)
95 {
96 struct _inode *this = root_i;
97 struct _inode *next = NULL;
98 struct _inode *temp = NULL;
99 struct jffs2_inode_info *f = NULL;
100 jffs_lock();
101 restart:
102 D2(PRINTK("icache_evict\n"));
103 // If this is an absolute search path from the root,
104 // remove all cached inodes with i_count of zero (these are only
105 // held where needed for dotdot filepaths)
106
107 while (this) {
108 next = this->i_cache_next;
109 if (this != i && this->i_count == 0) {
110 struct _inode *parent = this->i_parent;
111
112 if (this->i_cache_next)
113 this->i_cache_next->i_cache_prev = this->i_cache_prev;
114 if (this->i_cache_prev)
115 this->i_cache_prev->i_cache_next = this->i_cache_next;
116 jffs2_clear_inode(this);
117 f = JFFS2_INODE_INFO(this);
118 (void)mutex_destroy(&(f->sem));
119 (void)memset_s(this, sizeof(*this), 0x5a, sizeof(*this));
120 temp = this;
121 free(this);
122 if (parent && parent != temp) {
123 parent->i_count--;
124 this = root_i;
125 goto restart;
126 }
127 }
128 this = next;
129 }
130 jffs_unlock();
131 }
132
133 //==========================================================================
134 // Directory search
135
136 // -------------------------------------------------------------------------
137 // init_dirsearch()
138 // Initialize a dirsearch object to start a search
139
init_dirsearch(jffs2_dirsearch * ds,struct _inode * dir,const unsigned char * name,int flags)140 void init_dirsearch(jffs2_dirsearch * ds,
141 struct _inode *dir, const unsigned char *name, int flags)
142 {
143 D2(PRINTK("init_dirsearch name = %s\n", name));
144 D2(PRINTK("init_dirsearch dir = %x\n", dir));
145
146 dir->i_count++;
147 ds->dir = dir;
148 ds->path = name;
149 ds->node = dir;
150 ds->name = name;
151 ds->namelen = 0;
152 ds->last = false;
153 ds->accMode = flags;
154 }
155
156 // -------------------------------------------------------------------------
157 // find_entry()
158 // Search a single directory for the next name in a path and update the
159 // dirsearch object appropriately.
160
find_entry(jffs2_dirsearch * ds)161 static int find_entry(jffs2_dirsearch * ds)
162 {
163 struct _inode *dir = ds->dir;
164 const unsigned char *name = ds->path;
165 const unsigned char *n = name;
166 int namelen = 0;
167 struct _inode *d;
168 int accMode = 0;
169
170 // Isolate the next element of the path name.
171 while (*n != '\0' && *n != '/') {
172 n++;
173 namelen++;
174 }
175
176 // Check if this is the last path element.
177 while( *n == '/') n++;
178 if (*n == '\0')
179 ds->last = true;
180
181 // update name in dirsearch object
182 ds->name = name;
183 ds->namelen = namelen;
184 if (name[0] == '.')
185 switch (namelen) {
186 default:
187 break;
188 case 2:
189 // Dot followed by not Dot, treat as any other name
190 if (name[1] != '.')
191 break;
192 // Dot Dot
193 // Move back up the search path
194 ds->dir = ds->node;
195 ds->node = ds->dir->i_parent;
196 ds->node->i_count++;
197 return ENOERR;
198 case 1:
199 // Dot is consumed
200 ds->node = ds->dir;
201 ds->dir->i_count++;
202 return ENOERR;
203 }
204
205 // Here we have the name and its length set up.
206 // Search the directory for a matching entry
207 d = jffs2_lookup(dir, name, namelen);
208
209 if (d == NULL) {
210 return ENOENT;
211 }
212 if (IS_ERR(d)) {
213 return -(int)(PTR_ERR(d));}
214
215 // If it's a new directory inode, increase refcount on its parent
216 if (S_ISDIR(d->i_mode) && !d->i_parent) {
217 d->i_parent = dir;
218 dir->i_count++;
219 }
220
221 accMode = (ds->last) ? ds->accMode : EXEC_OP;
222
223 if (CheckPermission(d, accMode)) {
224 jffs2_iput(d);
225 return EACCES;
226 }
227
228 // pass back the node we have found
229 ds->node = d;
230 return ENOERR;
231 }
232
233 // -------------------------------------------------------------------------
234 // jffs2_find()
235 // Main interface to directory search code. This is used in all file
236 // level operations to locate the object named by the pathname.
237
238 // Returns with use count incremented on both the sought object and
239 // the directory it was found in
jffs2_find(jffs2_dirsearch * d)240 static int jffs2_find(jffs2_dirsearch * d)
241 {
242 int err;
243
244 D2(PRINTK("jffs2_find for path =%s\n", d->path));
245 // Short circuit empty paths
246 if (*(d->path) == '\0') {
247 d->node->i_count++;
248 return ENOERR;
249 }
250
251 // iterate down directory tree until we find the object
252 // we want.
253 for (;;) {
254 // check that we really have a directory
255 if (!S_ISDIR(d->dir->i_mode)) {
256 return ENOTDIR;
257 }
258
259 err = find_entry(d);
260 if (err != ENOERR) {
261 return err;
262 }
263 if (d->last)
264 return ENOERR;
265
266 /* We're done with it, although it we found a subdir that
267 will have caused the refcount to have been increased */
268 jffs2_iput(d->dir);
269
270 // Update dirsearch object to search next directory.
271 d->dir = d->node;
272 d->path += d->namelen;
273 while (*(d->path) == '/')
274 d->path++; // skip dirname separators
275 }
276 }
277
278
279 //==========================================================================
280 // Filesystem operations
281 // -------------------------------------------------------------------------
282 // jffs2_mount()
283 // Process a mount request. This mainly creates a root for the
284 // filesystem.
jffs2_read_super(struct super_block * sb)285 static int jffs2_read_super(struct super_block *sb)
286 {
287 int err;
288 struct jffs2_sb_info *c;
289 struct MtdNorDev *device;
290
291 c = JFFS2_SB_INFO(sb);
292 device = (struct MtdNorDev*)(sb->s_dev);
293
294 /* initialize mutex lock */
295 (void)mutex_init(&c->alloc_sem);
296 (void)mutex_init(&c->erase_free_sem);
297 spin_lock_init(&c->erase_completion_lock);
298 spin_lock_init(&c->inocache_lock);
299
300 /* sector size is the erase block size */
301 c->sector_size = device->blockSize;
302 c->flash_size = (device->blockEnd - device->blockStart + 1) * device->blockSize;
303 c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
304 err = jffs2_do_mount_fs(c);
305
306 if (err) {
307 (void)mutex_destroy(&c->alloc_sem);
308 (void)mutex_destroy(&c->erase_free_sem);
309 return -err;
310 }
311 D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n"));
312
313 sb->s_root = jffs2_iget(sb, 1);
314
315 if (IS_ERR(sb->s_root)) {
316 D1(printk(KERN_WARNING "get root inode failed\n"));
317 err = PTR_ERR(sb->s_root);
318 sb->s_root = NULL;
319 goto out_nodes;
320 }
321 return 0;
322
323 out_nodes:
324 jffs2_free_ino_caches(c);
325 jffs2_free_raw_node_refs(c);
326 free(c->blocks);
327 (void)mutex_destroy(&c->alloc_sem);
328 (void)mutex_destroy(&c->erase_free_sem);
329
330 return err;
331 }
332
jffs2_mount(cyg_mtab_entry * mte,int partition_num)333 static int jffs2_mount(cyg_mtab_entry *mte, int partition_num)
334 {
335 struct super_block *jffs2_sb = NULL;
336 struct jffs2_sb_info *c = NULL;
337 mtd_partition *current_node = GetSpinorPartitionHead();
338 LOS_DL_LIST *patition_head = NULL;
339 int err;
340 struct MtdDev *spinor_mtd = NULL;
341
342 jffs2_dbg(1, "begin los_jffs2_mount:%d\n", partition_num);
343
344 jffs2_sb = malloc(sizeof (struct super_block));
345
346 if (jffs2_sb == NULL) {
347 return ENOMEM;
348 }
349 c = JFFS2_SB_INFO(jffs2_sb);
350 (void)memset_s(jffs2_sb, sizeof (struct super_block), 0, sizeof (struct super_block));
351 patition_head = &(GetSpinorPartitionHead()->node_info);
352 LOS_DL_LIST_FOR_EACH_ENTRY(current_node,patition_head, mtd_partition, node_info) {
353 if (current_node->patitionnum == partition_num)
354 break;
355 }
356 #ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
357 spinor_mtd = GetMtd("spinor");
358 #else
359 spinor_mtd = (struct MtdDev *)LOS_DL_LIST_ENTRY(patition_head->pstNext, mtd_partition, node_info)->mtd_info;
360 #endif
361 if (spinor_mtd == NULL) {
362 free(jffs2_sb);
363 return EPERM;
364 }
365 jffs_part[partition_num].blockEnd = current_node->end_block;
366 jffs_part[partition_num].blockSize = spinor_mtd->eraseSize;
367 jffs_part[partition_num].blockStart = current_node->start_block;
368 #ifndef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
369 (void)FreeMtd(spinor_mtd);
370 #endif
371 jffs2_sb->jffs2_sb.mtd = current_node->mtd_info;
372 jffs2_sb->s_dev = (cyg_io_handle_t)(&jffs_part[partition_num]);
373
374 c->flash_size = (current_node->end_block - current_node->start_block + 1) * spinor_mtd->eraseSize;
375 c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
376 c->sector_size = spinor_mtd->eraseSize;
377
378 jffs2_dbg(1, "C mtd_size:%d,mtd-erase:%d,blocks:%d,hashsize:%d\n",
379 c->flash_size, c->sector_size, c->flash_size / c->sector_size, c->inocache_hashsize);
380
381 c->inocache_list = malloc(sizeof(struct jffs2_inode_cache *) * c->inocache_hashsize);
382 if (c->inocache_list == NULL) {
383 free(jffs2_sb);
384 return ENOMEM;
385 }
386 (void)memset_s(c->inocache_list, sizeof(struct jffs2_inode_cache *) * c->inocache_hashsize, 0,
387 sizeof(struct jffs2_inode_cache *) * c->inocache_hashsize);
388 if (n_fs_mounted++ == 0) {
389 (void)jffs2_create_slab_caches(); // No error check, cannot fail
390 (void)jffs2_compressors_init();
391 }
392
393 err = jffs2_read_super(jffs2_sb);
394
395 if (err) {
396 if (--n_fs_mounted == 0) {
397 jffs2_destroy_slab_caches();
398 (void)jffs2_compressors_exit();
399 }
400
401 free(jffs2_sb);
402 free(c->inocache_list);
403 c->inocache_list = NULL;
404 return err;
405 }
406 jffs2_sb->s_root->i_parent = jffs2_sb->s_root; // points to itself, no dotdot paths above mountpoint
407 jffs2_sb->s_root->i_cache_prev = NULL; // root inode, so always null
408 jffs2_sb->s_root->i_cache_next = NULL;
409 jffs2_sb->s_root->i_count = 1; // Ensures the root inode is always in ram until umount
410
411 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
412 jffs2_start_garbage_collect_thread(c);
413 #endif
414
415 mte->data = (CYG_ADDRWORD)jffs2_sb;
416 jffs2_sb->s_mount_count++;
417 mte->root = (cyg_dir)jffs2_sb->s_root;
418 D2(PRINTK("jffs2_mounted superblock at %x\n", mte->root));
419 return ENOERR;
420 }
421
422
423 // -------------------------------------------------------------------------
424 // jffs2_umount()
425 // Unmount the filesystem.
426
jffs2_umount(cyg_mtab_entry * mte)427 static int jffs2_umount(cyg_mtab_entry *mte)
428 {
429 struct _inode *root = (struct _inode *) mte->root;
430 struct super_block *jffs2_sb = root->i_sb;
431 struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb);
432 struct jffs2_full_dirent *fd, *next;
433
434 D2(PRINTK("jffs2_umount\n"));
435
436 // Only really umount if this is the only mount
437 if (jffs2_sb->s_mount_count == 1) {
438 icache_evict(root, NULL);
439 if (root->i_cache_next != NULL) {
440 struct _inode *inode = root;
441 while (inode) {
442 PRINTK("Ino #%u has use count %d\n",
443 inode->i_ino, inode->i_count);
444 inode = inode->i_cache_next;
445 }
446 // root icount was set to 1 on mount
447 return EBUSY;
448 }
449 if (root->i_count != 1) {
450 PRINTK("Ino #1 has use count %d\n",
451 root->i_count);
452 return EBUSY;
453 }
454 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
455 jffs2_stop_garbage_collect_thread(c);
456 #endif
457 jffs2_iput(root); // Time to free the root inode
458
459 // free directory entries
460 for (fd = root->jffs2_i.dents; fd; fd = next) {
461 next = fd->next;
462 jffs2_free_full_dirent(fd);
463 }
464
465 free(root);
466
467 // Clean up the super block and root inode
468 jffs2_free_ino_caches(c);
469 jffs2_free_raw_node_refs(c);
470 free(c->blocks);
471 c->blocks = NULL;
472 free(c->inocache_list);
473 c->inocache_list = NULL;
474
475 (void)mutex_destroy(&c->alloc_sem);
476 (void)mutex_destroy(&c->erase_free_sem);
477 free(jffs2_sb);
478 // Clear superblock & root pointer
479 mte->root = 0;
480 mte->data = 0;
481 // That's all folks.
482 D2(PRINTK("jffs2_umount No current mounts\n"));
483 } else {
484 jffs2_sb->s_mount_count--;
485 }
486 if (--n_fs_mounted == 0) {
487 jffs2_destroy_slab_caches();
488 (void)jffs2_compressors_exit();
489 }
490 return ENOERR;
491 }
492
493 // -------------------------------------------------------------------------
494 // jffs2_open()
495 // Open a file for reading or writing.
496
jffs2_open(cyg_mtab_entry * mte,const char * name,int flags,int mode,cyg_file * fte)497 static int jffs2_open (cyg_mtab_entry *mte, const char *name, int flags,
498 int mode, cyg_file *fte)
499 {
500 jffs2_dirsearch ds;
501 struct _inode *node = NULL;
502 int err;
503 jffs2_dbg(1, "open %s at mode: %d\n",name,mode);
504
505 #ifndef CYGOPT_FS_JFFS2_WRITE
506 if (flags & (O_CREAT | O_TRUNC | O_WRONLY))
507 return EROFS;
508 #endif
509
510 if (jffs_check_path(name))
511 return ENAMETOOLONG;
512
513 init_dirsearch(&ds, (struct _inode *)mte->root,
514 (const unsigned char *) name, jffs2_oflag_to_accmode(flags));
515
516 err = jffs2_find(&ds);
517
518 if (err == ENOENT) {
519 #ifdef CYGOPT_FS_JFFS2_WRITE
520 if (ds.last && (flags & O_CREAT)) {
521
522 // No node there, if the O_CREAT bit is set then we must
523 // create a new one. The dir and name fields of the dirsearch
524 // object will have been updated so we know where to put it.
525 err = jffs2_create(ds.dir, ds.name, mode, &node);
526 if (err != 0) {
527 //Possible orphaned inode on the flash - but will be gc'd
528 jffs2_iput(ds.dir);
529 return -err;
530 }
531
532 err = ENOERR;
533 }
534 #endif
535 } else if (err == ENOERR) {
536 // The node exists. If the O_CREAT and O_EXCL bits are set, we
537 // must fail the open.
538
539 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
540 jffs2_iput(ds.node);
541 err = EEXIST;
542 } else
543 node = ds.node;
544 } else if (err == EACCES) {
545 jffs2_iput(ds.dir);
546 return -err;
547 }
548
549 D1(PRINTK("%s, %d, uid %d gid %d mode %d%d%d\n", __FUNCTION__, __LINE__, node->i_uid, node->i_gid,
550 (node->i_mode >> JFFS2_USER_SHFIT) & JFFS2_MODE_ALL, (node->i_mode >> JFFS2_GROUP_SHFIT) & JFFS2_MODE_ALL,
551 (node->i_mode) & JFFS2_MODE_ALL));
552
553 // Finished with the directory now
554 jffs2_iput(ds.dir);
555
556 if (err != ENOERR) {
557 return err;
558 }
559 // Check that we actually have a file here
560 if (S_ISDIR(node->i_mode)) {
561 jffs2_iput(node);
562 return EISDIR;
563 }
564
565 // If the O_TRUNC bit is set we must clean out the file data.
566 if (flags & O_TRUNC) {
567 #ifdef CYGOPT_FS_JFFS2_WRITE
568 err = jffs2_truncate_file(node);
569 if (err) {
570 jffs2_iput(node);
571 return err;
572 }
573 #else
574 jffs2_iput(node);
575 return EROFS;
576 #endif
577 }
578
579 // Initialise the file object
580 fte->f_flag = flags & JFFS2_O_ACCMODE;
581 fte->f_offset = (flags & O_APPEND) ? node->i_size : 0;
582 fte->f_data = (UINTPTR) node;
583
584 return ENOERR;
585 }
586
587 // -------------------------------------------------------------------------
588 // jffs2_ops_unlink()
589 // Remove a file link from its directory.
590
jffs2_ops_unlink(cyg_mtab_entry * mte,const char * name)591 static int jffs2_ops_unlink(cyg_mtab_entry *mte, const char *name)
592 {
593 jffs2_dirsearch ds;
594 int err;
595
596 jffs2_dbg(1, "unlink: %s\n", name);
597
598 if (jffs_check_path(name))
599 return ENAMETOOLONG;
600
601 init_dirsearch(&ds, (struct _inode *) mte->root,
602 (const unsigned char *)name, 0);
603
604 err = jffs2_find(&ds);
605
606 if (err != ENOERR) {
607 jffs2_iput(ds.dir);
608 return err;
609 }
610
611 if (CheckPermission(ds.dir, WRITE_OP | EXEC_OP)) {
612 jffs2_iput(ds.dir);
613 jffs2_iput(ds.node);
614 return EACCES;
615 }
616
617 // Cannot unlink directories, use rmdir() instead
618 if (S_ISDIR(ds.node->i_mode)) {
619 jffs2_iput(ds.dir);
620 jffs2_iput(ds.node);
621 return EISDIR;
622 }
623
624 // Delete it from its directory
625
626 err = jffs2_unlink(ds.dir, ds.node, ds.name);
627 jffs2_iput(ds.dir);
628 jffs2_iput(ds.node);
629
630 return -err;
631 }
632
633 // -------------------------------------------------------------------------
634 // jffs2_ops_mkdir()
635 // Create a new directory.
636
jffs2_ops_mkdir(cyg_mtab_entry * mte,const char * name,int mode)637 static int jffs2_ops_mkdir(cyg_mtab_entry *mte, const char *name,int mode)
638 {
639 jffs2_dirsearch ds;
640 int err;
641
642 jffs2_dbg(1, "mkdir: %s\n",name);
643
644 if (jffs_check_path(name))
645 return ENAMETOOLONG;
646
647 init_dirsearch(&ds, (struct _inode *)mte->root, (const unsigned char *)name, 0);
648
649 err = jffs2_find(&ds);
650 if (err == ENOENT) {
651 if (ds.last) {
652 // The entry does not exist, and it is the last element in
653 // the pathname, so we can create it here.
654 err = jffs2_mkdir(ds.dir, ds.name, mode);
655 }
656 // If this was not the last element, then an intermediate
657 // directory does not exist.
658 } else {
659 // If there we no error, something already exists with that
660 // name, so we cannot create another one.
661 if (err == ENOERR) {
662 jffs2_iput(ds.node);
663 err = -EEXIST;
664 }
665 }
666 jffs2_iput(ds.dir);
667 if (err == EACCES) {
668 err = -EACCES;
669 }
670 return err;
671 }
672
673 // -------------------------------------------------------------------------
674 // jffs2_ops_rmdir()
675 // Remove a directory.
676
jffs2_ops_rmdir(cyg_mtab_entry * mte,const char * name)677 static int jffs2_ops_rmdir(cyg_mtab_entry *mte, const char *name)
678 {
679 jffs2_dirsearch ds;
680 int err;
681
682 jffs2_dbg(1, "rmdir: %s\n",name);
683
684 if (jffs_check_path(name))
685 return ENAMETOOLONG;
686
687 init_dirsearch(&ds, (struct _inode *)mte->root, (const unsigned char *)name, 0);
688
689 err = jffs2_find(&ds);
690 if (err != ENOERR) {
691 jffs2_iput(ds.dir);
692 return -err;
693 }
694
695 if (CheckPermission(ds.dir, WRITE_OP | EXEC_OP)) {
696 jffs2_iput(ds.dir);
697 jffs2_iput(ds.node);
698 return -EACCES;
699 }
700
701 // Check that this is actually a directory.
702 if (!S_ISDIR(ds.node->i_mode)) {
703 jffs2_iput(ds.dir);
704 jffs2_iput(ds.node);
705 return -ENOTDIR;
706 }
707
708 err = jffs2_rmdir(ds.dir, ds.node, ds.name);
709
710 jffs2_iput(ds.dir);
711 jffs2_iput(ds.node);
712 return err;
713 }
714
715 // -------------------------------------------------------------------------
716 // jffs2_ops_rename()
717 // Rename a file/dir.
718
jffs2_ops_rename(cyg_mtab_entry * mte,const char * name1,const char * name2)719 static int jffs2_ops_rename(cyg_mtab_entry *mte, const char *name1, const char *name2)
720 {
721 jffs2_dirsearch ds1, ds2;
722 int err;
723 struct jffs2_inode_info *f = NULL;
724 struct jffs2_full_dirent *fd = NULL;
725 unsigned int oldrelpath_len, newrelpath_len, cmp_namelen;
726
727 jffs2_dbg(1, "from: %s to: %s\n", name1, name2);
728
729 if (jffs_check_path(name1))
730 return ENAMETOOLONG;
731
732 if (jffs_check_path(name2))
733 return ENAMETOOLONG;
734
735 oldrelpath_len = strlen(name1);
736 newrelpath_len = strlen(name2);
737 if (!oldrelpath_len || !newrelpath_len)
738 return EPERM;
739
740 cmp_namelen = (oldrelpath_len <= newrelpath_len) ? oldrelpath_len : newrelpath_len;
741 if ((!strncmp(name1, name2, cmp_namelen)) && ((name1[cmp_namelen] == '/') || (name2[cmp_namelen] == '/'))) {
742 err = -EPERM;
743 return err;
744 }
745
746 init_dirsearch(&ds1, (struct _inode *)mte->root,
747 (const unsigned char *)name1, 0);
748
749 err = jffs2_find(&ds1);
750
751 if (err != ENOERR) {
752 jffs2_iput(ds1.dir);
753 return err;
754 }
755
756 if (CheckPermission(ds1.dir, WRITE_OP | EXEC_OP)) {
757 jffs2_iput(ds1.dir);
758 jffs2_iput(ds1.node);
759 return -EACCES;
760 }
761
762
763 init_dirsearch(&ds2, (struct _inode *)mte->root,
764 (const unsigned char *)name2, 0);
765
766 err = jffs2_find(&ds2);
767
768 // Allow through renames to non-existent objects.
769 if (ds2.last && err == ENOENT) {
770 ds2.node = NULL;
771 err = ENOERR;
772 } else if ((err == ENOERR) && S_ISDIR(ds2.node->i_mode)) {
773 f = JFFS2_INODE_INFO(ds2.node);
774 for (fd = f->dents; fd; fd = fd->next) {
775 if (fd->ino) {
776 jffs2_iput(ds2.node);
777 err = ENOTEMPTY;
778 break;
779 }
780 }
781 }
782 if (err != ENOERR) {
783 jffs2_iput(ds1.dir);
784 jffs2_iput(ds1.node);
785 jffs2_iput(ds2.dir);
786 return err;
787 }
788
789 if (CheckPermission(ds2.dir, WRITE_OP | EXEC_OP)) {
790 jffs2_iput(ds1.dir);
791 jffs2_iput(ds1.node);
792 jffs2_iput(ds2.dir);
793 jffs2_iput(ds2.node);
794 return -EACCES;
795 }
796
797 // Null rename, just return
798 if (ds1.node == ds2.node) {
799 err = ENOERR;
800 goto out;
801 }
802
803 // First deal with any entry that is at the destination
804 if (ds2.node != NULL) {
805 // Check that we are renaming like-for-like
806
807 if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode)) {
808 err = EISDIR;
809 goto out;
810 }
811
812 if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) {
813 err = ENOTDIR;
814 goto out;
815 }
816
817 // Now delete the destination directory entry
818 /* Er, what happened to atomicity of rename()? */
819 err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name);
820
821 if (err != 0)
822 goto out;
823 }
824 // Now we know that there is no clashing node at the destination,
825 // make a new direntry at the destination and delete the old entry
826 // at the source.
827
828 err = -jffs2_rename(ds1.dir, ds1.node, ds1.name, ds2.dir, ds2.name);
829
830 // Update directory times
831 if (!err)
832 ds1.dir->i_ctime =
833 ds1.dir->i_mtime =
834 ds2.dir->i_ctime = ds2.dir->i_mtime = jffs2_get_timestamp();
835 out:
836 jffs2_iput(ds1.dir);
837 if (S_ISDIR(ds1.node->i_mode)) {
838 /* Renamed a directory to elsewhere... so fix up its
839 i_parent pointer and the i_counts of its old and
840 new parents. */
841 jffs2_iput(ds1.node->i_parent);
842 ds1.node->i_parent = ds2.dir;
843 /* We effectively increase its use count by not... */
844 } else {
845 jffs2_iput(ds2.dir); /* ... doing this */
846 }
847 jffs2_iput(ds1.node);
848 if (ds2.node != NULL)
849 jffs2_iput(ds2.node);
850
851 return err;
852 }
853
jffsfs_IsPathDivider(char ch)854 static int jffsfs_IsPathDivider(char ch)
855 {
856 const char *str = JFFS_PATH_DIVIDERS;
857 while (*str) {
858 if (*str == ch)
859 return 1;
860 str++;
861 }
862 return 0;
863 }
864
865 // -------------------------------------------------------------------------
866 // jffs2_opendir()
867 // Open a directory for reading.
868
jffs2_opendir(cyg_mtab_entry * mte,const char * name,cyg_file * fte)869 static int jffs2_opendir(cyg_mtab_entry *mte, const char *name, cyg_file *fte)
870 {
871 jffs2_dirsearch ds;
872 int err;
873
874 jffs2_dbg(1, "opendir: %s\n",name);
875
876 if (jffs_check_path(name))
877 return ENAMETOOLONG;
878
879 init_dirsearch(&ds, (struct _inode *) mte->root,
880 (const unsigned char *) name, jffs2_oflag_to_accmode(O_RDONLY | O_EXECVE));
881
882 err = jffs2_find(&ds);
883
884 jffs2_iput(ds.dir);
885
886 if (err != ENOERR) {
887 return err;
888 }
889
890 // check it is really a directory.
891 if (!S_ISDIR(ds.node->i_mode)) {
892 jffs2_iput(ds.node);
893 return ENOTDIR;
894 }
895
896 // Initialize the file object, setting the f_ops field to a
897 // special set of file ops.
898
899 fte->f_flag = 0;
900 fte->f_offset = 0;
901 fte->f_data = (UINTPTR) ds.node;
902
903 return ENOERR;
904 }
905
jffs2_fo_chattr(cyg_mtab_entry * mte,const char * name,iattr * attr)906 static int jffs2_fo_chattr(cyg_mtab_entry *mte, const char *name, iattr *attr)
907 {
908 jffs2_dirsearch ds;
909 int ret;
910 int flags = 0;
911 D2(PRINTK("jffs2_chattr: %s\n", name));
912
913 if (jffs_check_path(name))
914 return ENAMETOOLONG;
915
916 init_dirsearch(&ds, (struct _inode *)mte->root, (const unsigned char *)name, flags);
917
918 ret = jffs2_find(&ds);
919 if (ret == ENOERR) {
920 ret = jffs2_chattr(ds.dir, ds.name, attr, ds.node);
921 jffs2_iput(ds.node);
922 } else {
923 ret = -ret;
924 }
925 jffs2_iput(ds.dir);
926 return ret;
927 }
928
929 // -------------------------------------------------------------------------
930 // jffs2_stat()
931 // Get struct stat info for named object.
932
jffs2_stat(cyg_mtab_entry * mte,const char * name,struct jffs2_stat * buf)933 static int jffs2_stat(cyg_mtab_entry *mte, const char *name, struct jffs2_stat *buf)
934 {
935 jffs2_dirsearch ds;
936 int err;
937
938 jffs2_dbg(1, "get %s stat\n", name);
939
940 if (jffs_check_path(name))
941 return ENAMETOOLONG;
942
943 init_dirsearch(&ds, (struct _inode *)mte->root,
944 (const unsigned char *) name, 0);
945
946 err = jffs2_find(&ds);
947 jffs2_iput(ds.dir);
948
949 if (err != ENOERR)
950 return err;
951
952 // Fill in the status
953 buf->st_mode = ds.node->i_mode;
954 buf->st_ino = ds.node->i_ino;
955 buf->st_dev = 0;
956 buf->st_nlink = ds.node->i_nlink;
957 buf->st_uid = ds.node->i_uid;
958 buf->st_gid = ds.node->i_gid;
959 buf->st_size = ds.node->i_size;
960 buf->sddst_atime = ds.node->i_atime;
961 buf->sddst_mtime = ds.node->i_mtime;
962 buf->sddst_ctime = ds.node->i_ctime;
963
964 jffs2_iput(ds.node);
965
966 return ENOERR;
967 }
968
969 //==========================================================================
970 // File operations
971
972 // -------------------------------------------------------------------------
973 // jffs2_fo_read()
974 // Read data from the file.
975
jffs2_fo_read(struct CYG_FILE_TAG * fp,struct CYG_UIO_TAG * uio)976 static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
977 {
978 struct _inode *inode = (struct _inode *) fp->f_data;
979 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
980 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
981 int i;
982 ssize_t resid = uio->uio_resid;
983 off_t pos = fp->f_offset;
984
985 mutex_lock(&f->sem);
986
987 // Loop over the io vectors until there are none left
988 for (i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++) {
989 int ret;
990 jffs2_iovec *iov = &uio->uio_iov[i];
991 off_t len = min((iov->iov_len), (inode->i_size - pos));
992
993 D2(PRINTK("jffs2_fo_read inode size %d\n", inode->i_size));
994
995 ret = jffs2_read_inode_range(c, f,(unsigned char *) iov->iov_base, pos,len);
996 if (ret) {
997 D1(PRINTK
998 ("jffs2_fo_read(): read_inode_range failed %d\n",
999 ret));
1000 uio->uio_resid = resid;
1001 mutex_unlock(&f->sem);
1002 return -ret;
1003 }
1004 resid -= len;
1005 pos += len;
1006 }
1007
1008 // We successfully read some data, update the node's access time
1009 // and update the file offset and transfer residue.
1010
1011 inode->i_atime = jffs2_get_timestamp();
1012
1013 uio->uio_resid = resid;
1014 fp->f_offset = pos;
1015
1016 mutex_unlock(&f->sem);
1017
1018 return ENOERR;
1019 }
1020
1021 #ifdef CYGOPT_FS_JFFS2_WRITE
1022 // -------------------------------------------------------------------------
1023 // jffs2_fo_write()
1024 // Write data to file.
jffs2_extend_file(struct _inode * inode,struct jffs2_raw_inode * ri,unsigned long offset)1025 static int jffs2_extend_file (struct _inode *inode, struct jffs2_raw_inode *ri,
1026 unsigned long offset)
1027 {
1028 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1029 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1030 struct jffs2_full_dnode *fn;
1031 uint32_t alloc_len;
1032 int ret = 0;
1033
1034 /* Make new hole frag from old EOF to new page */
1035 D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
1036 (unsigned int)inode->i_size, offset));
1037
1038 ret = jffs2_reserve_space(c, sizeof(*ri), &alloc_len, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
1039 if (ret)
1040 return ret;
1041
1042 mutex_lock(&f->sem);
1043
1044 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
1045 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
1046 ri->totlen = cpu_to_je32(sizeof(*ri));
1047 ri->hdr_crc = cpu_to_je32(crc32(0, ri, (sizeof(struct jffs2_unknown_node)-4)));
1048
1049 ri->version = cpu_to_je32(++f->highest_version);
1050 ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset));
1051
1052 ri->offset = cpu_to_je32(inode->i_size);
1053 ri->dsize = cpu_to_je32((offset - inode->i_size));
1054 ri->csize = cpu_to_je32(0);
1055 ri->compr = JFFS2_COMPR_ZERO;
1056 ri->node_crc = cpu_to_je32(crc32(0, ri, (sizeof(*ri)-8)));
1057 ri->data_crc = cpu_to_je32(0);
1058
1059 fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
1060 jffs2_complete_reservation(c);
1061 if (IS_ERR(fn)) {
1062 ret = PTR_ERR(fn);
1063 (void)mutex_unlock(&f->sem);
1064 return ret;
1065 }
1066 ret = jffs2_add_full_dnode_to_inode(c, f, fn);
1067 if (f->metadata) {
1068 jffs2_mark_node_obsolete(c, f->metadata->raw);
1069 jffs2_free_full_dnode(f->metadata);
1070 f->metadata = NULL;
1071 }
1072 if (ret) {
1073 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret));
1074 jffs2_mark_node_obsolete(c, fn->raw);
1075 jffs2_free_full_dnode(fn);
1076 mutex_unlock(&f->sem);
1077 return ret;
1078 }
1079 inode->i_size = offset;
1080 mutex_unlock(&f->sem);
1081 return 0;
1082 }
1083
1084 // jffs2_fo_open()
1085 // Truncate a file
jffs2_truncate_file(struct _inode * inode)1086 static int jffs2_truncate_file (struct _inode *inode)
1087 {
1088 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1089 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1090 struct jffs2_full_dnode *new_metadata, * old_metadata;
1091 struct jffs2_raw_inode *ri;
1092 uint32_t alloclen;
1093 int err;
1094
1095 ri = jffs2_alloc_raw_inode();
1096 if (!ri) {
1097 return ENOMEM;
1098 }
1099 err = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
1100
1101 if (err) {
1102 jffs2_free_raw_inode(ri);
1103 return err;
1104 }
1105 mutex_lock(&f->sem);
1106 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
1107 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
1108 ri->totlen = cpu_to_je32(sizeof(*ri));
1109 ri->hdr_crc = cpu_to_je32(crc32(0, ri, (sizeof(struct jffs2_unknown_node)-4)));
1110
1111 ri->ino = cpu_to_je32(inode->i_ino);
1112 ri->version = cpu_to_je32(++f->highest_version);
1113
1114 ri->uid = cpu_to_je16(inode->i_uid);
1115 ri->gid = cpu_to_je16(inode->i_gid);
1116 ri->mode = cpu_to_jemode(inode->i_mode);
1117 ri->isize = cpu_to_je32(0);
1118 ri->atime = cpu_to_je32(inode->i_atime);
1119 ri->mtime = cpu_to_je32(jffs2_get_timestamp());
1120 ri->offset = cpu_to_je32(0);
1121 ri->csize = ri->dsize = cpu_to_je32(0);
1122 ri->compr = JFFS2_COMPR_NONE;
1123 ri->node_crc = cpu_to_je32(crc32(0, ri, (sizeof(*ri)-8)));
1124 ri->data_crc = cpu_to_je32(0);
1125 new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
1126 if (IS_ERR(new_metadata)) {
1127 jffs2_complete_reservation(c);
1128 jffs2_free_raw_inode(ri);
1129 mutex_unlock(&f->sem);
1130 return PTR_ERR(new_metadata);
1131 }
1132
1133 /* It worked. Update the inode */
1134 inode->i_mtime = jffs2_get_timestamp();
1135 inode->i_size = 0;
1136 old_metadata = f->metadata;
1137 jffs2_truncate_fragtree (c, &f->fragtree, 0);
1138 f->metadata = new_metadata;
1139 if (old_metadata) {
1140 jffs2_mark_node_obsolete(c, old_metadata->raw);
1141 jffs2_free_full_dnode(old_metadata);
1142 }
1143 jffs2_free_raw_inode(ri);
1144
1145 mutex_unlock(&f->sem);
1146 jffs2_complete_reservation(c);
1147
1148 return 0;
1149 }
1150
1151 // jffs2_fo_open()
1152 // Truncate a file
1153
jffs2_fo_write(struct CYG_FILE_TAG * fp,struct CYG_UIO_TAG * uio)1154 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1155 {
1156 struct _inode *inode = (struct _inode *) fp->f_data;
1157 off_t pos = fp->f_offset;
1158 ssize_t resid = uio->uio_resid;
1159 struct jffs2_raw_inode ri;
1160 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1161 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1162 int i;
1163
1164 #ifdef LOSCFG_KERNEL_SMP
1165 struct super_block *sb = inode->i_sb;
1166 UINT16 gc_cpu_mask = LOS_TaskCpuAffiGet(sb->s_gc_thread);
1167 UINT32 cur_task_id = LOS_CurTaskIDGet();
1168 UINT16 cur_cpu_mask = LOS_TaskCpuAffiGet(cur_task_id);
1169
1170 if (cur_cpu_mask != gc_cpu_mask) {
1171 if (cur_cpu_mask != LOSCFG_KERNEL_CPU_MASK)
1172 (void)LOS_TaskCpuAffiSet(sb->s_gc_thread, cur_cpu_mask);
1173 else
1174 (void)LOS_TaskCpuAffiSet(cur_task_id, gc_cpu_mask);
1175 }
1176 #endif
1177 // If the APPEND mode bit was supplied, force all writes to
1178 // the end of the file.
1179 if (fp->f_flag & O_APPEND)
1180 pos = fp->f_offset = inode->i_size;
1181
1182 if (pos < 0)
1183 return EINVAL;
1184
1185 (void)memset_s(&ri, sizeof(ri), 0, sizeof(ri));
1186
1187 ri.ino = cpu_to_je32(f->inocache->ino);
1188 ri.mode = cpu_to_jemode(inode->i_mode);
1189 ri.uid = cpu_to_je16(inode->i_uid);
1190 ri.gid = cpu_to_je16(inode->i_gid);
1191 ri.atime = ri.ctime = ri.mtime = cpu_to_je32(jffs2_get_timestamp());
1192
1193 if (pos > inode->i_size) {
1194 int err;
1195 ri.version = cpu_to_je32(++f->highest_version);
1196 err = jffs2_extend_file(inode, &ri, pos);
1197 if (err)
1198 return -err;
1199 }
1200 ri.isize = cpu_to_je32(inode->i_size);
1201
1202 // Now loop over the iovecs until they are all done, or
1203 // we get an error.
1204 for (i = 0; i < uio->uio_iovcnt; i++) {
1205 jffs2_iovec *iov = &uio->uio_iov[i];
1206 unsigned char *buf = iov->iov_base;
1207 off_t len = iov->iov_len;
1208
1209 uint32_t writtenlen;
1210 int err;
1211
1212 D2(PRINTK("jffs2_fo_write page_start_pos %d\n", pos));
1213 D2(PRINTK("jffs2_fo_write transfer size %d\n", len));
1214
1215 err = jffs2_write_inode_range(c, f, &ri, buf,
1216 pos, len, &writtenlen);
1217 if (err) {
1218 pos += writtenlen;
1219 resid -= writtenlen;
1220
1221 inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
1222 if (pos > inode->i_size)
1223 inode->i_size = pos;
1224
1225 uio->uio_resid = resid;
1226 fp->f_offset = pos;
1227
1228 return -err;
1229 }
1230
1231 if (writtenlen != len) {
1232 pos += writtenlen;
1233 resid -= writtenlen;
1234
1235 inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
1236 if (pos > inode->i_size)
1237 inode->i_size = pos;
1238
1239 uio->uio_resid = resid;
1240 fp->f_offset = pos;
1241
1242 return ENOSPC;
1243 }
1244
1245 pos += len;
1246 resid -= len;
1247 }
1248
1249 // We wrote some data successfully, update the modified and access
1250 // times of the inode, increase its size appropriately, and update
1251 // the file offset and transfer residue.
1252 inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
1253 if (pos > inode->i_size)
1254 inode->i_size = pos;
1255
1256 uio->uio_resid = resid;
1257 fp->f_offset = pos;
1258
1259 return ENOERR;
1260 }
1261 #endif /* CYGOPT_FS_JFFS2_WRITE */
1262
1263 // -------------------------------------------------------------------------
1264 // jffs2_fo_lseek()
1265 // Seek to a new file position.
1266
jffs2_fo_lseek(struct CYG_FILE_TAG * fp,off_t * apos,int whence)1267 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
1268 {
1269 struct _inode *node = (struct _inode *) fp->f_data;
1270 off_t pos = *apos;
1271
1272 D2(PRINTK("jffs2_fo_lseek\n"));
1273
1274 switch (whence) {
1275 case SEEK_SET:
1276 // Pos is already where we want to be.
1277 break;
1278
1279 case SEEK_CUR:
1280 // Add pos to current offset.
1281 pos += fp->f_offset;
1282 break;
1283
1284 case SEEK_END:
1285 // Add pos to file size.
1286 pos += node->i_size;
1287 break;
1288
1289 default:
1290 return EINVAL;
1291 }
1292
1293 if (pos < 0)
1294 return EINVAL;
1295
1296 // All OK, set fp offset and return new position.
1297 *apos = fp->f_offset = pos;
1298
1299 return ENOERR;
1300 }
1301
1302 // -------------------------------------------------------------------------
1303 // jffs2_fo_close()
1304 // Close a file. We just decrement the refcnt and let it go away if
1305 // that is all that is keeping it here.
1306
jffs2_fo_close(struct CYG_FILE_TAG * fp)1307 static int jffs2_fo_close(struct CYG_FILE_TAG *fp)
1308 {
1309 struct _inode *node = (struct _inode *) fp->f_data;
1310
1311 jffs2_dbg(1, "jffs close data: 0x%x\n",fp->f_data);
1312 if (node == NULL) {
1313 return ENOENT;
1314 }
1315 jffs2_iput(node);
1316
1317 fp->f_data = 0;
1318 free(fp);
1319
1320 return ENOERR;
1321 }
1322
1323 //==========================================================================
1324 // Directory operations
1325
1326 // -------------------------------------------------------------------------
1327 // jffs2_fo_dirread()
1328 // Read a single directory entry from a file.
1329
filldir(char * nbuf,int nlen,const unsigned char * name,int namlen)1330 static __inline void filldir(char *nbuf, int nlen, const unsigned char *name, int namlen)
1331 {
1332 int len = nlen < namlen ? nlen : namlen;
1333 (void)memcpy_s(nbuf, nlen, name, len);
1334 nbuf[len] = '\0';
1335 }
1336
jffs2_fo_dirread(struct CYG_FILE_TAG * fp,struct CYG_UIO_TAG * uio)1337 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1338 {
1339 struct _inode *d_inode = (struct _inode *) fp->f_data;
1340 struct jffs2_dirent *ent = (struct jffs2_dirent *) uio->uio_iov[0].iov_base;
1341 char *nbuf = ent->d_name;
1342 int nlen = sizeof(ent->d_name) - 1;
1343 off_t len = uio->uio_iov[0].iov_len;
1344 struct jffs2_inode_info *f;
1345 struct _inode *inode = d_inode;
1346 struct jffs2_full_dirent *fd;
1347 unsigned long offset, curofs;
1348 int found = 1;
1349
1350 jffs2_dbg(1, "read at: 0x%x \n", fp->f_data);
1351
1352 if (len < (off_t)sizeof (struct jffs2_dirent))
1353 return EINVAL;
1354
1355 if (CheckPermission(inode, READ_OP)) {
1356 return EACCES;
1357 }
1358
1359 D1(printk
1360 (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino));
1361
1362 f = JFFS2_INODE_INFO(inode);
1363
1364 offset = fp->f_offset;
1365 if (offset == 0) {
1366 D1(printk
1367 (KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino));
1368 filldir(nbuf, nlen, (const unsigned char *) ".", 1);
1369 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE
1370 // Flags here are the same as jffs2_mkdir. Make sure
1371 // d_type is the same as st_mode of calling stat.
1372 ent->d_type =
1373 jemode_to_cpu(cpu_to_jemode(S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR));
1374 #endif
1375 goto out;
1376 }
1377 if (offset == 1) {
1378 filldir(nbuf, nlen, (const unsigned char *) "..", 2);
1379 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE
1380 // Flags here are the same as jffs2_mkdir. Make sure
1381 // d_type is the same as st_mode of calling stat.
1382 ent->d_type =
1383 jemode_to_cpu(cpu_to_jemode(S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR));
1384 #endif
1385 goto out;
1386 }
1387 curofs = 1;
1388 mutex_lock(&f->sem);
1389 for (fd = f->dents; fd; fd = fd->next) {
1390 curofs++;
1391 /* First loop: curofs = 2; offset = 2 */
1392 if (curofs < offset) {
1393 D2(printk
1394 (KERN_DEBUG
1395 "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
1396 fd->name, fd->ino, fd->type, curofs, offset));
1397 continue;
1398 }
1399 if (!fd->ino) {
1400 D2(printk
1401 (KERN_DEBUG "Skipping deletion dirent \"%s\"\n",
1402 fd->name));
1403 offset++;
1404 continue;
1405 }
1406 D2(printk
1407 (KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset,
1408 fd->name, fd->ino, fd->type));
1409 filldir(nbuf, nlen, fd->name, strlen((char *)fd->name));
1410 ent->d_type = fd->type;
1411 goto out_sem;
1412 }
1413 /* Reached the end of the directory */
1414 found = 0;
1415 out_sem:
1416 mutex_unlock(&f->sem);
1417 if (fd == NULL) {
1418 D2(printk
1419 (KERN_DEBUG "reached the end of the directory\n"));
1420 return ENOENT;
1421 }
1422 out:
1423 fp->f_offset = ++offset;
1424
1425
1426 if (found) {
1427 uio->uio_resid -= sizeof (struct jffs2_dirent);
1428 }
1429 return ENOERR;
1430 }
1431
jffs2_fo_dirlseek(struct CYG_FILE_TAG * fp,off_t * pos,int whence)1432 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
1433 {
1434 // Only allow SEEK_SET to zero
1435 jffs2_dbg(1, "lseekdir at: %d \n", whence);
1436
1437 if (whence != SEEK_SET || *pos != 0)
1438 return EINVAL;
1439
1440 *pos = fp->f_offset = 2;
1441
1442 return ENOERR;
1443 }
1444
1445 //==========================================================================
1446 //
1447 // Called by JFFS2
1448 // ===============
1449 //
1450 //
1451 //==========================================================================
1452
jffs2_gc_fetch_page(struct jffs2_sb_info * c,struct jffs2_inode_info * f,unsigned long offset,unsigned long * priv)1453 unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
1454 struct jffs2_inode_info *f,
1455 unsigned long offset,
1456 unsigned long *priv)
1457 {
1458 /* FIXME: This works only with one file system mounted at a time */
1459 int ret;
1460
1461 ret = jffs2_read_inode_range(c, f, gc_buffer,
1462 offset & ~(PAGE_CACHE_SIZE-1), PAGE_CACHE_SIZE);
1463 if (ret)
1464 return ERR_PTR(ret);
1465
1466 return gc_buffer;
1467 }
1468
jffs2_gc_release_page(struct jffs2_sb_info * c,unsigned char * ptr,unsigned long * priv)1469 void jffs2_gc_release_page(struct jffs2_sb_info *c,
1470 unsigned char *ptr,
1471 unsigned long *priv)
1472 {
1473 /* Do nothing */
1474 }
1475
new_inode(struct super_block * sb)1476 struct _inode *new_inode(struct super_block *sb)
1477 {
1478 struct _inode *inode;
1479 struct _inode *cached_inode;
1480
1481 inode = malloc(sizeof (struct _inode));
1482 if (inode == NULL)
1483 return 0;
1484
1485 D2(PRINTK("malloc new_inode %x ####################################\n",
1486 inode));
1487
1488 (void)memset_s(inode, sizeof (struct _inode), 0, sizeof (struct _inode));
1489 inode->i_sb = sb;
1490 inode->i_ino = 1;
1491 inode->i_count = 1;
1492 inode->i_nlink = 1; // Let JFFS2 manage the link count
1493 inode->i_size = 0;
1494
1495 inode->i_cache_next = NULL; // Newest inode, about to be cached
1496 // Add to the icache
1497 for (cached_inode = sb->s_root; cached_inode != NULL;
1498 cached_inode = cached_inode->i_cache_next) {
1499 if (cached_inode->i_cache_next == NULL) {
1500 cached_inode->i_cache_next = inode; // Current last in cache points to newcomer
1501 inode->i_cache_prev = cached_inode; // Newcomer points back to last
1502 break;
1503 }
1504 }
1505 return inode;
1506 }
1507
ilookup(struct super_block * sb,uint32_t ino)1508 static struct _inode *ilookup(struct super_block *sb, uint32_t ino)
1509 {
1510 struct _inode *inode = NULL;
1511
1512 D2(PRINTK("ilookup\n"));
1513 // Check for this inode in the cache
1514 jffs_lock();
1515 for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) {
1516 if (inode->i_ino == ino) {
1517 inode->i_count++;
1518 break;
1519 }
1520 }
1521 jffs_unlock();
1522 return inode;
1523 }
1524
jffs2_iget(struct super_block * sb,uint32_t ino)1525 struct _inode *jffs2_iget(struct super_block *sb, uint32_t ino)
1526 {
1527 // Called in super.c jffs2_read_super, dir.c jffs2_lookup,
1528 // and gc.c jffs2_garbage_collect_pass
1529
1530 // Must first check for cached inode
1531 // If this fails let new_inode create one
1532
1533 struct _inode *inode;
1534 int err;
1535
1536 D2(PRINTK("jffs2_iget\n"));
1537
1538 jffs_lock();
1539 inode = ilookup(sb, ino);
1540 if (inode) {
1541 jffs_unlock();
1542 return inode;
1543 }
1544
1545 // Not cached, so malloc it
1546
1547 inode = new_inode(sb);
1548 if (inode == NULL) {
1549 jffs_unlock();
1550 return ERR_PTR(-ENOMEM);
1551 }
1552 inode->i_ino = ino;
1553 err = jffs2_read_inode(inode);
1554
1555 if (err) {
1556 PRINTK("jffs2_read_inode() failed\n");
1557 inode->i_nlink = 0; // free _this_ bad inode right now
1558
1559 jffs2_iput(inode);
1560 jffs_unlock();
1561 return ERR_PTR(err);
1562 }
1563
1564 jffs_unlock();
1565 return inode;
1566 }
1567
1568 // -------------------------------------------------------------------------
1569 // Decrement the reference count on an inode. If this makes the ref count
1570 // zero, then this inode can be freed.
1571
jffs2_iput(struct _inode * i)1572 void jffs2_iput(struct _inode *i)
1573 {
1574 // Called in jffs2_find
1575 // (and jffs2_open and jffs2_ops_mkdir?)
1576 // super.c jffs2_read_super,
1577 // and gc.c jffs2_garbage_collect_pass
1578 struct jffs2_inode_info *f = NULL;
1579 struct _inode *temp = NULL;
1580 jffs_lock();
1581 recurse:
1582 if (!i) {
1583 PRINT_ERR("jffs2_iput() called with NULL inode\n");
1584 // and let it fault...
1585 jffs_unlock();
1586 return;
1587 }
1588 i->i_count--;
1589 if (i->i_count < 0)
1590 BUG();
1591
1592 if (i->i_count) {
1593 jffs_unlock();
1594 return;
1595 }
1596
1597 if (!i->i_nlink) {
1598 struct _inode *parent;
1599 // Remove from the icache linked list and free immediately
1600 if (i->i_cache_prev)
1601 i->i_cache_prev->i_cache_next = i->i_cache_next;
1602 if (i->i_cache_next)
1603 i->i_cache_next->i_cache_prev = i->i_cache_prev;
1604 parent = i->i_parent;
1605 jffs2_clear_inode(i);
1606 f = JFFS2_INODE_INFO(i);
1607 (void)mutex_destroy(&(f->sem));
1608 (void)memset_s(i, sizeof(*i), 0x5a, sizeof(*i));
1609 temp = i;
1610 free(i);
1611
1612 if (parent && parent != temp) {
1613 i = parent;
1614 goto recurse;
1615 }
1616
1617 } else {
1618 // Evict some _other_ inode with i_count zero, leaving
1619 // this latest one in the cache for a while
1620 icache_evict(i->i_sb->s_root, i);
1621 }
1622 jffs_unlock();
1623 }
1624
1625
1626 // -------------------------------------------------------------------------
1627 // EOF jffs2.c
1628
1629
jffs2_init_inode_info(struct jffs2_inode_info * f)1630 static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
1631 {
1632 (void)memset_s(f, sizeof(struct jffs2_inode_info), 0, sizeof(struct jffs2_inode_info));
1633 (void)mutex_init(&f->sem);
1634 (void)mutex_lock(&f->sem);
1635 }
1636
jffs2_clear_inode(struct _inode * inode)1637 static void jffs2_clear_inode (struct _inode *inode)
1638 {
1639 /* We can forget about this inode for now - drop all
1640 * the nodelists associated with it, etc.
1641 */
1642 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1643 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1644
1645 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
1646
1647 jffs2_do_clear_inode(c, f);
1648 }
1649
1650
1651 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
1652 fill in the raw_inode while you're at it. */
jffs2_new_inode(struct _inode * dir_i,int mode,struct jffs2_raw_inode * ri)1653 struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri)
1654 {
1655 struct _inode *inode;
1656 struct super_block *sb = dir_i->i_sb;
1657 struct jffs2_sb_info *c;
1658 struct jffs2_inode_info *f;
1659 int ret;
1660
1661 D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode));
1662
1663 c = JFFS2_SB_INFO(sb);
1664
1665 if (CheckPermission(dir_i, WRITE_OP | EXEC_OP)) {
1666 D1(PRINTK("%s, %d, check permission fail\n", __FUNCTION__, __LINE__));
1667 return ERR_PTR(-EACCES);
1668 }
1669
1670 jffs_lock();
1671 inode = new_inode(sb);
1672 if (!inode) {
1673 jffs_unlock();
1674 return ERR_PTR(-ENOMEM);
1675 }
1676
1677 f = JFFS2_INODE_INFO(inode);
1678 jffs2_init_inode_info(f);
1679 (void)memset_s(ri, sizeof(*ri), 0, sizeof(*ri));
1680 /* Set OS-specific defaults for new inodes */
1681 ri->uid = cpu_to_je16(OsCurrUserGet()->effUserID);
1682 ri->gid = cpu_to_je16(OsCurrUserGet()->effGid);
1683 ri->mode = cpu_to_jemode(mode);
1684 ret = jffs2_do_new_inode (c, f, mode, ri);
1685 if (ret) {
1686 // forceful evict: f->sem is locked already, and the
1687 // inode is bad.
1688 if (inode->i_cache_prev)
1689 inode->i_cache_prev->i_cache_next = inode->i_cache_next;
1690 if (inode->i_cache_next)
1691 inode->i_cache_next->i_cache_prev = inode->i_cache_prev;
1692 mutex_unlock(&(f->sem));
1693 jffs2_clear_inode(inode);
1694 (void)mutex_destroy(&(f->sem));
1695 (void)memset_s(inode, sizeof(*inode), 0x6a, sizeof(*inode));
1696 free(inode);
1697 jffs_unlock();
1698 return ERR_PTR(ret);
1699 }
1700 inode->i_nlink = 1;
1701 inode->i_ino = je32_to_cpu(ri->ino);
1702 inode->i_mode = jemode_to_cpu(ri->mode);
1703 inode->i_gid = je16_to_cpu(ri->gid);
1704 inode->i_uid = je16_to_cpu(ri->uid);
1705 inode->i_atime = inode->i_ctime = inode->i_mtime = jffs2_get_timestamp();
1706 ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
1707
1708 inode->i_size = 0;
1709 jffs_unlock();
1710
1711 return inode;
1712 }
1713
1714
jffs2_read_inode(struct _inode * inode)1715 static int jffs2_read_inode (struct _inode *inode)
1716 {
1717 struct jffs2_inode_info *f;
1718 struct jffs2_sb_info *c;
1719 struct jffs2_raw_inode latest_node;
1720 int ret;
1721
1722 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
1723
1724 f = JFFS2_INODE_INFO(inode);
1725 c = JFFS2_SB_INFO(inode->i_sb);
1726
1727 jffs2_init_inode_info(f);
1728
1729 ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
1730
1731 if (ret) {
1732 (void)mutex_unlock(&f->sem);
1733
1734 return ret;
1735 }
1736 inode->i_mode = jemode_to_cpu(latest_node.mode);
1737 inode->i_uid = je16_to_cpu(latest_node.uid);
1738 inode->i_gid = je16_to_cpu(latest_node.gid);
1739 inode->i_size = je32_to_cpu(latest_node.isize);
1740 inode->i_atime = je32_to_cpu(latest_node.atime);
1741 inode->i_mtime = je32_to_cpu(latest_node.mtime);
1742 inode->i_ctime = je32_to_cpu(latest_node.ctime);
1743
1744 inode->i_nlink = f->inocache->pino_nlink;
1745 mutex_unlock(&f->sem);
1746
1747 D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
1748 return 0;
1749 }
1750
1751
jffs2_gc_release_inode(struct jffs2_sb_info * c,struct jffs2_inode_info * f)1752 void jffs2_gc_release_inode(struct jffs2_sb_info *c,
1753 struct jffs2_inode_info *f)
1754 {
1755 jffs2_iput(OFNI_EDONI_2SFFJ(f));
1756 }
1757
jffs2_gc_fetch_inode(struct jffs2_sb_info * c,int inum,int unlinked)1758 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
1759 int inum, int unlinked)
1760 {
1761 struct _inode *inode;
1762 struct jffs2_inode_cache *ic;
1763
1764 if (unlinked) {
1765 /* The inode has zero nlink but its nodes weren't yet marked
1766 obsolete. This has to be because we're still waiting for
1767 the final (close() and) jffs2_iput() to happen.
1768
1769 There's a possibility that the final jffs2_iput() could have
1770 happened while we were contemplating. In order to ensure
1771 that we don't cause a new read_inode() (which would fail)
1772 for the inode in question, we use ilookup() in this case
1773 instead of jffs2_iget().
1774
1775 The nlink can't _become_ zero at this point because we're
1776 holding the alloc_sem, and jffs2_do_unlink() would also
1777 need that while decrementing nlink on any inode.
1778 */
1779 inode = ilookup(OFNI_BS_2SFFJ(c), inum);
1780 if (!inode) {
1781 D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n",
1782 inum));
1783
1784 spin_lock(&c->inocache_lock);
1785 ic = jffs2_get_ino_cache(c, inum);
1786 if (!ic) {
1787 D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum));
1788 spin_unlock(&c->inocache_lock);
1789 return NULL;
1790 }
1791 if (ic->state != INO_STATE_CHECKEDABSENT) {
1792 /* Wait for progress. Don't just loop */
1793 D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n",
1794 ic->ino, ic->state));
1795 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
1796 } else {
1797 spin_unlock(&c->inocache_lock);
1798 }
1799
1800 return NULL;
1801 }
1802 } else {
1803 /* Inode has links to it still; they're not going away because
1804 jffs2_do_unlink() would need the alloc_sem and we have it.
1805 Just jffs2_iget() it, and if read_inode() is necessary that's OK.
1806 */
1807 inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
1808 if (IS_ERR(inode))
1809 return (void *)inode;
1810 }
1811
1812 return JFFS2_INODE_INFO(inode);
1813 }
jffs_check_path(const char * path)1814 static int jffs_check_path(const char *path)
1815 {
1816 int n = 0;
1817 int divs = 0;
1818 while (*path && n < NAME_MAX && divs < 100) { // File depth cannot exceed 100
1819 if (jffsfs_IsPathDivider(*path)) {
1820 n = 0;
1821 divs++;
1822 } else
1823 n++;
1824 path++;
1825 }
1826 return (*path) ? -1 : 0;
1827 }
1828
jffs2_oflag_to_accmode(int oflags)1829 int jffs2_oflag_to_accmode(int oflags)
1830 {
1831 /* regular file operations */
1832 int acc_mode = 0;
1833 if ((oflags & O_ACCMODE) == O_RDONLY) {
1834 acc_mode |= READ_OP;
1835 }
1836
1837 if (oflags & O_WRONLY) {
1838 acc_mode |= WRITE_OP;
1839 }
1840
1841 if (oflags & O_RDWR) {
1842 acc_mode |= READ_OP | WRITE_OP;
1843 }
1844
1845 /* Opens the file, if it is existing. If not, a new file is created. */
1846 if (oflags & O_CREAT) {
1847 acc_mode |= WRITE_OP;
1848 }
1849
1850 /* Creates a new file. If the file is existing, it is truncated and overwritten. */
1851 if (oflags & O_TRUNC) {
1852 acc_mode |= WRITE_OP;
1853 }
1854
1855 /* Creates a new file. The function fails if the file is already existing. */
1856 if (oflags & O_EXCL) {
1857 acc_mode |= WRITE_OP;
1858 }
1859
1860 if (oflags & O_APPEND) {
1861 acc_mode |= WRITE_OP;
1862 }
1863
1864 /* mark for executing operation */
1865 if (oflags & O_EXECVE) {
1866 acc_mode |= EXEC_OP;
1867 }
1868
1869 return acc_mode;
1870 }
1871
CheckPermission(struct _inode * node,int accMode)1872 static unsigned int CheckPermission(struct _inode *node, int accMode)
1873 {
1874 uint uid = OsCurrUserGet()->effUserID;
1875 mode_t file_mode = node->i_mode;
1876
1877 if (uid == node->i_uid) {
1878 file_mode >>= JFFS2_USER_SHFIT;
1879 } else if (LOS_CheckInGroups(node->i_gid)) {
1880 file_mode >>= JFFS2_GROUP_SHFIT;
1881 }
1882
1883 file_mode &= JFFS2_MODE_ALL;
1884
1885 if ((accMode & file_mode) == accMode) {
1886 return 0;
1887 }
1888
1889 file_mode = 0;
1890 if (S_ISDIR(node->i_mode)) {
1891 if ((accMode & EXEC_OP) && (IsCapPermit(CAP_DAC_READ_SEARCH))) {
1892 file_mode |= EXEC_OP;
1893 }
1894 } else {
1895 if ((accMode & EXEC_OP) && (IsCapPermit(CAP_DAC_EXECUTE)) && (node->i_mode & S_IXUGO)) {
1896 file_mode |= EXEC_OP;
1897 }
1898 }
1899
1900 if ((accMode & WRITE_OP) && IsCapPermit(CAP_DAC_WRITE)) {
1901 file_mode |= WRITE_OP;
1902 }
1903
1904 if ((accMode & READ_OP) && IsCapPermit(CAP_DAC_READ_SEARCH)) {
1905 file_mode |= READ_OP;
1906 }
1907
1908 if ((accMode & file_mode) == accMode) {
1909 return 0;
1910 }
1911
1912 D1(PRINTK("%s, %d, permission check fail,uid %d, gid %d, mode %d, accMode %d, cuid %d\n",
1913 __FUNCTION__, __LINE__, node->i_uid, node->i_gid, (node->i_mode) & UMASK_FULL, accMode, uid));
1914
1915 return 1;
1916 }
1917
check_to_setattr(struct jffs2_raw_inode * ri,struct jffs2_inode_info * f,const struct _inode * node,iattr * attr)1918 static int check_to_setattr(struct jffs2_raw_inode *ri, struct jffs2_inode_info *f,
1919 const struct _inode *node, iattr *attr)
1920 {
1921 unsigned int valid;
1922 mode_t tmp_mode;
1923 uint c_uid = OsCurrUserGet()->effUserID;
1924 uint c_gid = OsCurrUserGet()->effGid;
1925
1926 valid = attr->attr_chg_valid;
1927 ri->uid = cpu_to_je16(node->i_uid);
1928 ri->gid = cpu_to_je16(node->i_gid);
1929 tmp_mode = node->i_mode;
1930 if (valid & CHG_UID) {
1931 if (((c_uid != node->i_uid) || (attr->attr_chg_uid != node->i_uid)) && (!IsCapPermit(CAP_CHOWN))) {
1932 return -EPERM;
1933 } else {
1934 ri->uid = cpu_to_je16(attr->attr_chg_uid);
1935 }
1936 }
1937
1938 if (valid & CHG_GID) {
1939 if (((c_gid != node->i_gid) || (attr->attr_chg_gid != node->i_gid)) && (!IsCapPermit(CAP_CHOWN))) {
1940 return -EPERM;
1941 } else {
1942 ri->gid = cpu_to_je16(attr->attr_chg_gid);
1943 }
1944 }
1945
1946 if (valid & CHG_MODE) {
1947 if (!IsCapPermit(CAP_FOWNER) && (c_uid != node->i_uid)) {
1948 return -EPERM;
1949 } else {
1950 attr->attr_chg_mode &= ~S_IFMT; // delete file type
1951 tmp_mode &= S_IFMT;
1952 tmp_mode = attr->attr_chg_mode | tmp_mode; // add old file type
1953 }
1954 }
1955 ri->mode = cpu_to_jemode(tmp_mode);
1956 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
1957 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
1958 ri->totlen = cpu_to_je32(sizeof(*ri));
1959 ri->hdr_crc = cpu_to_je32(crc32(0, ri, (sizeof(struct jffs2_unknown_node)-4)));
1960 ri->ino = cpu_to_je32(node->i_ino);
1961 ri->version = cpu_to_je32(++f->highest_version);
1962 ri->isize = cpu_to_je32((uint32_t)node->i_size);
1963 ri->atime = cpu_to_je32(node->i_atime);
1964 ri->mtime = cpu_to_je32(jffs2_get_timestamp());
1965 ri->offset = cpu_to_je32(0);
1966 ri->csize = ri->dsize = cpu_to_je32(0);
1967 ri->compr = JFFS2_COMPR_NONE;
1968 ri->node_crc = cpu_to_je32(crc32(0, ri, (sizeof(*ri)-8)));
1969 ri->data_crc = cpu_to_je32(0);
1970 return 0;
1971 }
1972
jffs2_chattr(struct _inode * dir_i,const unsigned char * d_name,iattr * attr,struct _inode * node_old)1973 int jffs2_chattr (struct _inode *dir_i, const unsigned char *d_name, iattr *attr, struct _inode *node_old)
1974 {
1975 struct jffs2_inode_info *f = NULL;
1976 struct jffs2_sb_info *c = NULL;
1977 struct jffs2_raw_inode *ri = NULL;
1978 struct jffs2_full_dnode *new_metadata = NULL;
1979 struct jffs2_full_dnode *old_metadata = NULL;
1980 uint32_t alloclen;
1981 int ret;
1982 ri = jffs2_alloc_raw_inode();
1983 if (!ri) {
1984 set_errno(ENOMEM);
1985 return -ENOMEM;
1986 }
1987 c = JFFS2_SB_INFO(dir_i->i_sb);
1988 /* Try to reserve enough space for both node and dirent.
1989 * Just the node will do for now, though
1990 */
1991 ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
1992 if (ret) {
1993 jffs2_free_raw_inode(ri);
1994 return ret;
1995 }
1996
1997 f = JFFS2_INODE_INFO(node_old);
1998 mutex_lock(&f->sem);
1999 ret = check_to_setattr(ri, f, node_old, attr);
2000
2001 if (ret < 0) {
2002 set_errno(-ret);
2003 goto errout;
2004 }
2005 new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
2006 if (IS_ERR(new_metadata)) {
2007 ret = PTR_ERR(new_metadata);
2008 set_errno(-ret);
2009 goto errout;
2010 }
2011 node_old->i_atime = je32_to_cpu(ri->atime);
2012 node_old->i_ctime = je32_to_cpu(ri->ctime);
2013 node_old->i_mtime = je32_to_cpu(ri->mtime);
2014 node_old->i_mode = jemode_to_cpu(ri->mode);
2015 node_old->i_uid = je16_to_cpu(ri->uid);
2016 node_old->i_gid = je16_to_cpu(ri->gid);
2017
2018 old_metadata = f->metadata;
2019 f->metadata = new_metadata;
2020 if (old_metadata) {
2021 jffs2_mark_node_obsolete(c, old_metadata->raw);
2022 jffs2_free_full_dnode(old_metadata);
2023 }
2024 jffs2_complete_reservation(c);
2025 jffs2_free_raw_inode(ri);
2026 mutex_unlock(&f->sem);
2027 return 0;
2028 errout:
2029 jffs2_complete_reservation(c);
2030 jffs2_free_raw_inode(ri);
2031 mutex_unlock(&f->sem);
2032 return ret;
2033 }
2034
2035 struct los_jffs2_operations jffs2_dir_operations = {
2036 .opendir = jffs2_opendir,
2037 .lseekdir = jffs2_fo_dirlseek,
2038 .readdir = jffs2_fo_dirread,
2039
2040 };
2041
2042 struct los_jffs2_operations jffs2_fs_type = {
2043 .mount = jffs2_mount,
2044 .stat = jffs2_stat,
2045 .umount = jffs2_umount
2046 };
2047
2048
2049 struct los_jffs2_operations jffs2_file_operations = {
2050 .open = jffs2_open,
2051 .close = jffs2_fo_close,
2052 .read = jffs2_fo_read,
2053 .write = jffs2_fo_write,
2054 .lseek = jffs2_fo_lseek,
2055 .chattr = jffs2_fo_chattr
2056 };
2057
2058 struct los_jffs2_operations jffs2_dir_inode_operations = {
2059 .mkdir = jffs2_ops_mkdir,
2060 .rmdir = jffs2_ops_rmdir,
2061 .unlink = jffs2_ops_unlink,
2062 .rename = jffs2_ops_rename,
2063 };
2064