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
237/* #Specification: mount / options
238 * Umsdos run on top of msdos. Currently, it supports no
239 * mount option, but happily pass all option received to
240 * the msdos driver. I am not sure if all msdos mount option
241 * make sense with Umsdos. Here are at least those who
242 * are useful.
243 * uid=
244 * gid=
245 * 
246 * These options affect the operation of umsdos in directories
247 * which do not have an EMD file. They behave like normal
248 * msdos directory, with all limitation of msdos.
249 */
250
251/* #Specification: pseudo root / mount
252 * When a umsdos fs is mounted, a special handling is done
253 * if it is the root partition. We check for the presence
254 * of the file /linux/etc/init or /linux/etc/rc or
255 * /linux/sbin/init. If one is there, we do a chroot("/linux").
256 * 
257 * We check both because (see init/main.c) the kernel
258 * try to exec init at different place and if it fails
259 * it tries /bin/sh /etc/rc. To be consistent with
260 * init/main.c, many more test would have to be done
261 * to locate init. Any complain ?
262 * 
263 * The chroot is done manually in init/main.c but the
264 * info (the inode) is located at mount time and store
265 * in a global variable (pseudo_root) which is used at
266 * different place in the umsdos driver. There is no
267 * need to store this variable elsewhere because it
268 * will always be one, not one per mount.
269 * 
270 * This feature allows the installation
271 * of a linux system within a DOS system in a subdirectory.
272 * 
273 * A user may install its linux stuff in c:\linux
274 * avoiding any clash with existing DOS file and subdirectory.
275 * When linux boots, it hides this fact, showing a normal
276 * root directory with /etc /bin /tmp ...
277 * 
278 * The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
279 * in the macro UMSDOS_PSDROOT_NAME.
280 */
281