1 /*
2 * linux/fs/umsdos/file.c
3 *
4 * Written 1992 by Jacques Gelinas
5 * inspired from linux/fs/msdos/file.c Werner Almesberger
6 *
7 * Extended MS-DOS regular file handling primitives
8 */
9
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>
18
19 #include <asm/segment.h>
20 #include <asm/system.h>
21
22 #define PRINTK(x)
23 #define Printk(x) printk x
24
25 /*
26 Read the data associate with the symlink.
27 Return length read in buffer or a negative error code.
28 */
29 static int umsdos_readlink_x (
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
30 struct inode *inode,
31 char *buffer,
32 int (*msdos_read)(struct inode *, struct file *, char *, int),
33 int bufsiz)
34 {
35 int ret = inode->i_size;
36 struct file filp;
37 filp.f_pos = 0;
38 filp.f_reada = 0;
39 if (ret > bufsiz) ret = bufsiz;
40 if ((*msdos_read) (inode, &filp, buffer,ret) != ret){
41 ret = -EIO;
42 }
43 return ret;
44 }
45 /*
46 Follow a symbolic link chain by calling open_namei recursively
47 until an inode is found.
48
49 Return 0 if ok, or a negative error code if not.
50 */
51 static int UMSDOS_follow_link(
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
52 struct inode * dir,
53 struct inode * inode,
54 int flag,
55 int mode,
56 struct inode ** res_inode)
57 {
58 int ret = -ELOOP;
59 *res_inode = NULL;
60 if (current->link_count < 5) {
61 char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
62 if (path == NULL){
63 ret = -ENOMEM;
64 }else{
65 if (!dir) {
66 dir = current->fs[1].root;
67 dir->i_count++;
68 }
69 if (!inode){
70 PRINTK (("symlink: inode = NULL\n"));
71 ret = -ENOENT;
72 }else if (!S_ISLNK(inode->i_mode)){
73 PRINTK (("symlink: Not ISLNK\n"));
74 *res_inode = inode;
75 inode = NULL;
76 ret = 0;
77 }else{
78 ret = umsdos_readlink_x (inode,path
79 ,umsdos_file_read_kmem,PATH_MAX-1);
80 if (ret > 0){
81 path[ret] = '\0';
82 PRINTK (("follow :%s: %d ",path,ret));
83 iput(inode);
84 inode = NULL;
85 current->link_count++;
86 ret = open_namei(path,flag,mode,res_inode,dir);
87 current->link_count--;
88 dir = NULL;
89 }else{
90 ret = -EIO;
91 }
92 }
93 kfree (path);
94 }
95 }
96 iput(inode);
97 iput(dir);
98 PRINTK (("follow_link ret %d\n",ret));
99 return ret;
100 }
101
102 static int UMSDOS_readlink(struct inode * inode, char * buffer, int buflen)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
103 {
104 int ret = -EINVAL;
105 if (S_ISLNK(inode->i_mode)) {
106 ret = umsdos_readlink_x (inode,buffer,fat_file_read,buflen);
107 }
108 PRINTK (("readlink %d %x bufsiz %d\n",ret,inode->i_mode,buflen));
109 iput(inode);
110 return ret;
111
112 }
113
114 static struct file_operations umsdos_symlink_operations = {
115 NULL, /* lseek - default */
116 NULL, /* read */
117 NULL, /* write */
118 NULL, /* readdir - bad */
119 NULL, /* select - default */
120 NULL, /* ioctl - default */
121 NULL, /* mmap */
122 NULL, /* no special open is needed */
123 NULL, /* release */
124 NULL /* fsync */
125 };
126
127 struct inode_operations umsdos_symlink_inode_operations = {
128 &umsdos_symlink_operations, /* default file operations */
129 NULL, /* create */
130 NULL, /* lookup */
131 NULL, /* link */
132 NULL, /* unlink */
133 NULL, /* symlink */
134 NULL, /* mkdir */
135 NULL, /* rmdir */
136 NULL, /* mknod */
137 NULL, /* rename */
138 UMSDOS_readlink, /* readlink */
139 UMSDOS_follow_link, /* follow_link */
140 NULL, /* readpage */
141 NULL, /* writepage */
142 NULL, /* bmap */
143 NULL, /* truncate */
144 NULL /* permission */
145 };
146
147
148