2 * linux/fs/umsdos/emd.c
4 * Written 1993 by Jacques Gelinas
6 * Extended MS-DOS directory handling functions
9 #include <linux/types.h>
10 #include <linux/fcntl.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/msdos_fs.h>
16 #include <linux/umsdos_fs.h>
17 #include <linux/dcache.h>
18 #include <linux/pagemap.h>
20 #include <asm/delay.h>
22 static void copy_entry(struct umsdos_dirent
*p
, struct umsdos_dirent
*q
)
24 p
->name_len
= q
->name_len
;
25 p
->name
[p
->name_len
]='\0';
27 p
->nlink
= le16_to_cpu (q
->nlink
);
28 /* FIXME -- 32bit UID/GID issues */
29 p
->uid
= le16_to_cpu (q
->uid
);
30 p
->gid
= le16_to_cpu (q
->gid
);
31 p
->atime
= le32_to_cpu (q
->atime
);
32 p
->mtime
= le32_to_cpu (q
->mtime
);
33 p
->ctime
= le32_to_cpu (q
->ctime
);
34 p
->rdev
= le16_to_cpu (q
->rdev
);
35 p
->mode
= le16_to_cpu (q
->mode
);
39 * Lookup the EMD dentry for a directory.
41 * Note: the caller must hold a lock on the parent directory.
43 struct dentry
*umsdos_get_emd_dentry(struct dentry
*parent
)
47 demd
= umsdos_lookup_dentry(parent
, UMSDOS_EMD_FILE
,
48 UMSDOS_EMD_NAMELEN
, 1);
53 * Check whether a directory has an EMD file.
55 * Note: the caller must hold a lock on the parent directory.
57 int umsdos_have_emd(struct dentry
*dir
)
59 struct dentry
*demd
= umsdos_get_emd_dentry (dir
);
71 * Create the EMD file for a directory if it doesn't
72 * already exist. Returns 0 or an error code.
74 * Note: the caller must hold a lock on the parent directory.
76 int umsdos_make_emd(struct dentry
*parent
)
78 struct dentry
*demd
= umsdos_get_emd_dentry(parent
);
79 int err
= PTR_ERR(demd
);
82 printk("umsdos_make_emd: can't get dentry in %s, err=%d\n",
83 parent
->d_name
.name
, err
);
87 /* already created? */
92 Printk(("umsdos_make_emd: creating EMD %s/%s\n",
93 parent
->d_name
.name
, demd
->d_name
.name
));
95 err
= msdos_create(parent
->d_inode
, demd
, S_IFREG
| 0777);
98 "umsdos_make_emd: create %s/%s failed, err=%d\n",
99 parent
->d_name
.name
, demd
->d_name
.name
, err
);
109 * Read an entry from the EMD file.
110 * Support variable length record.
111 * Return -EIO if error, 0 if OK.
113 * does not change {d,i}_count
116 int umsdos_emd_dir_readentry (struct dentry
*demd
, loff_t
*pos
, struct umsdos_dirent
*entry
)
118 struct address_space
*mapping
= demd
->d_inode
->i_mapping
;
120 struct umsdos_dirent
*p
;
121 int offs
= *pos
& ~PAGE_CACHE_MASK
;
125 page
= read_cache_page(mapping
, *pos
>>PAGE_CACHE_SHIFT
,
126 (filler_t
*)mapping
->a_ops
->readpage
, NULL
);
130 if (!Page_Uptodate(page
))
132 p
= (struct umsdos_dirent
*)((char*)kmap(page
)+offs
);
134 /* if this is an invalid entry (invalid name length), ignore it */
135 if( p
->name_len
> UMSDOS_MAXNAME
)
137 printk (KERN_WARNING
"Ignoring invalid EMD entry with size %d\n", entry
->name_len
);
139 ret
= -ENAMETOOLONG
; /* notify umssync(8) code that something is wrong */
142 recsize
= umsdos_evalrecsize(p
->name_len
);
143 if (offs
+ recsize
> PAGE_CACHE_SIZE
) {
145 int part
= (char *)(page_address(page
) + PAGE_CACHE_SIZE
) - p
->spare
;
146 page2
= read_cache_page(mapping
, 1+(*pos
>>PAGE_CACHE_SHIFT
),
147 (filler_t
*)mapping
->a_ops
->readpage
, NULL
);
150 page_cache_release(page
);
155 if (!Page_Uptodate(page2
)) {
157 page_cache_release(page2
);
160 memcpy(entry
->spare
,p
->spare
,part
);
161 memcpy(entry
->spare
+part
,(char*)kmap(page2
),
162 recsize
+offs
-PAGE_CACHE_SIZE
);
164 page_cache_release(page2
);
166 memcpy(entry
->spare
,p
->spare
,((char*)p
+recsize
)-p
->spare
);
167 copy_entry(entry
, p
);
169 page_cache_release(page
);
173 page_cache_release(page
);
174 page
= ERR_PTR(-EIO
);
176 return PTR_ERR(page
);
181 * Write an entry in the EMD file.
182 * Return 0 if OK, -EIO if some error.
184 * Note: the caller must hold a lock on the parent directory.
186 int umsdos_writeentry (struct dentry
*parent
, struct umsdos_info
*info
,
189 struct inode
*dir
= parent
->d_inode
;
190 struct umsdos_dirent
*entry
= &info
->entry
;
191 struct dentry
*emd_dentry
;
193 struct umsdos_dirent entry0
,*p
;
194 struct address_space
*mapping
;
195 struct page
*page
, *page2
= NULL
;
198 emd_dentry
= umsdos_get_emd_dentry(parent
);
199 ret
= PTR_ERR(emd_dentry
);
200 if (IS_ERR(emd_dentry
))
202 /* make sure there's an EMD file */
204 if (!emd_dentry
->d_inode
) {
206 "umsdos_writeentry: no EMD file in %s/%s\n",
207 parent
->d_parent
->d_name
.name
, parent
->d_name
.name
);
212 /* #Specification: EMD file / empty entries
213 * Unused entries in the EMD file are identified
214 * by the name_len field equal to 0. However to
215 * help future extension (or bug correction :-( ),
216 * empty entries are filled with 0.
218 memset (&entry0
, 0, sizeof (entry0
));
220 } else if (entry
->name_len
> 0) {
221 memset (entry
->name
+ entry
->name_len
, '\0',
222 sizeof (entry
->name
) - entry
->name_len
);
223 /* #Specification: EMD file / spare bytes
224 * 10 bytes are unused in each record of the EMD. They
225 * are set to 0 all the time, so it will be possible
226 * to do new stuff and rely on the state of those
227 * bytes in old EMD files.
229 memset (entry
->spare
, 0, sizeof (entry
->spare
));
232 /* write the entry and update the parent timestamps */
233 mapping
= emd_dentry
->d_inode
->i_mapping
;
234 offs
= info
->f_pos
& ~PAGE_CACHE_MASK
;
236 page
= grab_cache_page(mapping
, info
->f_pos
>>PAGE_CACHE_SHIFT
);
239 p
= (struct umsdos_dirent
*) (page_address(page
) + offs
);
240 if (offs
+ info
->recsize
> PAGE_CACHE_SIZE
) {
241 ret
= mapping
->a_ops
->prepare_write(NULL
,page
,offs
,
245 page2
= grab_cache_page(mapping
,
246 (info
->f_pos
>>PAGE_CACHE_SHIFT
)+1);
249 ret
= mapping
->a_ops
->prepare_write(NULL
,page2
,0,
250 offs
+info
->recsize
-PAGE_CACHE_SIZE
);
253 p
->name_len
= entry
->name_len
;
254 p
->flags
= entry
->flags
;
255 p
->nlink
= cpu_to_le16(entry
->nlink
);
256 p
->uid
= cpu_to_le16(entry
->uid
);
257 p
->gid
= cpu_to_le16(entry
->gid
);
258 p
->atime
= cpu_to_le32(entry
->atime
);
259 p
->mtime
= cpu_to_le32(entry
->mtime
);
260 p
->ctime
= cpu_to_le32(entry
->ctime
);
261 p
->rdev
= cpu_to_le16(entry
->rdev
);
262 p
->mode
= cpu_to_le16(entry
->mode
);
263 memcpy(p
->name
,entry
->name
,
264 (char *)(page_address(page
) + PAGE_CACHE_SIZE
) - p
->spare
);
265 memcpy(page_address(page2
),
266 entry
->spare
+PAGE_CACHE_SIZE
-offs
,
267 offs
+info
->recsize
-PAGE_CACHE_SIZE
);
268 ret
= mapping
->a_ops
->commit_write(NULL
,page2
,0,
269 offs
+info
->recsize
-PAGE_CACHE_SIZE
);
272 ret
= mapping
->a_ops
->commit_write(NULL
,page
,offs
,
275 page_cache_release(page2
);
279 ret
= mapping
->a_ops
->prepare_write(NULL
,page
,offs
,
280 offs
+ info
->recsize
);
283 p
->name_len
= entry
->name_len
;
284 p
->flags
= entry
->flags
;
285 p
->nlink
= cpu_to_le16(entry
->nlink
);
286 p
->uid
= cpu_to_le16(entry
->uid
);
287 p
->gid
= cpu_to_le16(entry
->gid
);
288 p
->atime
= cpu_to_le32(entry
->atime
);
289 p
->mtime
= cpu_to_le32(entry
->mtime
);
290 p
->ctime
= cpu_to_le32(entry
->ctime
);
291 p
->rdev
= cpu_to_le16(entry
->rdev
);
292 p
->mode
= cpu_to_le16(entry
->mode
);
293 memcpy(p
->spare
,entry
->spare
,((char*)p
+info
->recsize
)-p
->spare
);
294 ret
= mapping
->a_ops
->commit_write(NULL
,page
,offs
,
295 offs
+ info
->recsize
);
300 page_cache_release(page
);
302 dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
303 mark_inode_dirty(dir
);
308 Printk (("umsdos_writeentry /mn/: returning %d...\n", ret
));
312 page_cache_release(page2
);
314 ClearPageUptodate(page
);
318 page_cache_release(page
);
319 printk ("UMSDOS: problem with EMD file: can't write\n");
324 * General search, locate a name in the EMD file or an empty slot to
325 * store it. if info->entry.name_len == 0, search the first empty
326 * slot (of the proper size).
328 * Return 0 if found, -ENOENT if not found, another error code if
331 * So this routine is used to either find an existing entry or to
332 * create a new one, while making sure it is a new one. After you
333 * get -ENOENT, you make sure the entry is stuffed correctly and
334 * call umsdos_writeentry().
336 * To delete an entry, you find it, zero out the entry (memset)
337 * and call umsdos_writeentry().
339 * All this to say that umsdos_writeentry must be called after this
340 * function since it relies on the f_pos field of info.
342 * Note: the caller must hold a lock on the parent directory.
344 /* #Specification: EMD file structure
345 * The EMD file uses a fairly simple layout. It is made of records
346 * (UMSDOS_REC_SIZE == 64). When a name can't be written in a single
347 * record, multiple contiguous records are allocated.
350 static int umsdos_find (struct dentry
*demd
, struct umsdos_info
*info
)
352 struct umsdos_dirent
*entry
= &info
->entry
;
353 int recsize
= info
->recsize
;
354 struct inode
*emd_dir
;
357 off_t posok
; /* Position available to store the entry */
358 off_t one
; /* One empty position -> maybe <- large enough */
362 struct address_space
*mapping
;
364 struct page
*page
= NULL
;
366 int offs
= PAGE_CACHE_SIZE
,max_offs
= PAGE_CACHE_SIZE
;
370 /* make sure there's an EMD file ... */
372 emd_dir
= demd
->d_inode
;
375 mapping
= emd_dir
->i_mapping
;
376 readpage
= (filler_t
*)mapping
->a_ops
->readpage
;
378 empty
.posok
= emd_dir
->i_size
;
380 struct umsdos_dirent
*rentry
;
383 if (offs
>= max_offs
) {
386 page_cache_release(page
);
389 if (pos
>= emd_dir
->i_size
) {
390 info
->f_pos
= empty
.posok
;
393 if (++index
== (emd_dir
->i_size
>>PAGE_CACHE_SHIFT
))
394 max_offs
= emd_dir
->i_size
& ~PAGE_CACHE_MASK
;
395 offs
-= PAGE_CACHE_SIZE
;
396 page
= read_cache_page(mapping
,index
,readpage
,NULL
);
400 if (!Page_Uptodate(page
))
402 p
= (char*)kmap(page
);
405 rentry
= (struct umsdos_dirent
*)(p
+offs
);
407 if (rentry
->name_len
== 0) {
408 /* We are looking for an empty section at least */
409 /* as large as recsize. */
410 if (entry
->name_len
== 0) {
415 offs
+= UMSDOS_REC_SIZE
;
416 pos
+= UMSDOS_REC_SIZE
;
420 empty
.one
= pos
-UMSDOS_REC_SIZE
;
421 empty_size
+= UMSDOS_REC_SIZE
;
422 if (empty_size
== recsize
) {
423 /* Here is a large enough section. */
424 empty
.posok
= empty
.one
;
430 entry_size
= umsdos_evalrecsize(rentry
->name_len
);
431 if (entry_size
> PAGE_CACHE_SIZE
)
434 if (entry
->name_len
!= rentry
->name_len
)
437 if (entry_size
+ offs
> PAGE_CACHE_SIZE
) {
438 /* Sucker spans the page boundary */
439 int len
= (p
+PAGE_CACHE_SIZE
)-rentry
->name
;
440 struct page
*next_page
;
442 next_page
= read_cache_page(mapping
,index
+1,readpage
,NULL
);
443 if (IS_ERR(next_page
)) {
444 page_cache_release(page
);
448 wait_on_page(next_page
);
449 if (!Page_Uptodate(next_page
)) {
450 page_cache_release(page
);
454 q
= (char*)kmap(next_page
);
455 if (memcmp(entry
->name
, rentry
->name
, len
) ||
456 memcmp(entry
->name
+len
, q
, entry
->name_len
-len
)) {
458 page_cache_release(next_page
);
462 page_cache_release(next_page
);
463 } else if (memcmp (entry
->name
, rentry
->name
, entry
->name_len
))
467 copy_entry(entry
, rentry
);
476 page_cache_release(page
);
478 umsdos_manglename (info
);
485 page_cache_release(page
);
486 page
= ERR_PTR(-EIO
);
488 return PTR_ERR(page
);
493 * Add a new entry in the EMD file.
494 * Return 0 if OK or a negative error code.
495 * Return -EEXIST if the entry already exists.
497 * Complete the information missing in info.
499 * N.B. What if the EMD file doesn't exist?
502 int umsdos_newentry (struct dentry
*parent
, struct umsdos_info
*info
)
504 int err
, ret
= -EEXIST
;
505 struct dentry
*demd
= umsdos_get_emd_dentry(parent
);
510 err
= umsdos_find (demd
, info
);
511 if (err
&& err
== -ENOENT
) {
512 ret
= umsdos_writeentry (parent
, info
, 0);
513 Printk (("umsdos_writeentry EMD ret = %d\n", ret
));
521 * Create a new hidden link.
522 * Return 0 if OK, an error code if not.
525 /* #Specification: hard link / hidden name
526 * When a hard link is created, the original file is renamed
527 * to a hidden name. The name is "..LINKNNN" where NNN is a
528 * number define from the entry offset in the EMD file.
530 int umsdos_newhidden (struct dentry
*parent
, struct umsdos_info
*info
)
533 struct dentry
*demd
= umsdos_get_emd_dentry(parent
);
538 umsdos_parse ("..LINK", 6, info
);
539 info
->entry
.name_len
= 0;
540 ret
= umsdos_find (demd
, info
);
541 if (ret
== -ENOENT
|| ret
== 0) {
542 info
->entry
.name_len
= sprintf (info
->entry
.name
,
543 "..LINK%ld", info
->f_pos
);
552 * Remove an entry from the EMD file.
553 * Return 0 if OK, a negative error code otherwise.
555 * Complete the information missing in info.
558 int umsdos_delentry (struct dentry
*parent
, struct umsdos_info
*info
, int isdir
)
561 struct dentry
*demd
= umsdos_get_emd_dentry(parent
);
566 ret
= umsdos_find (demd
, info
);
569 if (info
->entry
.name_len
== 0)
572 if ((isdir
!= 0) != (S_ISDIR (info
->entry
.mode
) != 0)) {
573 if (S_ISDIR (info
->entry
.mode
)) {
580 ret
= umsdos_writeentry (parent
, info
, 1);
588 * Verify that an EMD directory is empty.
591 * 1 if empty (except for EMD file),
592 * 2 if empty or no EMD file.
595 int umsdos_isempty (struct dentry
*dentry
)
601 demd
= umsdos_get_emd_dentry(dentry
);
604 /* If the EMD file does not exist, it is certainly empty. :-) */
609 while (pos
< demd
->d_inode
->i_size
) {
610 struct umsdos_dirent entry
;
612 if (umsdos_emd_dir_readentry (demd
, &pos
, &entry
) != 0) {
616 if (entry
.name_len
!= 0) {
629 * Locate an entry in a EMD directory.
630 * Return 0 if OK, error code if not, generally -ENOENT.
638 int umsdos_findentry (struct dentry
*parent
, struct umsdos_info
*info
,
642 struct dentry
*demd
= umsdos_get_emd_dentry(parent
);
647 ret
= umsdos_find (demd
, info
);
653 if (S_ISDIR (info
->entry
.mode
))
657 if (!S_ISDIR (info
->entry
.mode
))
662 Printk (("umsdos_findentry: returning %d\n", ret
));