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>
19 #include <asm/uaccess.h>
21 #include <asm/delay.h>
25 * Read a file into kernel space memory
26 * returns how many bytes read (from fat_file_read)
29 ssize_t
umsdos_file_read_kmem ( struct file
*filp
,
34 mm_segment_t old_fs
= get_fs ();
37 MSDOS_I (filp
->f_dentry
->d_inode
)->i_binary
= 2;
38 ret
= fat_file_read (filp
, buf
, count
, &filp
->f_pos
);
45 * Write to file from kernel space.
46 * Does the real job, assumes all structures are initialized!
50 ssize_t
umsdos_file_write_kmem_real (struct file
* filp
,
54 mm_segment_t old_fs
= get_fs ();
57 /* note: i_binary=2 is for CVF-FAT. We put it here, instead of
58 * umsdos_file_write_kmem, since it is also wise not to compress
59 * symlinks (in the unlikely event that they are > 512 bytes and
61 * FIXME: should we set it when reading symlinks too?
64 MSDOS_I (filp
->f_dentry
->d_inode
)->i_binary
= 2;
67 ret
= fat_file_write (filp
, buf
, count
, &filp
->f_pos
);
70 printk(KERN_WARNING
"umsdos_file_write: ret=%d\n", ret
);
73 #ifdef UMSDOS_PARANOIA
75 printk(KERN_WARNING
"umsdos_file_write: count=%u, ret=%u\n", count
, ret
);
83 * Write to a file from kernel space.
86 ssize_t
umsdos_file_write_kmem (struct file
*filp
,
92 ret
= umsdos_file_write_kmem_real (filp
, buf
, count
);
99 * Write a block of bytes into one EMD file.
100 * The block of data is NOT in user space.
102 * Return 0 if OK, a negative error code if not.
104 * Note: buffer is in kernel memory, not in user space.
107 ssize_t
umsdos_emd_dir_write ( struct file
*filp
,
114 struct umsdos_dirent
*d
= (struct umsdos_dirent
*) buf
;
116 d
->nlink
= cpu_to_le16 (d
->nlink
);
117 d
->uid
= cpu_to_le16 (d
->uid
);
118 d
->gid
= cpu_to_le16 (d
->gid
);
119 d
->atime
= cpu_to_le32 (d
->atime
);
120 d
->mtime
= cpu_to_le32 (d
->mtime
);
121 d
->ctime
= cpu_to_le32 (d
->ctime
);
122 d
->rdev
= cpu_to_le16 (d
->rdev
);
123 d
->mode
= cpu_to_le16 (d
->mode
);
127 Printk (("umsdos_emd_dir_write /mn/: calling write_kmem with %p, %p, %d, %Ld\n",
128 filp
, buf
, count
, filp
->f_pos
));
129 written
= umsdos_file_write_kmem (filp
, buf
, count
);
132 d
->nlink
= le16_to_cpu (d
->nlink
);
133 d
->uid
= le16_to_cpu (d
->uid
);
134 d
->gid
= le16_to_cpu (d
->gid
);
135 d
->atime
= le32_to_cpu (d
->atime
);
136 d
->mtime
= le32_to_cpu (d
->mtime
);
137 d
->ctime
= le32_to_cpu (d
->ctime
);
138 d
->rdev
= le16_to_cpu (d
->rdev
);
139 d
->mode
= le16_to_cpu (d
->mode
);
142 #ifdef UMSDOS_PARANOIA
143 if (written
!= count
)
144 printk(KERN_ERR
"umsdos_emd_dir_write: ERROR: written (%d) != count (%d)\n",
148 return (written
!= count
) ? -EIO
: 0;
154 * Read a block of bytes from one EMD file.
155 * The block of data is NOT in user space.
156 * Return 0 if OK, -EIO if any error.
158 /* buffer in kernel memory, not in user space */
160 ssize_t
umsdos_emd_dir_read (struct file
*filp
, char *buf
, size_t count
)
162 ssize_t sizeread
, ret
= 0;
165 struct umsdos_dirent
*d
= (struct umsdos_dirent
*) buf
;
170 sizeread
= umsdos_file_read_kmem (filp
, buf
, count
);
171 if (sizeread
!= count
) {
173 "UMSDOS: EMD problem, pos=%Ld, count=%d, read=%d\n",
174 filp
->f_pos
, count
, sizeread
);
178 d
->nlink
= le16_to_cpu (d
->nlink
);
179 d
->uid
= le16_to_cpu (d
->uid
);
180 d
->gid
= le16_to_cpu (d
->gid
);
181 d
->atime
= le32_to_cpu (d
->atime
);
182 d
->mtime
= le32_to_cpu (d
->mtime
);
183 d
->ctime
= le32_to_cpu (d
->ctime
);
184 d
->rdev
= le16_to_cpu (d
->rdev
);
185 d
->mode
= le16_to_cpu (d
->mode
);
192 * Lookup the EMD dentry for a directory.
194 * Note: the caller must hold a lock on the parent directory.
196 struct dentry
*umsdos_get_emd_dentry(struct dentry
*parent
)
200 demd
= umsdos_lookup_dentry(parent
, UMSDOS_EMD_FILE
,
201 UMSDOS_EMD_NAMELEN
, 1);
206 * Check whether a directory has an EMD file.
208 * Note: the caller must hold a lock on the parent directory.
210 int umsdos_have_emd(struct dentry
*dir
)
212 struct dentry
*demd
= umsdos_get_emd_dentry (dir
);
224 * Create the EMD file for a directory if it doesn't
225 * already exist. Returns 0 or an error code.
227 * Note: the caller must hold a lock on the parent directory.
229 int umsdos_make_emd(struct dentry
*parent
)
231 struct dentry
*demd
= umsdos_get_emd_dentry(parent
);
232 int err
= PTR_ERR(demd
);
235 printk("umsdos_make_emd: can't get dentry in %s, err=%d\n",
236 parent
->d_name
.name
, err
);
240 /* already created? */
245 Printk(("umsdos_make_emd: creating EMD %s/%s\n",
246 parent
->d_name
.name
, demd
->d_name
.name
));
248 err
= msdos_create(parent
->d_inode
, demd
, S_IFREG
| 0777);
251 "umsdos_make_emd: create %s/%s failed, err=%d\n",
252 parent
->d_name
.name
, demd
->d_name
.name
, err
);
256 parent
->d_inode
->u
.umsdos_i
.i_emd_dir
= demd
->d_inode
->i_ino
;
266 * Read an entry from the EMD file.
267 * Support variable length record.
268 * Return -EIO if error, 0 if OK.
270 * does not change {d,i}_count
273 int umsdos_emd_dir_readentry (struct file
*filp
, struct umsdos_dirent
*entry
)
277 Printk ((KERN_DEBUG
"umsdos_emd_dir_readentry /mn/: entering.\n"));
279 ret
= umsdos_emd_dir_read (filp
, (char *) entry
, UMSDOS_REC_SIZE
);
280 if (ret
== 0) { /* if no error */
281 /* Variable size record. Maybe, we have to read some more */
282 int recsize
= umsdos_evalrecsize (entry
->name_len
);
284 if (recsize
> UMSDOS_REC_SIZE
) {
285 Printk ((KERN_DEBUG
"umsdos_emd_dir_readentry /mn/: %d > %d!\n",
286 recsize
, UMSDOS_REC_SIZE
));
287 ret
= umsdos_emd_dir_read (filp
,
288 ((char *) entry
) + UMSDOS_REC_SIZE
,
289 recsize
- UMSDOS_REC_SIZE
);
292 Printk (("umsdos_emd_dir_readentry /mn/: ret=%d.\n", ret
));
293 if (entry
&& ret
== 0) {
294 Printk (("umsdos_emd_dir_readentry /mn/: returning len=%d,name=%.*s\n",
295 (int) entry
->name_len
, (int) entry
->name_len
, entry
->name
));
303 * Write an entry in the EMD file.
304 * Return 0 if OK, -EIO if some error.
306 * Note: the caller must hold a lock on the parent directory.
308 static int umsdos_writeentry (struct dentry
*parent
, struct umsdos_info
*info
,
311 struct inode
*dir
= parent
->d_inode
;
312 struct umsdos_dirent
*entry
= &info
->entry
;
313 struct dentry
*emd_dentry
;
315 struct umsdos_dirent entry0
;
318 emd_dentry
= umsdos_get_emd_dentry(parent
);
319 ret
= PTR_ERR(emd_dentry
);
320 if (IS_ERR(emd_dentry
))
322 /* make sure there's an EMD file */
324 if (!emd_dentry
->d_inode
) {
326 "umsdos_writeentry: no EMD file in %s/%s\n",
327 parent
->d_parent
->d_name
.name
, parent
->d_name
.name
);
332 /* #Specification: EMD file / empty entries
333 * Unused entries in the EMD file are identified
334 * by the name_len field equal to 0. However to
335 * help future extension (or bug correction :-( ),
336 * empty entries are filled with 0.
338 memset (&entry0
, 0, sizeof (entry0
));
340 } else if (entry
->name_len
> 0) {
341 memset (entry
->name
+ entry
->name_len
, '\0',
342 sizeof (entry
->name
) - entry
->name_len
);
343 /* #Specification: EMD file / spare bytes
344 * 10 bytes are unused in each record of the EMD. They
345 * are set to 0 all the time, so it will be possible
346 * to do new stuff and rely on the state of those
347 * bytes in old EMD files.
349 memset (entry
->spare
, 0, sizeof (entry
->spare
));
352 fill_new_filp (&filp
, emd_dentry
);
353 filp
.f_pos
= info
->f_pos
;
355 filp
.f_flags
= O_RDWR
;
357 /* write the entry and update the parent timestamps */
358 ret
= umsdos_emd_dir_write (&filp
, (char *) entry
, info
->recsize
);
360 dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
361 mark_inode_dirty(dir
);
363 printk ("UMSDOS: problem with EMD file: can't write\n");
368 Printk (("umsdos_writeentry /mn/: returning %d...\n", ret
));
374 #define CHUNK_SIZE (8*UMSDOS_REC_SIZE)
376 char buffer
[CHUNK_SIZE
];
377 int pos
; /* read offset in buffer */
378 int size
; /* Current size of buffer */
385 * Fill the read buffer and take care of the bytes remaining inside.
386 * Unread bytes are simply moved to the beginning.
388 * Return -ENOENT if EOF, 0 if OK, a negative error code if any problem.
390 * Note: the caller must hold a lock on the parent directory.
393 static int umsdos_fillbuf (struct find_buffer
*buf
)
395 struct inode
*inode
= buf
->filp
.f_dentry
->d_inode
;
396 int mustmove
= buf
->size
- buf
->pos
;
397 int mustread
, remain
;
401 memcpy (buf
->buffer
, buf
->buffer
+ buf
->pos
, mustmove
);
404 mustread
= CHUNK_SIZE
- mustmove
;
405 remain
= inode
->i_size
- buf
->filp
.f_pos
;
406 if (remain
< mustread
)
409 ret
= umsdos_emd_dir_read (&buf
->filp
, buf
->buffer
+ mustmove
,
412 buf
->size
= mustmove
+ mustread
;
413 } else if (mustmove
) {
414 buf
->size
= mustmove
;
423 * General search, locate a name in the EMD file or an empty slot to
424 * store it. if info->entry.name_len == 0, search the first empty
425 * slot (of the proper size).
427 * Return 0 if found, -ENOENT if not found, another error code if
430 * So this routine is used to either find an existing entry or to
431 * create a new one, while making sure it is a new one. After you
432 * get -ENOENT, you make sure the entry is stuffed correctly and
433 * call umsdos_writeentry().
435 * To delete an entry, you find it, zero out the entry (memset)
436 * and call umsdos_writeentry().
438 * All this to say that umsdos_writeentry must be called after this
439 * function since it relies on the f_pos field of info.
441 * Note: the caller must hold a lock on the parent directory.
443 /* #Specification: EMD file structure
444 * The EMD file uses a fairly simple layout. It is made of records
445 * (UMSDOS_REC_SIZE == 64). When a name can't be written in a single
446 * record, multiple contiguous records are allocated.
449 static int umsdos_find (struct dentry
*parent
, struct umsdos_info
*info
)
451 struct umsdos_dirent
*entry
= &info
->entry
;
452 int recsize
= info
->recsize
;
454 struct inode
*emd_dir
;
456 struct find_buffer buf
;
458 off_t posok
; /* Position available to store the entry */
459 int found
; /* A valid empty position has been found. */
460 off_t one
; /* One empty position -> maybe <- large enough */
461 int onesize
; /* size of empty region starting at one */
464 Printk (("umsdos_find: locating %s in %s/%s\n",
465 entry
->name
, parent
->d_parent
->d_name
.name
, parent
->d_name
.name
));
468 * Lookup the EMD file in the parent directory.
470 demd
= umsdos_get_emd_dentry(parent
);
474 /* make sure there's an EMD file ... */
476 emd_dir
= demd
->d_inode
;
480 Printk(("umsdos_find: found EMD file %s/%s, ino=%p\n",
481 demd
->d_parent
->d_name
.name
, demd
->d_name
.name
, emd_dir
));
483 fill_new_filp (&buf
.filp
, demd
);
489 empty
.posok
= emd_dir
->i_size
;
492 struct umsdos_dirent
*rentry
= (struct umsdos_dirent
*)
493 (buf
.buffer
+ buf
.pos
);
494 int file_pos
= buf
.filp
.f_pos
- buf
.size
+ buf
.pos
;
496 if (buf
.pos
== buf
.size
) {
497 ret
= umsdos_fillbuf (&buf
);
499 /* Not found, so note where it can be added */
500 info
->f_pos
= empty
.posok
;
503 } else if (rentry
->name_len
== 0) {
504 /* We are looking for an empty section at least */
505 /* as large as recsize. */
506 if (entry
->name_len
== 0) {
507 info
->f_pos
= file_pos
;
510 } else if (!empty
.found
) {
511 if (empty
.onesize
== 0) {
512 /* This is the first empty record of a section. */
513 empty
.one
= file_pos
;
515 /* grow the empty section */
516 empty
.onesize
+= UMSDOS_REC_SIZE
;
517 if (empty
.onesize
== recsize
) {
518 /* Here is a large enough section. */
519 empty
.posok
= empty
.one
;
523 buf
.pos
+= UMSDOS_REC_SIZE
;
525 int entry_size
= umsdos_evalrecsize (rentry
->name_len
);
527 if (buf
.pos
+ entry_size
> buf
.size
) {
528 ret
= umsdos_fillbuf (&buf
);
530 /* Not found, so note where it can be added */
531 info
->f_pos
= empty
.posok
;
535 empty
.onesize
= 0; /* Reset the free slot search. */
536 if (entry
->name_len
== rentry
->name_len
537 && memcmp (entry
->name
, rentry
->name
, rentry
->name_len
) == 0) {
538 info
->f_pos
= file_pos
;
543 buf
.pos
+= entry_size
;
548 Printk(("umsdos_find: ready to mangle %s, len=%d, pos=%ld\n",
549 entry
->name
, entry
->name_len
, (long)info
->f_pos
));
550 umsdos_manglename (info
);
556 Printk (("umsdos_find: returning %d\n", ret
));
562 * Add a new entry in the EMD file.
563 * Return 0 if OK or a negative error code.
564 * Return -EEXIST if the entry already exists.
566 * Complete the information missing in info.
568 * N.B. What if the EMD file doesn't exist?
571 int umsdos_newentry (struct dentry
*parent
, struct umsdos_info
*info
)
573 int err
, ret
= -EEXIST
;
575 err
= umsdos_find (parent
, info
);
576 if (err
&& err
== -ENOENT
) {
577 ret
= umsdos_writeentry (parent
, info
, 0);
578 Printk (("umsdos_writeentry EMD ret = %d\n", ret
));
585 * Create a new hidden link.
586 * Return 0 if OK, an error code if not.
589 /* #Specification: hard link / hidden name
590 * When a hard link is created, the original file is renamed
591 * to a hidden name. The name is "..LINKNNN" where NNN is a
592 * number define from the entry offset in the EMD file.
594 int umsdos_newhidden (struct dentry
*parent
, struct umsdos_info
*info
)
598 umsdos_parse ("..LINK", 6, info
);
599 info
->entry
.name_len
= 0;
600 ret
= umsdos_find (parent
, info
);
601 if (ret
== -ENOENT
|| ret
== 0) {
602 info
->entry
.name_len
= sprintf (info
->entry
.name
,
603 "..LINK%ld", info
->f_pos
);
611 * Remove an entry from the EMD file.
612 * Return 0 if OK, a negative error code otherwise.
614 * Complete the information missing in info.
617 int umsdos_delentry (struct dentry
*parent
, struct umsdos_info
*info
, int isdir
)
621 ret
= umsdos_find (parent
, info
);
624 if (info
->entry
.name_len
== 0)
627 if ((isdir
!= 0) != (S_ISDIR (info
->entry
.mode
) != 0)) {
628 if (S_ISDIR (info
->entry
.mode
)) {
635 ret
= umsdos_writeentry (parent
, info
, 1);
643 * Verify that an EMD directory is empty.
646 * 1 if empty (except for EMD file),
647 * 2 if empty or no EMD file.
650 int umsdos_isempty (struct dentry
*dentry
)
656 demd
= umsdos_get_emd_dentry(dentry
);
659 /* If the EMD file does not exist, it is certainly empty. :-) */
663 fill_new_filp (&filp
, demd
);
664 filp
.f_flags
= O_RDONLY
;
667 while (filp
.f_pos
< demd
->d_inode
->i_size
) {
668 struct umsdos_dirent entry
;
670 if (umsdos_emd_dir_readentry (&filp
, &entry
) != 0) {
674 if (entry
.name_len
!= 0) {
683 Printk(("umsdos_isempty: checked %s/%s, empty=%d\n",
684 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, ret
));
690 * Locate an entry in a EMD directory.
691 * Return 0 if OK, error code if not, generally -ENOENT.
699 int umsdos_findentry (struct dentry
*parent
, struct umsdos_info
*info
,
704 ret
= umsdos_find (parent
, info
);
710 if (S_ISDIR (info
->entry
.mode
))
714 if (!S_ISDIR (info
->entry
.mode
))
719 Printk (("umsdos_findentry: returning %d\n", ret
));