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