1/* #Specification: umsdos / readdir 2 * umsdos_readdir() should fill a struct dirent with 3 * an inode number. The cheap way to get it is to 4 * do a lookup in the MSDOS directory for each 5 * entry processed by the readdir() function. 6 * This is not very efficient, but very simple. The 7 * other way around is to maintain a copy of the inode 8 * number in the EMD file. This is a problem because 9 * this has to be maintained in sync using tricks. 10 * Remember that MSDOS (the OS) does not update the 11 * modification time (mtime) of a directory. There is 12 * no easy way to tell that a directory was modified 13 * during a DOS session and synchronise the EMD file. 14 */ 15 /* #Specification: readdir / . and .. 16 * The msdos filesystem manages the . and .. entry properly 17 * so the EMD file won't hold any info about it. 18 * 19 * In readdir, we assume that for the root directory 20 * the read position will be 0 for ".", 1 for "..". For 21 * a non root directory, the read position will be 0 for "." 22 * and 32 for "..". 23 */ 24 /* 25 * This is a trick used by the msdos file system (fs/msdos/dir.c) 26 * to manage . and .. for the root directory of a file system. 27 * Since there is no such entry in the root, fs/msdos/dir.c 28 * use the following: 29 * 30 * if f_pos == 0, return ".". 31 * if f_pos == 1, return "..". 32 * 33 * So let msdos handle it 34 * 35 * Since umsdos entries are much larger, we share the same f_pos. 36 * if f_pos is 0 or 1 or 32, we are clearly looking at . and 37 * .. 38 * 39 * As soon as we get f_pos == 2 or f_pos == 64, then back to 40 * 0, but this time we are reading the EMD file. 41 * 42 * Well, not so true. The problem, is that UMSDOS_REC_SIZE is 43 * also 64, so as soon as we read the first record in the 44 * EMD, we are back at offset 64. So we set the offset 45 * to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the 46 * .. entry from msdos. 47 * 48 * Now (linux 1.3), umsdos_readdir can read more than one 49 * entry even if we limit (umsdos_dir_once) to only one: 50 * It skips over hidden file. So we switch to 51 * UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully 52 * the .. entry. 53 */ 54 /* #Specification: umsdos / lookup / inode info 55 * After successfully reading an inode from the MSDOS 56 * filesystem, we use the EMD file to complete it. 57 * We update the following field. 58 * 59 * uid, gid, atime, ctime, mtime, mode. 60 * 61 * We rely on MSDOS for mtime. If the file 62 * was modified during an MSDOS session, at least 63 * mtime will be meaningful. We do this only for regular 64 * file. 65 * 66 * We don't rely on MS-DOS for mtime for directories 67 * because the MS-DOS date on a directory is its 68 * creation time (strange MSDOS behavior) which 69 * corresponds to none of the three Unix time stamps. 70 */ 71 /* #Specification: umsdos / conversion mode 72 * The msdos filesystem can do some inline conversion 73 * of the data of a file. It can translate silently 74 * from the MS-DOS text file format to the Unix one 75 * (CRLF -> LF) while reading, and the reverse 76 * while writing. This is activated using the mount 77 * option conv=.... 78 * 79 * This is not useful for Linux files in a promoted 80 * directory. It can even be harmful. For this 81 * reason, the binary (no conversion) mode is 82 * always activated. 83 */ 84 /* #Specification: umsdos / conversion mode / todo 85 * A flag could be added to file and directories 86 * forcing an automatic conversion mode (as 87 * done with the msdos filesystem). 88 * 89 * This flag could be setup on a directory basis 90 * (instead of file) and all files in it would 91 * logically inherit it. If the conversion mode 92 * is active (conv=) then the i_binary flag would 93 * be left untouched in those directories. 94 * 95 * It was proposed that the sticky bit be used to set 96 * this. A problem with that is that new files would 97 * be written incorrectly. The other problem is that 98 * the sticky bit has a meaning for directories. So 99 * another bit should be used (there is some space 100 * in the EMD file for it) and a special utility 101 * would be used to assign the flag to a directory). 102 * I don't think it is useful to assign this flag 103 * on a single file. 104 */ 105 * #Specification: weakness / rename 106 * There is a case where UMSDOS rename has a different behavior 107 * than a normal Unix file system. Renaming an open file across 108 * directory boundary does not work. Renaming an open file within 109 * a directory does work, however. 110 * 111 * The problem may is in Linux VFS driver for msdos. 112 * I believe this is not a bug but a design feature, because 113 * an inode number represents some sort of directory address 114 * in the MSDOS directory structure, so moving the file into 115 * another directory does not preserve the inode number. 116 */ 117/* #Specification: rename / new name exist 118 * If the destination name already exists, it will 119 * silently be removed. EXT2 does it this way 120 * and this is the spec of SunOS. So does UMSDOS. 121 * 122 * If the destination is an empty directory it will 123 * also be removed. 124 */ 125/* #Specification: rename / new name exist / possible flaw 126 * The code to handle the deletion of the target (file 127 * and directory) use to be in umsdos_rename_f, surrounded 128 * by proper directory locking. This was ensuring that only 129 * one process could achieve a rename (modification) operation 130 * in the source and destination directory. This was also 131 * ensuring the operation was "atomic". 132 * 133 * This has been changed because this was creating a 134 * stack overflow (the stack is only 4 kB) in the kernel. To avoid 135 * the code doing the deletion of the target (if exist) has 136 * been moved to a upper layer. umsdos_rename_f is tried 137 * once and if it fails with EEXIST, the target is removed 138 * and umsdos_rename_f is done again. 139 * 140 * This makes the code cleaner and may solve a 141 * deadlock problem one tester was experiencing. 142 * 143 * The point is to mention that possibly, the semantic of 144 * "rename" may be wrong. Anyone dare to check that :-) 145 * Be aware that IF it is wrong, to produce the problem you 146 * will need two process trying to rename a file to the 147 * same target at the same time. Again, I am not sure it 148 * is a problem at all. 149 */ 150 151/* #Specification: hard link / strategy 152 * Hard links are difficult to implement on top of an MS-DOS FAT file 153 * system. Unlike Unix file systems, there are no inodes. A directory 154 * entry holds the functionality of the inode and the entry. 155 * 156 * We will used the same strategy as a normal Unix file system 157 * (with inodes) except we will do it symbolically (using paths). 158 * 159 * Because anything can happen during a DOS session (defragment, 160 * directory sorting, etc.), we can't rely on an MS-DOS pseudo 161 * inode number to record the link. For this reason, the link 162 * will be done using hidden symbolic links. The following 163 * scenario illustrates how it works. 164 * 165 * Given a file /foo/file 166 * 167 * # 168 * ln /foo/file /tmp/file2 169 * 170 * become internally 171 * 172 * mv /foo/file /foo/-LINK1 173 * ln -s /foo/-LINK1 /foo/file 174 * ln -s /foo/-LINK1 /tmp/file2 175 * # 176 * 177 * Using this strategy, we can operate on /foo/file or /foo/file2. 178 * We can remove one and keep the other, like a normal Unix hard link. 179 * We can rename /foo/file or /tmp/file2 independently. 180 * 181 * The entry -LINK1 will be hidden. It will hold a link count. 182 * When all link are erased, the hidden file is erased too. 183 */ 184 185/* #Specification: weakness / hard link 186 * The strategy for hard link introduces a side effect that 187 * may or may not be acceptable. Here is the sequence 188 * 189 * # 190 * mkdir subdir1 191 * touch subdir1/file 192 * mkdir subdir2 193 * ln subdir1/file subdir2/file 194 * rm subdir1/file 195 * rmdir subdir1 196 * rmdir: subdir1: Directory not empty 197 * # 198 * 199 * This happen because there is an invisible file (--link) in 200 * subdir1 which is referenced by subdir2/file. 201 * 202 * Any idea ? 203 */ 204/* #Specification: weakness / hard link / rename directory 205 * Another weakness of hard link come from the fact that 206 * it is based on hidden symbolic links. Here is an example. 207 * 208 * # 209 * mkdir /subdir1 210 * touch /subdir1/file 211 * mkdir /subdir2 212 * ln /subdir1/file subdir2/file 213 * mv /subdir1 subdir3 214 * ls -l /subdir2/file 215 * # 216 * 217 * Since /subdir2/file is a hidden symbolic link 218 * to /subdir1/..hlinkNNN, accessing it will fail since 219 * /subdir1 does not exist anymore (has been renamed). 220 */ 221/* #Specification: hard link / directory 222 * A hard link can't be made on a directory. EPERM is returned 223 * in this case. 224 */ 225/* #Specification: hard link / first hard link 226 * The first time a hard link is done on a file, this 227 * file must be renamed and hidden. Then an internal 228 * symbolic link must be done on the hidden file. 229 * 230 * The second link is done after on this hidden file. 231 * 232 * It is expected that the Linux MSDOS file system 233 * keeps the same pseudo inode when a rename operation 234 * is done on a file in the same directory. 235 */ 236/* #Specification: function name / convention 237 * A simple convention for function names has been used in 238 * the UMSDOS filesystem. First, all functions use the prefix 239 * umsdos_ to avoid name clashes with other parts of the kernel. 240 * 241 * Standard VFS entry points use the prefix UMSDOS (upper case) 242 * so it's easier to tell them apart. 243 * N.B. (FIXME) PTW, the order and contents of this struct changed. 244 */ 245 246/* #Specification: mount / options 247 * Umsdos run on top of msdos. Currently, it supports no 248 * mount option, but happily pass all option received to 249 * the msdos driver. I am not sure if all msdos mount option 250 * make sense with Umsdos. Here are at least those who 251 * are useful. 252 * uid= 253 * gid= 254 * 255 * These options affect the operation of umsdos in directories 256 * which do not have an EMD file. They behave like normal 257 * msdos directory, with all limitation of msdos. 258 */ 259 260/* #Specification: pseudo root / mount 261 * When a umsdos fs is mounted, a special handling is done 262 * if it is the root partition. We check for the presence 263 * of the file /linux/etc/init or /linux/etc/rc or 264 * /linux/sbin/init. If one is there, we do a chroot("/linux"). 265 * 266 * We check both because (see init/main.c) the kernel 267 * try to exec init at different place and if it fails 268 * it tries /bin/sh /etc/rc. To be consistent with 269 * init/main.c, many more test would have to be done 270 * to locate init. Any complain ? 271 * 272 * The chroot is done manually in init/main.c but the 273 * info (the inode) is located at mount time and store 274 * in a global variable (pseudo_root) which is used at 275 * different place in the umsdos driver. There is no 276 * need to store this variable elsewhere because it 277 * will always be one, not one per mount. 278 * 279 * This feature allows the installation 280 * of a linux system within a DOS system in a subdirectory. 281 * 282 * A user may install its linux stuff in c:\linux 283 * avoiding any clash with existing DOS file and subdirectory. 284 * When linux boots, it hides this fact, showing a normal 285 * root directory with /etc /bin /tmp ... 286 * 287 * The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h 288 * in the macro UMSDOS_PSDROOT_NAME. 289 */ 290