2 * ramfs.c - a malloc based filesystem
4 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <linux/stat.h>
33 #define CHUNK_SIZE 512
37 struct ramfs_chunk
*next
;
42 struct ramfs_inode
*parent
;
43 struct ramfs_inode
*next
;
44 struct ramfs_inode
*child
;
47 struct handle_d
*handle
;
50 struct ramfs_chunk
*data
;
54 struct ramfs_inode root
;
57 /* ---------------------------------------------------------------*/
58 static struct ramfs_inode
* lookup(struct ramfs_inode
*node
, const char *name
)
60 debug("lookup: %s in %p\n",name
, node
);
61 if(!S_ISDIR(node
->mode
))
69 debug("lookup: %s\n", node
->name
);
70 if (!strcmp(node
->name
, name
)) {
71 debug("lookup: found: 0x%p\n",node
);
79 static struct ramfs_inode
* rlookup(struct ramfs_priv
*priv
, const char *path
)
81 struct ramfs_inode
*node
= &priv
->root
;
85 debug("rlookup %s in %p\n",path
, node
);
88 part
= strtok(buf
, "/");
93 node
= lookup(node
, part
);
96 part
= strtok(NULL
, "/");
104 static struct ramfs_inode
* rlookup_parent(struct ramfs_priv
*priv
, const char *pathname
, char **file
)
107 struct ramfs_inode
*node
;
110 path
= strdup(pathname
);
112 if ((*file
= strrchr((char *) pathname
, '/'))) {
116 tmp
= strrchr(path
, '/');
118 node
= rlookup(priv
, path
);
124 *file
= (char *)pathname
;
133 static int chunks
= 0;
135 static struct ramfs_chunk
*ramfs_get_chunk(void)
137 struct ramfs_chunk
*data
= malloc(sizeof(struct ramfs_chunk
));
141 data
->data
= malloc(CHUNK_SIZE
);
152 static void ramfs_put_chunk(struct ramfs_chunk
*data
)
159 static struct ramfs_inode
* ramfs_get_inode(void)
161 struct ramfs_inode
*node
= xzalloc(sizeof(struct ramfs_inode
));
165 static void ramfs_put_inode(struct ramfs_inode
*node
)
167 struct ramfs_chunk
*data
= node
->data
;
170 struct ramfs_chunk
*tmp
= data
->next
;
171 ramfs_put_chunk(data
);
179 static struct ramfs_inode
* node_insert(struct ramfs_inode
*parent_node
, const char *filename
, ulong mode
)
181 struct ramfs_inode
*node
, *new_node
= ramfs_get_inode();
182 new_node
->name
= strdup(filename
);
183 new_node
->mode
= mode
;
185 node
= parent_node
->child
;
188 struct ramfs_inode
*n
= ramfs_get_inode();
189 n
->name
= strdup(".");
190 n
->mode
= S_IFDIR
| S_IRWXU
| S_IRWXG
| S_IRWXO
;
192 n
->parent
= new_node
;
194 n
= ramfs_get_inode();
195 n
->name
= strdup("..");
196 n
->mode
= S_IFDIR
| S_IRWXU
| S_IRWXG
| S_IRWXO
;
197 n
->parent
= new_node
;
198 n
->child
= parent_node
->child
;
199 new_node
->child
->next
= n
;
205 node
->next
= new_node
;
209 /* ---------------------------------------------------------------*/
211 static int ramfs_create(struct device_d
*dev
, const char *pathname
, mode_t mode
)
213 struct ramfs_priv
*priv
= dev
->priv
;
214 struct ramfs_inode
*node
;
217 node
= rlookup_parent(priv
, pathname
, &file
);
219 node_insert(node
, file
, mode
);
225 static int ramfs_unlink(struct device_d
*dev
, const char *pathname
)
227 struct ramfs_priv
*priv
= dev
->priv
;
228 struct ramfs_inode
*node
, *lastnode
;
231 node
= rlookup_parent(priv
, pathname
, &file
);
233 lastnode
= node
->child
->next
;
234 node
= lastnode
->next
;
237 if (!strcmp(node
->name
, file
)) {
238 struct ramfs_inode
*tmp
;
240 lastnode
->next
= node
->next
;
241 ramfs_put_inode(tmp
);
250 static int ramfs_mkdir(struct device_d
*dev
, const char *pathname
)
252 return ramfs_create(dev
, pathname
, S_IFDIR
| S_IRWXU
| S_IRWXG
| S_IRWXO
);
255 static int ramfs_rmdir(struct device_d
*dev
, const char *pathname
)
257 struct ramfs_priv
*priv
= dev
->priv
;
258 struct ramfs_inode
*node
, *lastnode
;
261 node
= rlookup_parent(priv
, pathname
, &file
);
263 lastnode
= node
->child
->next
;
264 node
= lastnode
->next
;
267 if (!strcmp(node
->name
, file
)) {
268 struct ramfs_inode
*tmp
;
270 lastnode
->next
= node
->next
;
271 ramfs_put_inode(tmp
->child
->next
);
272 ramfs_put_inode(tmp
->child
);
273 ramfs_put_inode(tmp
);
282 static int ramfs_open(struct device_d
*dev
, FILE *file
, const char *filename
)
284 struct ramfs_priv
*priv
= dev
->priv
;
285 struct ramfs_inode
*node
= rlookup(priv
, filename
);
290 file
->size
= node
->size
;
295 static int ramfs_close(struct device_d
*dev
, FILE *f
)
300 static int ramfs_read(struct device_d
*_dev
, FILE *f
, void *buf
, size_t insize
)
302 struct ramfs_inode
*node
= (struct ramfs_inode
*)f
->inode
;
304 struct ramfs_chunk
*data
;
310 chunk
= f
->pos
/ CHUNK_SIZE
;
311 debug("%s: reading from chunk %d\n", __FUNCTION__
, chunk
);
313 /* Position ourself in stream */
319 ofs
= f
->pos
% CHUNK_SIZE
;
321 /* Read till end of current chunk */
323 now
= min(size
, CHUNK_SIZE
- ofs
);
324 debug("Reading till end of node. size: %d\n", size
);
325 memcpy(buf
, data
->data
+ ofs
, now
);
329 if (pos
> node
->size
)
335 while (size
>= CHUNK_SIZE
) {
336 debug("do full chunk. size: %d\n", size
);
337 memcpy(buf
, data
->data
, CHUNK_SIZE
);
346 debug("do rest. size: %d\n", size
);
347 memcpy(buf
, data
->data
, size
);
353 static int ramfs_write(struct device_d
*_dev
, FILE *f
, const void *buf
, size_t insize
)
355 struct ramfs_inode
*node
= (struct ramfs_inode
*)f
->inode
;
357 struct ramfs_chunk
*data
;
363 chunk
= f
->pos
/ CHUNK_SIZE
;
364 debug("%s: writing to chunk %d\n", __FUNCTION__
, chunk
);
366 /* Position ourself in stream */
372 ofs
= f
->pos
% CHUNK_SIZE
;
374 /* Write till end of current chunk */
376 now
= min(size
, CHUNK_SIZE
- ofs
);
377 debug("writing till end of node. size: %d\n", size
);
378 memcpy(data
->data
+ ofs
, buf
, now
);
382 if (pos
> node
->size
)
388 while (size
>= CHUNK_SIZE
) {
389 debug("do full chunk. size: %d\n", size
);
390 memcpy(data
->data
, buf
, CHUNK_SIZE
);
399 debug("do rest. size: %d\n", size
);
400 memcpy(data
->data
, buf
, size
);
406 static off_t
ramfs_lseek(struct device_d
*dev
, FILE *f
, off_t pos
)
412 static int ramfs_truncate(struct device_d
*dev
, FILE *f
, ulong size
)
414 struct ramfs_inode
*node
= (struct ramfs_inode
*)f
->inode
;
415 int oldchunks
, newchunks
;
416 struct ramfs_chunk
*data
= node
->data
;
418 newchunks
= (size
+ CHUNK_SIZE
- 1) / CHUNK_SIZE
;
419 oldchunks
= (node
->size
+ CHUNK_SIZE
- 1) / CHUNK_SIZE
;
421 if (newchunks
< oldchunks
) {
427 struct ramfs_chunk
*tmp
;
429 ramfs_put_chunk(data
);
434 if (newchunks
> oldchunks
) {
436 node
->data
= ramfs_get_chunk();
448 while (newchunks
--) {
449 data
->next
= ramfs_get_chunk();
459 static DIR* ramfs_opendir(struct device_d
*dev
, const char *pathname
)
462 struct ramfs_priv
*priv
= dev
->priv
;
463 struct ramfs_inode
*node
;
465 debug("opendir: %s\n", pathname
);
467 node
= rlookup(priv
, pathname
);
472 if (!S_ISDIR(node
->mode
))
475 dir
= xmalloc(sizeof(DIR));
477 dir
->priv
= node
->child
;
482 static struct dirent
* ramfs_readdir(struct device_d
*dev
, DIR *dir
)
484 struct ramfs_inode
*node
= dir
->priv
;
487 strcpy(dir
->d
.d_name
, node
->name
);
488 dir
->priv
= node
->next
;
494 static int ramfs_closedir(struct device_d
*dev
, DIR *dir
)
500 static int ramfs_stat(struct device_d
*dev
, const char *filename
, struct stat
*s
)
502 struct ramfs_priv
*priv
= dev
->priv
;
503 struct ramfs_inode
*node
= rlookup(priv
, filename
);
508 s
->st_size
= node
->size
;
509 s
->st_mode
= node
->mode
;
514 static int ramfs_probe(struct device_d
*dev
)
516 struct ramfs_inode
*n
;
517 struct ramfs_priv
*priv
= xzalloc(sizeof(struct ramfs_priv
));
521 priv
->root
.name
= "/";
522 priv
->root
.mode
= S_IFDIR
| S_IRWXU
| S_IRWXG
| S_IRWXO
;
523 priv
->root
.parent
= &priv
->root
;
524 n
= ramfs_get_inode();
525 n
->name
= strdup(".");
527 n
->parent
= &priv
->root
;
529 priv
->root
.child
= n
;
530 n
= ramfs_get_inode();
531 n
->name
= strdup("..");
532 n
->mode
= S_IFDIR
| S_IRWXU
| S_IRWXG
| S_IRWXO
;
533 n
->parent
= &priv
->root
;
534 n
->child
= priv
->root
.child
;
535 priv
->root
.child
->next
= n
;
540 static void ramfs_remove(struct device_d
*dev
)
545 static struct fs_driver_d ramfs_driver
= {
546 .type
= FS_TYPE_RAMFS
,
547 .create
= ramfs_create
,
548 .unlink
= ramfs_unlink
,
550 .close
= ramfs_close
,
551 .truncate
= ramfs_truncate
,
553 .write
= ramfs_write
,
554 .lseek
= ramfs_lseek
,
555 .mkdir
= ramfs_mkdir
,
556 .rmdir
= ramfs_rmdir
,
557 .opendir
= ramfs_opendir
,
558 .readdir
= ramfs_readdir
,
559 .closedir
= ramfs_closedir
,
561 .flags
= FS_DRIVER_NO_DEV
,
563 .probe
= ramfs_probe
,
564 .remove
= ramfs_remove
,
566 .type_data
= &ramfs_driver
,
570 static int ramfs_init(void)
572 return register_fs_driver(&ramfs_driver
);
575 coredevice_initcall(ramfs_init
);