blob: 1e6fc37998768faf3539d31fd8960e7d9404e3f4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 *
5 * Ported the filesystem routines to 2.5.
6 * 2003-02-10 Petr Baudis <pasky@ucw.cz>
7 */
8
9#include <linux/stddef.h>
10#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/pagemap.h>
15#include <linux/blkdev.h>
16#include <linux/list.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/statfs.h>
18#include <linux/kdev_t.h>
19#include <asm/uaccess.h>
20#include "hostfs.h"
21#include "kern_util.h"
22#include "kern.h"
23#include "user_util.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include "init.h"
25
26struct hostfs_inode_info {
27 char *host_filename;
28 int fd;
29 int mode;
30 struct inode vfs_inode;
31};
32
33static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
34{
35 return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
36}
37
Josef Sipek680b0da2006-12-08 02:37:05 -080038#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40int hostfs_d_delete(struct dentry *dentry)
41{
42 return(1);
43}
44
45struct dentry_operations hostfs_dentry_ops = {
46 .d_delete = hostfs_d_delete,
47};
48
49/* Changed in hostfs_args before the kernel starts running */
50static char *root_ino = "/";
51static int append = 0;
52
53#define HOSTFS_SUPER_MAGIC 0x00c0ffee
54
55static struct inode_operations hostfs_iops;
56static struct inode_operations hostfs_dir_iops;
Christoph Hellwigf5e54d62006-06-28 04:26:44 -070057static const struct address_space_operations hostfs_link_aops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59#ifndef MODULE
60static int __init hostfs_args(char *options, int *add)
61{
62 char *ptr;
63
64 ptr = strchr(options, ',');
65 if(ptr != NULL)
66 *ptr++ = '\0';
67 if(*options != '\0')
68 root_ino = options;
69
70 options = ptr;
71 while(options){
72 ptr = strchr(options, ',');
73 if(ptr != NULL)
74 *ptr++ = '\0';
75 if(*options != '\0'){
76 if(!strcmp(options, "append"))
77 append = 1;
78 else printf("hostfs_args - unsupported option - %s\n",
79 options);
80 }
81 options = ptr;
82 }
83 return(0);
84}
85
86__uml_setup("hostfs=", hostfs_args,
87"hostfs=<root dir>,<flags>,...\n"
88" This is used to set hostfs parameters. The root directory argument\n"
89" is used to confine all hostfs mounts to within the specified directory\n"
90" tree on the host. If this isn't specified, then a user inside UML can\n"
91" mount anything on the host that's accessible to the user that's running\n"
92" it.\n"
93" The only flag currently supported is 'append', which specifies that all\n"
94" files opened by hostfs will be opened in append mode.\n\n"
95);
96#endif
97
98static char *dentry_name(struct dentry *dentry, int extra)
99{
100 struct dentry *parent;
101 char *root, *name;
102 int len;
103
104 len = 0;
105 parent = dentry;
106 while(parent->d_parent != parent){
107 len += parent->d_name.len + 1;
108 parent = parent->d_parent;
109 }
110
111 root = HOSTFS_I(parent->d_inode)->host_filename;
112 len += strlen(root);
113 name = kmalloc(len + extra + 1, GFP_KERNEL);
114 if(name == NULL) return(NULL);
115
116 name[len] = '\0';
117 parent = dentry;
118 while(parent->d_parent != parent){
119 len -= parent->d_name.len + 1;
120 name[len] = '/';
121 strncpy(&name[len + 1], parent->d_name.name,
122 parent->d_name.len);
123 parent = parent->d_parent;
124 }
125 strncpy(name, root, strlen(root));
126 return(name);
127}
128
129static char *inode_name(struct inode *ino, int extra)
130{
131 struct dentry *dentry;
132
133 dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
134 return(dentry_name(dentry, extra));
135}
136
137static int read_name(struct inode *ino, char *name)
138{
139 /* The non-int inode fields are copied into ints by stat_file and
140 * then copied into the inode because passing the actual pointers
141 * in and having them treated as int * breaks on big-endian machines
142 */
143 int err;
144 int i_mode, i_nlink, i_blksize;
145 unsigned long long i_size;
146 unsigned long long i_ino;
147 unsigned long long i_blocks;
148
149 err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
150 &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
151 &ino->i_ctime, &i_blksize, &i_blocks);
152 if(err)
153 return(err);
154
155 ino->i_ino = i_ino;
156 ino->i_mode = i_mode;
157 ino->i_nlink = i_nlink;
158 ino->i_size = i_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 ino->i_blocks = i_blocks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 return(0);
161}
162
163static char *follow_link(char *link)
164{
165 int len, n;
166 char *name, *resolved, *end;
167
168 len = 64;
169 while(1){
170 n = -ENOMEM;
171 name = kmalloc(len, GFP_KERNEL);
172 if(name == NULL)
173 goto out;
174
175 n = do_readlink(link, name, len);
176 if(n < len)
177 break;
178 len *= 2;
179 kfree(name);
180 }
181 if(n < 0)
182 goto out_free;
183
184 if(*name == '/')
185 return(name);
186
187 end = strrchr(link, '/');
188 if(end == NULL)
189 return(name);
190
191 *(end + 1) = '\0';
192 len = strlen(link) + strlen(name) + 1;
193
194 resolved = kmalloc(len, GFP_KERNEL);
195 if(resolved == NULL){
196 n = -ENOMEM;
197 goto out_free;
198 }
199
200 sprintf(resolved, "%s%s", link, name);
201 kfree(name);
202 kfree(link);
203 return(resolved);
204
205 out_free:
206 kfree(name);
207 out:
208 return(ERR_PTR(n));
209}
210
211static int read_inode(struct inode *ino)
212{
213 char *name;
214 int err = 0;
215
216 /* Unfortunately, we are called from iget() when we don't have a dentry
217 * allocated yet.
218 */
219 if(list_empty(&ino->i_dentry))
220 goto out;
221
222 err = -ENOMEM;
223 name = inode_name(ino, 0);
224 if(name == NULL)
225 goto out;
226
227 if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){
228 name = follow_link(name);
229 if(IS_ERR(name)){
230 err = PTR_ERR(name);
231 goto out;
232 }
233 }
234
235 err = read_name(ino, name);
236 kfree(name);
237 out:
238 return(err);
239}
240
David Howells726c3342006-06-23 02:02:58 -0700241int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242{
243 /* do_statfs uses struct statfs64 internally, but the linux kernel
244 * struct statfs still has 32-bit versions for most of these fields,
245 * so we convert them here
246 */
247 int err;
248 long long f_blocks;
249 long long f_bfree;
250 long long f_bavail;
251 long long f_files;
252 long long f_ffree;
253
David Howells726c3342006-06-23 02:02:58 -0700254 err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
256 &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
257 &sf->f_namelen, sf->f_spare);
258 if(err) return(err);
259 sf->f_blocks = f_blocks;
260 sf->f_bfree = f_bfree;
261 sf->f_bavail = f_bavail;
262 sf->f_files = f_files;
263 sf->f_ffree = f_ffree;
264 sf->f_type = HOSTFS_SUPER_MAGIC;
265 return(0);
266}
267
268static struct inode *hostfs_alloc_inode(struct super_block *sb)
269{
270 struct hostfs_inode_info *hi;
271
272 hi = kmalloc(sizeof(*hi), GFP_KERNEL);
273 if(hi == NULL)
274 return(NULL);
275
276 *hi = ((struct hostfs_inode_info) { .host_filename = NULL,
277 .fd = -1,
278 .mode = 0 });
279 inode_init_once(&hi->vfs_inode);
280 return(&hi->vfs_inode);
281}
282
283static void hostfs_delete_inode(struct inode *inode)
284{
Mark Fashehfef26652005-09-09 13:01:31 -0700285 truncate_inode_pages(&inode->i_data, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 if(HOSTFS_I(inode)->fd != -1) {
287 close_file(&HOSTFS_I(inode)->fd);
288 HOSTFS_I(inode)->fd = -1;
289 }
290 clear_inode(inode);
291}
292
293static void hostfs_destroy_inode(struct inode *inode)
294{
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800295 kfree(HOSTFS_I(inode)->host_filename);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297 /*XXX: This should not happen, probably. The check is here for
298 * additional safety.*/
299 if(HOSTFS_I(inode)->fd != -1) {
300 close_file(&HOSTFS_I(inode)->fd);
301 printk(KERN_DEBUG "Closing host fd in .destroy_inode\n");
302 }
303
304 kfree(HOSTFS_I(inode));
305}
306
307static void hostfs_read_inode(struct inode *inode)
308{
309 read_inode(inode);
310}
311
312static struct super_operations hostfs_sbops = {
313 .alloc_inode = hostfs_alloc_inode,
314 .drop_inode = generic_delete_inode,
315 .delete_inode = hostfs_delete_inode,
316 .destroy_inode = hostfs_destroy_inode,
317 .read_inode = hostfs_read_inode,
318 .statfs = hostfs_statfs,
319};
320
321int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
322{
323 void *dir;
324 char *name;
325 unsigned long long next, ino;
326 int error, len;
327
Josef Sipek680b0da2006-12-08 02:37:05 -0800328 name = dentry_name(file->f_path.dentry, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if(name == NULL) return(-ENOMEM);
330 dir = open_dir(name, &error);
331 kfree(name);
332 if(dir == NULL) return(-error);
333 next = file->f_pos;
334 while((name = read_dir(dir, &next, &ino, &len)) != NULL){
335 error = (*filldir)(ent, name, len, file->f_pos,
336 ino, DT_UNKNOWN);
337 if(error) break;
338 file->f_pos = next;
339 }
340 close_dir(dir);
341 return(0);
342}
343
344int hostfs_file_open(struct inode *ino, struct file *file)
345{
346 char *name;
347 int mode = 0, r = 0, w = 0, fd;
348
349 mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
350 if((mode & HOSTFS_I(ino)->mode) == mode)
351 return(0);
352
353 /* The file may already have been opened, but with the wrong access,
354 * so this resets things and reopens the file with the new access.
355 */
356 if(HOSTFS_I(ino)->fd != -1){
357 close_file(&HOSTFS_I(ino)->fd);
358 HOSTFS_I(ino)->fd = -1;
359 }
360
361 HOSTFS_I(ino)->mode |= mode;
362 if(HOSTFS_I(ino)->mode & FMODE_READ)
363 r = 1;
364 if(HOSTFS_I(ino)->mode & FMODE_WRITE)
365 w = 1;
366 if(w)
367 r = 1;
368
Josef Sipek680b0da2006-12-08 02:37:05 -0800369 name = dentry_name(file->f_path.dentry, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 if(name == NULL)
371 return(-ENOMEM);
372
373 fd = open_file(name, r, w, append);
374 kfree(name);
375 if(fd < 0) return(fd);
376 FILE_HOSTFS_I(file)->fd = fd;
377
378 return(0);
379}
380
381int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
382{
Paolo 'Blaisorblade' Giarrussoa2d76bd2005-07-28 21:16:15 -0700383 return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384}
385
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800386static const struct file_operations hostfs_file_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 .llseek = generic_file_llseek,
Badari Pulavarty543ade12006-09-30 23:28:48 -0700388 .read = do_sync_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 .sendfile = generic_file_sendfile,
390 .aio_read = generic_file_aio_read,
391 .aio_write = generic_file_aio_write,
Badari Pulavarty543ade12006-09-30 23:28:48 -0700392 .write = do_sync_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 .mmap = generic_file_mmap,
394 .open = hostfs_file_open,
395 .release = NULL,
396 .fsync = hostfs_fsync,
397};
398
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800399static const struct file_operations hostfs_dir_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 .llseek = generic_file_llseek,
401 .readdir = hostfs_readdir,
402 .read = generic_read_dir,
403};
404
405int hostfs_writepage(struct page *page, struct writeback_control *wbc)
406{
407 struct address_space *mapping = page->mapping;
408 struct inode *inode = mapping->host;
409 char *buffer;
410 unsigned long long base;
411 int count = PAGE_CACHE_SIZE;
412 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
413 int err;
414
415 if (page->index >= end_index)
416 count = inode->i_size & (PAGE_CACHE_SIZE-1);
417
418 buffer = kmap(page);
419 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
420
421 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
422 if(err != count){
423 ClearPageUptodate(page);
424 goto out;
425 }
426
427 if (base > inode->i_size)
428 inode->i_size = base;
429
430 if (PageError(page))
431 ClearPageError(page);
432 err = 0;
433
434 out:
435 kunmap(page);
436
437 unlock_page(page);
438 return err;
439}
440
441int hostfs_readpage(struct file *file, struct page *page)
442{
443 char *buffer;
444 long long start;
445 int err = 0;
446
447 start = (long long) page->index << PAGE_CACHE_SHIFT;
448 buffer = kmap(page);
449 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
450 PAGE_CACHE_SIZE);
451 if(err < 0) goto out;
452
453 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
454
455 flush_dcache_page(page);
456 SetPageUptodate(page);
457 if (PageError(page)) ClearPageError(page);
458 err = 0;
459 out:
460 kunmap(page);
461 unlock_page(page);
462 return(err);
463}
464
465int hostfs_prepare_write(struct file *file, struct page *page,
466 unsigned int from, unsigned int to)
467{
468 char *buffer;
469 long long start, tmp;
470 int err;
471
472 start = (long long) page->index << PAGE_CACHE_SHIFT;
473 buffer = kmap(page);
474 if(from != 0){
475 tmp = start;
476 err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
477 from);
478 if(err < 0) goto out;
479 }
480 if(to != PAGE_CACHE_SIZE){
481 start += to;
482 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
483 PAGE_CACHE_SIZE - to);
484 if(err < 0) goto out;
485 }
486 err = 0;
487 out:
488 kunmap(page);
489 return(err);
490}
491
492int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
493 unsigned to)
494{
495 struct address_space *mapping = page->mapping;
496 struct inode *inode = mapping->host;
497 char *buffer;
498 long long start;
499 int err = 0;
500
Paolo 'Blaisorblade' Giarrusso30f04a42005-12-29 17:39:57 +0100501 start = (((long long) page->index) << PAGE_CACHE_SHIFT) + from;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 buffer = kmap(page);
503 err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
504 to - from);
505 if(err > 0) err = 0;
Paolo 'Blaisorblade' Giarrusso30f04a42005-12-29 17:39:57 +0100506
507 /* Actually, if !err, write_file has added to-from to start, so, despite
508 * the appearance, we are comparing i_size against the _last_ written
509 * location, as we should. */
510
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 if(!err && (start > inode->i_size))
512 inode->i_size = start;
513
514 kunmap(page);
515 return(err);
516}
517
Christoph Hellwigf5e54d62006-06-28 04:26:44 -0700518static const struct address_space_operations hostfs_aops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 .writepage = hostfs_writepage,
520 .readpage = hostfs_readpage,
Paolo 'Blaisorblade' Giarrussoffa0aea2005-05-01 08:58:56 -0700521 .set_page_dirty = __set_page_dirty_nobuffers,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 .prepare_write = hostfs_prepare_write,
523 .commit_write = hostfs_commit_write
524};
525
526static int init_inode(struct inode *inode, struct dentry *dentry)
527{
528 char *name;
529 int type, err = -ENOMEM;
530 int maj, min;
531 dev_t rdev = 0;
532
533 if(dentry){
534 name = dentry_name(dentry, 0);
535 if(name == NULL)
536 goto out;
537 type = file_type(name, &maj, &min);
538 /*Reencode maj and min with the kernel encoding.*/
539 rdev = MKDEV(maj, min);
540 kfree(name);
541 }
542 else type = OS_TYPE_DIR;
543
544 err = 0;
545 if(type == OS_TYPE_SYMLINK)
546 inode->i_op = &page_symlink_inode_operations;
547 else if(type == OS_TYPE_DIR)
548 inode->i_op = &hostfs_dir_iops;
549 else inode->i_op = &hostfs_iops;
550
551 if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
552 else inode->i_fop = &hostfs_file_fops;
553
554 if(type == OS_TYPE_SYMLINK)
555 inode->i_mapping->a_ops = &hostfs_link_aops;
556 else inode->i_mapping->a_ops = &hostfs_aops;
557
558 switch (type) {
559 case OS_TYPE_CHARDEV:
560 init_special_inode(inode, S_IFCHR, rdev);
561 break;
562 case OS_TYPE_BLOCKDEV:
563 init_special_inode(inode, S_IFBLK, rdev);
564 break;
565 case OS_TYPE_FIFO:
566 init_special_inode(inode, S_IFIFO, 0);
567 break;
568 case OS_TYPE_SOCK:
569 init_special_inode(inode, S_IFSOCK, 0);
570 break;
571 }
572 out:
573 return(err);
574}
575
576int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
577 struct nameidata *nd)
578{
579 struct inode *inode;
580 char *name;
581 int error, fd;
582
583 error = -ENOMEM;
584 inode = iget(dir->i_sb, 0);
585 if(inode == NULL) goto out;
586
587 error = init_inode(inode, dentry);
588 if(error)
589 goto out_put;
590
591 error = -ENOMEM;
592 name = dentry_name(dentry, 0);
593 if(name == NULL)
594 goto out_put;
595
596 fd = file_create(name,
597 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
598 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
599 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
600 if(fd < 0)
601 error = fd;
602 else error = read_name(inode, name);
603
604 kfree(name);
605 if(error)
606 goto out_put;
607
608 HOSTFS_I(inode)->fd = fd;
609 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
610 d_instantiate(dentry, inode);
611 return(0);
612
613 out_put:
614 iput(inode);
615 out:
616 return(error);
617}
618
619struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
620 struct nameidata *nd)
621{
622 struct inode *inode;
623 char *name;
624 int err;
625
626 err = -ENOMEM;
627 inode = iget(ino->i_sb, 0);
628 if(inode == NULL)
629 goto out;
630
631 err = init_inode(inode, dentry);
632 if(err)
633 goto out_put;
634
635 err = -ENOMEM;
636 name = dentry_name(dentry, 0);
637 if(name == NULL)
638 goto out_put;
639
640 err = read_name(inode, name);
641 kfree(name);
642 if(err == -ENOENT){
643 iput(inode);
644 inode = NULL;
645 }
646 else if(err)
647 goto out_put;
648
649 d_add(dentry, inode);
650 dentry->d_op = &hostfs_dentry_ops;
651 return(NULL);
652
653 out_put:
654 iput(inode);
655 out:
656 return(ERR_PTR(err));
657}
658
659static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
660{
661 char *file;
662 int len;
663
664 file = inode_name(ino, dentry->d_name.len + 1);
665 if(file == NULL) return(NULL);
666 strcat(file, "/");
667 len = strlen(file);
668 strncat(file, dentry->d_name.name, dentry->d_name.len);
669 file[len + dentry->d_name.len] = '\0';
670 return(file);
671}
672
673int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
674{
675 char *from_name, *to_name;
676 int err;
677
678 if((from_name = inode_dentry_name(ino, from)) == NULL)
679 return(-ENOMEM);
680 to_name = dentry_name(to, 0);
681 if(to_name == NULL){
682 kfree(from_name);
683 return(-ENOMEM);
684 }
685 err = link_file(to_name, from_name);
686 kfree(from_name);
687 kfree(to_name);
688 return(err);
689}
690
691int hostfs_unlink(struct inode *ino, struct dentry *dentry)
692{
693 char *file;
694 int err;
695
696 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
697 if(append)
698 return(-EPERM);
699
700 err = unlink_file(file);
701 kfree(file);
702 return(err);
703}
704
705int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
706{
707 char *file;
708 int err;
709
710 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
711 err = make_symlink(file, to);
712 kfree(file);
713 return(err);
714}
715
716int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
717{
718 char *file;
719 int err;
720
721 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
722 err = do_mkdir(file, mode);
723 kfree(file);
724 return(err);
725}
726
727int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
728{
729 char *file;
730 int err;
731
732 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
733 err = do_rmdir(file);
734 kfree(file);
735 return(err);
736}
737
738int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
739{
740 struct inode *inode;
741 char *name;
742 int err = -ENOMEM;
743
744 inode = iget(dir->i_sb, 0);
745 if(inode == NULL)
746 goto out;
747
748 err = init_inode(inode, dentry);
749 if(err)
750 goto out_put;
751
752 err = -ENOMEM;
753 name = dentry_name(dentry, 0);
754 if(name == NULL)
755 goto out_put;
756
757 init_special_inode(inode, mode, dev);
758 err = do_mknod(name, mode, dev);
759 if(err)
760 goto out_free;
761
762 err = read_name(inode, name);
763 kfree(name);
764 if(err)
765 goto out_put;
766
767 d_instantiate(dentry, inode);
768 return(0);
769
770 out_free:
771 kfree(name);
772 out_put:
773 iput(inode);
774 out:
775 return(err);
776}
777
778int hostfs_rename(struct inode *from_ino, struct dentry *from,
779 struct inode *to_ino, struct dentry *to)
780{
781 char *from_name, *to_name;
782 int err;
783
784 if((from_name = inode_dentry_name(from_ino, from)) == NULL)
785 return(-ENOMEM);
786 if((to_name = inode_dentry_name(to_ino, to)) == NULL){
787 kfree(from_name);
788 return(-ENOMEM);
789 }
790 err = rename_file(from_name, to_name);
791 kfree(from_name);
792 kfree(to_name);
793 return(err);
794}
795
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
797{
798 char *name;
799 int r = 0, w = 0, x = 0, err;
800
801 if (desired & MAY_READ) r = 1;
802 if (desired & MAY_WRITE) w = 1;
803 if (desired & MAY_EXEC) x = 1;
804 name = inode_name(ino, 0);
805 if (name == NULL) return(-ENOMEM);
806
807 if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
808 S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
809 err = 0;
810 else
811 err = access_file(name, r, w, x);
812 kfree(name);
813 if(!err)
814 err = generic_permission(ino, desired, NULL);
815 return err;
816}
817
818int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
819{
820 struct hostfs_iattr attrs;
821 char *name;
822 int err;
823
824 err = inode_change_ok(dentry->d_inode, attr);
825 if (err)
826 return err;
827
828 if(append)
829 attr->ia_valid &= ~ATTR_SIZE;
830
831 attrs.ia_valid = 0;
832 if(attr->ia_valid & ATTR_MODE){
833 attrs.ia_valid |= HOSTFS_ATTR_MODE;
834 attrs.ia_mode = attr->ia_mode;
835 }
836 if(attr->ia_valid & ATTR_UID){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 attrs.ia_valid |= HOSTFS_ATTR_UID;
838 attrs.ia_uid = attr->ia_uid;
839 }
840 if(attr->ia_valid & ATTR_GID){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 attrs.ia_valid |= HOSTFS_ATTR_GID;
842 attrs.ia_gid = attr->ia_gid;
843 }
844 if(attr->ia_valid & ATTR_SIZE){
845 attrs.ia_valid |= HOSTFS_ATTR_SIZE;
846 attrs.ia_size = attr->ia_size;
847 }
848 if(attr->ia_valid & ATTR_ATIME){
849 attrs.ia_valid |= HOSTFS_ATTR_ATIME;
850 attrs.ia_atime = attr->ia_atime;
851 }
852 if(attr->ia_valid & ATTR_MTIME){
853 attrs.ia_valid |= HOSTFS_ATTR_MTIME;
854 attrs.ia_mtime = attr->ia_mtime;
855 }
856 if(attr->ia_valid & ATTR_CTIME){
857 attrs.ia_valid |= HOSTFS_ATTR_CTIME;
858 attrs.ia_ctime = attr->ia_ctime;
859 }
860 if(attr->ia_valid & ATTR_ATIME_SET){
861 attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
862 }
863 if(attr->ia_valid & ATTR_MTIME_SET){
864 attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
865 }
866 name = dentry_name(dentry, 0);
867 if(name == NULL) return(-ENOMEM);
868 err = set_attr(name, &attrs);
869 kfree(name);
870 if(err)
871 return(err);
872
873 return(inode_setattr(dentry->d_inode, attr));
874}
875
876int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
877 struct kstat *stat)
878{
879 generic_fillattr(dentry->d_inode, stat);
880 return(0);
881}
882
883static struct inode_operations hostfs_iops = {
884 .create = hostfs_create,
885 .link = hostfs_link,
886 .unlink = hostfs_unlink,
887 .symlink = hostfs_symlink,
888 .mkdir = hostfs_mkdir,
889 .rmdir = hostfs_rmdir,
890 .mknod = hostfs_mknod,
891 .rename = hostfs_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 .permission = hostfs_permission,
893 .setattr = hostfs_setattr,
894 .getattr = hostfs_getattr,
895};
896
897static struct inode_operations hostfs_dir_iops = {
898 .create = hostfs_create,
899 .lookup = hostfs_lookup,
900 .link = hostfs_link,
901 .unlink = hostfs_unlink,
902 .symlink = hostfs_symlink,
903 .mkdir = hostfs_mkdir,
904 .rmdir = hostfs_rmdir,
905 .mknod = hostfs_mknod,
906 .rename = hostfs_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 .permission = hostfs_permission,
908 .setattr = hostfs_setattr,
909 .getattr = hostfs_getattr,
910};
911
912int hostfs_link_readpage(struct file *file, struct page *page)
913{
914 char *buffer, *name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 int err;
916
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 buffer = kmap(page);
918 name = inode_name(page->mapping->host, 0);
919 if(name == NULL) return(-ENOMEM);
920 err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
921 kfree(name);
922 if(err == PAGE_CACHE_SIZE)
923 err = -E2BIG;
924 else if(err > 0){
925 flush_dcache_page(page);
926 SetPageUptodate(page);
927 if (PageError(page)) ClearPageError(page);
928 err = 0;
929 }
930 kunmap(page);
931 unlock_page(page);
932 return(err);
933}
934
Christoph Hellwigf5e54d62006-06-28 04:26:44 -0700935static const struct address_space_operations hostfs_link_aops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 .readpage = hostfs_link_readpage,
937};
938
939static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
940{
941 struct inode *root_inode;
942 char *name, *data = d;
943 int err;
944
945 sb->s_blocksize = 1024;
946 sb->s_blocksize_bits = 10;
947 sb->s_magic = HOSTFS_SUPER_MAGIC;
948 sb->s_op = &hostfs_sbops;
949
950 if((data == NULL) || (*data == '\0'))
951 data = root_ino;
952
953 err = -ENOMEM;
954 name = kmalloc(strlen(data) + 1, GFP_KERNEL);
955 if(name == NULL)
956 goto out;
957
958 strcpy(name, data);
959
960 root_inode = iget(sb, 0);
961 if(root_inode == NULL)
962 goto out_free;
963
964 err = init_inode(root_inode, NULL);
965 if(err)
966 goto out_put;
967
968 HOSTFS_I(root_inode)->host_filename = name;
969
970 err = -ENOMEM;
971 sb->s_root = d_alloc_root(root_inode);
972 if(sb->s_root == NULL)
973 goto out_put;
974
975 err = read_inode(root_inode);
Jeff Dike51a14112005-05-05 16:15:34 -0700976 if(err){
977 /* No iput in this case because the dput does that for us */
978 dput(sb->s_root);
979 sb->s_root = NULL;
980 goto out_free;
981 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
983 return(0);
984
985 out_put:
Jeff Dike51a14112005-05-05 16:15:34 -0700986 iput(root_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 out_free:
988 kfree(name);
989 out:
990 return(err);
991}
992
David Howells454e2392006-06-23 02:02:57 -0700993static int hostfs_read_sb(struct file_system_type *type,
994 int flags, const char *dev_name,
995 void *data, struct vfsmount *mnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996{
David Howells454e2392006-06-23 02:02:57 -0700997 return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998}
999
1000static struct file_system_type hostfs_type = {
1001 .owner = THIS_MODULE,
1002 .name = "hostfs",
1003 .get_sb = hostfs_read_sb,
1004 .kill_sb = kill_anon_super,
1005 .fs_flags = 0,
1006};
1007
1008static int __init init_hostfs(void)
1009{
1010 return(register_filesystem(&hostfs_type));
1011}
1012
1013static void __exit exit_hostfs(void)
1014{
1015 unregister_filesystem(&hostfs_type);
1016}
1017
1018module_init(init_hostfs)
1019module_exit(exit_hostfs)
1020MODULE_LICENSE("GPL");
1021
1022/*
1023 * Overrides for Emacs so that we follow Linus's tabbing style.
1024 * Emacs will notice this stuff at the end of the file and automatically
1025 * adjust the settings for this buffer only. This must remain at the end
1026 * of the file.
1027 * ---------------------------------------------------------------------------
1028 * Local variables:
1029 * c-file-style: "linux"
1030 * End:
1031 */