1 /* 2 * linux/fs/umsdos/rdir.c 3 * 4 * Written 1994 by Jacques Gelinas 5 * 6 * Extended MS-DOS directory pure MS-DOS handling functions 7 * (For directory without EMD file). 8 */ 9
10 #include <asm/segment.h>
11
12 #include <linux/sched.h>
13 #include <linux/fs.h>
14 #include <linux/msdos_fs.h>
15 #include <linux/errno.h>
16 #include <linux/stat.h>
17 #include <linux/limits.h>
18 #include <linux/umsdos_fs.h>
19 #include <linux/malloc.h>
20
21 #definePRINTK(x)
22 #definePrintk(x) printkx 23
24
25 externstructinode *pseudo_root;
26
27 staticintUMSDOS_rreaddir (
/* */ 28 structinode *dir,
29 structfile *filp,
30 structdirent *dirent,
31 intcount)
32 { 33 intret = 0;
34 while (1){ 35 intlen = -1;
36 ret = msdos_readdir(dir,filp,dirent,count);
37 if (ret > 0) len = get_fs_word(&dirent->d_reclen);
38 if (len == 5
39 && pseudo_root != NULL 40 && dir->i_sb->s_mounted == pseudo_root->i_sb->s_mounted){ 41 /* 42 In pseudo root mode, we must eliminate logically 43 the directory linux from the real root. 44 */ 45 charname[5];
46 memcpy_fromfs (name,dirent->d_name,5);
47 if (memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0) break;
48 }else{ 49 if (pseudo_root != NULL 50 && len == 2
51 && dir == dir->i_sb->s_mounted 52 && dir == pseudo_root->i_sb->s_mounted){ 53 charname[2];
54 memcpy_fromfs (name,dirent->d_name,2);
55 if (name[0] == '.' && name[1] == '.'){ 56 put_fs_long (pseudo_root->i_ino,&dirent->d_ino);
57 } 58 } 59 break;
60 } 61 } 62 returnret;
63 } 64
65 intUMSDOS_rlookup(
/* */ 66 structinode *dir,
67 constchar *name,
68 intlen,
69 structinode **result) /* Will hold inode of the file, if successful */ 70 { 71 intret;
72 if (pseudo_root != NULL 73 && len == 2
74 && name[0] == '.'
75 && name[1] == '.'
76 && dir == dir->i_sb->s_mounted 77 && dir == pseudo_root->i_sb->s_mounted){ 78 *result = pseudo_root;
79 pseudo_root->i_count++;
80 ret = 0;
81 /* #Specification: pseudo root / DOS/.. 82 In the real root directory (c:\), the directory .. 83 is the pseudo root (c:\linux). 84 */ 85 }else{ 86 ret = umsdos_real_lookup (dir,name,len,result);
87 if (ret == 0){ 88 structinode *inode = *result;
89 if (inode == pseudo_root){ 90 /* #Specification: pseudo root / DOS/linux 91 Even in the real root directory (c:\), the directory 92 /linux won't show 93 */ 94 ret = -ENOENT;
95 iput (pseudo_root);
96 *result = NULL;
97 }elseif (S_ISDIR(inode->i_mode)){ 98 /* We must place the proper function table */ 99 /* depending if this is a MsDOS directory or an UMSDOS directory */ 100 umsdos_setup_dir_inode(inode);
101 } 102 } 103 } 104 iput (dir);
105 returnret;
106 } 107
108 staticintUMSDOS_rrmdir (
/* */ 109 structinode *dir,
110 constchar *name,
111 intlen)
112 { 113 /* #Specification: dual mode / rmdir in a DOS directory 114 In a DOS (not EMD in it) directory, we use a reverse strategy 115 compared with an Umsdos directory. We assume that a subdirectory 116 of a DOS directory is also a DOS directory. This is not always 117 true (umssync may be used anywhere), but make sense. 118
119 So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY 120 then we check if it is a Umsdos directory. We check if it is 121 really empty (only . .. and --linux-.--- in it). If it is true 122 we remove the EMD and do a msdos_rmdir() again. 123
124 In a Umsdos directory, we assume all subdirectory are also 125 Umsdos directory, so we check the EMD file first. 126 */ 127 intret;
128 if (umsdos_is_pseudodos(dir,name,len)){ 129 /* #Specification: pseudo root / rmdir /DOS 130 The pseudo sub-directory /DOS can't be removed! 131 This is done even if the pseudo root is not a Umsdos 132 directory anymore (very unlikely), but an accident (under 133 MsDOS) is always possible. 134
135 EPERM is returned. 136 */ 137 ret = -EPERM;
138 }else{ 139 umsdos_lockcreate (dir);
140 dir->i_count++;
141 ret = msdos_rmdir (dir,name,len);
142 if (ret == -ENOTEMPTY){ 143 structinode *sdir;
144 dir->i_count++;
145 ret = UMSDOS_rlookup (dir,name,len,&sdir);
146 PRINTK (("rrmdir lookup %d ",ret));
147 if (ret == 0){ 148 intempty;
149 if ((empty = umsdos_isempty (sdir)) != 0){ 150 PRINTK (("isempty %d i_count %d ",empty,sdir->i_count));
151 if (empty == 2){ 152 /* 153 Not a Umsdos directory, so the previous msdos_rmdir 154 was not lying :-) 155 */ 156 ret = -ENOTEMPTY;
157 }elseif (empty == 1){ 158 /* We have to removed the EMD file */ 159 ret = msdos_unlink(sdir,UMSDOS_EMD_FILE 160 ,UMSDOS_EMD_NAMELEN);
161 sdir = NULL;
162 if (ret == 0){ 163 dir->i_count++;
164 ret = msdos_rmdir (dir,name,len);
165 } 166 } 167 }else{ 168 ret = -ENOTEMPTY;
169 } 170 iput (sdir);
171 } 172 } 173 umsdos_unlockcreate (dir);
174 } 175 iput (dir);
176 returnret;
177 } 178
179 /* #Specification: dual mode / introduction 180 One goal of UMSDOS is to allow a practical and simple coexistence 181 between MsDOS and Linux in a single partition. Using the EMD file 182 in each directory, UMSDOS add Unix semantics and capabilities to 183 normal DOS file system. To help and simplify coexistence, here is 184 the logic related to the EMD file. 185
186 If it is missing, then the directory is managed by the MsDOS driver. 187 The names are limited to DOS limits (8.3). No links, no device special 188 and pipe and so on. 189
190 If it is there, it is the directory. If it is there but empty, then 191 the directory looks empty. The utility umssync allows synchronisation 192 of the real DOS directory and the EMD. 193
194 Whenever umssync is applied to a directory without EMD, one is 195 created on the fly. The directory is promoted to full unix semantic. 196 Of course, the ls command will show exactly the same content as before 197 the umssync session. 198
199 It is believed that the user/admin will promote directories to unix 200 semantic as needed. 201
202 The strategy to implement this is to use two function table (struct 203 inode_operations). One for true UMSDOS directory and one for directory 204 with missing EMD. 205
206 Functions related to the DOS semantic (but aware of UMSDOS) generally 207 have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate 208 from the one with full UMSDOS semantic. 209 */ 210 staticstructfile_operationsumsdos_rdir_operations = { 211 NULL, /* lseek - default */ 212 UMSDOS_dir_read, /* read */ 213 NULL, /* write - bad */ 214 UMSDOS_rreaddir, /* readdir */ 215 NULL, /* select - default */ 216 UMSDOS_ioctl_dir, /* ioctl - default */ 217 NULL, /* mmap */ 218 NULL, /* no special open code */ 219 NULL, /* no special release code */ 220 NULL/* fsync */ 221 };
222
223 structinode_operationsumsdos_rdir_inode_operations = { 224 &umsdos_rdir_operations, /* default directory file-ops */ 225 msdos_create, /* create */ 226 UMSDOS_rlookup, /* lookup */ 227 NULL, /* link */ 228 msdos_unlink, /* unlink */ 229 NULL, /* symlink */ 230 msdos_mkdir, /* mkdir */ 231 UMSDOS_rrmdir, /* rmdir */ 232 NULL, /* mknod */ 233 msdos_rename, /* rename */ 234 NULL, /* readlink */ 235 NULL, /* follow_link */ 236 NULL, /* bmap */ 237 NULL, /* truncate */ 238 NULL/* permission */ 239 };
240
241