2 * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
6 #include "linux/stddef.h"
7 #include "linux/string.h"
8 #include "linux/types.h"
9 #include "linux/errno.h"
10 #include "linux/slab.h"
11 #include "linux/init.h"
13 #include "linux/stat.h"
17 #include "kern_util.h"
18 #include "filehandle.h"
21 /* Changed in hostfs_args before the kernel starts running */
22 static char *jail_dir = "/";
25 static int __init hostfs_args(char *options, int *add)
29 ptr = strchr(options, ',');
37 ptr = strchr(options, ',');
41 if(!strcmp(options, "append"))
43 else printf("hostfs_args - unsupported option - %s\n",
51 __uml_setup("hostfs=", hostfs_args,
52 "hostfs=<root dir>,<flags>,...\n"
53 " This is used to set hostfs parameters. The root directory argument\n"
54 " is used to confine all hostfs mounts to within the specified directory\n"
55 " tree on the host. If this isn't specified, then a user inside UML can\n"
56 " mount anything on the host that's accessible to the user that's running\n"
58 " The only flag currently supported is 'append', which specifies that all\n"
59 " files opened by hostfs will be opened in append mode.\n\n"
63 struct externfs_data ext;
68 struct externfs_inode ext;
69 struct file_handle fh;
72 static int hostfs_access_file(char *file, int uid, int w, int x, int gid,
73 int r, struct externfs_data *ed)
75 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
76 const char *path[] = { jail_dir, mount, file, NULL };
77 char tmp[HOSTFS_BUFSIZE];
80 if(r) mode = OS_ACC_R_OK;
81 if(w) mode |= OS_ACC_W_OK;
82 if(x) mode |= OS_ACC_X_OK;
85 file = get_path(path, tmp, sizeof(tmp));
89 err = os_access(file, mode);
95 static int hostfs_make_node(const char *file, int mode, int uid, int gid,
96 int type, int major, int minor,
97 struct externfs_data *ed)
99 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
100 const char *path[] = { jail_dir, mount, file, NULL };
101 char tmp[HOSTFS_BUFSIZE];
104 file = get_path(path, tmp, sizeof(tmp));
108 /* XXX Pass type in an OS-independent way */
111 err = os_make_dev(file, mode, major, minor);
112 free_path(file, tmp);
117 static int hostfs_stat_file(const char *file, struct externfs_data *ed,
118 dev_t *dev_out, unsigned long long *inode_out,
119 int *mode_out, int *nlink_out, int *uid_out,
120 int *gid_out, unsigned long long *size_out,
121 unsigned long *atime_out, unsigned long *mtime_out,
122 unsigned long *ctime_out, int *blksize_out,
123 unsigned long long *blocks_out)
125 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
126 const char *path[] = { jail_dir, mount, file, NULL };
128 /* XXX Why pretend everything is owned by root? */
131 return(host_stat_file(path, dev_out, inode_out, mode_out, nlink_out,
132 NULL, NULL, size_out, atime_out, mtime_out,
133 ctime_out, blksize_out, blocks_out));
136 static int hostfs_file_type(const char *file, int *rdev,
137 struct externfs_data *ed)
139 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
140 const char *path[] = { jail_dir, mount, file, NULL };
142 return(host_file_type(path, rdev));
145 static char *hostfs_name(struct inode *inode)
147 struct externfs_data *ed = inode_externfs_info(inode);
148 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
150 return(inode_name_prefix(inode, mount));
153 static struct externfs_inode *hostfs_init_file(struct externfs_data *ed)
155 struct hostfs_file *hf;
157 hf = kmalloc(sizeof(*hf), GFP_KERNEL);
165 static int hostfs_open_file(struct externfs_inode *ext, char *file,
166 int uid, int gid, struct inode *inode,
167 struct externfs_data *ed)
169 struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
170 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
171 const char *path[] = { jail_dir, mount, file, NULL };
174 err = host_open_file(path, 1, 1, &hf->fh);
179 err = host_open_file(path, 1, 0, &hf->fh);
184 is_reclaimable(&hf->fh, hostfs_name, inode);
189 static void *hostfs_open_dir(char *file, int uid, int gid,
190 struct externfs_data *ed)
192 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
193 const char *path[] = { jail_dir, mount, file, NULL };
195 return(host_open_dir(path));
198 static void hostfs_close_dir(void *stream, struct externfs_data *ed)
200 os_close_dir(stream);
203 static char *hostfs_read_dir(void *stream, unsigned long long *pos,
204 unsigned long long *ino_out, int *len_out,
205 struct externfs_data *ed)
207 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
209 return(generic_host_read_dir(stream, pos, ino_out, len_out, mount));
212 static int hostfs_read_file(struct externfs_inode *ext,
213 unsigned long long offset, char *buf, int len,
214 int ignore_start, int ignore_end,
215 void (*completion)(char *, int, void *), void *arg,
216 struct externfs_data *ed)
218 struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
221 if(ignore_start != 0){
222 err = read_file(&hf->fh, offset, buf, ignore_start);
227 if(ignore_end != len)
228 err = read_file(&hf->fh, offset + ignore_end, buf + ignore_end,
233 (*completion)(buf, err, arg);
239 static int hostfs_write_file(struct externfs_inode *ext,
240 unsigned long long offset, const char *buf,
242 void (*completion)(char *, int, void *),
243 void *arg, struct externfs_data *ed)
245 struct file_handle *fh;
248 fh = &container_of(ext, struct hostfs_file, ext)->fh;
249 err = write_file(fh, offset + start, buf + start, len);
251 (*completion)((char *) buf, err, arg);
258 static int hostfs_create_file(struct externfs_inode *ext, char *file, int mode,
259 int uid, int gid, struct inode *inode,
260 struct externfs_data *ed)
262 struct hostfs_file *hf = container_of(ext, struct hostfs_file,
264 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
265 const char *path[] = { jail_dir, mount, file, NULL };
268 err = host_create_file(path, mode, &hf->fh);
272 is_reclaimable(&hf->fh, hostfs_name, inode);
277 static int hostfs_set_attr(const char *file, struct externfs_iattr *attrs,
278 struct externfs_data *ed)
280 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
281 const char *path[] = { jail_dir, mount, file, NULL };
283 return(host_set_attr(path, attrs));
286 static int hostfs_make_symlink(const char *from, const char *to, int uid,
287 int gid, struct externfs_data *ed)
289 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
290 const char *path[] = { jail_dir, mount, from, NULL };
292 return(host_make_symlink(path, to));
295 static int hostfs_link_file(const char *to, const char *from, int uid, int gid,
296 struct externfs_data *ed)
298 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
299 const char *to_path[] = { jail_dir, mount, to, NULL };
300 const char *from_path[] = { jail_dir, mount, from, NULL };
302 return(host_link_file(to_path, from_path));
305 static int hostfs_unlink_file(const char *file, struct externfs_data *ed)
307 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
308 const char *path[] = { jail_dir, mount, file, NULL };
310 return(host_unlink_file(path));
313 static int hostfs_make_dir(const char *file, int mode, int uid, int gid,
314 struct externfs_data *ed)
316 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
317 const char *path[] = { jail_dir, mount, file, NULL };
319 return(host_make_dir(path, mode));
322 static int hostfs_remove_dir(const char *file, int uid, int gid,
323 struct externfs_data *ed)
325 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
326 const char *path[] = { jail_dir, mount, file, NULL };
328 return(host_remove_dir(path));
331 static int hostfs_read_link(char *file, int uid, int gid, char *buf, int size,
332 struct externfs_data *ed)
334 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
335 const char *path[] = { jail_dir, mount, file, NULL };
337 return(host_read_link(path, buf, size));
340 static int hostfs_rename_file(char *from, char *to, struct externfs_data *ed)
342 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
343 const char *to_path[] = { jail_dir, mount, to, NULL };
344 const char *from_path[] = { jail_dir, mount, from, NULL };
346 return(host_rename_file(from_path, to_path));
349 static int hostfs_stat_fs(long *bsize_out, long long *blocks_out,
350 long long *bfree_out, long long *bavail_out,
351 long long *files_out, long long *ffree_out,
352 void *fsid_out, int fsid_size, long *namelen_out,
353 long *spare_out, struct externfs_data *ed)
355 char *mount = container_of(ed, struct hostfs_data, ext)->mount;
356 const char *path[] = { jail_dir, mount, NULL };
358 return(host_stat_fs(path, bsize_out, blocks_out, bfree_out, bavail_out,
359 files_out, ffree_out, fsid_out, fsid_size,
360 namelen_out, spare_out));
363 void hostfs_close_file(struct externfs_inode *ext,
364 unsigned long long size)
366 struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
369 truncate_file(&hf->fh, size);
376 int hostfs_truncate_file(struct externfs_inode *ext, __u64 size,
377 struct externfs_data *ed)
379 struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
381 return(truncate_file(&hf->fh, size));
384 static struct externfs_file_ops hostfs_file_ops = {
385 .stat_file = hostfs_stat_file,
386 .file_type = hostfs_file_type,
387 .access_file = hostfs_access_file,
388 .open_file = hostfs_open_file,
389 .open_dir = hostfs_open_dir,
390 .read_dir = hostfs_read_dir,
391 .read_file = hostfs_read_file,
392 .write_file = hostfs_write_file,
393 .map_file_page = NULL,
394 .close_file = hostfs_close_file,
395 .close_dir = hostfs_close_dir,
397 .create_file = hostfs_create_file,
398 .set_attr = hostfs_set_attr,
399 .make_symlink = hostfs_make_symlink,
400 .unlink_file = hostfs_unlink_file,
401 .make_dir = hostfs_make_dir,
402 .remove_dir = hostfs_remove_dir,
403 .make_node = hostfs_make_node,
404 .link_file = hostfs_link_file,
405 .read_link = hostfs_read_link,
406 .rename_file = hostfs_rename_file,
407 .statfs = hostfs_stat_fs,
408 .truncate_file = hostfs_truncate_file
411 static struct externfs_data *mount_fs(char *mount_arg)
413 struct hostfs_data *hd;
416 hd = kmalloc(sizeof(*hd), GFP_KERNEL);
420 hd->mount = host_root_filename(mount_arg);
421 if(hd->mount == NULL)
424 init_externfs(&hd->ext, &hostfs_file_ops);
431 return(ERR_PTR(err));
434 static struct externfs_mount_ops hostfs_mount_ops = {
435 .init_file = hostfs_init_file,
439 static int __init init_hostfs(void)
441 return(register_externfs("hostfs", &hostfs_mount_ops));
444 static void __exit exit_hostfs(void)
446 unregister_externfs("hostfs");
449 __initcall(init_hostfs);
450 __exitcall(exit_hostfs);
453 module_init(init_hostfs)
454 module_exit(exit_hostfs)
455 MODULE_LICENSE("GPL");
459 * Overrides for Emacs so that we follow Linus's tabbing style.
460 * Emacs will notice this stuff at the end of the file and automatically
461 * adjust the settings for this buffer only. This must remain at the end
463 * ---------------------------------------------------------------------------
465 * c-file-style: "linux"