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