Import 2.1.118
[davej-history.git] / fs / umsdos / symlink.c
blob696059ce21c9e49f62a7c11acfdf102d5fa31531
1 /*
2 * linux/fs/umsdos/file.c
4 * Written 1992 by Jacques Gelinas
5 * inspired from linux/fs/msdos/file.c Werner Almesberger
7 * Extended MS-DOS regular file handling primitives
8 */
10 #include <linux/sched.h>
11 #include <linux/fs.h>
12 #include <linux/msdos_fs.h>
13 #include <linux/errno.h>
14 #include <linux/fcntl.h>
15 #include <linux/stat.h>
16 #include <linux/umsdos_fs.h>
17 #include <linux/malloc.h>
19 #include <asm/uaccess.h>
20 #include <asm/system.h>
22 #define PRINTK(x)
23 #define Printk(x) printk x
25 static struct file_operations umsdos_symlink_operations;
29 * Read the data associate with the symlink.
30 * Return length read in buffer or a negative error code.
34 static int umsdos_readlink_x (
35 struct dentry *dentry,
36 char *buffer,
37 int bufsiz)
39 int ret;
40 loff_t loffs = 0;
41 struct file filp;
43 ret = dentry->d_inode->i_size;
45 check_dentry (dentry);
46 fill_new_filp (&filp, dentry);
48 filp.f_reada = 0;
49 filp.f_flags = O_RDONLY;
50 filp.f_op = &umsdos_symlink_operations; /* /mn/ - we have to fill it with dummy values so we won't segfault */
52 if (ret > bufsiz)
53 ret = bufsiz;
55 PRINTK ((KERN_DEBUG "umsdos_readlink_x /mn/: Checkin: filp=%p, buffer=%p, size=%d, offs=%Lu\n", &filp, buffer, ret, loffs));
56 PRINTK ((KERN_DEBUG " f_op=%p\n", filp.f_op));
57 PRINTK ((KERN_DEBUG " inode=%lu, i_size=%lu\n", filp.f_dentry->d_inode->i_ino, filp.f_dentry->d_inode->i_size));
58 PRINTK ((KERN_DEBUG " f_pos=%Lu\n", filp.f_pos));
59 PRINTK ((KERN_DEBUG " name=%.*s\n", (int) filp.f_dentry->d_name.len, filp.f_dentry->d_name.name));
60 PRINTK ((KERN_DEBUG " i_binary(sb)=%d\n", MSDOS_I (filp.f_dentry->d_inode)->i_binary));
61 PRINTK ((KERN_DEBUG " f_count=%d, f_flags=%d\n", filp.f_count, filp.f_flags));
62 PRINTK ((KERN_DEBUG " f_owner=%d\n", filp.f_owner.uid));
63 PRINTK ((KERN_DEBUG " f_version=%ld\n", filp.f_version));
64 PRINTK ((KERN_DEBUG " f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp.f_reada, filp.f_ramax, filp.f_raend, filp.f_ralen, filp.f_rawin));
67 PRINTK ((KERN_DEBUG "umsdos_readlink_x: FIXME /mn/: running fat_file_read (%p, %p, %d, %Lu)\n", &filp, buffer, ret, loffs));
68 if (fat_file_read (&filp, buffer, (size_t) ret, &loffs) != ret) {
69 ret = -EIO;
71 #if 0 /* DEBUG */
73 struct umsdos_dirent *mydirent = buffer;
75 PRINTK ((KERN_DEBUG " (DDD) uid=%d\n", mydirent->uid));
76 PRINTK ((KERN_DEBUG " (DDD) gid=%d\n", mydirent->gid));
77 PRINTK ((KERN_DEBUG " (DDD) name=>%.20s<\n", mydirent->name));
79 #endif
81 PRINTK ((KERN_DEBUG "umsdos_readlink_x: FIXME /mn/: fat_file_read returned offs=%Lu ret=%d\n", loffs, ret));
82 return ret;
87 static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
89 int ret;
91 PRINTK ((KERN_DEBUG "UMSDOS_readlink: calling umsdos_readlink_x for %.*s\n", (int) dentry->d_name.len, dentry->d_name.name));
92 ret = umsdos_readlink_x (dentry, buffer, buflen);
93 PRINTK ((KERN_DEBUG "readlink %d bufsiz %d\n", ret, buflen));
94 /* dput(dentry); / * FIXME /mn/ */
95 Printk ((KERN_WARNING "UMSDOS_readlink /mn/: FIXME! skipped dput(dentry). returning %d\n", ret));
96 return ret;
100 /* this one mostly stolen from romfs :) */
101 static struct dentry *UMSDOS_followlink (struct dentry *dentry, struct dentry *base)
103 struct inode *inode = dentry->d_inode;
104 char *symname = NULL;
105 int len, cnt;
106 mm_segment_t old_fs = get_fs ();
108 Printk ((KERN_DEBUG "UMSDOS_followlink /mn/: (%.*s/%.*s)\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name, (int) dentry->d_name.len, dentry->d_name.name));
110 len = inode->i_size;
112 if (!(symname = kmalloc (len + 1, GFP_KERNEL))) {
113 dentry = ERR_PTR (-EAGAIN); /* correct? */
114 goto outnobuf;
116 set_fs (KERNEL_DS); /* we read into kernel space this time */
117 PRINTK ((KERN_DEBUG "UMSDOS_followlink /mn/: Here goes umsdos_readlink_x %p, %p, %d\n", dentry, symname, len));
118 cnt = umsdos_readlink_x (dentry, symname, len);
119 PRINTK ((KERN_DEBUG "UMSDOS_followlink /mn/: back from umsdos_readlink_x %p, %p, %d!\n", dentry, symname, len));
120 set_fs (old_fs);
121 Printk ((KERN_DEBUG "UMSDOS_followlink /mn/: link name is %.*s with len %d\n", cnt, symname, cnt));
123 if (len != cnt) {
124 dentry = ERR_PTR (-EIO);
125 goto out;
126 } else
127 symname[len] = 0;
129 dentry = lookup_dentry (symname, base, 1);
130 kfree (symname);
132 if (0) {
133 out:
134 kfree (symname);
135 outnobuf:
136 dput (base);
138 return dentry;
142 static struct file_operations umsdos_symlink_operations =
144 NULL, /* lseek - default */
145 NULL, /* read */
146 NULL, /* write */
147 NULL, /* readdir - bad */
148 NULL, /* poll - default */
149 NULL, /* ioctl - default */
150 NULL, /* mmap */
151 NULL, /* no special open is needed */
152 NULL, /* no flush code */
153 NULL, /* release */
154 NULL /* fsync */
158 struct inode_operations umsdos_symlink_inode_operations =
160 NULL, /* default file operations */
161 NULL, /* create */
162 NULL, /* lookup */
163 NULL, /* link */
164 NULL, /* unlink */
165 NULL, /* symlink */
166 NULL, /* mkdir */
167 NULL, /* rmdir */
168 NULL, /* mknod */
169 NULL, /* rename */
170 UMSDOS_readlink, /* readlink */
171 UMSDOS_followlink, /* followlink *//* /mn/ is this REALLY needed ? I recall seeing it working w/o it... */
172 generic_readpage, /* readpage *//* in original NULL. changed to generic_readpage. FIXME? /mn/ */
173 NULL, /* writepage */
174 fat_bmap, /* bmap *//* in original NULL. changed to fat_bmap. FIXME? /mn/ */
175 NULL, /* truncate */
176 NULL, /* permission */
177 NULL, /* smap */
178 NULL, /* updatepage */
179 NULL /* revalidate */