Linux 2.2.0
[davej-history.git] / fs / umsdos / symlink.c
blob4b3678a22a2cb43cb35089c8ed86caac6be778a7
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 static struct file_operations umsdos_symlink_operations;
26 * Read the data associate with the symlink.
27 * Return length read in buffer or a negative error code.
31 int umsdos_readlink_x ( struct dentry *dentry,
32 char *buffer,
33 int bufsiz)
35 size_t size = dentry->d_inode->i_size;
36 loff_t loffs = 0;
37 ssize_t ret;
38 struct file filp;
40 Printk((KERN_DEBUG "UMSDOS_read: %s/%s, size=%u\n",
41 dentry->d_parent->d_name.name, dentry->d_name.name, size));
43 fill_new_filp (&filp, dentry);
44 filp.f_reada = 0;
45 filp.f_flags = O_RDONLY;
46 filp.f_op = &umsdos_symlink_operations;
48 if (size > bufsiz)
49 size = bufsiz;
51 ret = fat_file_read (&filp, buffer, size, &loffs);
52 if (ret != size) {
53 ret = -EIO;
55 return ret;
60 static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
62 return umsdos_readlink_x (dentry, buffer, buflen);
65 /* this one mostly stolen from romfs :) */
66 static struct dentry *UMSDOS_followlink (struct dentry *dentry,
67 struct dentry *base,
68 unsigned int follow)
70 struct inode *inode = dentry->d_inode;
71 char *symname;
72 int len, cnt;
73 mm_segment_t old_fs = get_fs ();
75 Printk((KERN_DEBUG "UMSDOS_followlink /mn/: (%s/%s)\n",
76 dentry->d_parent->d_name.name, dentry->d_name.name));
78 len = inode->i_size;
80 if (!(symname = kmalloc (len + 1, GFP_KERNEL))) {
81 dentry = ERR_PTR (-ENOMEM);
82 goto outnobuf;
85 set_fs (KERNEL_DS); /* we read into kernel space this time */
86 cnt = umsdos_readlink_x (dentry, symname, len);
87 set_fs (old_fs);
89 if (len != cnt) {
90 dentry = ERR_PTR (-EIO);
91 goto out;
94 symname[len] = 0;
95 dentry = lookup_dentry (symname, base, follow);
96 kfree (symname);
98 if (0) {
99 out:
100 kfree (symname);
101 outnobuf:
102 dput (base);
104 return dentry;
107 /* needed to patch the file structure */
108 static struct file_operations umsdos_symlink_operations =
110 NULL, /* lseek - default */
111 NULL, /* read */
112 NULL, /* write */
113 NULL, /* readdir - bad */
114 NULL, /* poll - default */
115 NULL, /* ioctl - default */
116 NULL, /* mmap */
117 NULL, /* no special open is needed */
118 NULL, /* no flush code */
119 NULL, /* release */
120 NULL /* fsync */
124 struct inode_operations umsdos_symlink_inode_operations =
126 NULL, /* default file operations (none) */
127 NULL, /* create */
128 NULL, /* lookup */
129 NULL, /* link */
130 NULL, /* unlink */
131 NULL, /* symlink */
132 NULL, /* mkdir */
133 NULL, /* rmdir */
134 NULL, /* mknod */
135 NULL, /* rename */
136 UMSDOS_readlink, /* readlink */
137 UMSDOS_followlink, /* followlink */
138 generic_readpage, /* readpage */
139 NULL, /* writepage */
140 fat_bmap, /* bmap */
141 NULL, /* truncate */
142 NULL, /* permission */
143 NULL, /* smap */
144 NULL, /* updatepage */
145 NULL /* revalidate */