1 diff -Nru linux/Documentation/Configure.help linux.new/Documentation/Configure.help
2 --- linux/Documentation/Configure.help Fri Sep 7 11:18:50 2001
3 +++ linux.new/Documentation/Configure.help Fri Sep 7 11:32:15 2001
5 like lynx or netscape). Say Y here if you want to be able to read
6 Joliet CDROMs under Linux.
8 +UDF Filesystem support (EXPERIMENTAL)
10 + This is the new filesystem used by some CDROMS and DVD drivers. Say
11 + Y if you intend to mount DVD discs or CDRWs written in packet mode,
12 + or if written to by other UDF utilities, such as DirectCD. Please
13 + read Documentation/filesystems/udf.txt
15 + This filesystem support is also available as a module ( = code which
16 + can be inserted in and removed from the running kernel whenever you
17 + want). The module is called udf.o. If you want to compile it as a
18 + module, say M here and read Documentation/modules.txt.
22 +UDF read-write support (FOR TESTING ONLY)
24 + Say Y if you want to test write support for UDF filesystems.
25 + Due to lack of support for writing to CDR/CDRW's, this option
26 + is only supported for Hard Discs, DVD-RAM, and loopback files.
30 If you want to use one of the FAT-based filesystems (the MS-DOS,
31 diff -Nru linux/Documentation/filesystems/00-INDEX linux.new/Documentation/filesystems/00-INDEX
32 --- linux/Documentation/filesystems/00-INDEX Sun Mar 25 18:31:56 2001
33 +++ linux.new/Documentation/filesystems/00-INDEX Fri Sep 7 11:32:15 2001
35 - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
37 - info on the SystemV/Coherent filesystem.
39 + - info and mount options for the UDF filesystem.
41 - info on the ufs filesystem.
43 diff -Nru linux/Documentation/filesystems/udf.txt linux.new/Documentation/filesystems/udf.txt
44 --- linux/Documentation/filesystems/udf.txt Thu Jan 1 01:00:00 1970
45 +++ linux.new/Documentation/filesystems/udf.txt Fri Sep 7 11:32:15 2001
48 +* ./Documentation/filesystems/udf.txt
50 +UDF Filesystem version 0.9.2.1
52 +If you encounter problems with reading UDF discs using this driver,
53 +please report them to linux_udf@hpesjro.fc.hp.com, which is the
56 +Write support requires a block driver which supports writing. The current
57 +scsi and ide cdrom drivers do not support writing.
59 +-------------------------------------------------------------------------------
60 +The following mount options are supported:
62 + gid= Set the default group.
63 + umask= Set the default umask.
64 + uid= Set the default user.
65 + bs= Set the block size.
66 + unhide Show otherwise hidden files.
67 + undelete Show deleted files in lists.
68 + adinicb Embed data in the inode (default)
69 + noadinicb Don't embed data in the inode
70 + shortad Use short ad's
71 + longad Use long ad's (default)
72 + strict Set strict conformance (unused)
74 +The remaining are for debugging and disaster recovery:
76 + novrs Skip volume sequence recognition
78 +The following expect a offset from 0.
80 + session= Set the CDROM session (default= last session)
81 + anchor= Override standard anchor location. (default= 256)
82 + volume= Override the VolumeDesc location. (unused)
83 + partition= Override the PartitionDesc location. (unused)
84 + lastblock= Set the last block of the filesystem/
86 +The following expect a offset from the partition root.
88 + fileset= Override the fileset block location. (unused)
89 + rootdir= Override the root directory location. (unused)
90 + WARNING: overriding the rootdir to a non-directory may
91 + yield highly unpredictable results.
92 +-------------------------------------------------------------------------------
95 +For more information see:
96 + http://www.trylinux.com/projects/udf/index.html
98 +For the latest version and toolset see:
99 + http://www.csc.calpoly.edu/~bfennema/udf.html
100 + http://linux-udf.sourceforge.net/
102 +Documentation on UDF and ECMA 167 is available FREE from:
103 + http://www.osta.org/
104 + http://www.ecma.ch/
106 +Ben Fennema <bfennema@falcon.csc.calpoly.edu>
107 diff -Nru linux/Documentation/ioctl-number.txt linux.new/Documentation/ioctl-number.txt
108 --- linux/Documentation/ioctl-number.txt Sun Mar 25 18:37:29 2001
109 +++ linux.new/Documentation/ioctl-number.txt Fri Sep 7 11:32:15 2001
111 'k' all asm-sparc/kbio.h, asm-sparc64/kbio.h
112 'l' 00-3F linux/tcfs_fs.h in development:
113 <http://mikonos.dia.unisa.it/tcfs>
114 +'l' 40-7F linux/udf_fs_i.h in development:
115 + <http://www.trylinux.com/projects/udf/>
116 'm' all linux/mtio.h conflict!
117 'm' all linux/soundcard.h conflict!
118 'n' all linux/ncp_fs.h
119 diff -Nru linux/MAINTAINERS linux.new/MAINTAINERS
120 --- linux/MAINTAINERS Fri Sep 7 11:18:22 2001
121 +++ linux.new/MAINTAINERS Fri Sep 7 11:32:15 2001
122 @@ -1042,6 +1042,15 @@
123 L: linux-scsi@vger.kernel.org
128 +M: bfennema@falcon.csc.calpoly.edu
130 +M: dave@trylinux.com
131 +L: linux_udf@hootie.lvld.hp.com
132 +W: http://www.trylinux.com/projects/udf/index.html
137 M: mnalis-umsdos@voyager.hr
138 diff -Nru linux/fs/Config.in linux.new/fs/Config.in
139 --- linux/fs/Config.in Fri Sep 7 11:18:14 2001
140 +++ linux.new/fs/Config.in Fri Sep 7 11:32:16 2001
142 # needed by nls/Config.in
143 define_bool CONFIG_JOLIET n
145 +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
146 + tristate 'UDF filesystem support (EXPERIMENTAL)' CONFIG_UDF_FS
147 + if [ "$CONFIG_UDF_FS" != "n" ]; then
148 + bool ' UDF read-write support (FOR TESTING ONLY)' CONFIG_UDF_RW
153 tristate 'Minix fs support' CONFIG_MINIX_FS
154 tristate 'NTFS filesystem support (read only)' CONFIG_NTFS_FS
155 diff -Nru linux.orig/fs/Makefile linux/fs/Makefile
156 --- linux.orig/fs/Makefile Wed Nov 21 21:18:15 2001
157 +++ linux/fs/Makefile Wed Nov 21 21:27:00 2001
159 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
161 hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd \
162 - nfsd nls devpts adfs qnx4 efs
163 + nfsd nls devpts adfs qnx4 udf efs
165 ifeq ($(CONFIG_QUOTA),y)
171 +ifeq ($(CONFIG_UDF_FS),y)
174 + ifeq ($(CONFIG_UDF_FS),m)
175 + MOD_SUB_DIRS += udf
179 ifeq ($(CONFIG_AUTOFS_FS),y)
182 diff -Nru linux/fs/filesystems.c linux.new/fs/filesystems.c
183 --- linux/fs/filesystems.c Fri Sep 7 11:17:42 2001
184 +++ linux.new/fs/filesystems.c Fri Sep 7 11:32:16 2001
186 #include <linux/romfs_fs.h>
187 #include <linux/auto_fs.h>
188 #include <linux/qnx4_fs.h>
189 +#include <linux/udf_fs.h>
190 #include <linux/ntfs_fs.h>
191 #include <linux/hfs_fs.h>
192 #include <linux/devpts_fs.h>
197 +#ifdef CONFIG_UDF_FS
203 diff -Nru linux/fs/udf/Makefile linux.new/fs/udf/Makefile
204 --- linux/fs/udf/Makefile Thu Jan 1 01:00:00 1970
205 +++ linux.new/fs/udf/Makefile Fri Sep 7 11:32:16 2001
208 +# Makefile for the linux udf-filesystem routines.
210 +# Note! Dependencies are done automagically by 'make dep', which also
211 +# removes any old dependencies. DON'T put your own dependencies here
212 +# unless it's something special (ie not a .o file).
214 +# Note 2! The CFLAGS definitions are now in the main makefile..
217 +O_OBJS := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \
218 + partition.o super.o truncate.o symlink.o fsync.o \
219 + crc.o directory.o misc.o udftime.o unicode.o
220 +M_OBJS := $(O_TARGET)
222 +include $(TOPDIR)/Rules.make
223 diff -Nru linux/fs/udf/balloc.c linux.new/fs/udf/balloc.c
224 --- linux/fs/udf/balloc.c Thu Jan 1 01:00:00 1970
225 +++ linux.new/fs/udf/balloc.c Fri Sep 7 11:32:16 2001
231 + * Block allocation handling routines for the OSTA-UDF(tm) filesystem.
234 + * E-mail regarding any portion of the Linux UDF file system should be
235 + * directed to the development team mailing list (run by majordomo):
236 + * linux_udf@hootie.lvld.hp.com
239 + * This file is distributed under the terms of the GNU General Public
240 + * License (GPL). Copies of the GPL can be obtained from:
241 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
242 + * Each contributing author retains all rights to their own work.
244 + * (C) 1999-2000 Ben Fennema
245 + * (C) 1999 Stelias Computing Inc
249 + * 02/24/99 blf Created.
253 +#include "udfdecl.h"
254 +#include <linux/fs.h>
255 +#include <linux/locks.h>
256 +#include <linux/quotaops.h>
257 +#include <linux/udf_fs.h>
259 +#include <asm/bitops.h>
264 +#define udf_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
265 +#define udf_set_bit(nr,addr) ext2_set_bit(nr,addr)
266 +#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
267 +#define udf_find_first_one_bit(addr, size) find_first_one_bit(addr, size)
268 +#define udf_find_next_one_bit(addr, size, offset) find_next_one_bit(addr, size, offset)
270 +#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
271 +#define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y)
272 +#define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
274 +extern inline int find_next_one_bit (void * addr, int size, int offset)
276 + unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
277 + unsigned long result = offset & ~(BITS_PER_LONG-1);
280 + if (offset >= size)
283 + offset &= (BITS_PER_LONG-1);
286 + tmp = leBPL_to_cpup(p++);
287 + tmp &= ~0UL << offset;
288 + if (size < BITS_PER_LONG)
292 + size -= BITS_PER_LONG;
293 + result += BITS_PER_LONG;
295 + while (size & ~(BITS_PER_LONG-1))
297 + if ((tmp = leBPL_to_cpup(p++)))
299 + result += BITS_PER_LONG;
300 + size -= BITS_PER_LONG;
304 + tmp = leBPL_to_cpup(p);
306 + tmp &= ~0UL >> (BITS_PER_LONG-size);
308 + return result + ffz(~tmp);
311 +#define find_first_one_bit(addr, size)\
312 + find_next_one_bit((addr), (size), 0)
314 +static int read_block_bitmap(struct super_block * sb,
315 + struct udf_bitmap *bitmap, unsigned int block, unsigned long bitmap_nr)
317 + struct buffer_head *bh = NULL;
321 + loc.logicalBlockNum = bitmap->s_extPosition;
322 + loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
324 + bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block), sb->s_blocksize);
329 + bitmap->s_block_bitmap[bitmap_nr] = bh;
333 +static int __load_block_bitmap(struct super_block * sb,
334 + struct udf_bitmap *bitmap, unsigned int block_group)
337 + int nr_groups = bitmap->s_nr_groups;
339 + if (block_group >= nr_groups)
341 + udf_debug("block_group (%d) > nr_groups (%d)\n", block_group, nr_groups);
344 + if (bitmap->s_block_bitmap[block_group])
345 + return block_group;
348 + retval = read_block_bitmap(sb, bitmap, block_group, block_group);
351 + return block_group;
355 +static inline int load_block_bitmap(struct super_block *sb,
356 + struct udf_bitmap *bitmap, unsigned int block_group)
360 + if (bitmap->s_block_bitmap[block_group])
363 + slot = __load_block_bitmap(sb, bitmap, block_group);
368 + if (!bitmap->s_block_bitmap[slot])
374 +static void udf_bitmap_free_blocks(const struct inode * inode,
375 + struct udf_bitmap *bitmap, lb_addr bloc, Uint32 offset, Uint32 count)
377 + struct buffer_head * bh = NULL;
378 + unsigned long block;
379 + unsigned long block_group;
383 + unsigned long overflow;
384 + struct super_block * sb;
389 + udf_debug("nonexistent device");
394 + if (bloc.logicalBlockNum < 0 ||
395 + (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum))
397 + udf_debug("%d < %d || %d + %d > %d\n",
398 + bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count,
399 + UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum));
403 + block = bloc.logicalBlockNum + offset + (sizeof(struct SpaceBitmapDesc) << 3);
407 + block_group = block >> (sb->s_blocksize_bits + 3);
408 + bit = block % (sb->s_blocksize << 3);
411 + * Check to see if we are freeing blocks across a group boundary.
413 + if (bit + count > (sb->s_blocksize << 3))
415 + overflow = bit + count - (sb->s_blocksize << 3);
418 + bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
422 + bh = bitmap->s_block_bitmap[bitmap_nr];
423 + for (i=0; i < count; i++)
425 + if (udf_set_bit(bit + i, bh->b_data))
427 + udf_debug("bit %ld already set\n", bit + i);
428 + udf_debug("byte=%2x\n", ((char *)bh->b_data)[(bit + i) >> 3]);
432 + DQUOT_FREE_BLOCK(sb, inode, 1);
433 + if (UDF_SB_LVIDBH(sb))
435 + UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
436 + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)])+1);
440 + mark_buffer_dirty(bh, 1);
449 + if (UDF_SB_LVIDBH(sb))
450 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
455 +static int udf_bitmap_prealloc_blocks(const struct inode * inode,
456 + struct udf_bitmap *bitmap, Uint16 partition, Uint32 first_block,
457 + Uint32 block_count)
459 + int alloc_count = 0;
460 + int bit, block, block_group, group_start;
461 + int nr_groups, bitmap_nr;
462 + struct buffer_head *bh;
463 + struct super_block *sb;
468 + udf_debug("nonexistent device\n");
473 + if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
477 + nr_groups = (UDF_SB_PARTLEN(sb, partition) +
478 + (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8);
479 + block = first_block + (sizeof(struct SpaceBitmapDesc) << 3);
480 + block_group = block >> (sb->s_blocksize_bits + 3);
481 + group_start = block_group ? 0 : sizeof(struct SpaceBitmapDesc);
483 + bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
486 + bh = bitmap->s_block_bitmap[bitmap_nr];
488 + bit = block % (sb->s_blocksize << 3);
490 + while (bit < (sb->s_blocksize << 3) && block_count > 0)
492 + if (!udf_test_bit(bit, bh->b_data))
494 + else if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))
496 + else if (!udf_clear_bit(bit, bh->b_data))
498 + udf_debug("bit already cleared for block %d\n", bit);
499 + DQUOT_FREE_BLOCK(sb, inode, 1);
507 + mark_buffer_dirty(bh, 1);
508 + if (block_count > 0)
511 + if (UDF_SB_LVIDBH(sb))
513 + UDF_SB_LVID(sb)->freeSpaceTable[partition] =
514 + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-alloc_count);
515 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
519 + return alloc_count;
522 +static int udf_bitmap_new_block(const struct inode * inode,
523 + struct udf_bitmap *bitmap,Uint16 partition, Uint32 goal, int *err)
525 + int tmp, newbit, bit=0, block, block_group, group_start;
526 + int end_goal, nr_groups, bitmap_nr, i;
527 + struct buffer_head *bh = NULL;
528 + struct super_block *sb;
536 + udf_debug("nonexistent device\n");
542 + if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition))
545 + nr_groups = bitmap->s_nr_groups;
546 + block = goal + (sizeof(struct SpaceBitmapDesc) << 3);
547 + block_group = block >> (sb->s_blocksize_bits + 3);
548 + group_start = block_group ? 0 : sizeof(struct SpaceBitmapDesc);
550 + bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
553 + bh = bitmap->s_block_bitmap[bitmap_nr];
554 + ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start);
556 + if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize)
558 + bit = block % (sb->s_blocksize << 3);
560 + if (udf_test_bit(bit, bh->b_data))
564 + end_goal = (bit + 63) & ~63;
565 + bit = udf_find_next_one_bit(bh->b_data, end_goal, bit);
566 + if (bit < end_goal)
568 + ptr = memscan((char *)bh->b_data + (bit >> 3), 0xFF, sb->s_blocksize - ((bit + 7) >> 3));
569 + newbit = (ptr - ((char *)bh->b_data)) << 3;
570 + if (newbit < sb->s_blocksize << 3)
575 + newbit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, bit);
576 + if (newbit < sb->s_blocksize << 3)
583 + for (i=0; i<(nr_groups*2); i++)
586 + if (block_group >= nr_groups)
588 + group_start = block_group ? 0 : sizeof(struct SpaceBitmapDesc);
590 + bitmap_nr = load_block_bitmap(sb,bitmap, block_group);
593 + bh = bitmap->s_block_bitmap[bitmap_nr];
596 + ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start);
597 + if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize)
599 + bit = (ptr - ((char *)bh->b_data)) << 3;
605 + bit = udf_find_next_one_bit((char *)bh->b_data, sb->s_blocksize << 3, group_start << 3);
606 + if (bit < sb->s_blocksize << 3)
610 + if (i >= (nr_groups*2))
615 + if (bit < sb->s_blocksize << 3)
618 + bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, group_start << 3);
619 + if (bit >= sb->s_blocksize << 3)
626 + for (i=0; i<7 && bit > (group_start << 3) && udf_test_bit(bit - 1, bh->b_data); i++, bit--);
631 + * Check quota for allocation of this block.
633 + if (DQUOT_ALLOC_BLOCK(sb, inode, 1))
640 + newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
641 + (sizeof(struct SpaceBitmapDesc) << 3);
643 + tmp = udf_get_pblock(sb, newblock, partition, 0);
644 + if (!udf_clear_bit(bit, bh->b_data))
646 + udf_debug("bit already cleared for block %d\n", bit);
650 + mark_buffer_dirty(bh, 1);
651 + if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize)))
653 + udf_debug("cannot get block %d\n", tmp);
657 + memset(bh->b_data, 0, sb->s_blocksize);
658 + mark_buffer_uptodate(bh, 1);
659 + mark_buffer_dirty(bh, 1);
660 + udf_release_data(bh);
662 + if (UDF_SB_LVIDBH(sb))
664 + UDF_SB_LVID(sb)->freeSpaceTable[partition] =
665 + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-1);
666 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
679 +static void udf_table_free_blocks(const struct inode * inode,
680 + struct inode * table, lb_addr bloc, Uint32 offset, Uint32 count)
682 + struct super_block * sb;
684 + Uint32 nextoffset, oextoffset, elen;
685 + lb_addr nbloc, obloc, eloc;
686 + struct buffer_head *obh, *nbh;
690 + udf_debug("ino=%ld, bloc=%d, offset=%d, count=%d\n",
691 + inode->i_ino, bloc.logicalBlockNum, offset, count);
696 + udf_debug("nonexistent device");
704 + if (bloc.logicalBlockNum < 0 ||
705 + (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum))
707 + udf_debug("%d < %d || %d + %d > %d\n",
708 + bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count,
709 + UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum));
713 + /* We do this up front - There are some error conditions that could occure,
715 + DQUOT_FREE_BLOCK(sb, inode, count);
716 + if (UDF_SB_LVIDBH(sb))
718 + UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
719 + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)])+count);
720 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
723 + start = bloc.logicalBlockNum + offset;
724 + end = bloc.logicalBlockNum + offset + count - 1;
726 + oextoffset = nextoffset = sizeof(struct UnallocatedSpaceEntry);
728 + obloc = nbloc = UDF_I_LOCATION(table);
730 + obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0), sb->s_blocksize);
733 + while (count && (etype =
734 + udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
736 + if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) ==
739 + if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits))
741 + count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
742 + start += ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
743 + elen = (etype << 30) | (0x40000000 - sb->s_blocksize);
747 + elen = (etype << 30) |
748 + (elen + (count << sb->s_blocksize_bits));
752 + udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
754 + else if (eloc.logicalBlockNum == (end + 1))
756 + if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits))
758 + count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
759 + end -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
760 + eloc.logicalBlockNum -=
761 + ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
762 + elen = (etype << 30) | (0x40000000 - sb->s_blocksize);
766 + eloc.logicalBlockNum = start;
767 + elen = (etype << 30) |
768 + (elen + (count << sb->s_blocksize_bits));
772 + udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
775 + if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
779 + udf_release_data(obh);
785 + oextoffset = nextoffset;
790 + /* NOTE: we CANNOT use udf_add_aext here, as it can try to allocate
791 + a new block, and since we hold the super block lock already
792 + very bad things would happen :)
794 + We copy the behavior of udf_add_aext, but instead of
795 + trying to allocate a new block close to the existing one,
796 + we just steal a block from the extent we are trying to add.
798 + It would be nice if the blocks were close together, but it
803 + short_ad *sad = NULL;
804 + long_ad *lad = NULL;
805 + struct AllocExtDesc *aed;
807 + eloc.logicalBlockNum = start;
808 + elen = (EXTENT_RECORDED_ALLOCATED << 30) |
809 + (count << sb->s_blocksize_bits);
811 + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT)
812 + adsize = sizeof(short_ad);
813 + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG)
814 + adsize = sizeof(long_ad);
817 + udf_release_data(obh);
818 + udf_release_data(nbh);
822 + if (nextoffset + (2 * adsize) > sb->s_blocksize)
827 + udf_release_data(obh);
830 + oextoffset = nextoffset;
832 + /* Steal a block from the extent being free'd */
833 + nbloc.logicalBlockNum = eloc.logicalBlockNum;
834 + eloc.logicalBlockNum ++;
835 + elen -= sb->s_blocksize;
837 + if (!(nbh = udf_tread(sb,
838 + udf_get_lb_pblock(sb, nbloc, 0),
841 + udf_release_data(obh);
844 + aed = (struct AllocExtDesc *)(nbh->b_data);
845 + aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
846 + if (nextoffset + adsize > sb->s_blocksize)
848 + loffset = nextoffset;
849 + aed->lengthAllocDescs = cpu_to_le32(adsize);
850 + sptr = (obh)->b_data + nextoffset - adsize;
851 + dptr = nbh->b_data + sizeof(struct AllocExtDesc);
852 + memcpy(dptr, sptr, adsize);
853 + nextoffset = sizeof(struct AllocExtDesc) + adsize;
857 + loffset = nextoffset + adsize;
858 + aed->lengthAllocDescs = cpu_to_le32(0);
859 + sptr = (obh)->b_data + nextoffset;
860 + nextoffset = sizeof(struct AllocExtDesc);
862 + if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
864 + aed = (struct AllocExtDesc *)(obh)->b_data;
865 + aed->lengthAllocDescs =
866 + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
870 + UDF_I_LENALLOC(table) += adsize;
871 + mark_inode_dirty(table);
874 + udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1,
875 + nbloc.logicalBlockNum, sizeof(tag));
876 + switch (UDF_I_ALLOCTYPE(table))
878 + case ICB_FLAG_AD_SHORT:
880 + sad = (short_ad *)sptr;
881 + sad->extLength = cpu_to_le32(
882 + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
884 + sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum);
887 + case ICB_FLAG_AD_LONG:
889 + lad = (long_ad *)sptr;
890 + lad->extLength = cpu_to_le32(
891 + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
893 + lad->extLocation = cpu_to_lelb(nbloc);
897 + udf_update_tag(obh->b_data, loffset);
898 + mark_buffer_dirty(obh, 1);
901 + if (elen) /* It's possible that stealing the block emptied the extent */
903 + udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
905 + if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
907 + UDF_I_LENALLOC(table) += adsize;
908 + mark_inode_dirty(table);
912 + aed = (struct AllocExtDesc *)nbh->b_data;
913 + aed->lengthAllocDescs =
914 + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
915 + udf_update_tag(nbh->b_data, nextoffset);
916 + mark_buffer_dirty(nbh, 1);
921 + udf_release_data(nbh);
922 + udf_release_data(obh);
930 +static int udf_table_prealloc_blocks(const struct inode * inode,
931 + struct inode *table, Uint16 partition, Uint32 first_block,
932 + Uint32 block_count)
934 + struct super_block *sb;
935 + int alloc_count = 0;
936 + Uint32 extoffset, elen, adsize;
937 + lb_addr bloc, eloc;
938 + struct buffer_head *bh;
941 + udf_debug("ino=%ld, partition=%d, first_block=%d, block_count=%d\n",
942 + inode->i_ino, partition, first_block, block_count);
947 + udf_debug("nonexistent device\n");
951 + if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
957 + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT)
958 + adsize = sizeof(short_ad);
959 + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG)
960 + adsize = sizeof(long_ad);
966 + extoffset = sizeof(struct UnallocatedSpaceEntry);
967 + bloc = UDF_I_LOCATION(table);
969 + bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize);
970 + eloc.logicalBlockNum = 0xFFFFFFFF;
972 + while (first_block != eloc.logicalBlockNum && (etype =
973 + udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
975 + udf_debug("eloc=%d, elen=%d, first_block=%d\n",
976 + eloc.logicalBlockNum, elen, first_block);
977 + ; /* empty loop body */
980 + if (first_block == eloc.logicalBlockNum)
982 + extoffset -= adsize;
984 + alloc_count = (elen >> sb->s_blocksize_bits);
985 + if (alloc_count > block_count)
987 + alloc_count = block_count;
988 + eloc.logicalBlockNum += alloc_count;
989 + elen -= (alloc_count << sb->s_blocksize_bits);
990 + udf_write_aext(table, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1);
993 + udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);
998 + udf_release_data(bh);
1000 + if (alloc_count && UDF_SB_LVIDBH(sb))
1002 + UDF_SB_LVID(sb)->freeSpaceTable[partition] =
1003 + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-alloc_count);
1004 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
1008 + udf_debug("alloc_count=%d\n", alloc_count);
1009 + return alloc_count;
1012 +static int udf_table_new_block(const struct inode * inode,
1013 + struct inode *table, Uint16 partition, Uint32 goal, int *err)
1015 + struct super_block *sb;
1016 + Uint32 spread = 0xFFFFFFFF, nspread;
1017 + Uint32 newblock = 0, tmp, adsize;
1018 + Uint32 extoffset, goal_extoffset, elen, goal_elen = 0;
1019 + lb_addr bloc, goal_bloc, eloc, goal_eloc;
1020 + struct buffer_head *bh, *goal_bh;
1023 + udf_debug("ino=%ld, partition=%d, goal=%d\n",
1024 + inode->i_ino, partition, goal);
1030 + udf_debug("nonexistent device\n");
1034 + if (table == NULL)
1037 + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT)
1038 + adsize = sizeof(short_ad);
1039 + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG)
1040 + adsize = sizeof(long_ad);
1046 + if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition))
1049 + /* We search for the closest matching block to goal. If we find a exact hit, we stop. Otherwise we keep going till we run out of extents.
1050 + We store the buffer_head, bloc, and extoffset of the current closest
1051 + match and use that when we are done.
1054 + extoffset = sizeof(struct UnallocatedSpaceEntry);
1055 + bloc = UDF_I_LOCATION(table);
1057 + goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize);
1058 + goal_bh->b_count ++;
1060 + while (spread && (etype =
1061 + udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
1063 + if (goal >= eloc.logicalBlockNum)
1065 + if (goal < eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits))
1068 + nspread = goal - eloc.logicalBlockNum -
1069 + (elen >> sb->s_blocksize_bits);
1072 + nspread = eloc.logicalBlockNum - goal;
1074 + if (nspread < spread)
1077 + if (goal_bh != bh)
1079 + udf_release_data(goal_bh);
1081 + goal_bh->b_count ++;
1084 + goal_extoffset = extoffset - adsize;
1086 + goal_elen = (etype << 30) | elen;
1090 + udf_release_data(bh);
1092 + if (spread == 0xFFFFFFFF)
1094 + udf_release_data(goal_bh);
1099 + /* Only allocate blocks from the beginning of the extent.
1100 + That way, we only delete (empty) extents, never have to insert an
1101 + extent because of splitting */
1102 + /* This works, but very poorly.... */
1104 + newblock = goal_eloc.logicalBlockNum;
1105 + goal_eloc.logicalBlockNum ++;
1106 + goal_elen -= sb->s_blocksize;
1108 + tmp = udf_get_pblock(sb, newblock, partition, 0);
1109 + if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize)))
1111 + udf_debug("cannot get block %d\n", tmp);
1112 + udf_release_data(bh);
1116 + memset(bh->b_data, 0, sb->s_blocksize);
1117 + mark_buffer_uptodate(bh, 1);
1118 + mark_buffer_dirty(bh, 1);
1119 + udf_release_data(bh);
1122 + udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);
1124 + udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh);
1125 + udf_release_data(goal_bh);
1127 + if (UDF_SB_LVIDBH(sb))
1129 + UDF_SB_LVID(sb)->freeSpaceTable[partition] =
1130 + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-1);
1131 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
1140 +inline void udf_free_blocks(const struct inode * inode, lb_addr bloc,
1141 + Uint32 offset, Uint32 count)
1143 + if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_BITMAP)
1145 + return udf_bitmap_free_blocks(inode,
1146 + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_bitmap,
1147 + bloc, offset, count);
1149 + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_TABLE)
1151 + return udf_table_free_blocks(inode,
1152 + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_table,
1153 + bloc, offset, count);
1155 + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_BITMAP)
1157 + return udf_bitmap_free_blocks(inode,
1158 + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_bitmap,
1159 + bloc, offset, count);
1161 + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_TABLE)
1163 + return udf_table_free_blocks(inode,
1164 + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_table,
1165 + bloc, offset, count);
1171 +inline int udf_prealloc_blocks(const struct inode * inode, Uint16 partition,
1172 + Uint32 first_block, Uint32 block_count)
1174 + if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
1176 + return udf_bitmap_prealloc_blocks(inode,
1177 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap,
1178 + partition, first_block, block_count);
1180 + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
1182 + return udf_table_prealloc_blocks(inode,
1183 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table,
1184 + partition, first_block, block_count);
1186 + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
1188 + return udf_bitmap_prealloc_blocks(inode,
1189 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap,
1190 + partition, first_block, block_count);
1192 + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE)
1194 + return udf_table_prealloc_blocks(inode,
1195 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table,
1196 + partition, first_block, block_count);
1202 +inline int udf_new_block(const struct inode * inode, Uint16 partition,
1203 + Uint32 goal, int *err)
1205 + if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
1207 + return udf_bitmap_new_block(inode,
1208 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap,
1209 + partition, goal, err);
1211 + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
1213 + return udf_table_new_block(inode,
1214 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table,
1215 + partition, goal, err);
1217 + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
1219 + return udf_bitmap_new_block(inode,
1220 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap,
1221 + partition, goal, err);
1223 + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE)
1225 + return udf_table_new_block(inode,
1226 + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table,
1227 + partition, goal, err);
1235 diff -Nru linux/fs/udf/crc.c linux.new/fs/udf/crc.c
1236 --- linux/fs/udf/crc.c Thu Jan 1 01:00:00 1970
1237 +++ linux.new/fs/udf/crc.c Fri Sep 7 11:32:16 2001
1243 + * Routines to generate, calculate, and test a 16-bit CRC.
1246 + * The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories
1247 + * and Ned W. Rhodes of Software Systems Group. It has been published in
1248 + * "Design and Validation of Computer Protocols", Prentice Hall,
1249 + * Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4.
1251 + * Copyright is held by AT&T.
1253 + * AT&T gives permission for the free use of the CRC source code.
1256 + * E-mail regarding any portion of the Linux UDF file system should be
1257 + * directed to the development team mailing list (run by majordomo):
1258 + * linux_udf@hootie.lvld.hp.com
1261 + * This file is distributed under the terms of the GNU General Public
1262 + * License (GPL). Copies of the GPL can be obtained from:
1263 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
1264 + * Each contributing author retains all rights to their own work.
1267 +#include "udfdecl.h"
1269 +static Uint16 crc_table[256] = {
1270 + 0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U,
1271 + 0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU,
1272 + 0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U,
1273 + 0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU,
1274 + 0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U,
1275 + 0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU,
1276 + 0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U,
1277 + 0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU,
1278 + 0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U,
1279 + 0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU,
1280 + 0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U,
1281 + 0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU,
1282 + 0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U,
1283 + 0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U,
1284 + 0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U,
1285 + 0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U,
1286 + 0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU,
1287 + 0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U,
1288 + 0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU,
1289 + 0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U,
1290 + 0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU,
1291 + 0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U,
1292 + 0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU,
1293 + 0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U,
1294 + 0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU,
1295 + 0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U,
1296 + 0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU,
1297 + 0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U,
1298 + 0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U,
1299 + 0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U,
1300 + 0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U,
1301 + 0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U
1308 + * Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial.
1311 + * The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory.
1312 + * The polynomial used is: x^16 + x^12 + x^15 + 1
1315 + * data Pointer to the data block.
1316 + * size Size of the data block.
1319 + * <return> CRC of the data block.
1322 + * July 21, 1997 - Andrew E. Mileski
1323 + * Adapted from OSTA-UDF(tm) 1.50 standard.
1326 +udf_crc(Uint8 *data, Uint32 size, Uint16 crc)
1329 + crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8);
1334 +/****************************************************************************/
1342 + * July 21, 1997 - Andrew E. Mileski
1343 + * Adapted from OSTA-UDF(tm) 1.50 standard.
1346 +unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U };
1352 + x = udf_crc16(bytes, sizeof bytes);
1353 + printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
1358 +#endif /* defined(TEST) */
1360 +/****************************************************************************/
1361 +#if defined(GENERATE)
1365 + * Generate a table for fast 16-bit CRC calculations (any polynomial).
1368 + * The ITU-T V.41 polynomial is 010041.
1371 + * July 21, 1997 - Andrew E. Mileski
1372 + * Adapted from OSTA-UDF(tm) 1.50 standard.
1377 +int main(int argc, char **argv)
1379 + unsigned long crc, poly;
1382 + /* Get the polynomial */
1383 + sscanf(argv[1], "%lo", &poly);
1384 + if (poly & 0xffff0000U){
1385 + fprintf(stderr, "polynomial is too large\en");
1389 + printf("/* CRC 0%o */\n", poly);
1391 + /* Create a table */
1392 + printf("static unsigned short crc_table[256] = {\n");
1393 + for (n = 0; n < 256; n++){
1397 + for (i = 0; i < 8; i++){
1399 + crc = (crc << 1) ^ poly;
1405 + printf("0x%04xU ", crc);
1407 + printf("0x%04xU, ", crc);
1416 +#endif /* defined(GENERATE) */
1417 diff -Nru linux/fs/udf/dir.c linux.new/fs/udf/dir.c
1418 --- linux/fs/udf/dir.c Thu Jan 1 01:00:00 1970
1419 +++ linux.new/fs/udf/dir.c Fri Sep 7 11:32:16 2001
1425 + * Directory handling routines for the OSTA-UDF(tm) filesystem.
1428 + * E-mail regarding any portion of the Linux UDF file system should be
1429 + * directed to the development team mailing list (run by majordomo):
1430 + * linux_udf@hootie.lvld.hp.com
1433 + * This file is distributed under the terms of the GNU General Public
1434 + * License (GPL). Copies of the GPL can be obtained from:
1435 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
1436 + * Each contributing author retains all rights to their own work.
1438 + * (C) 1998-2000 Ben Fennema
1442 + * 10/05/98 dgb Split directory operations into it's own file
1443 + * Implemented directory reads via do_udf_readdir
1444 + * 10/06/98 Made directory operations work!
1445 + * 11/17/98 Rewrote directory to support ICB_FLAG_AD_LONG
1446 + * 11/25/98 blf Rewrote directory handling (readdir+lookup) to support reading
1448 + * 12/12/98 Split out the lookup code to namei.c. bulk of directory
1449 + * code now in directory.c:udf_fileident_read.
1452 +#include "udfdecl.h"
1454 +#if defined(__linux__) && defined(__KERNEL__)
1455 +#include <linux/version.h>
1457 +#include "udf_sb.h"
1458 +#include <linux/string.h>
1459 +#include <linux/errno.h>
1460 +#include <linux/mm.h>
1461 +#include <linux/malloc.h>
1462 +#include <linux/udf_fs.h>
1465 +/* Prototypes for file operations */
1466 +static int udf_readdir(struct file *, void *, filldir_t);
1467 +static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
1469 +/* readdir and lookup functions */
1471 +static struct file_operations udf_dir_operations = {
1472 + NULL, /* lllseek */
1475 + udf_readdir, /* readdir */
1477 + udf_ioctl, /* ioctl */
1481 + NULL, /* release */
1482 + udf_sync_file, /* fsync */
1483 + NULL, /* fasync */
1484 + NULL, /* check_media_change */
1485 + NULL, /* revalidate */
1489 +struct inode_operations udf_dir_inode_operations = {
1490 + &udf_dir_operations,
1491 + udf_create, /* create */
1492 + udf_lookup, /* lookup */
1493 + udf_link, /* link */
1494 + udf_unlink, /* unlink */
1495 + udf_symlink, /* symlink */
1496 + udf_mkdir, /* mkdir */
1497 + udf_rmdir, /* rmdir */
1498 + udf_mknod, /* mknod */
1499 + udf_rename, /* rename */
1500 + NULL, /* readlink */
1501 + NULL, /* follow_link */
1502 + NULL, /* readpage */
1503 + NULL, /* writepage */
1505 + NULL, /* truncate */
1506 + NULL, /* permission */
1508 + NULL, /* updatepage */
1509 + NULL /* revalidate */
1516 + * Read a directory entry.
1519 + * Optional - sys_getdents() will return -ENOTDIR if this routine is not
1522 + * Refer to sys_getdents() in fs/readdir.c
1523 + * sys_getdents() -> .
1526 + * filp Pointer to directory file.
1527 + * buf Pointer to directory entry buffer.
1528 + * filldir Pointer to filldir function.
1531 + * <return> >=0 on success.
1534 + * July 1, 1997 - Andrew E. Mileski
1535 + * Written, tested, and released.
1538 +int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
1540 + struct inode *dir = filp->f_dentry->d_inode;
1546 + if (!S_ISDIR(dir->i_mode))
1549 + if ( filp->f_pos == 0 )
1551 + if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino))
1555 + result = do_udf_readdir(dir, filp, filldir, dirent);
1556 + UPDATE_ATIME(dir);
1561 +do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *dirent)
1563 + struct udf_fileident_bh fibh;
1564 + struct FileIdentDesc *fi=NULL;
1565 + struct FileIdentDesc cfi;
1566 + int block, iblock;
1567 + int nf_pos = filp->f_pos;
1573 + int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
1574 + struct buffer_head * bh = NULL;
1575 + lb_addr bloc, eloc;
1576 + Uint32 extoffset, elen, offset;
1578 + if (nf_pos >= size)
1582 + nf_pos = (udf_ext0_offset(dir) >> 2);
1584 + fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
1585 + if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
1586 + &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
1588 + block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
1589 + if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
1591 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
1592 + extoffset -= sizeof(short_ad);
1593 + else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
1594 + extoffset -= sizeof(long_ad);
1601 + udf_release_data(bh);
1605 + if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1607 + udf_release_data(bh);
1611 + while ( nf_pos < size )
1613 + filp->f_pos = nf_pos;
1615 + fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
1619 + if (fibh.sbh != fibh.ebh)
1620 + udf_release_data(fibh.ebh);
1621 + udf_release_data(fibh.sbh);
1622 + udf_release_data(bh);
1626 + liu = le16_to_cpu(cfi.lengthOfImpUse);
1627 + lfi = cfi.lengthFileIdent;
1629 + if (fibh.sbh == fibh.ebh)
1630 + nameptr = fi->fileIdent + liu;
1633 + int poffset; /* Unpaded ending offset */
1635 + poffset = fibh.soffset + sizeof(struct FileIdentDesc) + liu + lfi;
1637 + if (poffset >= lfi)
1638 + nameptr = (char *)(fibh.ebh->b_data + poffset - lfi);
1642 + memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
1643 + memcpy(nameptr + lfi - poffset, fibh.ebh->b_data, poffset);
1647 + if ( (cfi.fileCharacteristics & FILE_DELETED) != 0 )
1649 + if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
1653 + if ( (cfi.fileCharacteristics & FILE_HIDDEN) != 0 )
1655 + if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
1659 + iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
1661 + if (!lfi) /* parent directory */
1663 + if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino))
1665 + if (fibh.sbh != fibh.ebh)
1666 + udf_release_data(fibh.ebh);
1667 + udf_release_data(fibh.sbh);
1668 + udf_release_data(bh);
1674 + if ((flen = udf_get_filename(nameptr, fname, lfi)))
1676 + if (filldir(dirent, fname, flen, filp->f_pos, iblock))
1678 + if (fibh.sbh != fibh.ebh)
1679 + udf_release_data(fibh.ebh);
1680 + udf_release_data(fibh.sbh);
1681 + udf_release_data(bh);
1682 + return 1; /* halt enum */
1687 + udf_debug("size=%d, nf_pos=%d, liu=%d, lfi=%d\n", size, nf_pos, liu, lfi);
1692 + filp->f_pos = nf_pos;
1694 + if (fibh.sbh != fibh.ebh)
1695 + udf_release_data(fibh.ebh);
1696 + udf_release_data(fibh.sbh);
1697 + udf_release_data(bh);
1699 + if ( filp->f_pos >= size)
1704 diff -Nru linux/fs/udf/directory.c linux.new/fs/udf/directory.c
1705 --- linux/fs/udf/directory.c Thu Jan 1 01:00:00 1970
1706 +++ linux.new/fs/udf/directory.c Fri Sep 7 11:32:16 2001
1712 + * Directory related functions
1715 + * E-mail regarding any portion of the Linux UDF file system should be
1716 + * directed to the development team mailing list (run by majordomo):
1717 + * linux_udf@hootie.lvld.hp.com
1720 + * This file is distributed under the terms of the GNU General Public
1721 + * License (GPL). Copies of the GPL can be obtained from:
1722 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
1723 + * Each contributing author retains all rights to their own work.
1726 +#include "udfdecl.h"
1728 +#if defined(__linux__) && defined(__KERNEL__)
1730 +#include <linux/fs.h>
1731 +#include <linux/string.h>
1732 +#include <linux/udf_fs.h>
1736 +#include <sys/types.h>
1738 +#include <unistd.h>
1744 +Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size,
1745 + lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
1747 + int loffset = *offset;
1754 + ad = (Uint8 *)(*bh)->b_data + *offset;
1755 + *offset += ad_size;
1759 + udf_release_data(*bh);
1764 + if (*offset == dir->i_sb->s_blocksize)
1766 + udf_release_data(*bh);
1767 + block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
1770 + if (!(*bh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1773 + else if (*offset > dir->i_sb->s_blocksize)
1777 + remainder = dir->i_sb->s_blocksize - loffset;
1778 + memcpy((Uint8 *)ad, (*bh)->b_data + loffset, remainder);
1780 + udf_release_data(*bh);
1781 + block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
1784 + if (!((*bh) = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1787 + memcpy((Uint8 *)ad + remainder, (*bh)->b_data, ad_size - remainder);
1788 + *offset = ad_size - remainder;
1793 +struct FileIdentDesc *
1794 +udf_fileident_read(struct inode *dir, int *nf_pos,
1795 + struct udf_fileident_bh *fibh,
1796 + struct FileIdentDesc *cfi,
1797 + lb_addr *bloc, Uint32 *extoffset,
1798 + lb_addr *eloc, Uint32 *elen,
1799 + Uint32 *offset, struct buffer_head **bh)
1801 + struct FileIdentDesc *fi;
1804 + fibh->soffset = fibh->eoffset;
1806 + if (fibh->eoffset == dir->i_sb->s_blocksize)
1808 + int lextoffset = *extoffset;
1810 + if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
1811 + EXTENT_RECORDED_ALLOCATED)
1816 + block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
1820 + if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
1823 + *extoffset = lextoffset;
1825 + udf_release_data(fibh->sbh);
1826 + if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1828 + fibh->soffset = fibh->eoffset = 0;
1830 + else if (fibh->sbh != fibh->ebh)
1832 + udf_release_data(fibh->sbh);
1833 + fibh->sbh = fibh->ebh;
1836 + fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
1837 + &(fibh->eoffset));
1842 + *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
1844 + if (fibh->eoffset <= dir->i_sb->s_blocksize)
1846 + memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
1848 + else if (fibh->eoffset > dir->i_sb->s_blocksize)
1850 + int lextoffset = *extoffset;
1852 + if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
1853 + EXTENT_RECORDED_ALLOCATED)
1858 + block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
1862 + if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
1865 + *extoffset = lextoffset;
1867 + fibh->soffset -= dir->i_sb->s_blocksize;
1868 + fibh->eoffset -= dir->i_sb->s_blocksize;
1870 + if (!(fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1873 + if (sizeof(struct FileIdentDesc) > - fibh->soffset)
1877 + memcpy((Uint8 *)cfi, (Uint8 *)fi, - fibh->soffset);
1878 + memcpy((Uint8 *)cfi - fibh->soffset, fibh->ebh->b_data,
1879 + sizeof(struct FileIdentDesc) + fibh->soffset);
1881 + fi_len = (sizeof(struct FileIdentDesc) + cfi->lengthFileIdent +
1882 + le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
1884 + *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
1885 + fibh->eoffset = fibh->soffset + fi_len;
1889 + memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
1896 +struct FileIdentDesc *
1897 +udf_get_fileident(void * buffer, int bufsize, int * offset)
1899 + struct FileIdentDesc *fi;
1900 + int lengthThisIdent;
1904 + if ( (!buffer) || (!offset) ) {
1906 + udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
1913 + if ( (*offset > 0) && (*offset < bufsize) ) {
1916 + fi=(struct FileIdentDesc *)ptr;
1917 + if (le16_to_cpu(fi->descTag.tagIdent) != TID_FILE_IDENT_DESC)
1920 + udf_debug("0x%x != TID_FILE_IDENT_DESC\n",
1921 + le16_to_cpu(fi->descTag.tagIdent));
1922 + udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
1923 + *offset, (unsigned long)sizeof(struct FileIdentDesc), bufsize);
1927 + if ( (*offset + sizeof(struct FileIdentDesc)) > bufsize )
1929 + lengthThisIdent = sizeof(struct FileIdentDesc);
1932 + lengthThisIdent = sizeof(struct FileIdentDesc) +
1933 + fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
1935 + /* we need to figure padding, too! */
1936 + padlen = lengthThisIdent % UDF_NAME_PAD;
1938 + lengthThisIdent += (UDF_NAME_PAD - padlen);
1939 + *offset = *offset + lengthThisIdent;
1945 +udf_get_fileextent(void * buffer, int bufsize, int * offset)
1948 + struct FileEntry *fe;
1951 + if ( (!buffer) || (!offset) )
1954 + printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
1959 + fe = (struct FileEntry *)buffer;
1961 + if ( le16_to_cpu(fe->descTag.tagIdent) != TID_FILE_ENTRY )
1964 + udf_debug("0x%x != TID_FILE_ENTRY\n",
1965 + le16_to_cpu(fe->descTag.tagIdent));
1970 + ptr=(Uint8 *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
1972 + if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
1977 + ext = (extent_ad *)ptr;
1979 + *offset = *offset + sizeof(extent_ad);
1984 +udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
1989 + if ( (!buffer) || (!offset) )
1992 + printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
1997 + ptr = (Uint8 *)buffer;
1999 + if ( (*offset > 0) && (*offset < maxoffset) )
2004 + if ((sa = (short_ad *)ptr)->extLength == 0)
2007 + (*offset) += sizeof(short_ad);
2012 +udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
2017 + if ( (!buffer) || !(offset) )
2020 + printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
2025 + ptr = (Uint8 *)buffer;
2027 + if ( (*offset > 0) && (*offset < maxoffset) )
2032 + if ((la = (long_ad *)ptr)->extLength == 0)
2035 + (*offset) += sizeof(long_ad);
2038 diff -Nru linux/fs/udf/file.c linux.new/fs/udf/file.c
2039 --- linux/fs/udf/file.c Thu Jan 1 01:00:00 1970
2040 +++ linux.new/fs/udf/file.c Fri Sep 7 11:32:16 2001
2046 + * File handling routines for the OSTA-UDF(tm) filesystem.
2049 + * E-mail regarding any portion of the Linux UDF file system should be
2050 + * directed to the development team mailing list (run by majordomo):
2051 + * linux_udf@hootie.lvld.hp.com
2054 + * This file is distributed under the terms of the GNU General Public
2055 + * License (GPL). Copies of the GPL can be obtained from:
2056 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
2057 + * Each contributing author retains all rights to their own work.
2059 + * (C) 1998-1999 Dave Boynton
2060 + * (C) 1998-2000 Ben Fennema
2061 + * (C) 1999-2000 Stelias Computing Inc
2065 + * 10/02/98 dgb Attempt to integrate into udf.o
2066 + * 10/07/98 Switched to using generic_readpage, etc., like isofs
2068 + * 12/06/98 blf Added udf_file_read. uses generic_file_read for all cases but
2069 + * ICB_FLAG_AD_IN_ICB.
2070 + * 04/06/99 64 bit file handling on 32 bit systems taken from ext2 file.c
2071 + * 05/12/99 Preliminary file write support
2074 +#include "udfdecl.h"
2075 +#include <linux/fs.h>
2076 +#include <linux/udf_fs.h>
2077 +#include <asm/uaccess.h>
2078 +#include <linux/kernel.h>
2079 +#include <linux/string.h> /* memset */
2080 +#include <linux/errno.h>
2081 +#include <linux/locks.h>
2084 +#include "udf_sb.h"
2088 +typedef void * poll_table;
2091 + * Make sure the offset never goes beyond the 32-bit mark..
2093 +static long long udf_file_llseek(struct file * file, long long offset, int origin)
2095 + struct inode * inode = file->f_dentry->d_inode;
2101 + offset += inode->i_size;
2106 + offset += file->f_pos;
2110 +#if BITS_PER_LONG < 64
2111 + if (((unsigned long long) offset >> 32) != 0)
2116 + if (offset != file->f_pos)
2118 + file->f_pos = offset;
2119 + file->f_reada = 0;
2120 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
2121 + file->f_version = ++event;
2123 + file->f_version = ++global_event;
2129 +static inline void remove_suid(struct inode * inode)
2131 + unsigned int mode;
2133 + /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
2134 + mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
2136 + /* was any of the uid bits set? */
2137 + mode &= inode->i_mode;
2138 + if (mode && !capable(CAP_FSETID))
2140 + inode->i_mode &= ~mode;
2141 + mark_inode_dirty(inode);
2145 +static ssize_t udf_file_write(struct file * filp, const char * buf,
2146 + size_t count, loff_t *ppos)
2148 + struct inode * inode = filp->f_dentry->d_inode;
2153 + struct buffer_head * bh, * bufferlist[NBUF];
2154 + struct super_block * sb;
2156 + int i, buffercount, write_error, new_buffer;
2157 + unsigned long limit;
2159 + /* POSIX: mtime/ctime may not change for 0 count */
2162 + /* This makes the bounds-checking arithmetic later on much more
2164 + write_error = buffercount = 0;
2167 + printk("udf_file_write: inode = NULL\n");
2171 + if (sb->s_flags & MS_RDONLY)
2176 + if (!S_ISREG(inode->i_mode))
2178 + udf_warning(sb, "udf_file_write", "mode = %07o", inode->i_mode);
2181 + remove_suid(inode);
2183 + if (filp->f_flags & O_APPEND)
2184 + pos = inode->i_size;
2192 +#if BITS_PER_LONG < 64
2193 + /* If the fd's pos is already greater than or equal to the file
2194 + * descriptor's offset maximum, then we need to return EFBIG for
2195 + * any non-zero count (and we already tested for zero above). */
2196 + if (((off_t) pos) >= 0x7FFFFFFFUL)
2199 + /* If we are about to overflow the maximum file size, we also
2200 + * need to return the error, but only if no bytes can be written
2201 + * successfully. */
2202 + if (((off_t) pos + count) > 0x7FFFFFFFUL)
2204 + count = 0x7FFFFFFFL - pos;
2205 + if (((ssize_t) count) < 0)
2210 + limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
2211 + if (limit < RLIM_INFINITY)
2213 + if (((off_t) pos + count) >= limit)
2215 + count = limit - pos;
2216 + if (((ssize_t) count) <= 0)
2218 + send_sig(SIGXFSZ, current, 0);
2225 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
2227 + if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
2230 + udf_expand_file_adinicb(inode, pos + count, &err);
2231 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
2233 + udf_debug("udf_expand_file_adinicb: err=%d\n", err);
2239 + if (pos + count > inode->i_size)
2240 + UDF_I_LENALLOC(inode) = pos + count;
2242 + UDF_I_LENALLOC(inode) = inode->i_size;
2243 + pos += udf_file_entry_alloc_offset(inode);
2247 + if (filp->f_flags & O_SYNC)
2248 + ; /* Do something */
2249 + block = pos >> sb->s_blocksize_bits;
2250 + offset = pos & (sb->s_blocksize - 1);
2251 + c = sb->s_blocksize - offset;
2255 + bh = udf_getblk(inode, block, 1, &err);
2265 + new_buffer = (!buffer_uptodate(bh) && !buffer_locked(bh) &&
2266 + c == sb->s_blocksize);
2271 + set_bit(BH_Lock, &bh->b_state);
2272 + c -= copy_from_user(bh->b_data + offset, buf, c);
2273 + if (c != sb->s_blocksize)
2276 + unlock_buffer(bh);
2279 + written = -EFAULT;
2282 + mark_buffer_uptodate(bh, 1);
2283 + unlock_buffer(bh);
2287 + if (!buffer_uptodate(bh))
2289 + ll_rw_block(READ, 1, &bh);
2290 + wait_on_buffer(bh);
2291 + if (!buffer_uptodate(bh))
2299 + c -= copy_from_user(bh->b_data + offset, buf, c);
2305 + written = -EFAULT;
2308 + mark_buffer_dirty(bh, 0);
2309 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
2310 + update_vm_cache(inode, pos, bh->b_data + offset, c);
2312 + update_vm_cache_conditional(inode, pos, bh->b_data + offset, c,
2313 + (unsigned long) buf);
2320 + if (filp->f_flags & O_SYNC)
2321 + bufferlist[buffercount++] = bh;
2324 + if (buffercount == NBUF)
2326 + ll_rw_block(WRITE, buffercount, bufferlist);
2327 + for (i=0; i<buffercount; i++)
2329 + wait_on_buffer(bufferlist[i]);
2330 + if (!buffer_uptodate(bufferlist[i]))
2332 + brelse(bufferlist[i]);
2340 + c = sb->s_blocksize;
2345 + ll_rw_block(WRITE, buffercount, bufferlist);
2346 + for (i=0; i<buffercount; i++)
2348 + wait_on_buffer(bufferlist[i]);
2349 + if (!buffer_uptodate(bufferlist[i]))
2351 + brelse(bufferlist[i]);
2354 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
2355 + pos -= udf_file_entry_alloc_offset(inode);
2357 + if (pos > inode->i_size)
2358 + inode->i_size = pos;
2359 + if (filp->f_flags & O_SYNC)
2360 + ; /* Do something */
2361 + inode->i_ctime = inode->i_mtime = CURRENT_TIME;
2362 + UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
2364 + mark_inode_dirty(inode);
2375 + * Optional - sys_ioctl() will return -ENOTTY if this routine is not
2376 + * available, and the ioctl cannot be handled without filesystem help.
2378 + * sys_ioctl() handles these ioctls that apply only to regular files:
2379 + * FIBMAP [requires udf_bmap()], FIGETBSZ, FIONREAD
2380 + * These ioctls are also handled by sys_ioctl():
2381 + * FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
2382 + * All other ioctls are passed to the filesystem.
2384 + * Refer to sys_ioctl() in fs/ioctl.c
2385 + * sys_ioctl() -> .
2388 + * inode Pointer to inode that ioctl was issued on.
2389 + * filp Pointer to file that ioctl was issued on.
2390 + * cmd The ioctl command.
2391 + * arg The ioctl argument [can be interpreted as a
2392 + * user-space pointer if desired].
2395 + * <return> Success (>=0) or an error code (<=0) that
2396 + * sys_ioctl() will return.
2399 + * July 1, 1997 - Andrew E. Mileski
2400 + * Written, tested, and released.
2402 +int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
2403 + unsigned long arg)
2406 + struct buffer_head *bh = NULL;
2411 + if ( permission(inode, MAY_READ) != 0 )
2413 + udf_debug("no permission to access inode %lu\n",
2420 + udf_debug("invalid argument to udf_ioctl\n");
2424 + /* first, do ioctls that don't need to udf_read */
2427 + case UDF_GETVOLIDENT:
2428 + if ( (result == verify_area(VERIFY_WRITE, (char *)arg, 32)) == 0)
2429 + result = copy_to_user((char *)arg, UDF_SB_VOLIDENT(inode->i_sb), 32);
2434 + /* ok, we need to read the inode */
2435 + bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
2437 + if (!bh || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))
2439 + udf_debug("bread failed (ino=%ld) or ident (%d) != TID_(EXTENDED_)FILE_ENTRY",
2440 + inode->i_ino, ident);
2444 + if (UDF_I_EXTENDED_FE(inode) == 0)
2446 + struct FileEntry *fe;
2448 + fe = (struct FileEntry *)bh->b_data;
2449 + eaicb = lela_to_cpu(fe->extendedAttrICB);
2450 + if (UDF_I_LENEATTR(inode))
2451 + ea = fe->extendedAttr;
2455 + struct ExtendedFileEntry *efe;
2457 + efe = (struct ExtendedFileEntry *)bh->b_data;
2458 + eaicb = lela_to_cpu(efe->extendedAttrICB);
2459 + if (UDF_I_LENEATTR(inode))
2460 + ea = efe->extendedAttr;
2465 + case UDF_GETEASIZE:
2466 + if ( (result = verify_area(VERIFY_WRITE, (char *)arg, 4)) == 0)
2467 + result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
2470 + case UDF_GETEABLOCK:
2471 + if ( (result = verify_area(VERIFY_WRITE, (char *)arg, UDF_I_LENEATTR(inode))) == 0)
2472 + result = copy_to_user((char *)arg, ea, UDF_I_LENEATTR(inode));
2476 + udf_debug("ino=%ld, cmd=%d\n", inode->i_ino, cmd);
2480 + udf_release_data(bh);
2485 + * udf_release_file
2488 + * Called when all references to the file are closed
2491 + * Discard prealloced blocks
2496 +static int udf_release_file(struct inode * inode, struct file * filp)
2498 + if (filp->f_mode & FMODE_WRITE)
2499 + udf_discard_prealloc(inode);
2503 +#if BITS_PER_LONG < 64
2508 + * Called when an inode is about to be open.
2511 + * Use this to disallow opening RW large files on 32 bit systems.
2516 +static int udf_open_file(struct inode * inode, struct file * filp)
2518 + if (inode->i_size == (Uint32)-1 && (filp->f_mode & FMODE_WRITE))
2524 +static struct file_operations udf_file_operations = {
2525 + udf_file_llseek, /* llseek */
2526 + generic_file_read, /* read */
2527 + udf_file_write, /* write */
2528 + NULL, /* readdir */
2530 + udf_ioctl, /* ioctl */
2531 + generic_file_mmap, /* mmap */
2532 +#if BITS_PER_LONG == 64
2535 + udf_open_file, /* open */
2538 + udf_release_file, /* release */
2539 + udf_sync_file, /* fsync */
2540 + NULL, /* fasync */
2541 + NULL, /* check_media_change */
2542 + NULL, /* revalidate */
2546 +struct inode_operations udf_file_inode_operations = {
2547 + &udf_file_operations,
2548 + NULL, /* create */
2549 + NULL, /* lookup */
2551 + NULL, /* unlink */
2552 + NULL, /* symlink */
2556 + NULL, /* rename */
2557 + NULL, /* readlink */
2558 + NULL, /* follow_link */
2559 + generic_readpage, /* readpage */
2560 + NULL, /* writepage */
2561 + udf_bmap, /* bmap */
2562 + udf_truncate, /* truncate */
2563 + NULL, /* permission */
2565 + NULL, /* updatepage */
2566 + NULL /* revalidate */
2569 +struct inode_operations udf_file_inode_operations_adinicb = {
2570 + &udf_file_operations,
2571 + NULL, /* create */
2572 + NULL, /* lookup */
2574 + NULL, /* unlink */
2575 + NULL, /* symlink */
2579 + NULL, /* rename */
2580 + NULL, /* readlink */
2581 + NULL, /* follow_link */
2582 + udf_readpage_adinicb, /* readpage */
2583 + NULL, /* writepage */
2585 + udf_truncate_adinicb, /* truncate */
2586 + NULL, /* permission */
2588 + NULL, /* updatepage */
2589 + NULL /* revalidate */
2591 diff -Nru linux/fs/udf/fsync.c linux.new/fs/udf/fsync.c
2592 --- linux/fs/udf/fsync.c Thu Jan 1 01:00:00 1970
2593 +++ linux.new/fs/udf/fsync.c Fri Sep 7 11:32:16 2001
2599 + * Fsync handling routines for the OSTA-UDF(tm) filesystem.
2602 + * E-mail regarding any portion of the Linux UDF file system should be
2603 + * directed to the development team mailing list (run by majordomo):
2604 + * linux_udf@hootie.lvld.hp.com
2607 + * This file is distributed under the terms of the GNU General Public
2608 + * License (GPL). Copies of the GPL can be obtained from:
2609 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
2610 + * Each contributing author retains all rights to their own work.
2612 + * (C) 1999-2000 Ben Fennema
2613 + * (C) 1999-2000 Stelias Computing Inc
2617 + * 05/22/99 blf Created.
2620 +#include "udfdecl.h"
2622 +#include <linux/fs.h>
2623 +#include <linux/udf_fs.h>
2626 +static int sync_block (struct inode * inode, Uint32 * block, int wait)
2628 + struct buffer_head * bh;
2632 + bh = get_hash_table (inode->i_dev, *block, inode->i_sb->s_blocksize);
2635 + if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
2639 + if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
2643 + ll_rw_block (WRITE, 1, &bh);
2648 +static int sync_extent (struct inode * inode, lb_addr *loc, Uint32 *len, int wait)
2653 + for (i = 0; i < *len; i++)
2655 + block = udf_get_lb_pblock(inode->i_sb, *loc, i);
2656 + rc = sync_block (inode, &block, wait);
2663 +static int sync_all_extents(struct inode * inode, int wait)
2665 + lb_addr bloc, eloc;
2666 + Uint32 extoffset, elen, offset;
2667 + int err = 0, etype;
2668 + struct buffer_head *bh = NULL;
2670 + if ((etype = inode_bmap(inode, 0, &bloc, &extoffset, &eloc, &elen, &offset, &bh)) != -1)
2672 + err |= sync_extent(inode, &eloc, &elen, wait);
2674 + while ((etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
2676 + if (etype == EXTENT_RECORDED_ALLOCATED)
2677 + err |= sync_extent(inode, &eloc, &elen, wait);
2680 + udf_release_data(bh);
2685 + * File may be NULL when we are called. Perhaps we shouldn't
2686 + * even pass file to fsync ?
2689 +int udf_sync_file(struct file * file, struct dentry *dentry)
2691 + int wait, err = 0;
2692 + struct inode *inode = dentry->d_inode;
2694 + if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
2697 + * Don't sync fast links! or ICB_FLAG_AD_IN_ICB
2702 + for (wait=0; wait<=1; wait++)
2704 + err |= sync_all_extents (inode, wait);
2707 + err |= udf_sync_inode (inode);
2708 + return err ? -EIO : 0;
2710 diff -Nru linux/fs/udf/ialloc.c linux.new/fs/udf/ialloc.c
2711 --- linux/fs/udf/ialloc.c Thu Jan 1 01:00:00 1970
2712 +++ linux.new/fs/udf/ialloc.c Fri Sep 7 11:32:16 2001
2718 + * Inode allocation handling routines for the OSTA-UDF(tm) filesystem.
2721 + * E-mail regarding any portion of the Linux UDF file system should be
2722 + * directed to the development team mailing list (run by majordomo):
2723 + * linux_udf@hootie.lvld.hp.com
2726 + * This file is distributed under the terms of the GNU General Public
2727 + * License (GPL). Copies of the GPL can be obtained from:
2728 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
2729 + * Each contributing author retains all rights to their own work.
2731 + * (C) 1998-2000 Ben Fennema
2735 + * 02/24/99 blf Created.
2739 +#include "udfdecl.h"
2740 +#include <linux/fs.h>
2741 +#include <linux/locks.h>
2742 +#include <linux/quotaops.h>
2743 +#include <linux/udf_fs.h>
2744 +#include <linux/ext2_fs.h>
2747 +#include "udf_sb.h"
2749 +void udf_free_inode(struct inode * inode)
2751 + struct super_block * sb = inode->i_sb;
2753 + unsigned long ino;
2755 + if (!inode->i_dev)
2757 + udf_debug("inode has no device\n");
2760 + if (inode->i_count > 1)
2762 + udf_debug("inode has count=%d\n", inode->i_count);
2765 + if (inode->i_nlink)
2767 + udf_debug("inode has nlink=%d\n", inode->i_nlink);
2772 + udf_debug("inode on nonexistent device\n");
2776 + ino = inode->i_ino;
2779 + * Note: we must free any quota before locking the superblock,
2780 + * as writing the quota to disk may need the lock as well.
2782 + DQUOT_FREE_INODE(sb, inode);
2783 + DQUOT_DROP(inode);
2787 + is_directory = S_ISDIR(inode->i_mode);
2789 + clear_inode(inode);
2791 + if (UDF_SB_LVIDBH(sb))
2794 + UDF_SB_LVIDIU(sb)->numDirs =
2795 + cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs) - 1);
2797 + UDF_SB_LVIDIU(sb)->numFiles =
2798 + cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1);
2800 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
2805 + udf_free_blocks(inode, UDF_I_LOCATION(inode), 0, 1);
2808 +struct inode * udf_new_inode (const struct inode *dir, int mode, int * err)
2810 + struct super_block *sb;
2811 + struct inode * inode;
2813 + Uint32 start = UDF_I_LOCATION(dir).logicalBlockNum;
2815 + inode = get_empty_inode();
2823 + inode->i_flags = 0;
2826 + block = udf_new_block(dir, UDF_I_LOCATION(dir).partitionReferenceNum,
2835 + if (UDF_SB_LVIDBH(sb))
2837 + struct LogicalVolHeaderDesc *lvhd;
2839 + lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(sb)->logicalVolContentsUse);
2840 + if (S_ISDIR(mode))
2841 + UDF_SB_LVIDIU(sb)->numDirs =
2842 + cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs) + 1);
2844 + UDF_SB_LVIDIU(sb)->numFiles =
2845 + cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) + 1);
2846 + UDF_I_UNIQUE(inode) = uniqueID = le64_to_cpu(lvhd->uniqueID);
2847 + if (!(++uniqueID & 0x00000000FFFFFFFFUL))
2849 + lvhd->uniqueID = cpu_to_le64(uniqueID);
2850 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
2852 + inode->i_mode = mode;
2854 + inode->i_nlink = 1;
2855 + inode->i_dev = sb->s_dev;
2856 + inode->i_uid = current->fsuid;
2857 + if (test_opt (sb, GRPID))
2858 + inode->i_gid = dir->i_gid;
2859 + else if (dir->i_mode & S_ISGID)
2861 + inode->i_gid = dir->i_gid;
2862 + if (S_ISDIR(mode))
2866 + inode->i_gid = current->fsgid;
2868 + UDF_I_LOCATION(inode).logicalBlockNum = block;
2869 + UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
2870 + inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
2871 + inode->i_blksize = PAGE_SIZE;
2872 + inode->i_blocks = 0;
2873 + inode->i_size = 0;
2874 + UDF_I_LENEATTR(inode) = 0;
2875 + UDF_I_LENALLOC(inode) = 0;
2876 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
2878 + UDF_I_EXTENDED_FE(inode) = 1;
2879 + UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
2882 + UDF_I_EXTENDED_FE(inode) = 0;
2883 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
2884 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_IN_ICB;
2885 + else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
2886 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
2888 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
2889 + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
2890 + UDF_I_UMTIME(inode) = UDF_I_UATIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME;
2891 + UDF_I_NEW_INODE(inode) = 1;
2892 + inode->i_op = NULL;
2893 + insert_inode_hash(inode);
2894 + mark_inode_dirty(inode);
2897 + if (DQUOT_ALLOC_INODE(sb, inode))
2899 + sb->dq_op->drop(inode);
2900 + inode->i_nlink = 0;
2909 diff -Nru linux/fs/udf/inode.c linux.new/fs/udf/inode.c
2910 --- linux/fs/udf/inode.c Thu Jan 1 01:00:00 1970
2911 +++ linux.new/fs/udf/inode.c Fri Sep 7 11:32:16 2001
2917 + * Inode handling routines for the OSTA-UDF(tm) filesystem.
2920 + * E-mail regarding any portion of the Linux UDF file system should be
2921 + * directed to the development team mailing list (run by majordomo):
2922 + * linux_udf@hootie.lvld.hp.com
2925 + * This file is distributed under the terms of the GNU General Public
2926 + * License (GPL). Copies of the GPL can be obtained from:
2927 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
2928 + * Each contributing author retains all rights to their own work.
2930 + * (C) 1998 Dave Boynton
2931 + * (C) 1998-2000 Ben Fennema
2932 + * (C) 1999-2000 Stelias Computing Inc
2936 + * 10/04/98 dgb Added rudimentary directory functions
2937 + * 10/07/98 Fully working udf_bmap! It works!
2938 + * 11/25/98 bmap altered to better support extents
2939 + * 12/06/98 blf partition support in udf_iget, udf_bmap and udf_read_inode
2940 + * 12/12/98 rewrote udf_bmap to handle next extents and descs across
2941 + * block boundaries (which is not actually allowed)
2942 + * 12/20/98 added support for strategy 4096
2943 + * 03/07/99 rewrote udf_bmap (again)
2944 + * New funcs, inode_bmap, udf_next_aext
2945 + * 04/19/99 Support for writing device EA's for major/minor #
2948 +#include "udfdecl.h"
2949 +#include <linux/locks.h>
2950 +#include <linux/mm.h>
2953 +#include "udf_sb.h"
2955 +#define EXTENT_MERGE_SIZE 5
2957 +static mode_t udf_convert_permissions(struct FileEntry *);
2958 +static int udf_update_inode(struct inode *, int);
2959 +static void udf_fill_inode(struct inode *, struct buffer_head *);
2960 +static struct buffer_head *inode_getblk(struct inode *, long, int, int *);
2961 +static void udf_split_extents(struct inode *, int *, int, int,
2962 + long_ad [EXTENT_MERGE_SIZE], int *);
2963 +static void udf_prealloc_extents(struct inode *, int, int,
2964 + long_ad [EXTENT_MERGE_SIZE], int *);
2965 +static void udf_merge_extents(struct inode *,
2966 + long_ad [EXTENT_MERGE_SIZE], int *);
2967 +static void udf_update_extents(struct inode *,
2968 + long_ad [EXTENT_MERGE_SIZE], int, int,
2969 + lb_addr, Uint32, struct buffer_head **);
2977 + * This routine is called whenever the kernel no longer needs the inode.
2980 + * July 1, 1997 - Andrew E. Mileski
2981 + * Written, tested, and released.
2983 + * Called at each iput()
2985 +void udf_put_inode(struct inode * inode)
2987 + if (!(inode->i_sb->s_flags & MS_RDONLY))
2989 + udf_discard_prealloc(inode);
2990 + /* write the root inode on put, if dirty */
2991 + if (!inode->i_sb->s_root && inode->i_state & I_DIRTY)
2992 + udf_update_inode(inode, IS_SYNC(inode));
2997 + * udf_delete_inode
3000 + * Clean-up before the specified inode is destroyed.
3003 + * This routine is called when the kernel destroys an inode structure
3004 + * ie. when iput() finds i_count == 0.
3007 + * July 1, 1997 - Andrew E. Mileski
3008 + * Written, tested, and released.
3010 + * Called at the last iput() if i_nlink is zero.
3012 +void udf_delete_inode(struct inode * inode)
3014 + if (is_bad_inode(inode))
3016 + inode->i_size = 0;
3017 + if (inode->i_blocks)
3019 + if (inode->i_op && inode->i_op->truncate)
3020 + inode->i_op->truncate(inode);
3022 + udf_truncate(inode);
3024 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
3025 + udf_truncate_adinicb(inode);
3026 + udf_update_inode(inode, IS_SYNC(inode));
3027 + udf_free_inode(inode);
3030 +void udf_discard_prealloc(struct inode * inode)
3032 + if (inode->i_size && UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
3036 +void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
3038 + int block, newblock;
3039 + struct buffer_head *sbh = NULL, *dbh = NULL;
3040 + lb_addr bloc, eloc;
3041 + Uint32 elen, extoffset;
3043 + if (!UDF_I_LENALLOC(inode))
3045 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
3046 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
3048 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
3049 + mark_inode_dirty(inode);
3050 + inode->i_op = &udf_file_inode_operations;
3054 + /* alloc block, and copy data to it */
3055 + block = udf_new_block(inode,
3056 + UDF_I_LOCATION(inode).partitionReferenceNum,
3057 + UDF_I_LOCATION(inode).logicalBlockNum, err);
3061 + newblock = udf_get_pblock(inode->i_sb, block,
3062 + UDF_I_LOCATION(inode).partitionReferenceNum, 0);
3065 + sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
3068 + dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize);
3072 + memcpy(dbh->b_data, sbh->b_data + udf_file_entry_alloc_offset(inode),
3073 + UDF_I_LENALLOC(inode));
3075 + mark_buffer_dirty(dbh, 1);
3076 + udf_release_data(dbh);
3078 + memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
3079 + 0, UDF_I_LENALLOC(inode));
3081 + UDF_I_LENALLOC(inode) = 0;
3082 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
3083 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
3085 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
3086 + bloc = UDF_I_LOCATION(inode);
3087 + eloc.logicalBlockNum = block;
3088 + eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
3089 + elen = newsize > inode->i_sb->s_blocksize ?
3090 + inode->i_sb->s_blocksize : newsize;
3091 + extoffset = udf_file_entry_alloc_offset(inode);
3092 + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
3093 + /* UniqueID stuff */
3095 + inode->i_blocks = inode->i_sb->s_blocksize / 512;
3096 + mark_buffer_dirty(sbh, 1);
3097 + udf_release_data(sbh);
3098 + mark_inode_dirty(inode);
3099 + inode->i_version ++;
3100 + inode->i_op = &udf_file_inode_operations;
3103 +struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
3106 + struct buffer_head *sbh = NULL, *dbh = NULL;
3107 + lb_addr bloc, eloc;
3108 + Uint32 elen, extoffset;
3110 + struct udf_fileident_bh sfibh, dfibh;
3111 + int f_pos = udf_ext0_offset(inode) >> 2;
3112 + int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
3113 + struct FileIdentDesc cfi, *sfi, *dfi;
3115 + if (!inode->i_size)
3117 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
3118 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
3120 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
3121 + mark_inode_dirty(inode);
3125 + /* alloc block, and copy data to it */
3126 + *block = udf_new_block(inode,
3127 + UDF_I_LOCATION(inode).partitionReferenceNum,
3128 + UDF_I_LOCATION(inode).logicalBlockNum, err);
3132 + newblock = udf_get_pblock(inode->i_sb, *block,
3133 + UDF_I_LOCATION(inode).partitionReferenceNum, 0);
3136 + sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
3139 + dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize);
3143 + sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
3144 + sfibh.sbh = sfibh.ebh = sbh;
3145 + dfibh.soffset = dfibh.eoffset = 0;
3146 + dfibh.sbh = dfibh.ebh = dbh;
3147 + while ( (f_pos < size) )
3149 + sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
3152 + udf_release_data(sbh);
3153 + udf_release_data(dbh);
3156 + sfi->descTag.tagLocation = *block;
3157 + dfibh.soffset = dfibh.eoffset;
3158 + dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
3159 + dfi = (struct FileIdentDesc *)(dbh->b_data + dfibh.soffset);
3160 + if (udf_write_fi(sfi, dfi, &dfibh, sfi->impUse,
3161 + sfi->fileIdent + sfi->lengthOfImpUse))
3163 + udf_release_data(sbh);
3164 + udf_release_data(dbh);
3168 + mark_buffer_dirty(dbh, 1);
3170 + memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
3171 + 0, UDF_I_LENALLOC(inode));
3173 + UDF_I_LENALLOC(inode) = 0;
3174 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
3175 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
3177 + UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
3178 + bloc = UDF_I_LOCATION(inode);
3179 + eloc.logicalBlockNum = *block;
3180 + eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
3181 + elen = inode->i_size;
3182 + extoffset = udf_file_entry_alloc_offset(inode);
3183 + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
3184 + /* UniqueID stuff */
3186 + inode->i_blocks = inode->i_sb->s_blocksize / 512;
3187 + mark_buffer_dirty(sbh, 1);
3188 + udf_release_data(sbh);
3189 + mark_inode_dirty(inode);
3190 + inode->i_version ++;
3194 +struct buffer_head * udf_getblk(struct inode * inode, long block,
3195 + int create, int * err)
3200 + udf_warning(inode->i_sb, "udf_getblk", "block < 0");
3204 + if (block == UDF_I_NEXT_ALLOC_BLOCK(inode) + 1)
3206 + UDF_I_NEXT_ALLOC_BLOCK(inode) ++;
3207 + UDF_I_NEXT_ALLOC_GOAL(inode) ++;
3211 + return inode_getblk(inode, block, create, err);
3214 +static struct buffer_head * inode_getblk(struct inode * inode, long block,
3215 + int create, int * err)
3217 + struct buffer_head *pbh = NULL, *cbh = NULL, *result = NULL;
3218 + long_ad laarr[EXTENT_MERGE_SIZE];
3219 + Uint32 pextoffset = 0, cextoffset = 0, nextoffset = 0;
3220 + int count = 0, startnum = 0, endnum = 0;
3222 + lb_addr eloc, pbloc = UDF_I_LOCATION(inode), cbloc = UDF_I_LOCATION(inode);
3224 + int lbcount = 0, b_off = 0, offset = 0;
3225 + Uint32 newblocknum, newblock;
3227 + int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
3228 + char lastblock = 0;
3230 + pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
3231 + b_off = block << inode->i_sb->s_blocksize_bits;
3232 + pbloc = cbloc = UDF_I_LOCATION(inode);
3234 + /* find the extent which contains the block we are looking for.
3235 + alternate between laarr[0] and laarr[1] for locations of the
3236 + current extent, and the previous extent */
3241 + udf_release_data(pbh);
3249 + pextoffset = cextoffset;
3250 + cextoffset = nextoffset;
3252 + if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1)
3257 + laarr[c].extLength = (etype << 30) | elen;
3258 + laarr[c].extLocation = eloc;
3260 + if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
3261 + pgoal = eloc.logicalBlockNum +
3262 + ((elen + inode->i_sb->s_blocksize - 1) >>
3263 + inode->i_sb->s_blocksize);
3266 + } while (lbcount + elen <= b_off);
3269 + offset = b_off >> inode->i_sb->s_blocksize_bits;
3271 + /* if the extent is allocated and recorded, return the block
3272 + if the extent is not a multiple of the blocksize, round up */
3274 + if (etype == EXTENT_RECORDED_ALLOCATED)
3276 + if (elen & (inode->i_sb->s_blocksize - 1))
3278 + elen = (EXTENT_RECORDED_ALLOCATED << 30) |
3279 + ((elen + inode->i_sb->s_blocksize - 1) &
3280 + ~(inode->i_sb->s_blocksize - 1));
3281 + etype = udf_write_aext(inode, cbloc, &cextoffset, eloc, elen, cbh, 1);
3283 + udf_release_data(pbh);
3284 + udf_release_data(cbh);
3285 + newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
3286 + return getblk(inode->i_dev, newblock, inode->i_sb->s_blocksize);
3291 + endnum = startnum = ((count > 1) ? 1 : count);
3292 + if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
3294 + laarr[c].extLength =
3295 + (laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
3296 + (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
3297 + inode->i_sb->s_blocksize - 1) &
3298 + ~(inode->i_sb->s_blocksize - 1));
3301 + laarr[c].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
3302 + ((offset + 1) << inode->i_sb->s_blocksize_bits);
3303 + memset(&laarr[c].extLocation, 0x00, sizeof(lb_addr));
3309 + endnum = startnum = ((count > 2) ? 2 : count);
3311 + /* if the current extent is in position 0, swap it with the previous */
3312 + if (!c && count != 1)
3314 + laarr[2] = laarr[0];
3315 + laarr[0] = laarr[1];
3316 + laarr[1] = laarr[2];
3320 + /* if the current block is located in a extent, read the next extent */
3323 + if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 0)) != -1)
3325 + laarr[c+1].extLength = (etype << 30) | elen;
3326 + laarr[c+1].extLocation = eloc;
3334 + udf_release_data(cbh);
3337 + if (!create && etype != EXTENT_NOT_RECORDED_ALLOCATED)
3341 + unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
3342 + if (limit < RLIM_INFINITY)
3344 + limit >>= inode->i_sb->s_blocksize_bits;
3345 + if (block >= limit)
3347 + send_sig(SIGXFSZ, current, 0);
3355 + /* if the current extent is not recorded but allocated, get the
3356 + block in the extent corresponding to the requested block */
3357 + if ((laarr[c].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
3358 + newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
3359 + else /* otherwise, allocate a new block */
3361 + if (UDF_I_NEXT_ALLOC_BLOCK(inode) == block)
3362 + goal = UDF_I_NEXT_ALLOC_GOAL(inode);
3366 + if (!(goal = pgoal))
3367 + goal = UDF_I_LOCATION(inode).logicalBlockNum + 1;
3370 + if (!(newblocknum = udf_new_block(inode,
3371 + UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
3373 + udf_release_data(pbh);
3379 + /* if the extent the requsted block is located in contains multiple blocks,
3380 + split the extent into at most three extents. blocks prior to requested
3381 + block, requested block, and blocks after requested block */
3382 + udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);
3384 +#ifdef UDF_PREALLOCATE
3385 + /* preallocate blocks */
3386 + udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
3389 + /* merge any continuous blocks in laarr */
3390 + udf_merge_extents(inode, laarr, &endnum);
3392 + /* write back the new extents, inserting new extents if the new number
3393 + of extents is greater than the old number, and deleting extents if
3394 + the new number of extents is less than the old number */
3395 + udf_update_extents(inode, laarr, startnum, endnum, pbloc, pextoffset, &pbh);
3397 + udf_release_data(pbh);
3399 + if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
3400 + UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
3404 + if ((result = getblk(inode->i_dev, newblock, inode->i_sb->s_blocksize)))
3406 + memset(result->b_data, 0x00, inode->i_sb->s_blocksize);
3407 + mark_buffer_uptodate(result, 1);
3408 + mark_buffer_dirty(result, 1);
3410 + UDF_I_NEXT_ALLOC_BLOCK(inode) = block;
3411 + UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum;
3412 + inode->i_ctime = CURRENT_TIME;
3413 + UDF_I_UCTIME(inode) = CURRENT_UTIME;
3414 + inode->i_blocks += inode->i_sb->s_blocksize / 512;
3415 + if (IS_SYNC(inode))
3416 + udf_sync_inode(inode);
3418 + mark_inode_dirty(inode);
3422 +static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum,
3423 + long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
3425 + if ((laarr[*c].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED ||
3426 + (laarr[*c].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
3429 + int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
3430 + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
3431 + int type = laarr[curr].extLength & ~UDF_EXTENT_LENGTH_MASK;
3435 + else if (!offset || blen == offset + 1)
3437 + laarr[curr+2] = laarr[curr+1];
3438 + laarr[curr+1] = laarr[curr];
3442 + laarr[curr+3] = laarr[curr+1];
3443 + laarr[curr+2] = laarr[curr+1] = laarr[curr];
3448 + laarr[curr].extLength = type |
3449 + (offset << inode->i_sb->s_blocksize_bits);
3455 + laarr[curr].extLocation.logicalBlockNum = newblocknum;
3456 + if ((type >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
3457 + laarr[curr].extLocation.partitionReferenceNum =
3458 + UDF_I_LOCATION(inode).partitionReferenceNum;
3459 + laarr[curr].extLength = (EXTENT_RECORDED_ALLOCATED << 30) |
3460 + inode->i_sb->s_blocksize;
3463 + if (blen != offset + 1)
3465 + if ((type >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
3466 + laarr[curr].extLocation.logicalBlockNum += (offset + 1);
3467 + laarr[curr].extLength = type |
3468 + ((blen - (offset + 1)) << inode->i_sb->s_blocksize_bits);
3475 +static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
3476 + long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
3478 + int start, length = 0, currlength = 0, i;
3480 + if (*endnum >= (c+1) && !lastblock)
3483 + if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
3486 + length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) +
3487 + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
3492 + for (i=start+1; i<=*endnum; i++)
3497 + length += UDF_DEFAULT_PREALLOC_BLOCKS;
3499 + else if ((laarr[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
3500 + length += (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3501 + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
3508 + int next = laarr[start].extLocation.logicalBlockNum +
3509 + (((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
3510 + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
3511 + int numalloc = udf_prealloc_blocks(inode,
3512 + laarr[start].extLocation.partitionReferenceNum,
3513 + next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? length :
3514 + UDF_DEFAULT_PREALLOC_BLOCKS) - currlength);
3518 + if (start == (c+1))
3519 + laarr[start].extLength +=
3520 + (numalloc << inode->i_sb->s_blocksize_bits);
3523 + memmove(&laarr[c+2], &laarr[c+1],
3524 + sizeof(long_ad) * (*endnum - (c+1)));
3526 + laarr[c+1].extLocation.logicalBlockNum = next;
3527 + laarr[c+1].extLocation.partitionReferenceNum =
3528 + laarr[c].extLocation.partitionReferenceNum;
3529 + laarr[c+1].extLength = (EXTENT_NOT_RECORDED_ALLOCATED << 30) |
3530 + (numalloc << inode->i_sb->s_blocksize_bits);
3534 + for (i=start+1; numalloc && i<*endnum; i++)
3536 + int elen = ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3537 + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
3539 + if (elen > numalloc)
3541 + laarr[c+1].extLength -=
3542 + (numalloc << inode->i_sb->s_blocksize_bits);
3548 + if (*endnum > (i+1))
3549 + memmove(&laarr[i], &laarr[i+1],
3550 + sizeof(long_ad) * (*endnum - (i+1)));
3559 +static void udf_merge_extents(struct inode *inode,
3560 + long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
3564 + for (i=0; i<(*endnum-1); i++)
3566 + if ((laarr[i].extLength >> 30) == (laarr[i+1].extLength >> 30))
3568 + if (((laarr[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) ||
3569 + ((laarr[i+1].extLocation.logicalBlockNum - laarr[i].extLocation.logicalBlockNum) ==
3570 + (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3571 + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits)))
3573 + if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3574 + (laarr[i+1].extLength & UDF_EXTENT_LENGTH_MASK) +
3575 + inode->i_sb->s_blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK)
3577 + laarr[i+1].extLength = (laarr[i+1].extLength -
3578 + (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3579 + UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1);
3580 + laarr[i].extLength = (UDF_EXTENT_LENGTH_MASK + 1) -
3581 + inode->i_sb->s_blocksize;
3582 + laarr[i+1].extLocation.logicalBlockNum =
3583 + laarr[i].extLocation.logicalBlockNum +
3584 + ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >>
3585 + inode->i_sb->s_blocksize_bits);
3589 + laarr[i].extLength = laarr[i+1].extLength +
3590 + (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3591 + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
3592 + if (*endnum > (i+2))
3593 + memmove(&laarr[i+1], &laarr[i+2],
3594 + sizeof(long_ad) * (*endnum - (i+2)));
3603 +static void udf_update_extents(struct inode *inode,
3604 + long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
3605 + lb_addr pbloc, Uint32 pextoffset, struct buffer_head **pbh)
3611 + if (startnum > endnum)
3613 + for (i=0; i<(startnum-endnum); i++)
3615 + udf_delete_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
3616 + laarr[i].extLength, *pbh);
3619 + else if (startnum < endnum)
3621 + for (i=0; i<(endnum-startnum); i++)
3623 + udf_insert_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
3624 + laarr[i].extLength, *pbh);
3625 + udf_next_aext(inode, &pbloc, &pextoffset, &laarr[i].extLocation,
3626 + &laarr[i].extLength, pbh, 1);
3631 + for (i=start; i<endnum; i++)
3633 + udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0);
3634 + udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation,
3635 + laarr[i].extLength, *pbh, 1);
3639 +struct buffer_head * udf_bread(struct inode * inode, int block,
3640 + int create, int * err)
3642 + struct buffer_head * bh = NULL;
3645 + prev_blocks = inode->i_blocks;
3647 + bh = udf_getblk(inode, block, create, err);
3653 + S_ISDIR(inode->i_mode) &&
3654 + inode->i_blocks > prev_blocks)
3657 + struct buffer_head *tmp_bh = NULL;
3660 + i < UDF_DEFAULT_PREALLOC_DIR_BLOCKS;
3663 + tmp_bh = udf_getblk(inode, block+i, create, err);
3666 + udf_release_data(bh);
3669 + udf_release_data(tmp_bh);
3674 + if (buffer_uptodate(bh))
3676 + ll_rw_block(READ, 1, &bh);
3677 + wait_on_buffer(bh);
3678 + if (buffer_uptodate(bh))
3692 + * This routine is called by iget() [which is called by udf_iget()]
3693 + * (clean_inode() will have been called first)
3694 + * when an inode is first read into memory.
3697 + * July 1, 1997 - Andrew E. Mileski
3698 + * Written, tested, and released.
3700 + * 12/19/98 dgb Updated to fix size problems.
3703 +udf_read_inode(struct inode *inode)
3705 + memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(lb_addr));
3709 +__udf_read_inode(struct inode *inode)
3711 + struct buffer_head *bh = NULL;
3712 + struct FileEntry *fe;
3716 + * Set defaults, but the inode is still incomplete!
3717 + * Note: get_new_inode() sets the following on a new inode:
3719 + * i_dev = sb->s_dev;
3721 + * i_flags = sb->s_flags
3723 + * clean_inode(): zero fills and sets
3729 + inode->i_blksize = PAGE_SIZE;
3731 + bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
3735 + printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",
3737 + make_bad_inode(inode);
3741 + if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY &&
3742 + ident != TID_UNALLOCATED_SPACE_ENTRY)
3744 + printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",
3745 + inode->i_ino, ident);
3746 + udf_release_data(bh);
3747 + make_bad_inode(inode);
3751 + fe = (struct FileEntry *)bh->b_data;
3753 + if (le16_to_cpu(fe->icbTag.strategyType) == 4096)
3755 + struct buffer_head *ibh = NULL, *nbh = NULL;
3756 + struct IndirectEntry *ie;
3758 + ibh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1, &ident);
3759 + if (ident == TID_INDIRECT_ENTRY)
3764 + ie = (struct IndirectEntry *)ibh->b_data;
3766 + loc = lelb_to_cpu(ie->indirectICB.extLocation);
3768 + if (ie->indirectICB.extLength &&
3769 + (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident)))
3771 + if (ident == TID_FILE_ENTRY ||
3772 + ident == TID_EXTENDED_FILE_ENTRY)
3774 + memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(lb_addr));
3775 + udf_release_data(bh);
3776 + udf_release_data(ibh);
3777 + udf_release_data(nbh);
3778 + __udf_read_inode(inode);
3783 + udf_release_data(nbh);
3784 + udf_release_data(ibh);
3788 + udf_release_data(ibh);
3792 + udf_release_data(ibh);
3794 + else if (le16_to_cpu(fe->icbTag.strategyType) != 4)
3796 + printk(KERN_ERR "udf: unsupported strategy type: %d\n",
3797 + le16_to_cpu(fe->icbTag.strategyType));
3798 + udf_release_data(bh);
3799 + make_bad_inode(inode);
3802 + udf_fill_inode(inode, bh);
3803 + udf_release_data(bh);
3806 +static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
3808 + struct FileEntry *fe;
3809 + struct ExtendedFileEntry *efe;
3811 + long convtime_usec;
3814 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
3815 + inode->i_version = ++event;
3817 + inode->i_version = ++global_event;
3819 + UDF_I_NEW_INODE(inode) = 0;
3821 + fe = (struct FileEntry *)bh->b_data;
3822 + efe = (struct ExtendedFileEntry *)bh->b_data;
3824 + if (le16_to_cpu(fe->icbTag.strategyType) == 4)
3825 + UDF_I_STRAT4096(inode) = 0;
3826 + else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */
3827 + UDF_I_STRAT4096(inode) = 1;
3829 + UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK;
3831 + if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY)
3832 + UDF_I_EXTENDED_FE(inode) = 1;
3833 + else if (fe->descTag.tagIdent == TID_FILE_ENTRY)
3834 + UDF_I_EXTENDED_FE(inode) = 0;
3835 + else if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
3837 + UDF_I_LENALLOC(inode) =
3839 + ((struct UnallocatedSpaceEntry *)bh->b_data)->lengthAllocDescs);
3843 + inode->i_uid = udf_convert_uid(le32_to_cpu(fe->uid));
3844 + if ( !inode->i_uid ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
3846 + inode->i_gid = udf_convert_gid(le32_to_cpu(fe->gid));
3847 + if ( !inode->i_gid ) inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
3849 + inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
3850 + if (!inode->i_nlink)
3851 + inode->i_nlink = 1;
3853 + inode->i_size = le64_to_cpu(fe->informationLength);
3854 +#if BITS_PER_LONG < 64
3855 + if (le64_to_cpu(fe->informationLength) & 0xFFFFFFFF00000000ULL)
3856 + inode->i_size = (Uint32)-1;
3859 + inode->i_mode = udf_convert_permissions(fe);
3860 + inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
3862 + UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
3863 + UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
3865 + if (UDF_I_EXTENDED_FE(inode) == 0)
3867 + inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
3868 + (inode->i_sb->s_blocksize_bits - 9);
3870 + if ( udf_stamp_to_time(&convtime, &convtime_usec,
3871 + lets_to_cpu(fe->modificationTime)) )
3873 + inode->i_mtime = convtime;
3874 + UDF_I_UMTIME(inode) = convtime_usec;
3875 + inode->i_ctime = convtime;
3876 + UDF_I_UCTIME(inode) = convtime_usec;
3880 + inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
3881 + UDF_I_UMTIME(inode) = 0;
3882 + inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
3883 + UDF_I_UCTIME(inode) = 0;
3886 + if ( udf_stamp_to_time(&convtime, &convtime_usec,
3887 + lets_to_cpu(fe->accessTime)) )
3889 + inode->i_atime = convtime;
3890 + UDF_I_UATIME(inode) = convtime_usec;
3894 + inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
3895 + UDF_I_UATIME(inode) = convtime_usec;
3898 + UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
3899 + UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
3900 + UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);
3901 + offset = sizeof(struct FileEntry) + UDF_I_LENEATTR(inode);
3902 + alen = offset + UDF_I_LENALLOC(inode);
3906 + inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
3907 + (inode->i_sb->s_blocksize_bits - 9);
3909 + if ( udf_stamp_to_time(&convtime, &convtime_usec,
3910 + lets_to_cpu(efe->modificationTime)) )
3912 + inode->i_mtime = convtime;
3913 + UDF_I_UMTIME(inode) = convtime_usec;
3917 + inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
3918 + UDF_I_UMTIME(inode) = 0;
3921 + if ( udf_stamp_to_time(&convtime, &convtime_usec,
3922 + lets_to_cpu(efe->accessTime)) )
3924 + inode->i_atime = convtime;
3925 + UDF_I_UATIME(inode) = convtime_usec;
3929 + inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
3930 + UDF_I_UATIME(inode) = 0;
3933 + if ( udf_stamp_to_time(&convtime, &convtime_usec,
3934 + lets_to_cpu(efe->createTime)) )
3936 + inode->i_ctime = convtime;
3937 + UDF_I_UCTIME(inode) = convtime_usec;
3941 + inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
3942 + UDF_I_UCTIME(inode) = 0;
3945 + UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID);
3946 + UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
3947 + UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);
3948 + offset = sizeof(struct ExtendedFileEntry) + UDF_I_LENEATTR(inode);
3949 + alen = offset + UDF_I_LENALLOC(inode);
3952 + switch (fe->icbTag.fileType)
3954 + case FILE_TYPE_DIRECTORY:
3956 + inode->i_op = &udf_dir_inode_operations;
3957 + inode->i_mode |= S_IFDIR;
3958 + inode->i_nlink ++;
3961 + case FILE_TYPE_REGULAR:
3962 + case FILE_TYPE_NONE:
3964 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
3965 + inode->i_op = &udf_file_inode_operations_adinicb;
3967 + inode->i_op = &udf_file_inode_operations;
3968 + inode->i_mode |= S_IFREG;
3971 + case FILE_TYPE_BLOCK:
3973 + inode->i_op = &blkdev_inode_operations;
3974 + inode->i_mode |= S_IFBLK;
3977 + case FILE_TYPE_CHAR:
3979 + inode->i_op = &chrdev_inode_operations;
3980 + inode->i_mode |= S_IFCHR;
3983 + case FILE_TYPE_FIFO:
3988 + case FILE_TYPE_SYMLINK:
3991 + inode->i_op = &udf_symlink_inode_operations;
3992 + inode->i_mode = S_IFLNK|S_IRWXUGO;
3997 + printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown file type=%d\n",
3998 + inode->i_ino, fe->icbTag.fileType);
3999 + make_bad_inode(inode);
4003 + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
4005 + struct buffer_head *tbh = NULL;
4006 + struct DeviceSpecificationExtendedAttr *dsea =
4007 + (struct DeviceSpecificationExtendedAttr *)
4008 + udf_get_extendedattr(inode, 12, 1, &tbh);
4012 + inode->i_rdev = to_kdev_t(
4013 + (le32_to_cpu(dsea->majorDeviceIdent)) << 8) |
4014 + (le32_to_cpu(dsea->minorDeviceIdent) & 0xFF);
4015 + /* Developer ID ??? */
4016 + udf_release_data(tbh);
4020 + make_bad_inode(inode);
4026 +udf_convert_permissions(struct FileEntry *fe)
4029 + Uint32 permissions;
4032 + permissions = le32_to_cpu(fe->permissions);
4033 + flags = le16_to_cpu(fe->icbTag.flags);
4035 + mode = (( permissions ) & S_IRWXO) |
4036 + (( permissions >> 2 ) & S_IRWXG) |
4037 + (( permissions >> 4 ) & S_IRWXU) |
4038 + (( flags & ICB_FLAG_SETUID) ? S_ISUID : 0) |
4039 + (( flags & ICB_FLAG_SETGID) ? S_ISGID : 0) |
4040 + (( flags & ICB_FLAG_STICKY) ? S_ISVTX : 0);
4049 + * Write out the specified inode.
4052 + * This routine is called whenever an inode is synced.
4053 + * Currently this routine is just a placeholder.
4056 + * July 1, 1997 - Andrew E. Mileski
4057 + * Written, tested, and released.
4060 +void udf_write_inode(struct inode * inode)
4062 + udf_update_inode(inode, 0);
4065 +int udf_sync_inode(struct inode * inode)
4067 + return udf_update_inode(inode, 1);
4071 +udf_update_inode(struct inode *inode, int do_sync)
4073 + struct buffer_head *bh = NULL;
4074 + struct FileEntry *fe;
4075 + struct ExtendedFileEntry *efe;
4080 + timestamp cpu_time;
4083 + bh = udf_tread(inode->i_sb,
4084 + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0),
4085 + inode->i_sb->s_blocksize);
4088 + udf_debug("bread failure\n");
4091 + fe = (struct FileEntry *)bh->b_data;
4092 + efe = (struct ExtendedFileEntry *)bh->b_data;
4093 + if (UDF_I_NEW_INODE(inode) == 1)
4095 + if (UDF_I_EXTENDED_FE(inode) == 0)
4096 + memset(bh->b_data, 0x0, sizeof(struct FileEntry));
4098 + memset(bh->b_data, 0x00, sizeof(struct ExtendedFileEntry));
4099 + memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
4100 + UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
4101 + udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
4102 + UDF_I_NEW_INODE(inode) = 0;
4105 + if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
4107 + struct UnallocatedSpaceEntry *use =
4108 + (struct UnallocatedSpaceEntry *)bh->b_data;
4110 + use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
4111 + crclen = sizeof(struct UnallocatedSpaceEntry) + UDF_I_LENALLOC(inode) -
4113 + use->descTag.descCRCLength = cpu_to_le16(crclen);
4114 + use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0));
4116 + use->descTag.tagChecksum = 0;
4117 + for (i=0; i<16; i++)
4119 + use->descTag.tagChecksum += ((Uint8 *)&(use->descTag))[i];
4121 + mark_buffer_dirty(bh, 1);
4122 + udf_release_data(bh);
4126 + if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
4127 + fe->uid = cpu_to_le32(inode->i_uid);
4129 + if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid)
4130 + fe->gid = cpu_to_le32(inode->i_gid);
4132 + udfperms = ((inode->i_mode & S_IRWXO) ) |
4133 + ((inode->i_mode & S_IRWXG) << 2) |
4134 + ((inode->i_mode & S_IRWXU) << 4);
4136 + udfperms |= (le32_to_cpu(fe->permissions) &
4137 + (PERM_O_DELETE | PERM_O_CHATTR |
4138 + PERM_G_DELETE | PERM_G_CHATTR |
4139 + PERM_U_DELETE | PERM_U_CHATTR));
4140 + fe->permissions = cpu_to_le32(udfperms);
4142 + if (S_ISDIR(inode->i_mode))
4143 + fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
4145 + fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
4147 + fe->informationLength = cpu_to_le64(inode->i_size);
4149 + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
4152 + struct buffer_head *tbh = NULL;
4153 + struct DeviceSpecificationExtendedAttr *dsea =
4154 + (struct DeviceSpecificationExtendedAttr *)
4155 + udf_get_extendedattr(inode, 12, 1, &tbh);
4159 + dsea = (struct DeviceSpecificationExtendedAttr *)
4160 + udf_add_extendedattr(inode,
4161 + sizeof(struct DeviceSpecificationExtendedAttr) +
4162 + sizeof(EntityID), 12, 0x3, &tbh);
4163 + dsea->attrType = 12;
4164 + dsea->attrSubtype = 1;
4165 + dsea->attrLength = sizeof(struct DeviceSpecificationExtendedAttr) +
4167 + dsea->impUseLength = sizeof(EntityID);
4169 + eid = (EntityID *)dsea->impUse;
4170 + memset(eid, 0, sizeof(EntityID));
4171 + strcpy(eid->ident, UDF_ID_DEVELOPER);
4172 + eid->identSuffix[0] = UDF_OS_CLASS_UNIX;
4173 + eid->identSuffix[1] = UDF_OS_ID_LINUX;
4174 + dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8;
4175 + dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF;
4176 + mark_buffer_dirty(tbh, 1);
4177 + udf_release_data(tbh);
4180 + if (UDF_I_EXTENDED_FE(inode) == 0)
4182 + fe->logicalBlocksRecorded = cpu_to_le64(
4183 + (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
4184 + (inode->i_sb->s_blocksize_bits - 9));
4186 + if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode)))
4187 + fe->accessTime = cpu_to_lets(cpu_time);
4188 + if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
4189 + fe->modificationTime = cpu_to_lets(cpu_time);
4190 + memset(&(fe->impIdent), 0, sizeof(EntityID));
4191 + strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
4192 + fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
4193 + fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
4194 + fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
4195 + fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
4196 + fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
4197 + fe->descTag.tagIdent = le16_to_cpu(TID_FILE_ENTRY);
4198 + crclen = sizeof(struct FileEntry);
4202 + efe->logicalBlocksRecorded = cpu_to_le64(
4203 + (inode->i_blocks + (2 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
4204 + (inode->i_sb->s_blocksize_bits - 9));
4206 + if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode)))
4207 + efe->accessTime = cpu_to_lets(cpu_time);
4208 + if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
4209 + efe->modificationTime = cpu_to_lets(cpu_time);
4210 + if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
4211 + efe->createTime = cpu_to_lets(cpu_time);
4212 + memset(&(efe->impIdent), 0, sizeof(EntityID));
4213 + strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
4214 + efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
4215 + efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
4216 + efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
4217 + efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
4218 + efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
4219 + efe->descTag.tagIdent = le16_to_cpu(TID_EXTENDED_FILE_ENTRY);
4220 + crclen = sizeof(struct ExtendedFileEntry);
4222 + if (UDF_I_STRAT4096(inode))
4224 + fe->icbTag.strategyType = cpu_to_le16(4096);
4225 + fe->icbTag.strategyParameter = cpu_to_le16(1);
4226 + fe->icbTag.numEntries = cpu_to_le16(2);
4230 + fe->icbTag.strategyType = cpu_to_le16(4);
4231 + fe->icbTag.numEntries = cpu_to_le16(1);
4234 + if (S_ISDIR(inode->i_mode))
4235 + fe->icbTag.fileType = FILE_TYPE_DIRECTORY;
4236 + else if (S_ISREG(inode->i_mode))
4237 + fe->icbTag.fileType = FILE_TYPE_REGULAR;
4238 + else if (S_ISLNK(inode->i_mode))
4239 + fe->icbTag.fileType = FILE_TYPE_SYMLINK;
4240 + else if (S_ISBLK(inode->i_mode))
4241 + fe->icbTag.fileType = FILE_TYPE_BLOCK;
4242 + else if (S_ISCHR(inode->i_mode))
4243 + fe->icbTag.fileType = FILE_TYPE_CHAR;
4244 + else if (S_ISFIFO(inode->i_mode))
4245 + fe->icbTag.fileType = FILE_TYPE_FIFO;
4247 + icbflags = UDF_I_ALLOCTYPE(inode) |
4248 + ((inode->i_mode & S_ISUID) ? ICB_FLAG_SETUID : 0) |
4249 + ((inode->i_mode & S_ISGID) ? ICB_FLAG_SETGID : 0) |
4250 + ((inode->i_mode & S_ISVTX) ? ICB_FLAG_STICKY : 0) |
4251 + (le16_to_cpu(fe->icbTag.flags) &
4252 + ~(ICB_FLAG_ALLOC_MASK | ICB_FLAG_SETUID |
4253 + ICB_FLAG_SETGID | ICB_FLAG_STICKY));
4255 + fe->icbTag.flags = cpu_to_le16(icbflags);
4256 + fe->descTag.descVersion = cpu_to_le16(2);
4257 + fe->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
4258 + fe->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
4259 + crclen += UDF_I_LENEATTR(inode) + UDF_I_LENALLOC(inode) - sizeof(tag);
4260 + fe->descTag.descCRCLength = cpu_to_le16(crclen);
4261 + fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag), crclen, 0));
4263 + fe->descTag.tagChecksum = 0;
4264 + for (i=0; i<16; i++)
4266 + fe->descTag.tagChecksum += ((Uint8 *)&(fe->descTag))[i];
4268 + /* write the data blocks */
4269 + mark_buffer_dirty(bh, 1);
4272 + ll_rw_block(WRITE, 1, &bh);
4273 + wait_on_buffer(bh);
4274 + if (buffer_req(bh) && !buffer_uptodate(bh))
4276 + printk("IO error syncing udf inode [%s:%08lx]\n",
4277 + bdevname(inode->i_dev), inode->i_ino);
4281 + udf_release_data(bh);
4292 + * This routine replaces iget() and read_inode().
4295 + * October 3, 1997 - Andrew E. Mileski
4296 + * Written, tested, and released.
4298 + * 12/19/98 dgb Added semaphore and changed to be a wrapper of iget
4301 +udf_iget(struct super_block *sb, lb_addr ino)
4303 + struct inode *inode;
4304 + unsigned long block;
4306 + block = udf_get_lb_pblock(sb, ino, 0);
4308 + /* Get the inode */
4310 + inode = iget(sb, block);
4311 + /* calls udf_read_inode() ! */
4315 + printk(KERN_ERR "udf: iget() failed\n");
4318 + else if (is_bad_inode(inode))
4323 + else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&
4324 + UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)
4326 + memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
4327 + __udf_read_inode(inode);
4330 + if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) )
4332 + udf_debug("block=%d, partition=%d out of range\n",
4333 + ino.logicalBlockNum, ino.partitionReferenceNum);
4340 +int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
4341 + lb_addr eloc, Uint32 elen, struct buffer_head **bh, int inc)
4344 + short_ad *sad = NULL;
4345 + long_ad *lad = NULL;
4346 + struct AllocExtDesc *aed;
4351 + if (!(*bh = udf_tread(inode->i_sb,
4352 + udf_get_lb_pblock(inode->i_sb, *bloc, 0),
4353 + inode->i_sb->s_blocksize)))
4355 + udf_debug("reading block %d failed!\n",
4356 + udf_get_lb_pblock(inode->i_sb, *bloc, 0));
4361 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
4362 + adsize = sizeof(short_ad);
4363 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
4364 + adsize = sizeof(long_ad);
4368 + if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)
4370 + char *sptr, *dptr;
4371 + struct buffer_head *nbh;
4373 + lb_addr obloc = *bloc;
4375 + if (!(bloc->logicalBlockNum = udf_new_block(inode,
4376 + obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
4380 + if (!(nbh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
4381 + *bloc, 0), inode->i_sb->s_blocksize)))
4385 + aed = (struct AllocExtDesc *)(nbh->b_data);
4386 + aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
4387 + if (*extoffset + adsize > inode->i_sb->s_blocksize)
4389 + loffset = *extoffset;
4390 + aed->lengthAllocDescs = cpu_to_le32(adsize);
4391 + sptr = (*bh)->b_data + *extoffset - adsize;
4392 + dptr = nbh->b_data + sizeof(struct AllocExtDesc);
4393 + memcpy(dptr, sptr, adsize);
4394 + *extoffset = sizeof(struct AllocExtDesc) + adsize;
4398 + loffset = *extoffset + adsize;
4399 + aed->lengthAllocDescs = cpu_to_le32(0);
4400 + sptr = (*bh)->b_data + *extoffset;
4401 + *extoffset = sizeof(struct AllocExtDesc);
4403 + if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
4405 + aed = (struct AllocExtDesc *)(*bh)->b_data;
4406 + aed->lengthAllocDescs =
4407 + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
4411 + UDF_I_LENALLOC(inode) += adsize;
4412 + mark_inode_dirty(inode);
4415 + udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1,
4416 + bloc->logicalBlockNum, sizeof(tag));
4417 + switch (UDF_I_ALLOCTYPE(inode))
4419 + case ICB_FLAG_AD_SHORT:
4421 + sad = (short_ad *)sptr;
4422 + sad->extLength = cpu_to_le32(
4423 + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
4424 + inode->i_sb->s_blocksize);
4425 + sad->extPosition = cpu_to_le32(bloc->logicalBlockNum);
4428 + case ICB_FLAG_AD_LONG:
4430 + lad = (long_ad *)sptr;
4431 + lad->extLength = cpu_to_le32(
4432 + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
4433 + inode->i_sb->s_blocksize);
4434 + lad->extLocation = cpu_to_lelb(*bloc);
4438 + udf_update_tag((*bh)->b_data, loffset);
4439 + mark_buffer_dirty(*bh, 1);
4440 + udf_release_data(*bh);
4444 + ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
4446 + if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
4448 + UDF_I_LENALLOC(inode) += adsize;
4449 + mark_inode_dirty(inode);
4453 + aed = (struct AllocExtDesc *)(*bh)->b_data;
4454 + aed->lengthAllocDescs =
4455 + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
4456 + udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize));
4457 + mark_buffer_dirty(*bh, 1);
4463 +int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
4464 + lb_addr eloc, Uint32 elen, struct buffer_head *bh, int inc)
4467 + short_ad *sad = NULL;
4468 + long_ad *lad = NULL;
4472 + if (!(bh = udf_tread(inode->i_sb,
4473 + udf_get_lb_pblock(inode->i_sb, bloc, 0),
4474 + inode->i_sb->s_blocksize)))
4476 + udf_debug("reading block %d failed!\n",
4477 + udf_get_lb_pblock(inode->i_sb, bloc, 0));
4484 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
4485 + adsize = sizeof(short_ad);
4486 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
4487 + adsize = sizeof(long_ad);
4491 + switch (UDF_I_ALLOCTYPE(inode))
4493 + case ICB_FLAG_AD_SHORT:
4495 + sad = (short_ad *)((bh)->b_data + *extoffset);
4496 + sad->extLength = cpu_to_le32(elen);
4497 + sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
4500 + case ICB_FLAG_AD_LONG:
4502 + lad = (long_ad *)((bh)->b_data + *extoffset);
4503 + lad->extLength = cpu_to_le32(elen);
4504 + lad->extLocation = cpu_to_lelb(eloc);
4509 + if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
4511 + struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh)->b_data;
4512 + udf_update_tag((bh)->b_data,
4513 + le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc));
4516 + mark_inode_dirty(inode);
4518 + mark_buffer_dirty(bh, 1);
4521 + *extoffset += adsize;
4522 + udf_release_data(bh);
4523 + return (elen >> 30);
4526 +int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
4527 + lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc)
4535 + if (!(*bh = udf_tread(inode->i_sb,
4536 + udf_get_lb_pblock(inode->i_sb, *bloc, 0),
4537 + inode->i_sb->s_blocksize)))
4539 + udf_debug("reading block %d failed!\n",
4540 + udf_get_lb_pblock(inode->i_sb, *bloc, 0));
4545 + tagIdent = ((tag *)(*bh)->b_data)->tagIdent;
4547 + if (tagIdent == TID_FILE_ENTRY || tagIdent == TID_EXTENDED_FILE_ENTRY ||
4548 + UDF_I_NEW_INODE(inode))
4550 + pos = udf_file_entry_alloc_offset(inode);
4551 + alen = UDF_I_LENALLOC(inode) + pos;
4553 + else if (tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
4555 + pos = sizeof(struct UnallocatedSpaceEntry);
4556 + alen = UDF_I_LENALLOC(inode) + pos;
4558 + else if (tagIdent == TID_ALLOC_EXTENT_DESC)
4560 + struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data;
4562 + pos = sizeof(struct AllocExtDesc);
4563 + alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
4568 + if (!(*extoffset))
4571 + switch (UDF_I_ALLOCTYPE(inode))
4573 + case ICB_FLAG_AD_SHORT:
4577 + if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
4580 + if ((etype = le32_to_cpu(sad->extLength) >> 30) == EXTENT_NEXT_EXTENT_ALLOCDECS)
4582 + bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
4584 + udf_release_data(*bh);
4586 + return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
4590 + eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
4591 + eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
4592 + *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
4596 + case ICB_FLAG_AD_LONG:
4600 + if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
4603 + if ((etype = le32_to_cpu(lad->extLength) >> 30) == EXTENT_NEXT_EXTENT_ALLOCDECS)
4605 + *bloc = lelb_to_cpu(lad->extLocation);
4607 + udf_release_data(*bh);
4609 + return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
4613 + *eloc = lelb_to_cpu(lad->extLocation);
4614 + *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
4618 + case ICB_FLAG_AD_IN_ICB:
4620 + if (UDF_I_LENALLOC(inode) == 0)
4622 + etype = EXTENT_RECORDED_ALLOCATED;
4623 + *eloc = UDF_I_LOCATION(inode);
4624 + *elen = UDF_I_LENALLOC(inode);
4629 + udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
4636 + udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
4637 + inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *elen, etype, *extoffset);
4638 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
4639 + *extoffset -= sizeof(short_ad);
4640 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
4641 + *extoffset -= sizeof(long_ad);
4645 +int udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
4646 + lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc)
4653 + if (!(*bh = udf_tread(inode->i_sb,
4654 + udf_get_lb_pblock(inode->i_sb, *bloc, 0),
4655 + inode->i_sb->s_blocksize)))
4657 + udf_debug("reading block %d failed!\n",
4658 + udf_get_lb_pblock(inode->i_sb, *bloc, 0));
4661 + udf_debug("new bh, count=%d\n", (*bh)->b_count);
4664 + if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
4666 + if (!(UDF_I_EXTENDED_FE(inode)))
4667 + pos = sizeof(struct FileEntry) + UDF_I_LENEATTR(inode);
4669 + pos = sizeof(struct ExtendedFileEntry) + UDF_I_LENEATTR(inode);
4670 + alen = UDF_I_LENALLOC(inode) + pos;
4674 + struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data;
4676 + pos = sizeof(struct AllocExtDesc);
4677 + alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
4680 + if (!(*extoffset))
4683 + switch (UDF_I_ALLOCTYPE(inode))
4685 + case ICB_FLAG_AD_SHORT:
4689 + if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
4692 + etype = le32_to_cpu(sad->extLength) >> 30;
4693 + eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
4694 + eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
4695 + *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
4698 + case ICB_FLAG_AD_LONG:
4702 + if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
4705 + etype = le32_to_cpu(lad->extLength) >> 30;
4706 + *eloc = lelb_to_cpu(lad->extLocation);
4707 + *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
4712 + udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
4719 + udf_debug("Empty Extent!\n");
4720 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
4721 + *extoffset -= sizeof(short_ad);
4722 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
4723 + *extoffset -= sizeof(long_ad);
4727 +int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
4728 + lb_addr neloc, Uint32 nelen, struct buffer_head *bh)
4736 + if (!(bh = udf_tread(inode->i_sb,
4737 + udf_get_lb_pblock(inode->i_sb, bloc, 0),
4738 + inode->i_sb->s_blocksize)))
4740 + udf_debug("reading block %d failed!\n",
4741 + udf_get_lb_pblock(inode->i_sb, bloc, 0));
4748 + while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
4750 + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
4753 + nelen = (type << 30) | oelen;
4755 + udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
4756 + udf_release_data(bh);
4757 + return (nelen >> 30);
4760 +int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
4761 + lb_addr eloc, Uint32 elen, struct buffer_head *nbh)
4763 + struct buffer_head *obh;
4765 + int oextoffset, adsize;
4767 + struct AllocExtDesc *aed;
4771 + if (!(nbh = udf_tread(inode->i_sb,
4772 + udf_get_lb_pblock(inode->i_sb, nbloc, 0),
4773 + inode->i_sb->s_blocksize)))
4775 + udf_debug("reading block %d failed!\n",
4776 + udf_get_lb_pblock(inode->i_sb, nbloc, 0));
4784 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
4785 + adsize = sizeof(short_ad);
4786 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
4787 + adsize = sizeof(long_ad);
4793 + oextoffset = nextoffset;
4795 + if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)
4798 + while ((type = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
4800 + udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, obh, 1);
4801 + if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
4804 + udf_release_data(obh);
4807 + oextoffset = nextoffset - adsize;
4810 + memset(&eloc, 0x00, sizeof(lb_addr));
4813 + if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
4815 + udf_free_blocks(inode, nbloc, 0, 1);
4816 + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
4817 + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
4818 + if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
4820 + UDF_I_LENALLOC(inode) -= (adsize * 2);
4821 + mark_inode_dirty(inode);
4825 + aed = (struct AllocExtDesc *)(obh)->b_data;
4826 + aed->lengthAllocDescs =
4827 + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
4828 + udf_update_tag((obh)->b_data, oextoffset - (2*adsize));
4829 + mark_buffer_dirty(obh, 1);
4834 + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
4835 + if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
4837 + UDF_I_LENALLOC(inode) -= adsize;
4838 + mark_inode_dirty(inode);
4842 + aed = (struct AllocExtDesc *)(obh)->b_data;
4843 + aed->lengthAllocDescs =
4844 + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
4845 + udf_update_tag((obh)->b_data, oextoffset - adsize);
4846 + mark_buffer_dirty(obh, 1);
4850 + udf_release_data(nbh);
4851 + udf_release_data(obh);
4852 + return (elen >> 30);
4855 +int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
4856 + lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh)
4858 + int etype, lbcount = 0;
4862 + printk(KERN_ERR "udf: inode_bmap: block < 0\n");
4867 + printk(KERN_ERR "udf: inode_bmap: NULL inode\n");
4873 + *bloc = UDF_I_LOCATION(inode);
4877 + if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
4879 + *offset = block - lbcount;
4882 + lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >>
4883 + inode->i_sb->s_blocksize_bits);
4884 + } while (lbcount <= block);
4886 + *offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >>
4887 + inode->i_sb->s_blocksize_bits) - lbcount;
4892 +int udf_bmap(struct inode *inode, int block)
4894 + lb_addr eloc, bloc;
4895 + Uint32 offset, extoffset, elen;
4896 + struct buffer_head *bh = NULL;
4899 + if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
4900 + ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
4905 + udf_release_data(bh);
4907 + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
4908 + return udf_fixed_to_variable(ret);
4913 +int udf_readpage_adinicb (struct file * file, struct page * page)
4915 + struct inode * inode;
4916 + struct buffer_head *bh;
4919 + inode = file->f_dentry->d_inode;
4921 + memset((char *)page_address(page), 0, PAGE_SIZE);
4922 + block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
4923 + bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
4924 + if (!buffer_uptodate(bh))
4926 + ll_rw_block (READ, 1, &bh);
4927 + wait_on_buffer(bh);
4929 + memcpy((char *)page_address(page), bh->b_data + udf_ext0_offset(inode),
4932 + set_bit(PG_uptodate, &page->flags);
4935 diff -Nru linux/fs/udf/lowlevel.c linux.new/fs/udf/lowlevel.c
4936 --- linux/fs/udf/lowlevel.c Thu Jan 1 01:00:00 1970
4937 +++ linux.new/fs/udf/lowlevel.c Fri Sep 7 11:32:16 2001
4943 + * Low Level Device Routines for the UDF filesystem
4946 + * E-mail regarding any portion of the Linux UDF file system should be
4947 + * directed to the development team mailing list (run by majordomo):
4948 + * linux_udf@hootie.lvld.hp.com
4951 + * This file is distributed under the terms of the GNU General Public
4952 + * License (GPL). Copies of the GPL can be obtained from:
4953 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
4954 + * Each contributing author retains all rights to their own work.
4956 + * (C) 1999-2000 Ben Fennema
4960 + * 03/26/99 blf Created.
4963 +#include "udfdecl.h"
4965 +#include <linux/blkdev.h>
4966 +#include <linux/cdrom.h>
4967 +#include <asm/uaccess.h>
4968 +#include <scsi/scsi.h>
4970 +typedef struct scsi_device Scsi_Device;
4971 +typedef struct scsi_cmnd Scsi_Cmnd;
4973 +#include <scsi/scsi_ioctl.h>
4975 +#include <linux/udf_fs.h>
4976 +#include "udf_sb.h"
4979 +udf_get_last_session(struct super_block *sb)
4981 + struct cdrom_multisession ms_info;
4982 + unsigned int vol_desc_start;
4983 + kdev_t dev = sb->s_dev;
4984 + struct inode inode_fake;
4985 + extern struct file_operations * get_blkfops(unsigned int);
4989 + if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
4991 + /* Whoops. We must save the old FS, since otherwise
4992 + * we would destroy the kernels idea about FS on root
4993 + * mount in read_super... [chexum]
4995 + mm_segment_t old_fs=get_fs();
4996 + inode_fake.i_rdev=dev;
4997 + ms_info.addr_format=CDROM_LBA;
4998 + set_fs(KERNEL_DS);
4999 + i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
5001 + CDROMMULTISESSION,
5002 + (unsigned long) &ms_info);
5005 +#define WE_OBEY_THE_WRITTEN_STANDARDS 1
5009 + udf_debug("XA disk: %s, vol_desc_start=%d\n",
5010 + (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba);
5011 +#if WE_OBEY_THE_WRITTEN_STANDARDS
5012 + if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
5014 + vol_desc_start = ms_info.addr.lba;
5018 + udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i);
5023 + udf_debug("Device doesn't know how to ioctl?\n");
5025 + return vol_desc_start;
5028 +#ifdef CDROM_LAST_WRITTEN
5030 +static unsigned int
5031 +udf_get_last_written(kdev_t dev, struct inode *inode_fake)
5033 + extern struct file_operations * get_blkfops(unsigned int);
5034 + unsigned long lastsector;
5036 + if (!(get_blkfops(MAJOR(dev))->ioctl(inode_fake,
5038 + CDROM_LAST_WRITTEN,
5039 + (unsigned long) &lastsector)))
5041 + return lastsector - 1;
5050 +do_scsi(kdev_t dev, struct inode *inode_fake, Uint8 *command, int cmd_len,
5051 + Uint8 *buffer, Uint32 in_len, Uint32 out_len)
5053 + extern struct file_operations * get_blkfops(unsigned int);
5056 + ip = (Uint32 *)buffer;
5059 + memcpy(buffer + 8, command, cmd_len);
5060 + return get_blkfops(MAJOR(dev))->ioctl(inode_fake,
5061 + NULL, SCSI_IOCTL_SEND_COMMAND, (unsigned long)buffer);
5064 +static unsigned int
5065 +udf_get_last_rti(kdev_t dev, struct inode *inode_fake)
5071 + Uint32 trackstart, tracklength, freeblocks;
5073 + unsigned long lastsector = 0;
5076 + ip = (int *)(buffer + 8);
5077 + memset(cdb, 0, 10);
5080 + result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, 32);
5083 + track_no = buffer[14];
5084 + udf_debug("Generic Read Disc Info worked; last track is %d. status=0x%x\n",
5085 + track_no, buffer[10] & 0x3);
5086 + memset(buffer, 0, 128);
5089 + cdb[4] = (track_no & 0xFF00) >> 8;
5090 + cdb[5] = track_no & 0xFF;
5092 + result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, 8);
5095 + len = cdb[8] = ((buffer[8] << 8) | (buffer[9] & 0xFF)) + 2;
5096 + result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, len);
5099 + if (buffer[14] & 0x40)
5101 + cdb[4] = ((track_no - 1) & 0xFF00) >> 8;
5102 + cdb[5] = (track_no - 1) & 0xFF;
5103 + result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, len);
5107 + trackstart = be32_to_cpu(ip[2]);
5108 + tracklength = be32_to_cpu(ip[6]);
5109 + freeblocks = be32_to_cpu(ip[4]);
5110 + udf_debug("Start %d, length %d, freeblocks %d.\n", trackstart, tracklength, freeblocks);
5111 + if (buffer[14] & 0x20)
5113 + if (buffer[14] & 0x10)
5115 + udf_debug("Packet size is %d.\n", be32_to_cpu(ip[5]));
5116 + lastsector = trackstart + tracklength - 1;
5120 + udf_debug("Variable packet written track.\n");
5121 + lastsector = trackstart + tracklength - 1;
5124 + lastsector = lastsector - freeblocks - 7;
5132 + return lastsector;
5135 +static unsigned int
5136 +udf_get_toc_entry(kdev_t dev, struct inode *inode_fake)
5138 + extern struct file_operations * get_blkfops(unsigned int);
5139 + struct cdrom_tocentry toc;
5140 + int res, lastsector = 0;
5142 + toc.cdte_format = CDROM_LBA;
5143 + toc.cdte_track = 0xAA;
5145 + if (!(res = get_blkfops(MAJOR(dev))->ioctl(inode_fake,
5147 + CDROMREADTOCENTRY,
5148 + (unsigned long) &toc)))
5150 + lastsector = toc.cdte_addr.lba - 1;
5153 + return lastsector;
5156 +static unsigned int
5157 +udf_get_capacity(kdev_t dev, struct inode *inode_fake)
5163 + unsigned long lastsector = 0;
5165 + ip = (int *)(buffer + 8);
5166 + memset(cdb, 0, 10);
5168 + cdb[0] = READ_CAPACITY;
5169 + result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, 8);
5171 + lastsector = be32_to_cpu(ip[0]);
5173 + return lastsector;
5177 +is_mmc(kdev_t dev, struct inode *inode_fake)
5179 + Uint8 buffer[142];
5180 + int result = 0, n;
5182 + Uint8 *data = &buffer[8];
5185 + cdb[0] = MODE_SENSE;
5188 + cdb[1] = cdb[3] = cdb[5] = 0;
5190 + memset(buffer, 0, 142);
5191 + result = do_scsi(dev, inode_fake, cdb, 6, buffer, 0, len);
5194 + len = cdb[4] = data[3] + 4 + 2;
5195 + result = do_scsi(dev, inode_fake, cdb, 6, buffer, 0, len);
5199 + len = cdb[4] = n + 2 + data[n+1];
5200 + result = do_scsi(dev, inode_fake, cdb, 6, buffer, 0, len);
5201 + if (!result && ((data[n] & 0x3F) == 0x2A))
5203 + udf_debug("Page Code=0x%02x PS=0x%1x Page Length=0x%02x\n",
5204 + data[n] & 0x3F, (data[n] >> 7) & 0x01, data[n+1]);
5205 + udf_debug("DVD-RAM R/W(%c/%c) DVD-R R/W(%c/%c) DVD-ROM R(%c)\n",
5206 + data[n+2] & 0x20 ? 'Y' : 'N', data[n+3] & 0x20 ? 'Y' : 'N',
5207 + data[n+2] & 0x10 ? 'Y' : 'N', data[n+3] & 0x10 ? 'Y' : 'N',
5208 + data[n+2] & 0x08 ? 'Y' : 'N');
5209 + udf_debug("CD-RW R/W(%c/%c) CD-R R/W(%c/%c) Fixed Packet (%c)\n",
5210 + data[n+2] & 0x02 ? 'Y' : 'N', data[n+3] & 0x02 ? 'Y' : 'N',
5211 + data[n+2] & 0x01 ? 'Y' : 'N', data[n+3] & 0x01 ? 'Y' : 'N',
5212 + data[n+2] & 0x04 ? 'Y' : 'N');
5213 + udf_debug("Multi Session (%c) Mode 2 Form 2/1 (%c/%c) Digital Port (2)/(1) (%c/%c)\n",
5214 + data[n+4] & 0x40 ? 'Y' : 'N', data[n+4] & 0x20 ? 'Y' : 'N',
5215 + data[n+4] & 0x10 ? 'Y' : 'N', data[n+4] & 0x08 ? 'Y' : 'N',
5216 + data[n+4] & 0x04 ? 'Y' : 'N');
5217 + udf_debug("Composite (%c) Audio Play (%c) Read Bar Code (%c) UPC (%c) ISRC (%c)\n",
5218 + data[n+4] & 0x02 ? 'Y' : 'N', data[n+4] & 0x01 ? 'Y' : 'N',
5219 + data[n+5] & 0x80 ? 'Y' : 'N', data[n+5] & 0x40 ? 'Y' : 'N',
5220 + data[n+5] & 0x20 ? 'Y' : 'N');
5221 + udf_debug("C2 Pointers are supported (%c) R-W De-interleved & corrected (%c)\n",
5222 + data[n+5] & 0x10 ? 'Y' : 'N', data[n+5] & 0x80 ? 'Y' : 'N');
5223 + udf_debug("R-W Supported (%c) CD-DA Stream is Accurate (%c) CD-DA Commands Supported (%c)\n",
5224 + data[n+5] & 0x04 ? 'Y' : 'N', data[n+5] & 0x02 ? 'Y' : 'N',
5225 + data[n+5] & 0x01 ? 'Y' : 'N');
5226 + udf_debug("Loading Mechanism Type=0x%03x Eject (%c) Prevent Jumper (%c)\n",
5227 + (data[n+6] >> 5) & 0x07, data[n+6] & 0x08 ? 'Y' : 'N',
5228 + data[n+6] & 0x04 ? 'Y' : 'N');
5229 + udf_debug("Lock State (%c) Lock(%c)\n",
5230 + data[n+6] & 0x02 ? 'Y' : 'N', data[n+6] & 0x01 ? 'Y' : 'N');
5231 + udf_debug("P through W in Lead-In (%c) Side Change Capable (%c) S/W Slot Selection (%c)\n",
5232 + data[n+7] & 0x20 ? 'Y' : 'N', data[n+7] & 0x10 ? 'Y' : 'N',
5233 + data[n+7] & 0x08 ? 'Y' : 'N');
5234 + udf_debug("Changer Supports Disc Present (%c) Seperate Channel Mute (%c) Seperate Volume Levels (%c)\n",
5235 + data[n+7] & 0x04 ? 'Y' : 'N', data[n+7] & 0x02 ? 'Y' : 'N',
5236 + data[n+7] & 0x01 ? 'Y' : 'N');
5237 + udf_debug("Maximum Read Speed Supported (in kBps)=0x%04x (Obsolete)\n",
5238 + (data[n+8] << 8) | (data[n+9] & 0xFF));
5239 + udf_debug("Number of Volume Levels Support=0x%04x\n",
5240 + (data[n+10] << 8) | (data[n+11] & 0xFF));
5241 + udf_debug("Buffer Size supported by Drive (in KBytes)=0x%04x\n",
5242 + (data[n+12] << 8) | (data[n+13] & 0xFF));
5243 + udf_debug("Current Read Speed Selected (in kBps)=0x%04x (Obsolete)\n",
5244 + (data[n+14] << 8) | (data[n+15] & 0xFF));
5245 + udf_debug("Digital Out: Length=0x%01x LSBF (%c) RCK (%c) BCKF (%c)\n",
5246 + (data[n+17] >> 4) & 0x03, data[n+17] & 0x08 ? 'Y' : 'N',
5247 + data[n+17] & 0x04 ? 'Y' : 'N', data[n+17] & 0x02 ? 'Y' : 'N');
5248 + udf_debug("Maximum Write Speed Supported (in kBps)=0x%04x (Obsolete)\n",
5249 + (data[n+18] << 8) | (data[n+19] & 0xFF));
5250 + udf_debug("Current Write Speed Selected (in kBps)=0x%04x (Obsolete)\n",
5251 + (data[n+20] << 8) | (data[n+21] & 0xFF));
5252 + udf_debug("Copy Management Revision Supported=%04x\n",
5253 + (data[n+22] << 8) | (data[n+23] & 0xFF));
5265 +udf_get_last_block(struct super_block *sb)
5267 + kdev_t dev = sb->s_dev;
5268 + struct inode inode_fake;
5269 + extern struct file_operations * get_blkfops(unsigned int);
5271 + unsigned long lblock;
5274 + if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
5276 + /* Whoops. We must save the old FS, since otherwise
5277 + * we would destroy the kernels idea about FS on root
5278 + * mount in read_super... [chexum]
5280 + mm_segment_t old_fs=get_fs();
5281 + inode_fake.i_rdev=dev;
5282 + set_fs(KERNEL_DS);
5285 + ret = get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
5288 + (unsigned long) &lblock);
5290 + if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
5292 + udf_debug("BLKGETSIZE lblock=%ld\n", lblock);
5293 + lblock = ((512 * lblock) / sb->s_blocksize) - 1;
5298 +#ifdef CDROM_LAST_WRITTEN
5299 + if ((lblock = udf_get_last_written(dev, &inode_fake)))
5301 + udf_debug("last_written lblock=%ld\n", lblock);
5305 + if (is_mmc(dev, &inode_fake) &&
5306 + (lblock = udf_get_last_rti(dev, &inode_fake)))
5308 + udf_debug("LAST_RTI lblock=%ld\n", lblock);
5310 + else if ((lblock = udf_get_toc_entry(dev, &inode_fake)))
5312 + udf_debug("TOC_ENTRY lblock=%ld\n", lblock);
5314 + else if ((lblock = udf_get_capacity(dev, &inode_fake)))
5316 + udf_debug("READ_CAPACITY lblock=%ld\n", lblock);
5325 + udf_debug("Device doesn't know how to ioctl?\n");
5329 diff -Nru linux/fs/udf/misc.c linux.new/fs/udf/misc.c
5330 --- linux/fs/udf/misc.c Thu Jan 1 01:00:00 1970
5331 +++ linux.new/fs/udf/misc.c Fri Sep 7 11:32:16 2001
5337 + * Miscellaneous routines for the OSTA-UDF(tm) filesystem.
5340 + * E-mail regarding any portion of the Linux UDF file system should be
5341 + * directed to the development team mailing list (run by majordomo):
5342 + * linux_udf@hootie.lvld.hp.com
5345 + * This file is distributed under the terms of the GNU General Public
5346 + * License (GPL). Copies of the GPL can be obtained from:
5347 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
5348 + * Each contributing author retains all rights to their own work.
5350 + * (C) 1998 Dave Boynton
5351 + * (C) 1998-2000 Ben Fennema
5352 + * (C) 1999-2000 Stelias Computing Inc
5356 + * 04/19/99 blf partial support for reading/writing specific EA's
5359 +#include "udfdecl.h"
5361 +#if defined(__linux__) && defined(__KERNEL__)
5363 +#include "udf_sb.h"
5366 +#include <linux/fs.h>
5367 +#include <linux/string.h>
5368 +#include <linux/udf_fs.h>
5372 +#include <sys/types.h>
5374 +#include <unistd.h>
5375 +#include <string.h>
5377 +int udf_blocksize=0;
5381 +udf_setblocksize(int size)
5383 + udf_blocksize=size;
5388 +udf64_low32(Uint64 indat)
5390 + return indat & 0x00000000FFFFFFFFULL;
5394 +udf64_high32(Uint64 indat)
5396 + return indat >> 32;
5399 +uid_t udf_convert_uid(int uidin)
5401 + if ( uidin == -1 )
5403 + if ( uidin > (64*1024U - 1) ) /* 16 bit UID */
5408 +gid_t udf_convert_gid(int gidin)
5410 + if ( gidin == -1 )
5412 + if ( gidin > (64*1024U - 1) ) /* 16 bit GID */
5417 +#if defined(__linux__) && defined(__KERNEL__)
5419 +extern struct buffer_head *
5420 +udf_tread(struct super_block *sb, int block, int size)
5422 + if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
5423 + return bread(sb->s_dev, udf_fixed_to_variable(block), size);
5425 + return bread(sb->s_dev, block, size);
5428 +extern struct GenericAttrFormat *
5429 +udf_add_extendedattr(struct inode * inode, Uint32 size, Uint32 type,
5430 + Uint8 loc, struct buffer_head **bh)
5432 + Uint8 *ea = NULL, *ad = NULL;
5436 + *bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
5438 + if (UDF_I_EXTENDED_FE(inode) == 0)
5440 + struct FileEntry *fe;
5442 + fe = (struct FileEntry *)(*bh)->b_data;
5443 + eaicb = lela_to_cpu(fe->extendedAttrICB);
5444 + offset = sizeof(struct FileEntry);
5448 + struct ExtendedFileEntry *efe;
5450 + efe = (struct ExtendedFileEntry *)(*bh)->b_data;
5451 + eaicb = lela_to_cpu(efe->extendedAttrICB);
5452 + offset = sizeof(struct ExtendedFileEntry);
5455 + ea = &(*bh)->b_data[offset];
5456 + if (UDF_I_LENEATTR(inode))
5457 + offset += UDF_I_LENEATTR(inode);
5459 + size += sizeof(struct ExtendedAttrHeaderDesc);
5461 + ad = &(*bh)->b_data[offset];
5462 + if (UDF_I_LENALLOC(inode))
5463 + offset += UDF_I_LENALLOC(inode);
5465 + offset = inode->i_sb->s_blocksize - offset;
5467 + /* TODO - Check for FreeEASpace */
5469 + if (loc & 0x01 && offset >= size)
5471 + struct ExtendedAttrHeaderDesc *eahd;
5472 + eahd = (struct ExtendedAttrHeaderDesc *)ea;
5474 + if (UDF_I_LENALLOC(inode))
5476 + memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
5479 + if (UDF_I_LENEATTR(inode))
5481 + /* check checksum/crc */
5482 + if (le16_to_cpu(eahd->descTag.tagIdent) != TID_EXTENDED_ATTRE_HEADER_DESC ||
5483 + le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
5485 + udf_release_data(*bh);
5491 + size -= sizeof(struct ExtendedAttrHeaderDesc);
5492 + UDF_I_LENEATTR(inode) += sizeof(struct ExtendedAttrHeaderDesc);
5493 + eahd->descTag.tagIdent = cpu_to_le16(TID_EXTENDED_ATTRE_HEADER_DESC);
5494 + eahd->descTag.descVersion = cpu_to_le16(2);
5495 + eahd->descTag.tagSerialNum = cpu_to_le16(1);
5496 + eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
5497 + eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
5498 + eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
5501 + offset = UDF_I_LENEATTR(inode);
5504 + if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
5506 + Uint32 aal = le32_to_cpu(eahd->appAttrLocation);
5507 + memmove(&ea[offset - aal + size],
5508 + &ea[aal], offset - aal);
5510 + eahd->appAttrLocation = cpu_to_le32(aal + size);
5512 + if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode))
5514 + Uint32 ial = le32_to_cpu(eahd->impAttrLocation);
5515 + memmove(&ea[offset - ial + size],
5516 + &ea[ial], offset - ial);
5518 + eahd->impAttrLocation = cpu_to_le32(ial + size);
5521 + else if (type < 65536)
5523 + if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
5525 + Uint32 aal = le32_to_cpu(eahd->appAttrLocation);
5526 + memmove(&ea[offset - aal + size],
5527 + &ea[aal], offset - aal);
5529 + eahd->appAttrLocation = cpu_to_le32(aal + size);
5532 + /* rewrite CRC + checksum of eahd */
5533 + UDF_I_LENEATTR(inode) += size;
5534 + return (struct GenericAttrFormat *)&ea[offset];
5539 + udf_release_data(*bh);
5543 +extern struct GenericAttrFormat *
5544 +udf_get_extendedattr(struct inode * inode, Uint32 type, Uint8 subtype,
5545 + struct buffer_head **bh)
5547 + struct GenericAttrFormat *gaf;
5552 + *bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
5554 + if (UDF_I_EXTENDED_FE(inode) == 0)
5556 + struct FileEntry *fe;
5558 + fe = (struct FileEntry *)(*bh)->b_data;
5559 + eaicb = lela_to_cpu(fe->extendedAttrICB);
5560 + if (UDF_I_LENEATTR(inode))
5561 + ea = fe->extendedAttr;
5565 + struct ExtendedFileEntry *efe;
5567 + efe = (struct ExtendedFileEntry *)(*bh)->b_data;
5568 + eaicb = lela_to_cpu(efe->extendedAttrICB);
5569 + if (UDF_I_LENEATTR(inode))
5570 + ea = efe->extendedAttr;
5573 + if (UDF_I_LENEATTR(inode))
5575 + struct ExtendedAttrHeaderDesc *eahd;
5576 + eahd = (struct ExtendedAttrHeaderDesc *)ea;
5578 + /* check checksum/crc */
5579 + if (le16_to_cpu(eahd->descTag.tagIdent) != TID_EXTENDED_ATTRE_HEADER_DESC ||
5580 + le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
5582 + udf_release_data(*bh);
5587 + offset = sizeof(struct ExtendedAttrHeaderDesc);
5588 + else if (type < 65536)
5589 + offset = le32_to_cpu(eahd->impAttrLocation);
5591 + offset = le32_to_cpu(eahd->appAttrLocation);
5593 + while (offset < UDF_I_LENEATTR(inode))
5595 + gaf = (struct GenericAttrFormat *)&ea[offset];
5596 + if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
5599 + offset += le32_to_cpu(gaf->attrLength);
5603 + udf_release_data(*bh);
5604 + if (eaicb.extLength)
5611 +extern struct buffer_head *
5612 +udf_read_untagged(struct super_block *sb, Uint32 block, Uint32 offset)
5614 + struct buffer_head *bh = NULL;
5616 + /* Read the block */
5617 + bh = udf_tread(sb, block+offset, sb->s_blocksize);
5620 + printk(KERN_ERR "udf: udf_read_untagged(%p,%d,%d) failed\n",
5621 + sb, block, offset);
5631 + * Read the first block of a tagged descriptor.
5634 + * July 1, 1997 - Andrew E. Mileski
5635 + * Written, tested, and released.
5637 +extern struct buffer_head *
5638 +udf_read_tagged(struct super_block *sb, Uint32 block, Uint32 location, Uint16 *ident)
5641 + struct buffer_head *bh = NULL;
5642 + register Uint8 checksum;
5645 + /* Read the block */
5646 + if (block == 0xFFFFFFFF)
5649 + bh = udf_tread(sb, block, sb->s_blocksize);
5652 + udf_debug("block=%d, location=%d: read failed\n", block, location);
5656 + tag_p = (tag *)(bh->b_data);
5658 + *ident = le16_to_cpu(tag_p->tagIdent);
5660 + if ( location != le32_to_cpu(tag_p->tagLocation) )
5662 + udf_debug("location mismatch block %d, tag %d != %d\n",
5663 + block, le32_to_cpu(tag_p->tagLocation), location);
5667 + /* Verify the tag checksum */
5669 + for (i = 0; i < 4; i++)
5670 + checksum += (Uint8)(bh->b_data[i]);
5671 + for (i = 5; i < 16; i++)
5672 + checksum += (Uint8)(bh->b_data[i]);
5673 + if (checksum != tag_p->tagChecksum) {
5674 + printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
5678 + /* Verify the tag version */
5679 + if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
5680 + le16_to_cpu(tag_p->descVersion) != 0x0003U)
5682 + udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
5683 + le16_to_cpu(tag_p->descVersion), block);
5687 + /* Verify the descriptor CRC */
5688 + if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
5689 + le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
5690 + le16_to_cpu(tag_p->descCRCLength), 0))
5694 + udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
5695 + block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
5702 +extern struct buffer_head *
5703 +udf_read_ptagged(struct super_block *sb, lb_addr loc, Uint32 offset, Uint16 *ident)
5705 + return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
5706 + loc.logicalBlockNum + offset, ident);
5709 +void udf_release_data(struct buffer_head *bh)
5717 +void udf_update_tag(char *data, int length)
5719 + tag *tptr = (tag *)data;
5722 + length -= sizeof(tag);
5724 + tptr->tagChecksum = 0;
5725 + tptr->descCRCLength = le16_to_cpu(length);
5726 + tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0));
5728 + for (i=0; i<16; i++)
5730 + tptr->tagChecksum += (Uint8)(data[i]);
5733 +void udf_new_tag(char *data, Uint16 ident, Uint16 version, Uint16 snum,
5734 + Uint32 loc, int length)
5736 + tag *tptr = (tag *)data;
5737 + tptr->tagIdent = le16_to_cpu(ident);
5738 + tptr->descVersion = le16_to_cpu(version);
5739 + tptr->tagSerialNum = le16_to_cpu(snum);
5740 + tptr->tagLocation = le32_to_cpu(loc);
5741 + udf_update_tag(data, length);
5746 + * udf_read_tagged_data
5749 + * Read the first block of a tagged descriptor.
5750 + * Usable from user-land.
5753 + * 10/4/98 dgb: written
5756 +udf_read_tagged_data(char *buffer, int size, int fd, int block, int offset)
5759 + register Uint8 checksum;
5761 + unsigned long offs;
5769 + if ( !udf_blocksize )
5775 + if ( size < udf_blocksize )
5782 + offs=(long)block * udf_blocksize;
5783 + if ( lseek(fd, offs, SEEK_SET) != offs ) {
5788 + i=read(fd, buffer, udf_blocksize);
5789 + if ( i < udf_blocksize ) {
5794 + tag_p = (tag *)(buffer);
5796 + /* Verify the tag location */
5797 + if ((block-offset) != tag_p->tagLocation) {
5799 + printk(KERN_ERR "udf: location mismatch block %d, tag %d\n",
5800 + block, tag_p->tagLocation);
5807 + /* Verify the tag checksum */
5809 + for (i = 0; i < 4; i++)
5810 + checksum += (Uint8)(buffer[i]);
5811 + for (i = 5; i < 16; i++)
5812 + checksum += (Uint8)(buffer[i]);
5813 + if (checksum != tag_p->tagChecksum) {
5815 + printk(KERN_ERR "udf: tag checksum failed\n");
5822 + /* Verify the tag version */
5823 + if (tag_p->descVersion != 0x0002U) {
5825 + printk(KERN_ERR "udf: tag version 0x%04x != 0x0002U\n",
5826 + tag_p->descVersion);
5833 + /* Verify the descriptor CRC */
5834 + if (tag_p->descCRC == udf_crc(buffer + 16, tag_p->descCRCLength, 0)) {
5839 + printk(KERN_ERR "udf: crc failure in udf_read_tagged\n");
5848 diff -Nru linux/fs/udf/namei.c linux.new/fs/udf/namei.c
5849 --- linux/fs/udf/namei.c Thu Jan 1 01:00:00 1970
5850 +++ linux.new/fs/udf/namei.c Fri Sep 7 11:32:16 2001
5856 + * Inode name handling routines for the OSTA-UDF(tm) filesystem.
5859 + * E-mail regarding any portion of the Linux UDF file system should be
5860 + * directed to the development team mailing list (run by majordomo):
5861 + * linux_udf@hootie.lvld.hp.com
5864 + * This file is distributed under the terms of the GNU General Public
5865 + * License (GPL). Copies of the GPL can be obtained from:
5866 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
5867 + * Each contributing author retains all rights to their own work.
5869 + * (C) 1998-2000 Ben Fennema
5870 + * (C) 1999-2000 Stelias Computing Inc
5874 + * 12/12/98 blf Created. Split out the lookup code from dir.c
5875 + * 04/19/99 blf link, mknod, symlink support
5878 +#include "udfdecl.h"
5880 +#if defined(__linux__) && defined(__KERNEL__)
5881 +#include <linux/version.h>
5883 +#include "udf_sb.h"
5884 +#include <linux/string.h>
5885 +#include <linux/errno.h>
5886 +#include <linux/mm.h>
5887 +#include <linux/malloc.h>
5888 +#include <linux/quotaops.h>
5889 +#include <linux/udf_fs.h>
5892 +static inline int udf_match(int len, const char * const name, struct qstr *qs)
5894 + if (len != qs->len)
5896 + return !memcmp(name, qs->name, len);
5899 +int udf_write_fi(struct FileIdentDesc *cfi, struct FileIdentDesc *sfi,
5900 + struct udf_fileident_bh *fibh,
5901 + Uint8 *impuse, Uint8 *fileident)
5903 + Uint16 crclen = fibh->eoffset - fibh->soffset - sizeof(tag);
5905 + Uint8 checksum = 0;
5908 + Uint16 liu = le16_to_cpu(cfi->lengthOfImpUse);
5909 + Uint8 lfi = cfi->lengthFileIdent;
5910 + int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
5911 + sizeof(struct FileIdentDesc);
5914 + offset = fibh->soffset + sizeof(struct FileIdentDesc);
5918 + if (offset + liu < 0)
5919 + memcpy((Uint8 *)sfi->impUse, impuse, liu);
5920 + else if (offset >= 0)
5921 + memcpy(fibh->ebh->b_data + offset, impuse, liu);
5924 + memcpy((Uint8 *)sfi->impUse, impuse, -offset);
5925 + memcpy(fibh->ebh->b_data, impuse - offset, liu + offset);
5933 + if (offset + lfi < 0)
5934 + memcpy((Uint8 *)sfi->fileIdent + liu, fileident, lfi);
5935 + else if (offset >= 0)
5936 + memcpy(fibh->ebh->b_data + offset, fileident, lfi);
5939 + memcpy((Uint8 *)sfi->fileIdent + liu, fileident, -offset);
5940 + memcpy(fibh->ebh->b_data, fileident - offset, lfi + offset);
5946 + if (offset + padlen < 0)
5947 + memset((Uint8 *)sfi->padding + liu + lfi, 0x00, padlen);
5948 + else if (offset >= 0)
5949 + memset(fibh->ebh->b_data + offset, 0x00, padlen);
5952 + memset((Uint8 *)sfi->padding + liu + lfi, 0x00, -offset);
5953 + memset(fibh->ebh->b_data, 0x00, padlen + offset);
5956 + crc = udf_crc((Uint8 *)cfi + sizeof(tag), sizeof(struct FileIdentDesc) -
5959 + if (fibh->sbh == fibh->ebh)
5960 + crc = udf_crc((Uint8 *)sfi->impUse,
5961 + crclen + sizeof(tag) - sizeof(struct FileIdentDesc), crc);
5962 + else if (sizeof(struct FileIdentDesc) >= -fibh->soffset)
5963 + crc = udf_crc(fibh->ebh->b_data + sizeof(struct FileIdentDesc) + fibh->soffset,
5964 + crclen + sizeof(tag) - sizeof(struct FileIdentDesc), crc);
5967 + crc = udf_crc((Uint8 *)sfi->impUse,
5968 + -fibh->soffset - sizeof(struct FileIdentDesc), crc);
5969 + crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
5972 + cfi->descTag.descCRC = cpu_to_le32(crc);
5973 + cfi->descTag.descCRCLength = cpu_to_le16(crclen);
5975 + for (i=0; i<16; i++)
5977 + checksum += ((Uint8 *)&cfi->descTag)[i];
5979 + cfi->descTag.tagChecksum = checksum;
5980 + if (sizeof(struct FileIdentDesc) <= -fibh->soffset)
5981 + memcpy((Uint8 *)sfi, (Uint8 *)cfi, sizeof(struct FileIdentDesc));
5984 + memcpy((Uint8 *)sfi, (Uint8 *)cfi, -fibh->soffset);
5985 + memcpy(fibh->ebh->b_data, (Uint8 *)cfi - fibh->soffset,
5986 + sizeof(struct FileIdentDesc) + fibh->soffset);
5989 + if (fibh->sbh != fibh->ebh)
5990 + mark_buffer_dirty(fibh->ebh, 1);
5991 + mark_buffer_dirty(fibh->sbh, 1);
5995 +static struct FileIdentDesc *
5996 +udf_find_entry(struct inode *dir, struct dentry *dentry,
5997 + struct udf_fileident_bh *fibh,
5998 + struct FileIdentDesc *cfi)
6000 + struct FileIdentDesc *fi=NULL;
6007 + int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
6008 + lb_addr bloc, eloc;
6009 + Uint32 extoffset, elen, offset;
6010 + struct buffer_head *bh = NULL;
6015 + f_pos = (udf_ext0_offset(dir) >> 2);
6017 + fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
6018 + if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
6019 + &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
6021 + block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
6022 + if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
6024 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
6025 + extoffset -= sizeof(short_ad);
6026 + else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
6027 + extoffset -= sizeof(long_ad);
6034 + udf_release_data(bh);
6038 + if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
6040 + udf_debug("udf_tread failed: block=%d\n", block);
6041 + udf_release_data(bh);
6045 + while ( (f_pos < size) )
6047 + fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
6051 + if (fibh->sbh != fibh->ebh)
6052 + udf_release_data(fibh->ebh);
6053 + udf_release_data(fibh->sbh);
6054 + udf_release_data(bh);
6058 + liu = le16_to_cpu(cfi->lengthOfImpUse);
6059 + lfi = cfi->lengthFileIdent;
6061 + if (fibh->sbh == fibh->ebh)
6063 + nameptr = fi->fileIdent + liu;
6067 + int poffset; /* Unpaded ending offset */
6069 + poffset = fibh->soffset + sizeof(struct FileIdentDesc) + liu + lfi;
6071 + if (poffset >= lfi)
6072 + nameptr = (Uint8 *)(fibh->ebh->b_data + poffset - lfi);
6076 + memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
6077 + memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
6081 + if ( (cfi->fileCharacteristics & FILE_DELETED) != 0 )
6083 + if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
6087 + if ( (cfi->fileCharacteristics & FILE_HIDDEN) != 0 )
6089 + if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
6096 + if ((flen = udf_get_filename(nameptr, fname, lfi)))
6098 + if (udf_match(flen, fname, &(dentry->d_name)))
6100 + udf_release_data(bh);
6105 + if (fibh->sbh != fibh->ebh)
6106 + udf_release_data(fibh->ebh);
6107 + udf_release_data(fibh->sbh);
6108 + udf_release_data(bh);
6116 + * Look-up the inode for a given name.
6119 + * Required - lookup_dentry() will return -ENOTDIR if this routine is not
6120 + * available for a directory. The filesystem is useless if this routine is
6121 + * not available for at least the filesystem's root directory.
6123 + * This routine is passed an incomplete dentry - it must be completed by
6124 + * calling d_add(dentry, inode). If the name does not exist, then the
6125 + * specified inode must be set to null. An error should only be returned
6126 + * when the lookup fails for a reason other than the name not existing.
6127 + * Note that the directory inode semaphore is held during the call.
6129 + * Refer to lookup_dentry() in fs/namei.c
6130 + * lookup_dentry() -> lookup() -> real_lookup() -> .
6133 + * dir Pointer to inode of parent directory.
6134 + * dentry Pointer to dentry to complete.
6137 + * <return> Zero on success.
6140 + * July 1, 1997 - Andrew E. Mileski
6141 + * Written, tested, and released.
6144 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6149 +udf_lookup(struct inode *dir, struct dentry *dentry)
6151 + struct inode *inode = NULL;
6152 + struct FileIdentDesc cfi, *fi;
6153 + struct udf_fileident_bh fibh;
6155 + if (dentry->d_name.len > UDF_NAME_LEN)
6156 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6157 + return -ENAMETOOLONG;
6159 + return ERR_PTR(-ENAMETOOLONG);
6162 +#ifdef UDF_RECOVERY
6163 + /* temporary shorthand for specifying files by inode number */
6164 + if (!strncmp(dentry->d_name.name, ".B=", 3) )
6166 + lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
6167 + inode = udf_iget(dir->i_sb, lb);
6169 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6172 + return ERR_PTR(-EACCES);
6176 +#endif /* UDF_RECOVERY */
6178 + if ((fi = udf_find_entry(dir, dentry, &fibh, &cfi)))
6180 + if (fibh.sbh != fibh.ebh)
6181 + udf_release_data(fibh.ebh);
6182 + udf_release_data(fibh.sbh);
6184 + inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
6186 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6189 + return ERR_PTR(-EACCES);
6192 + d_add(dentry, inode);
6193 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6200 +static struct FileIdentDesc *
6201 +udf_add_entry(struct inode *dir, struct dentry *dentry,
6202 + struct udf_fileident_bh *fibh,
6203 + struct FileIdentDesc *cfi, int *err)
6205 + struct super_block *sb;
6206 + struct FileIdentDesc *fi=NULL;
6207 + struct ustr unifilename;
6208 + char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
6213 + int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
6218 + lb_addr bloc, eloc;
6219 + Uint32 extoffset, elen, offset;
6220 + struct buffer_head *bh = NULL;
6222 + if (!dir || !dir->i_nlink)
6226 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6227 + if (dentry->d_name.len >= UDF_NAME_LEN)
6229 + *err = -ENAMETOOLONG;
6234 + if (dentry->d_name.len)
6236 + if (!dentry->d_name.len)
6242 + if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
6244 + *err = -ENAMETOOLONG;
6248 + if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
6250 + *err = -ENAMETOOLONG;
6257 + nfidlen = (sizeof(struct FileIdentDesc) + namelen + 3) & ~3;
6259 + f_pos = (udf_ext0_offset(dir) >> 2);
6261 + fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
6262 + if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
6263 + &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
6265 + block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
6266 + if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
6268 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
6269 + extoffset -= sizeof(short_ad);
6270 + else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
6271 + extoffset -= sizeof(long_ad);
6276 + if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
6278 + udf_release_data(bh);
6283 + block = UDF_I_LOCATION(dir).logicalBlockNum;
6285 + while ( (f_pos < size) )
6287 + fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
6291 + if (fibh->sbh != fibh->ebh)
6292 + udf_release_data(fibh->ebh);
6293 + udf_release_data(fibh->sbh);
6294 + udf_release_data(bh);
6299 + liu = le16_to_cpu(cfi->lengthOfImpUse);
6300 + lfi = cfi->lengthFileIdent;
6302 + if (fibh->sbh == fibh->ebh)
6303 + nameptr = fi->fileIdent + liu;
6306 + int poffset; /* Unpaded ending offset */
6308 + poffset = fibh->soffset + sizeof(struct FileIdentDesc) + liu + lfi;
6310 + if (poffset >= lfi)
6311 + nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
6315 + memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
6316 + memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
6320 + if ( (cfi->fileCharacteristics & FILE_DELETED) != 0 )
6322 + if (((sizeof(struct FileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
6324 + udf_release_data(bh);
6325 + cfi->descTag.tagSerialNum = cpu_to_le16(1);
6326 + cfi->fileVersionNum = cpu_to_le16(1);
6327 + cfi->fileCharacteristics = 0;
6328 + cfi->lengthFileIdent = namelen;
6329 + cfi->lengthOfImpUse = cpu_to_le16(0);
6330 + if (!udf_write_fi(cfi, fi, fibh, NULL, name))
6343 + if ((flen = udf_get_filename(nameptr, fname, lfi)))
6345 + if (udf_match(flen, fname, &(dentry->d_name)))
6347 + if (fibh->sbh != fibh->ebh)
6348 + udf_release_data(fibh->ebh);
6349 + udf_release_data(fibh->sbh);
6350 + udf_release_data(bh);
6359 + block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
6360 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
6362 + fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize);
6363 + fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
6367 + fibh->sbh = fibh->ebh = NULL;
6368 + fibh->soffset = fibh->eoffset = sb->s_blocksize;
6374 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB &&
6375 + sb->s_blocksize - fibh->eoffset < nfidlen)
6377 + udf_release_data(bh);
6379 + fibh->soffset -= udf_ext0_offset(dir);
6380 + fibh->eoffset -= udf_ext0_offset(dir);
6381 + f_pos -= (udf_ext0_offset(dir) >> 2);
6382 + if (fibh->sbh != fibh->ebh)
6383 + udf_release_data(fibh->ebh);
6384 + udf_release_data(fibh->sbh);
6385 + if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
6387 + bloc = UDF_I_LOCATION(dir);
6388 + eloc.logicalBlockNum = block;
6389 + eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
6390 + elen = dir->i_sb->s_blocksize;
6391 + extoffset = udf_file_entry_alloc_offset(dir);
6392 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
6393 + extoffset += sizeof(short_ad);
6394 + else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
6395 + extoffset += sizeof(long_ad);
6398 + if (sb->s_blocksize - fibh->eoffset >= nfidlen)
6400 + fibh->soffset = fibh->eoffset;
6401 + fibh->eoffset += nfidlen;
6402 + if (fibh->sbh != fibh->ebh)
6404 + udf_release_data(fibh->sbh);
6405 + fibh->sbh = fibh->ebh;
6408 + if (UDF_I_ALLOCTYPE(dir) != ICB_FLAG_AD_IN_ICB)
6409 + block = eloc.logicalBlockNum + ((elen - 1) >>
6410 + dir->i_sb->s_blocksize_bits);
6412 + block = UDF_I_LOCATION(dir).logicalBlockNum;
6414 + fi = (struct FileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
6418 + fibh->soffset = fibh->eoffset - sb->s_blocksize;
6419 + fibh->eoffset += nfidlen - sb->s_blocksize;
6420 + if (fibh->sbh != fibh->ebh)
6422 + udf_release_data(fibh->sbh);
6423 + fibh->sbh = fibh->ebh;
6426 + block = eloc.logicalBlockNum + ((elen - 1) >>
6427 + dir->i_sb->s_blocksize_bits);
6429 + if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
6431 + udf_release_data(bh);
6432 + udf_release_data(fibh->sbh);
6436 + if (!(fibh->soffset))
6438 + if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==
6439 + EXTENT_RECORDED_ALLOCATED)
6441 + block = eloc.logicalBlockNum + ((elen - 1) >>
6442 + dir->i_sb->s_blocksize_bits);
6447 + udf_release_data(fibh->sbh);
6448 + fibh->sbh = fibh->ebh;
6449 + fi = (struct FileIdentDesc *)(fibh->sbh->b_data);
6453 + fi = (struct FileIdentDesc *)
6454 + (fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
6458 + memset(cfi, 0, sizeof(struct FileIdentDesc));
6459 + udf_new_tag((char *)cfi, TID_FILE_IDENT_DESC, 2, 1, block, sizeof(tag));
6460 + cfi->fileVersionNum = cpu_to_le16(1);
6461 + cfi->lengthFileIdent = namelen;
6462 + cfi->lengthOfImpUse = cpu_to_le16(0);
6463 + if (!udf_write_fi(cfi, fi, fibh, NULL, name))
6465 + udf_release_data(bh);
6466 + dir->i_size += nfidlen;
6467 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
6468 + UDF_I_LENALLOC(dir) += nfidlen;
6469 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6470 + dir->i_version = ++event;
6472 + dir->i_version = ++global_event;
6474 + mark_inode_dirty(dir);
6479 + udf_release_data(bh);
6480 + if (fibh->sbh != fibh->ebh)
6481 + udf_release_data(fibh->ebh);
6482 + udf_release_data(fibh->sbh);
6488 +static int udf_delete_entry(struct FileIdentDesc *fi,
6489 + struct udf_fileident_bh *fibh,
6490 + struct FileIdentDesc *cfi)
6492 + cfi->fileCharacteristics |= FILE_DELETED;
6493 + return udf_write_fi(cfi, fi, fibh, NULL, NULL);
6496 +int udf_create(struct inode *dir, struct dentry *dentry, int mode)
6498 + struct udf_fileident_bh fibh;
6499 + struct inode *inode;
6500 + struct FileIdentDesc cfi, *fi;
6503 + inode = udf_new_inode(dir, mode, &err);
6506 + udf_debug("udf_new_inode failure, err=%d\n", err);
6510 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
6511 + inode->i_op = &udf_file_inode_operations_adinicb;
6513 + inode->i_op = &udf_file_inode_operations;
6514 + inode->i_mode = mode;
6515 + mark_inode_dirty(inode);
6517 + if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
6519 + udf_debug("udf_add_entry failure!\n");
6520 + inode->i_nlink --;
6521 + mark_inode_dirty(inode);
6525 + cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
6526 + cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
6527 + *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
6528 + cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
6529 + udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
6530 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
6532 + mark_inode_dirty(dir);
6533 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6534 + dir->i_version = ++event;
6536 + dir->i_version = ++global_event;
6539 + if (fibh.sbh != fibh.ebh)
6540 + udf_release_data(fibh.ebh);
6541 + udf_release_data(fibh.sbh);
6542 + d_instantiate(dentry, inode);
6546 +int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
6548 + struct inode * inode;
6549 + struct udf_fileident_bh fibh;
6551 + struct FileIdentDesc cfi, *fi;
6553 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6554 + err = -ENAMETOOLONG;
6555 + if (dentry->d_name.len >= UDF_NAME_LEN)
6560 + inode = udf_new_inode(dir, mode, &err);
6564 + inode->i_uid = current->fsuid;
6565 + inode->i_mode = mode;
6566 + inode->i_op = NULL;
6567 + if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
6569 + udf_debug("udf_add_entry failure!\n");
6570 + inode->i_nlink --;
6571 + mark_inode_dirty(inode);
6575 + cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
6576 + cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
6577 + *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
6578 + cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
6579 + udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
6580 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
6582 + mark_inode_dirty(dir);
6583 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6584 + dir->i_version = ++event;
6586 + dir->i_version = ++global_event;
6589 + if (S_ISREG(inode->i_mode))
6591 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
6592 + inode->i_op = &udf_file_inode_operations_adinicb;
6594 + inode->i_op = &udf_file_inode_operations;
6596 + else if (S_ISCHR(inode->i_mode))
6598 + inode->i_op = &chrdev_inode_operations;
6600 + else if (S_ISBLK(inode->i_mode))
6602 + inode->i_op = &blkdev_inode_operations;
6604 + else if (S_ISFIFO(inode->i_mode))
6608 + if (S_ISBLK(mode) || S_ISCHR(mode))
6609 + inode->i_rdev = to_kdev_t(rdev);
6610 + mark_inode_dirty(inode);
6612 + if (fibh.sbh != fibh.ebh)
6613 + udf_release_data(fibh.ebh);
6614 + udf_release_data(fibh.sbh);
6615 + d_instantiate(dentry, inode);
6621 +int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
6623 + struct inode * inode;
6624 + struct udf_fileident_bh fibh;
6626 + struct FileIdentDesc cfi, *fi;
6628 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6629 + err = -ENAMETOOLONG;
6630 + if (dentry->d_name.len >= UDF_NAME_LEN)
6635 + if (dir->i_nlink >= (256<<sizeof(dir->i_nlink))-1)
6639 + inode = udf_new_inode(dir, S_IFDIR, &err);
6643 + inode->i_op = &udf_dir_inode_operations;
6644 + if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err)))
6647 + mark_inode_dirty(inode);
6651 + inode->i_nlink = 2;
6652 + cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
6653 + cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));
6654 + *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
6655 + cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
6656 + cfi.fileCharacteristics = FILE_DIRECTORY | FILE_PARENT;
6657 + udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
6658 + udf_release_data(fibh.sbh);
6659 + inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
6660 + if (dir->i_mode & S_ISGID)
6661 + inode->i_mode |= S_ISGID;
6662 + mark_inode_dirty(inode);
6664 + if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
6666 + udf_debug("udf_add_entry failure!\n");
6667 + inode->i_nlink = 0;
6668 + mark_inode_dirty(inode);
6672 + cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
6673 + cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
6674 + *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
6675 + cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
6676 + cfi.fileCharacteristics |= FILE_DIRECTORY;
6677 + udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
6678 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6679 + dir->i_version = ++event;
6681 + dir->i_version = ++global_event;
6684 + mark_inode_dirty(dir);
6685 + d_instantiate(dentry, inode);
6686 + if (fibh.sbh != fibh.ebh)
6687 + udf_release_data(fibh.ebh);
6688 + udf_release_data(fibh.sbh);
6694 +static int empty_dir(struct inode *dir)
6696 + struct FileIdentDesc *fi, cfi;
6697 + struct udf_fileident_bh fibh;
6699 + int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
6701 + lb_addr bloc, eloc;
6702 + Uint32 extoffset, elen, offset;
6703 + struct buffer_head *bh = NULL;
6705 + f_pos = (udf_ext0_offset(dir) >> 2);
6707 + fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
6708 + if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
6709 + &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
6711 + block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
6712 + if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
6714 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
6715 + extoffset -= sizeof(short_ad);
6716 + else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
6717 + extoffset -= sizeof(long_ad);
6724 + udf_release_data(bh);
6728 + if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
6731 + while ( (f_pos < size) )
6733 + fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
6737 + if (fibh.sbh != fibh.ebh)
6738 + udf_release_data(fibh.ebh);
6739 + udf_release_data(fibh.sbh);
6740 + udf_release_data(bh);
6744 + if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FILE_DELETED) == 0)
6746 + udf_release_data(bh);
6750 + if (fibh.sbh != fibh.ebh)
6751 + udf_release_data(fibh.ebh);
6752 + udf_release_data(fibh.sbh);
6753 + udf_release_data(bh);
6757 +int udf_rmdir(struct inode * dir, struct dentry * dentry)
6760 + struct inode * inode;
6761 + struct udf_fileident_bh fibh;
6762 + struct FileIdentDesc *fi, cfi;
6764 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6765 + retval = -ENAMETOOLONG;
6766 + if (dentry->d_name.len >= UDF_NAME_LEN)
6771 + fi = udf_find_entry(dir, dentry, &fibh, &cfi);
6775 + inode = dentry->d_inode;
6776 + DQUOT_INIT(inode);
6779 + if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino)
6782 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6783 + if (!empty_dir(inode))
6784 + retval = -ENOTEMPTY;
6785 + else if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) !=
6792 + retval = udf_delete_entry(fi, &fibh, &cfi);
6793 + dir->i_version = ++event;
6796 + retval = -ENOTEMPTY;
6797 + if (!empty_dir(inode))
6799 + retval = udf_delete_entry(fi, &fibh, &cfi);
6800 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6801 + dir->i_version = ++event;
6803 + dir->i_version = ++global_event;
6808 + if (inode->i_nlink != 2)
6809 + udf_warning(inode->i_sb, "udf_rmdir",
6810 + "empty directory has nlink != 2 (%d)",
6812 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6813 + inode->i_version = ++event;
6815 + inode->i_version = ++global_event;
6817 + inode->i_nlink = 0;
6818 + inode->i_size = 0;
6819 + mark_inode_dirty(inode);
6821 + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
6822 + UDF_I_UCTIME(inode) = UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME;
6823 + mark_inode_dirty(dir);
6827 + if (fibh.sbh != fibh.ebh)
6828 + udf_release_data(fibh.ebh);
6829 + udf_release_data(fibh.sbh);
6834 +int udf_unlink(struct inode * dir, struct dentry * dentry)
6837 + struct inode * inode;
6838 + struct udf_fileident_bh fibh;
6839 + struct FileIdentDesc *fi;
6840 + struct FileIdentDesc cfi;
6842 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6843 + retval = -ENAMETOOLONG;
6844 + if (dentry->d_name.len >= UDF_NAME_LEN)
6849 + fi = udf_find_entry(dir, dentry, &fibh, &cfi);
6853 + inode = dentry->d_inode;
6854 + DQUOT_INIT(inode);
6858 + if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) !=
6864 + if (!inode->i_nlink)
6866 + udf_debug("Deleting nonexistent file (%lu), %d\n",
6867 + inode->i_ino, inode->i_nlink);
6868 + inode->i_nlink = 1;
6870 + retval = udf_delete_entry(fi, &fibh, &cfi);
6873 + dir->i_ctime = dir->i_mtime = CURRENT_TIME;
6874 + UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME;
6875 + mark_inode_dirty(dir);
6877 + mark_inode_dirty(inode);
6878 + inode->i_ctime = dir->i_ctime;
6880 + d_delete(dentry); /* This also frees the inode */
6883 + if (fibh.sbh != fibh.ebh)
6884 + udf_release_data(fibh.ebh);
6885 + udf_release_data(fibh.sbh);
6890 +int udf_symlink(struct inode * dir, struct dentry * dentry, const char * symname)
6892 + struct inode * inode;
6893 + struct PathComponent *pc;
6895 + struct udf_fileident_bh fibh;
6896 + struct buffer_head *bh = NULL;
6897 + int eoffset, elen = 0;
6898 + struct FileIdentDesc *fi;
6899 + struct FileIdentDesc cfi;
6904 + if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
6907 + inode->i_mode = S_IFLNK | S_IRWXUGO;
6908 + inode->i_op = &udf_symlink_inode_operations;
6910 + if (UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
6912 + struct buffer_head *bh = NULL;
6913 + lb_addr bloc, eloc;
6914 + Uint32 elen, extoffset;
6916 + block = udf_new_block(inode,
6917 + UDF_I_LOCATION(inode).partitionReferenceNum,
6918 + UDF_I_LOCATION(inode).logicalBlockNum, &err);
6920 + goto out_no_entry;
6921 + bloc = UDF_I_LOCATION(inode);
6922 + eloc.logicalBlockNum = block;
6923 + eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
6924 + elen = inode->i_sb->s_blocksize;
6925 + extoffset = udf_file_entry_alloc_offset(inode);
6926 + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);
6927 + udf_release_data(bh);
6929 + inode->i_blocks = inode->i_sb->s_blocksize / 512;
6930 + block = udf_get_pblock(inode->i_sb, block,
6931 + UDF_I_LOCATION(inode).partitionReferenceNum, 0);
6934 + block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
6936 + bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize);
6937 + ea = bh->b_data + udf_ext0_offset(inode);
6939 + eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
6940 + pc = (struct PathComponent *)ea;
6942 + if (*symname == '/')
6947 + } while (*symname == '/');
6949 + pc->componentType = 1;
6950 + pc->lengthComponentIdent = 0;
6951 + pc->componentFileVersionNum = 0;
6952 + pc += sizeof(struct PathComponent);
6953 + elen += sizeof(struct PathComponent);
6956 + err = -ENAMETOOLONG;
6960 + if (elen + sizeof(struct PathComponent) > eoffset)
6961 + goto out_no_entry;
6963 + pc = (struct PathComponent *)(ea + elen);
6965 + compstart = (char *)symname;
6970 + } while (*symname && *symname != '/');
6972 + pc->componentType = 5;
6973 + pc->lengthComponentIdent = 0;
6974 + pc->componentFileVersionNum = 0;
6975 + if (pc->componentIdent[0] == '.')
6977 + if (pc->lengthComponentIdent == 1)
6978 + pc->componentType = 4;
6979 + else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
6980 + pc->componentType = 3;
6983 + if (pc->componentType == 5)
6985 + if (elen + sizeof(struct PathComponent) + symname - compstart > eoffset)
6986 + goto out_no_entry;
6988 + pc->lengthComponentIdent = symname - compstart;
6990 + memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
6993 + elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
7000 + } while (*symname == '/');
7004 + udf_release_data(bh);
7005 + inode->i_size = elen;
7006 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
7007 + UDF_I_LENALLOC(inode) = inode->i_size;
7008 + mark_inode_dirty(inode);
7010 + if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
7011 + goto out_no_entry;
7012 + cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
7013 + cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
7014 + if (UDF_SB_LVIDBH(inode->i_sb))
7016 + struct LogicalVolHeaderDesc *lvhd;
7018 + lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
7019 + uniqueID = le64_to_cpu(lvhd->uniqueID);
7020 + *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
7021 + cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
7022 + if (!(++uniqueID & 0x00000000FFFFFFFFUL))
7024 + lvhd->uniqueID = cpu_to_le64(uniqueID);
7025 + mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
7027 + udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
7028 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
7030 + mark_inode_dirty(dir);
7031 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7032 + dir->i_version = ++event;
7034 + dir->i_version = ++global_event;
7037 + if (fibh.sbh != fibh.ebh)
7038 + udf_release_data(fibh.ebh);
7039 + udf_release_data(fibh.sbh);
7040 + d_instantiate(dentry, inode);
7048 + mark_inode_dirty(inode);
7053 +int udf_link(struct dentry * old_dentry, struct inode * dir,
7054 + struct dentry *dentry)
7056 + struct inode *inode = old_dentry->d_inode;
7057 + struct udf_fileident_bh fibh;
7059 + struct FileIdentDesc cfi, *fi;
7061 + if (S_ISDIR(inode->i_mode))
7064 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
7065 + if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
7069 + if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
7072 + if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
7074 + cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
7075 + cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
7076 + if (UDF_SB_LVIDBH(inode->i_sb))
7078 + struct LogicalVolHeaderDesc *lvhd;
7080 + lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
7081 + uniqueID = le64_to_cpu(lvhd->uniqueID);
7082 + *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
7083 + cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
7084 + if (!(++uniqueID & 0x00000000FFFFFFFFUL))
7086 + lvhd->uniqueID = cpu_to_le64(uniqueID);
7087 + mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
7089 + udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
7090 + if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
7092 + mark_inode_dirty(dir);
7093 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7094 + dir->i_version = ++event;
7096 + dir->i_version = ++global_event;
7099 + if (fibh.sbh != fibh.ebh)
7100 + udf_release_data(fibh.ebh);
7101 + udf_release_data(fibh.sbh);
7102 + inode->i_nlink ++;
7103 + inode->i_ctime = CURRENT_TIME;
7104 + UDF_I_UCTIME(inode) = CURRENT_UTIME;
7105 + mark_inode_dirty(inode);
7106 + inode->i_count ++;
7107 + d_instantiate(dentry, inode);
7112 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
7115 + * rename uses retrying to avoid race-conditions: at least they should be
7117 + * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
7118 + * checks fail, it tries to restart itself again. Very practical - no changes
7119 + * are done until we know everything works ok.. and then all the changes can be
7120 + * done in one fell swoop when we have claimed all the buffers needed.
7122 + * Anybody can rename anything with this: the permission checks are left to the
7123 + * higher-level routines.
7125 +static int do_udf_rename(struct inode *old_dir, struct dentry *old_dentry,
7126 + struct inode *new_dir, struct dentry *new_dentry)
7128 + struct inode * old_inode, * new_inode;
7129 + struct udf_fileident_bh ofibh, nfibh;
7130 + struct FileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;
7131 + struct buffer_head *dir_bh = NULL;
7132 + int retval = -ENOENT;
7134 + if (old_dentry->d_name.len > UDF_NAME_LEN)
7137 + old_inode = old_dentry->d_inode;
7138 + ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);
7139 + if (!ofi || udf_get_lb_pblock(old_dir->i_sb, lelb_to_cpu(ocfi.icb.extLocation), 0) !=
7145 + new_inode = new_dentry->d_inode;
7146 + nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
7151 + if (nfibh.sbh != nfibh.ebh)
7152 + udf_release_data(nfibh.ebh);
7153 + udf_release_data(nfibh.sbh);
7158 + DQUOT_INIT(new_inode);
7162 + if (new_inode == old_inode)
7164 + if (S_ISDIR(old_inode->i_mode))
7166 + Uint32 offset = udf_ext0_offset(old_inode);
7168 + if (is_subdir(new_dentry, old_dentry))
7173 + /* Prune any children before testing for busy */
7174 + if (new_dentry->d_count > 1)
7175 + shrink_dcache_parent(new_dentry);
7177 + if (new_dentry->d_count > 1)
7179 + retval = -ENOTEMPTY;
7180 + if (!empty_dir(new_inode))
7183 + dir_bh = udf_bread(old_inode, 0, 0, &retval);
7186 + dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
7189 + if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
7195 + if (!new_inode && new_dir->i_nlink >= (256<<sizeof(new_dir->i_nlink))-1)
7200 + nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);
7204 + new_dir->i_version = ++event;
7207 + * Like most other Unix systems, set the ctime for inodes on a
7210 + old_inode->i_ctime = CURRENT_TIME;
7211 + UDF_I_UCTIME(old_inode) = CURRENT_UTIME;
7212 + mark_inode_dirty(old_inode);
7217 + ncfi.fileVersionNum = ocfi.fileVersionNum;
7218 + ncfi.fileCharacteristics = ocfi.fileCharacteristics;
7219 + memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad));
7220 + udf_write_fi(&ncfi, nfi, &nfibh, NULL, NULL);
7222 + udf_delete_entry(ofi, &ofibh, &ocfi);
7224 + old_dir->i_version = ++event;
7227 + new_inode->i_nlink--;
7228 + new_inode->i_ctime = CURRENT_TIME;
7229 + UDF_I_UCTIME(new_inode) = CURRENT_UTIME;
7230 + mark_inode_dirty(new_inode);
7232 + old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
7233 + UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
7234 + mark_inode_dirty(old_dir);
7238 + dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
7239 + udf_update_tag((char *)dir_fi, sizeof(struct FileIdentDesc) +
7240 + cpu_to_le16(dir_fi->lengthOfImpUse));
7241 + if (UDF_I_ALLOCTYPE(old_inode) == ICB_FLAG_AD_IN_ICB)
7243 + mark_inode_dirty(old_inode);
7244 + old_inode->i_version = ++event;
7247 + mark_buffer_dirty(dir_bh, 1);
7248 + old_dir->i_nlink --;
7249 + mark_inode_dirty(old_dir);
7252 + new_inode->i_nlink --;
7253 + mark_inode_dirty(new_inode);
7257 + new_dir->i_nlink ++;
7258 + mark_inode_dirty(new_dir);
7262 + /* Update the dcache */
7263 + d_move(old_dentry, new_dentry);
7267 + udf_release_data(dir_bh);
7270 + if (ofibh.sbh != ofibh.ebh)
7271 + udf_release_data(ofibh.ebh);
7272 + udf_release_data(ofibh.sbh);
7276 + if (nfibh.sbh != nfibh.ebh)
7277 + udf_release_data(nfibh.ebh);
7278 + udf_release_data(nfibh.sbh);
7283 +/* Ok, rename also locks out other renames, as they can change the parent of
7284 + * a directory, and we don't want any races. Other races are checked for by
7285 + * "do_rename()", which restarts if there are inconsistencies.
7287 + * Note that there is no race between different filesystems: it's only within
7288 + * the same device that races occur: many renames can happen at once, as long
7289 + * as they are on different partitions.
7291 + * In the udf file system, we use a lock flag stored in the memory
7292 + * super-block. This way, we really lock other renames only if they occur
7293 + * on the same file system
7296 +int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
7297 + struct inode *new_dir, struct dentry *new_dentry)
7301 + while (UDF_SB_RENAME_LOCK(old_dir->i_sb))
7302 + sleep_on(&UDF_SB_RENAME_WAIT(old_dir->i_sb));
7303 + UDF_SB_RENAME_LOCK(old_dir->i_sb) = 1;
7304 + result = do_udf_rename(old_dir, old_dentry, new_dir, new_dentry);
7305 + UDF_SB_RENAME_LOCK(old_dir->i_sb) = 0;
7306 + wake_up(&UDF_SB_RENAME_WAIT(old_dir->i_sb));
7312 +/* Anybody can rename anything with this: the permission checks are left to the
7313 + * higher-level routines.
7315 +int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
7316 + struct inode * new_dir, struct dentry * new_dentry)
7318 + struct inode * old_inode, * new_inode;
7319 + struct udf_fileident_bh ofibh, nfibh;
7320 + struct FileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;
7321 + struct buffer_head *dir_bh = NULL;
7322 + int retval = -ENOENT;
7324 + old_inode = old_dentry->d_inode;
7325 + ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);
7326 + if (!ofi || udf_get_lb_pblock(old_dir->i_sb, lelb_to_cpu(ocfi.icb.extLocation), 0) !=
7332 + new_inode = new_dentry->d_inode;
7333 + nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
7338 + if (nfibh.sbh != nfibh.ebh)
7339 + udf_release_data(nfibh.ebh);
7340 + udf_release_data(nfibh.sbh);
7345 + DQUOT_INIT(new_inode);
7348 + if (S_ISDIR(old_inode->i_mode))
7350 + Uint32 offset = udf_ext0_offset(old_inode);
7354 + retval = -ENOTEMPTY;
7355 + if (!empty_dir(new_inode))
7359 + dir_bh = udf_bread(old_inode, 0, 0, &retval);
7362 + dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
7365 + if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
7371 + if (!new_inode && new_dir->i_nlink >= (256<<sizeof(new_dir->i_nlink))-1)
7376 + nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);
7380 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7381 + new_dir->i_version = ++event;
7383 + new_dir->i_version = ++global_event;
7389 + ncfi.fileVersionNum = ocfi.fileVersionNum;
7390 + ncfi.fileCharacteristics = ocfi.fileCharacteristics;
7391 + memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad));
7392 + udf_write_fi(&ncfi, nfi, &nfibh, NULL, NULL);
7394 + udf_delete_entry(ofi, &ofibh, &ocfi);
7396 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7397 + old_dir->i_version = ++event;
7399 + old_dir->i_version = ++global_event;
7403 + new_inode->i_nlink--;
7404 + new_inode->i_ctime = CURRENT_TIME;
7405 + UDF_I_UCTIME(new_inode) = CURRENT_UTIME;
7406 + mark_inode_dirty(new_inode);
7408 + old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
7409 + UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
7410 + mark_inode_dirty(old_dir);
7414 + dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
7415 + udf_update_tag((char *)dir_fi, sizeof(struct FileIdentDesc) +
7416 + cpu_to_le16(dir_fi->lengthOfImpUse));
7417 + if (UDF_I_ALLOCTYPE(old_inode) == ICB_FLAG_AD_IN_ICB)
7419 + mark_inode_dirty(old_inode);
7420 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7421 + old_inode->i_version = ++event;
7423 + old_inode->i_version = ++global_event;
7427 + mark_buffer_dirty(dir_bh, 1);
7428 + old_dir->i_nlink --;
7429 + mark_inode_dirty(old_dir);
7432 + new_inode->i_nlink --;
7433 + mark_inode_dirty(new_inode);
7437 + new_dir->i_nlink ++;
7438 + mark_inode_dirty(new_dir);
7445 + udf_release_data(dir_bh);
7448 + if (ofibh.sbh != ofibh.ebh)
7449 + udf_release_data(ofibh.ebh);
7450 + udf_release_data(ofibh.sbh);
7454 + if (nfibh.sbh != nfibh.ebh)
7455 + udf_release_data(nfibh.ebh);
7456 + udf_release_data(nfibh.sbh);
7461 diff -Nru linux/fs/udf/partition.c linux.new/fs/udf/partition.c
7462 --- linux/fs/udf/partition.c Thu Jan 1 01:00:00 1970
7463 +++ linux.new/fs/udf/partition.c Fri Sep 7 11:32:16 2001
7469 + * Partition handling routines for the OSTA-UDF(tm) filesystem.
7472 + * E-mail regarding any portion of the Linux UDF file system should be
7473 + * directed to the development team mailing list (run by majordomo):
7474 + * linux_udf@hootie.lvld.hp.com
7477 + * This file is distributed under the terms of the GNU General Public
7478 + * License (GPL). Copies of the GPL can be obtained from:
7479 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
7480 + * Each contributing author retains all rights to their own work.
7482 + * (C) 1998-2000 Ben Fennema
7486 + * 12/06/98 blf Created file.
7490 +#include "udfdecl.h"
7491 +#include "udf_sb.h"
7494 +#include <linux/fs.h>
7495 +#include <linux/string.h>
7496 +#include <linux/udf_fs.h>
7497 +#include <linux/malloc.h>
7499 +inline Uint32 udf_get_pblock(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7501 + if (partition >= UDF_SB_NUMPARTS(sb))
7503 + udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
7504 + block, partition, offset);
7505 + return 0xFFFFFFFF;
7507 + if (UDF_SB_PARTFUNC(sb, partition))
7508 + return UDF_SB_PARTFUNC(sb, partition)(sb, block, partition, offset);
7510 + return UDF_SB_PARTROOT(sb, partition) + block + offset;
7513 +Uint32 udf_get_pblock_virt15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7515 + struct buffer_head *bh = NULL;
7520 + index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(Uint32);
7522 + if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries)
7524 + udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
7525 + block, UDF_SB_TYPEVIRT(sb,partition).s_num_entries);
7526 + return 0xFFFFFFFF;
7529 + if (block >= index)
7532 + newblock = 1 + (block / (sb->s_blocksize / sizeof(Uint32)));
7533 + index = block % (sb->s_blocksize / sizeof(Uint32));
7538 + index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block;
7541 + loc = udf_bmap(UDF_SB_VAT(sb), newblock);
7543 + if (!(bh = bread(sb->s_dev, loc, sb->s_blocksize)))
7545 + udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
7546 + sb, block, partition, loc, index);
7547 + return 0xFFFFFFFF;
7550 + loc = le32_to_cpu(((Uint32 *)bh->b_data)[index]);
7552 + udf_release_data(bh);
7554 + if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
7556 + udf_debug("recursive call to udf_get_pblock!\n");
7557 + return 0xFFFFFFFF;
7560 + return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset);
7563 +inline Uint32 udf_get_pblock_virt20(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7565 + return udf_get_pblock_virt15(sb, block, partition, offset);
7568 +Uint32 udf_get_pblock_spar15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7570 + Uint32 packet = (block + offset) >> UDF_SB_TYPESPAR(sb,partition).s_spar_pshift;
7573 + if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 8)
7574 + index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap8[packet];
7575 + else if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 16)
7576 + index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap16[packet];
7577 + else if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 32)
7578 + index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap32[packet];
7580 + if (index == ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize)-1))
7581 + return UDF_SB_PARTROOT(sb,partition) + block + offset;
7583 + packet = UDF_SB_TYPESPAR(sb,partition).s_spar_map[index];
7584 + return packet + ((block + offset) & ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_pshift)-1));
7587 +void udf_fill_spartable(struct super_block *sb, struct udf_sparing_data *sdata, int partlen)
7592 + struct buffer_head *bh;
7593 + struct SparingTable *st;
7595 + for (i=0; i<4; i++)
7597 + if (!(spartable = sdata->s_spar_loc[i]))
7600 + bh = udf_read_tagged(sb, spartable, spartable, &ident);
7604 + sdata->s_spar_loc[i] = 0;
7610 + st = (struct SparingTable *)bh->b_data;
7611 + if (!strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)))
7614 + Uint16 rtl = le16_to_cpu(st->reallocationTableLen);
7617 + if (!sdata->s_spar_map)
7619 + int num = 1, mapsize;
7620 + sdata->s_spar_indexsize = 8;
7621 + while (rtl*sizeof(Uint32) >= (1 << sdata->s_spar_indexsize))
7624 + sdata->s_spar_indexsize <<= 1;
7626 + mapsize = (rtl * sizeof(Uint32)) +
7627 + ((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num);
7628 + sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL);
7629 + sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl];
7630 + memset(sdata->s_spar_map, 0xFF, mapsize);
7633 + index = sizeof(struct SparingTable);
7634 + for (i=0; i<rtl; i++)
7636 + if (index > sb->s_blocksize)
7638 + udf_release_data(bh);
7639 + bh = udf_tread(sb, ++spartable, sb->s_blocksize);
7642 + sdata->s_spar_loc[i] = 0;
7647 + se = (SparingEntry *)&(bh->b_data[index]);
7648 + index += sizeof(SparingEntry);
7650 + if (sdata->s_spar_map[i] == 0xFFFFFFFF)
7651 + sdata->s_spar_map[i] = le32_to_cpu(se->mappedLocation);
7652 + else if (sdata->s_spar_map[i] != le32_to_cpu(se->mappedLocation))
7654 + udf_debug("Found conflicting Sparing Data (%d vs %d for entry %d)\n",
7655 + sdata->s_spar_map[i], le32_to_cpu(se->mappedLocation), i);
7658 + if (le32_to_cpu(se->origLocation) < 0xFFFFFFF0)
7660 + int packet = le32_to_cpu(se->origLocation) >> sdata->s_spar_pshift;
7661 + if (sdata->s_spar_indexsize == 8)
7663 + if (sdata->s_spar_remap.s_spar_remap8[packet] == 0xFF)
7664 + sdata->s_spar_remap.s_spar_remap8[packet] = i;
7665 + else if (sdata->s_spar_remap.s_spar_remap8[packet] != i)
7667 + udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
7668 + sdata->s_spar_remap.s_spar_remap8[packet], i);
7671 + else if (sdata->s_spar_indexsize == 16)
7673 + if (sdata->s_spar_remap.s_spar_remap16[packet] == 0xFFFF)
7674 + sdata->s_spar_remap.s_spar_remap16[packet] = i;
7675 + else if (sdata->s_spar_remap.s_spar_remap16[packet] != i)
7677 + udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
7678 + sdata->s_spar_remap.s_spar_remap16[packet], i);
7681 + else if (sdata->s_spar_indexsize == 32)
7683 + if (sdata->s_spar_remap.s_spar_remap32[packet] == 0xFFFFFFFF)
7684 + sdata->s_spar_remap.s_spar_remap32[packet] = i;
7685 + else if (sdata->s_spar_remap.s_spar_remap32[packet] != i)
7687 + udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
7688 + sdata->s_spar_remap.s_spar_remap32[packet], i);
7695 + udf_release_data(bh);
7698 diff -Nru linux/fs/udf/super.c linux.new/fs/udf/super.c
7699 --- linux/fs/udf/super.c Thu Jan 1 01:00:00 1970
7700 +++ linux.new/fs/udf/super.c Fri Sep 7 11:32:16 2001
7706 + * Super block routines for the OSTA-UDF(tm) filesystem.
7709 + * OSTA-UDF(tm) = Optical Storage Technology Association
7710 + * Universal Disk Format.
7712 + * This code is based on version 2.00 of the UDF specification,
7713 + * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
7714 + * http://www.osta.org/
7715 + * http://www.ecma.ch/
7716 + * http://www.iso.org/
7719 + * E-mail regarding any portion of the Linux UDF file system should be
7720 + * directed to the development team mailing list (run by majordomo):
7721 + * linux_udf@hootie.lvld.hp.com
7724 + * This file is distributed under the terms of the GNU General Public
7725 + * License (GPL). Copies of the GPL can be obtained from:
7726 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
7727 + * Each contributing author retains all rights to their own work.
7729 + * (C) 1998 Dave Boynton
7730 + * (C) 1998-2000 Ben Fennema
7731 + * (C) 2000 Stelias Computing Inc
7735 + * 09/24/98 dgb changed to allow compiling outside of kernel, and
7736 + * added some debugging.
7737 + * 10/01/98 dgb updated to allow (some) possibility of compiling w/2.0.34
7738 + * 10/16/98 attempting some multi-session support
7739 + * 10/17/98 added freespace count for "df"
7740 + * 11/11/98 gr added novrs option
7741 + * 11/26/98 dgb added fileset,anchor mount options
7742 + * 12/06/98 blf really hosed things royally. vat/sparing support. sequenced vol descs
7743 + * rewrote option handling based on isofs
7744 + * 12/20/98 find the free space bitmap (if it exists)
7747 +#include "udfdecl.h"
7749 +#include <linux/config.h>
7750 +#include <linux/version.h>
7751 +#include <linux/blkdev.h>
7752 +#include <linux/malloc.h>
7753 +#include <linux/kernel.h>
7754 +#include <linux/locks.h>
7755 +#include <linux/module.h>
7756 +#include <linux/stat.h>
7757 +#include <linux/cdrom.h>
7758 +#include <linux/nls.h>
7759 +#include <asm/byteorder.h>
7761 +#include <linux/udf_fs.h>
7762 +#include "udf_sb.h"
7765 +#include <linux/init.h>
7766 +#include <asm/uaccess.h>
7768 +#define VDS_POS_PRIMARY_VOL_DESC 0
7769 +#define VDS_POS_UNALLOC_SPACE_DESC 1
7770 +#define VDS_POS_LOGICAL_VOL_DESC 2
7771 +#define VDS_POS_PARTITION_DESC 3
7772 +#define VDS_POS_IMP_USE_VOL_DESC 4
7773 +#define VDS_POS_VOL_DESC_PTR 5
7774 +#define VDS_POS_TERMINATING_DESC 6
7775 +#define VDS_POS_LENGTH 7
7777 +static char error_buf[1024];
7779 +/* These are the "meat" - everything else is stuffing */
7780 +static struct super_block *udf_read_super(struct super_block *, void *, int);
7781 +static void udf_put_super(struct super_block *);
7782 +static void udf_write_super(struct super_block *);
7783 +static int udf_remount_fs(struct super_block *, int *, char *);
7784 +static int udf_check_valid(struct super_block *, int, int);
7785 +static int udf_vrs(struct super_block *sb, int silent);
7786 +static int udf_load_partition(struct super_block *, lb_addr *);
7787 +static int udf_load_logicalvol(struct super_block *, struct buffer_head *, lb_addr *);
7788 +static void udf_load_logicalvolint(struct super_block *, extent_ad);
7789 +static int udf_find_anchor(struct super_block *, int, int);
7790 +static int udf_find_fileset(struct super_block *, lb_addr *, lb_addr *);
7791 +static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
7792 +static void udf_load_fileset(struct super_block *, struct buffer_head *, lb_addr *);
7793 +static void udf_load_partdesc(struct super_block *, struct buffer_head *);
7794 +static void udf_open_lvid(struct super_block *);
7795 +static void udf_close_lvid(struct super_block *);
7796 +static unsigned int udf_count_free(struct super_block *);
7797 +static int udf_statfs(struct super_block *, struct statfs *, int);
7799 +/* UDF filesystem type */
7800 +static struct file_system_type udf_fstype = {
7802 + FS_REQUIRES_DEV, /* fs_flags */
7803 + udf_read_super, /* read_super */
7807 +/* Superblock operations */
7808 +static struct super_operations udf_sb_ops =
7810 + udf_read_inode, /* read_inode */
7811 + udf_write_inode, /* write_inode */
7812 + udf_put_inode, /* put_inode */
7813 + udf_delete_inode, /* delete_inode */
7814 + NULL, /* notify_change */
7815 + udf_put_super, /* put_super */
7816 + udf_write_super, /* write_super */
7817 + udf_statfs, /* statfs */
7818 + udf_remount_fs, /* remount_fs */
7819 + NULL, /* clear_inode */
7820 + NULL, /* umount_begin */
7825 + unsigned char novrs;
7826 + unsigned int blocksize;
7827 + unsigned int session;
7828 + unsigned int lastblock;
7829 + unsigned int anchor;
7830 + unsigned int volume;
7831 + unsigned short partition;
7832 + unsigned int fileset;
7833 + unsigned int rootdir;
7834 + unsigned int flags;
7840 +#if defined(MODULE)
7846 + * Unregister the UDF filesystem type.
7849 + * Clean-up before the module is unloaded.
7850 + * This routine only applies when compiled as a module.
7853 + * July 1, 1997 - Andrew E. Mileski
7854 + * Written, tested, and released.
7857 +cleanup_module(void)
7859 + printk(KERN_NOTICE "udf: unregistering filesystem\n");
7860 + return unregister_filesystem(&udf_fstype);
7864 + * init_module / init_udf_fs
7867 + * Register the UDF filesystem type.
7870 + * July 1, 1997 - Andrew E. Mileski
7871 + * Written, tested, and released.
7873 +int init_module(void)
7874 +#else /* if !defined(MODULE) */
7875 +__initfunc(int init_udf_fs(void))
7878 + printk(KERN_NOTICE "udf: registering filesystem\n");
7880 + struct super_block sb;
7883 + size = sizeof(struct super_block) +
7884 + (long)&sb.u - (long)&sb;
7885 + if ( size < sizeof(struct udf_sb_info) )
7887 + printk(KERN_ERR "udf: Danger! Kernel was compiled without enough room for udf_sb_info\n");
7888 + printk(KERN_ERR "udf: Kernel has room for %u bytes, udf needs %lu\n",
7889 + size, (unsigned long)sizeof(struct udf_sb_info));
7893 + return register_filesystem(&udf_fstype);
7897 + * udf_parse_options
7900 + * Parse mount options.
7903 + * The following mount options are supported:
7905 + * gid= Set the default group.
7906 + * umask= Set the default umask.
7907 + * uid= Set the default user.
7908 + * bs= Set the block size.
7909 + * unhide Show otherwise hidden files.
7910 + * undelete Show deleted files in lists.
7911 + * adinicb Embed data in the inode (default)
7912 + * noadinicb Don't embed data in the inode
7913 + * shortad Use short ad's
7914 + * longad Use long ad's (default)
7915 + * strict Set strict conformance (unused)
7917 + * The remaining are for debugging and disaster recovery:
7919 + * novrs Skip volume sequence recognition
7921 + * The following expect a offset from 0.
7923 + * session= Set the CDROM session (default= last session)
7924 + * anchor= Override standard anchor location. (default= 256)
7925 + * volume= Override the VolumeDesc location. (unused)
7926 + * partition= Override the PartitionDesc location. (unused)
7927 + * lastblock= Set the last block of the filesystem/
7929 + * The following expect a offset from the partition root.
7931 + * fileset= Override the fileset block location. (unused)
7932 + * rootdir= Override the root directory location. (unused)
7933 + * WARNING: overriding the rootdir to a non-directory may
7934 + * yield highly unpredictable results.
7937 + * options Pointer to mount options string.
7938 + * uopts Pointer to mount options variable.
7941 + * <return> 0 Mount options parsed okay.
7942 + * <return> -1 Error parsing mount options.
7945 + * July 1, 1997 - Andrew E. Mileski
7946 + * Written, tested, and released.
7950 +udf_parse_options(char *options, struct udf_options *uopt)
7955 + uopt->blocksize = 512;
7956 + uopt->partition = 0xFFFF;
7957 + uopt->session = 0xFFFFFFFF;
7958 + uopt->lastblock = 0xFFFFFFFF;
7959 + uopt->anchor = 0xFFFFFFFF;
7960 + uopt->volume = 0xFFFFFFFF;
7961 + uopt->rootdir = 0xFFFFFFFF;
7962 + uopt->fileset = 0xFFFFFFFF;
7967 + for (opt = strtok(options, ","); opt; opt = strtok(NULL, ","))
7969 + /* Make "opt=val" into two strings */
7970 + val = strchr(opt, '=');
7973 + if (!strcmp(opt, "novrs") && !val)
7975 + else if (!strcmp(opt, "bs") && val)
7976 + uopt->blocksize = simple_strtoul(val, NULL, 0);
7977 + else if (!strcmp(opt, "unhide") && !val)
7978 + uopt->flags |= (1 << UDF_FLAG_UNHIDE);
7979 + else if (!strcmp(opt, "undelete") && !val)
7980 + uopt->flags |= (1 << UDF_FLAG_UNDELETE);
7981 + else if (!strcmp(opt, "noadinicb") && !val)
7982 + uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
7983 + else if (!strcmp(opt, "adinicb") && !val)
7984 + uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
7985 + else if (!strcmp(opt, "shortad") && !val)
7986 + uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
7987 + else if (!strcmp(opt, "longad") && !val)
7988 + uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
7989 + else if (!strcmp(opt, "gid") && val)
7990 + uopt->gid = simple_strtoul(val, NULL, 0);
7991 + else if (!strcmp(opt, "umask") && val)
7992 + uopt->umask = simple_strtoul(val, NULL, 0);
7993 + else if (!strcmp(opt, "strict") && !val)
7994 + uopt->flags |= (1 << UDF_FLAG_STRICT);
7995 + else if (!strcmp(opt, "uid") && val)
7996 + uopt->uid = simple_strtoul(val, NULL, 0);
7997 + else if (!strcmp(opt, "session") && val)
7998 + uopt->session = simple_strtoul(val, NULL, 0);
7999 + else if (!strcmp(opt, "lastblock") && val)
8000 + uopt->lastblock = simple_strtoul(val, NULL, 0);
8001 + else if (!strcmp(opt, "anchor") && val)
8002 + uopt->anchor = simple_strtoul(val, NULL, 0);
8003 + else if (!strcmp(opt, "volume") && val)
8004 + uopt->volume = simple_strtoul(val, NULL, 0);
8005 + else if (!strcmp(opt, "partition") && val)
8006 + uopt->partition = simple_strtoul(val, NULL, 0);
8007 + else if (!strcmp(opt, "fileset") && val)
8008 + uopt->fileset = simple_strtoul(val, NULL, 0);
8009 + else if (!strcmp(opt, "rootdir") && val)
8010 + uopt->rootdir = simple_strtoul(val, NULL, 0);
8013 + printk(KERN_ERR "udf: bad mount option \"%s=%s\"\n",
8019 + printk(KERN_ERR "udf: bad mount option \"%s\"\n",
8028 +udf_write_super(struct super_block *sb)
8030 + if (!(sb->s_flags & MS_RDONLY))
8031 + udf_open_lvid(sb);
8036 +udf_remount_fs(struct super_block *sb, int *flags, char *options)
8038 + struct udf_options uopt;
8040 + uopt.flags = UDF_SB(sb)->s_flags ;
8041 + uopt.uid = UDF_SB(sb)->s_uid ;
8042 + uopt.gid = UDF_SB(sb)->s_gid ;
8043 + uopt.umask = UDF_SB(sb)->s_umask ;
8045 + if ( !udf_parse_options(options, &uopt) )
8048 + UDF_SB(sb)->s_flags = uopt.flags;
8049 + UDF_SB(sb)->s_uid = uopt.uid;
8050 + UDF_SB(sb)->s_gid = uopt.gid;
8051 + UDF_SB(sb)->s_umask = uopt.umask;
8053 +#if CONFIG_UDF_RW != 1
8054 + *flags |= MS_RDONLY;
8057 + if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
8059 + if (*flags & MS_RDONLY)
8060 + udf_close_lvid(sb);
8062 + udf_open_lvid(sb);
8068 + * udf_set_blocksize
8071 + * Set the block size to be used in all transfers.
8074 + * To allow room for a DMA transfer, it is best to guess big when unsure.
8075 + * This routine picks 2048 bytes as the blocksize when guessing. This
8076 + * should be adequate until devices with larger block sizes become common.
8078 + * Note that the Linux kernel can currently only deal with blocksizes of
8079 + * 512, 1024, 2048, 4096, and 8192 bytes.
8082 + * sb Pointer to _locked_ superblock.
8085 + * sb->s_blocksize Blocksize.
8086 + * sb->s_blocksize_bits log2 of blocksize.
8087 + * <return> 0 Blocksize is valid.
8088 + * <return> 1 Blocksize is invalid.
8091 + * July 1, 1997 - Andrew E. Mileski
8092 + * Written, tested, and released.
8095 +udf_set_blocksize(struct super_block *sb, int bsize)
8097 + /* Use specified block size if specified */
8098 + if (!(sb->s_blocksize = get_hardblocksize(sb->s_dev)))
8099 + sb->s_blocksize = 2048;
8100 + if (bsize > sb->s_blocksize)
8101 + sb->s_blocksize = bsize;
8103 + /* Block size must be an even multiple of 512 */
8104 + switch (sb->s_blocksize) {
8105 + case 512: sb->s_blocksize_bits = 9; break;
8106 + case 1024: sb->s_blocksize_bits = 10; break;
8107 + case 2048: sb->s_blocksize_bits = 11; break;
8108 + case 4096: sb->s_blocksize_bits = 12; break;
8109 + case 8192: sb->s_blocksize_bits = 13; break;
8112 + udf_debug("Bad block size (%ld)\n", sb->s_blocksize);
8113 + printk(KERN_ERR "udf: bad block size (%ld)\n", sb->s_blocksize);
8118 + /* Set the block size */
8119 + set_blocksize(sb->s_dev, sb->s_blocksize);
8120 + return sb->s_blocksize;
8124 +udf_vrs(struct super_block *sb, int silent)
8126 + struct VolStructDesc *vsd = NULL;
8127 + int sector = 32768;
8128 + struct buffer_head *bh = NULL;
8133 + /* Block size must be a multiple of 512 */
8134 + if (sb->s_blocksize & 511)
8137 + sector += (UDF_SB_SESSION(sb) << sb->s_blocksize_bits);
8139 + udf_debug("Starting at sector %u (%ld byte sectors)\n",
8140 + (sector >> sb->s_blocksize_bits), sb->s_blocksize);
8141 + /* Process the sequence (if applicable) */
8142 + for (;!nsr02 && !nsr03; sector += 2048)
8144 + /* Read a block */
8145 + bh = udf_tread(sb, sector >> sb->s_blocksize_bits, sb->s_blocksize);
8149 + /* Look for ISO descriptors */
8150 + vsd = (struct VolStructDesc *)(bh->b_data +
8151 + (sector & (sb->s_blocksize - 1)));
8153 + if (vsd->stdIdent[0] == 0)
8155 + udf_release_data(bh);
8158 + else if (!strncmp(vsd->stdIdent, STD_ID_CD001, STD_ID_LEN))
8161 + switch (vsd->structType)
8164 + udf_debug("ISO9660 Boot Record found\n");
8167 + udf_debug("ISO9660 Primary Volume Descriptor found\n");
8170 + udf_debug("ISO9660 Supplementary Volume Descriptor found\n");
8173 + udf_debug("ISO9660 Volume Partition Descriptor found\n");
8176 + udf_debug("ISO9660 Volume Descriptor Set Terminator found\n");
8179 + udf_debug("ISO9660 VRS (%u) found\n", vsd->structType);
8183 + else if (!strncmp(vsd->stdIdent, STD_ID_BEA01, STD_ID_LEN))
8186 + else if (!strncmp(vsd->stdIdent, STD_ID_TEA01, STD_ID_LEN))
8188 + udf_release_data(bh);
8191 + else if (!strncmp(vsd->stdIdent, STD_ID_NSR02, STD_ID_LEN))
8195 + else if (!strncmp(vsd->stdIdent, STD_ID_NSR03, STD_ID_LEN))
8199 + udf_release_data(bh);
8206 + else if (sector - (UDF_SB_SESSION(sb) << sb->s_blocksize_bits) == 32768)
8216 + * Find an anchor volume descriptor.
8219 + * sb Pointer to _locked_ superblock.
8220 + * lastblock Last block on media.
8223 + * <return> 1 if not found, 0 if ok
8226 + * July 1, 1997 - Andrew E. Mileski
8227 + * Written, tested, and released.
8230 +udf_find_anchor(struct super_block *sb, int useranchor, int lastblock)
8232 + int varlastblock = udf_variable_to_fixed(lastblock);
8233 + int last[] = { lastblock, lastblock - 2,
8234 + lastblock - 150, lastblock - 152,
8235 + varlastblock, varlastblock - 2,
8236 + varlastblock - 150, varlastblock - 152 };
8237 + struct buffer_head *bh = NULL;
8242 + UDF_SB_ANCHOR(sb)[0] = 0;
8243 + UDF_SB_ANCHOR(sb)[1] = 0;
8244 + UDF_SB_ANCHOR(sb)[2] = 0;
8245 + UDF_SB_ANCHOR(sb)[3] = 256 + UDF_SB_SESSION(sb);
8249 + /* Search for an anchor volume descriptor pointer */
8251 + /* according to spec, anchor is in either:
8255 + * however, if the disc isn't closed, it could be 512 */
8257 + for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++)
8259 + if (!(bh = bread(sb->s_dev, last[i], sb->s_blocksize)))
8261 + ident = location = 0;
8265 + ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
8266 + location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
8267 + udf_release_data(bh);
8270 + if (ident == TID_ANCHOR_VOL_DESC_PTR)
8272 + if (location == last[i] - UDF_SB_SESSION(sb))
8274 + lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
8275 + UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
8277 + else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
8279 + UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
8280 + lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
8281 + UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
8284 + udf_debug("Anchor found at block %d, location mismatch %d.\n",
8285 + last[i], location);
8287 + else if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY)
8289 + lastblock = last[i];
8290 + UDF_SB_ANCHOR(sb)[2] = 512 + UDF_SB_SESSION(sb);
8294 + if (!(bh = bread(sb->s_dev, last[i] - 256, sb->s_blocksize)))
8296 + ident = location = 0;
8300 + ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
8301 + location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
8302 + udf_release_data(bh);
8305 + if (ident == TID_ANCHOR_VOL_DESC_PTR &&
8306 + location == last[i] - 256 - UDF_SB_SESSION(sb))
8308 + lastblock = last[i];
8309 + UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
8313 + if (!(bh = bread(sb->s_dev, last[i] - 312 - UDF_SB_SESSION(sb),
8314 + sb->s_blocksize)))
8316 + ident = location = 0;
8320 + ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
8321 + location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
8322 + udf_release_data(bh);
8325 + if (ident == TID_ANCHOR_VOL_DESC_PTR &&
8326 + location == udf_variable_to_fixed(last[i]) - 256)
8328 + UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
8329 + lastblock = udf_variable_to_fixed(last[i]);
8330 + UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
8338 + /* We havn't found the lastblock. check 312 */
8339 + if ((bh = bread(sb->s_dev, 312 + UDF_SB_SESSION(sb), sb->s_blocksize)))
8341 + ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
8342 + location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
8343 + udf_release_data(bh);
8345 + if (ident == TID_ANCHOR_VOL_DESC_PTR && location == 256)
8346 + UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
8350 + for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
8352 + if (UDF_SB_ANCHOR(sb)[i])
8354 + if (!(bh = udf_read_tagged(sb,
8355 + UDF_SB_ANCHOR(sb)[i], UDF_SB_ANCHOR(sb)[i], &ident)))
8357 + UDF_SB_ANCHOR(sb)[i] = 0;
8361 + udf_release_data(bh);
8362 + if ((ident != TID_ANCHOR_VOL_DESC_PTR) && (i ||
8363 + (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY)))
8365 + UDF_SB_ANCHOR(sb)[i] = 0;
8369 + else if (useranchor != 0xFFFFFFFF)
8371 + UDF_SB_ANCHOR(sb)[i] = useranchor;
8372 + useranchor = 0xFFFFFFFF;
8381 +udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
8383 + struct buffer_head *bh = NULL;
8387 + if (fileset->logicalBlockNum != 0xFFFFFFFF ||
8388 + fileset->partitionReferenceNum != 0xFFFF)
8390 + bh = udf_read_ptagged(sb, *fileset, 0, &ident);
8394 + else if (ident != TID_FILE_SET_DESC)
8396 + udf_release_data(bh);
8402 + if (!bh) /* Search backwards through the partitions */
8404 + lb_addr newfileset;
8408 + for (newfileset.partitionReferenceNum=UDF_SB_NUMPARTS(sb)-1;
8409 + (newfileset.partitionReferenceNum != 0xFFFF &&
8410 + fileset->logicalBlockNum == 0xFFFFFFFF &&
8411 + fileset->partitionReferenceNum == 0xFFFF);
8412 + newfileset.partitionReferenceNum--)
8414 + lastblock = UDF_SB_PARTLEN(sb, newfileset.partitionReferenceNum);
8415 + newfileset.logicalBlockNum = 0;
8419 + bh = udf_read_ptagged(sb, newfileset, 0, &ident);
8422 + newfileset.logicalBlockNum ++;
8428 + case TID_SPACE_BITMAP_DESC:
8430 + struct SpaceBitmapDesc *sp;
8431 + sp = (struct SpaceBitmapDesc *)bh->b_data;
8432 + newfileset.logicalBlockNum += 1 +
8433 + ((le32_to_cpu(sp->numOfBytes) + sizeof(struct SpaceBitmapDesc) - 1)
8434 + >> sb->s_blocksize_bits);
8435 + udf_release_data(bh);
8438 + case TID_FILE_SET_DESC:
8440 + *fileset = newfileset;
8445 + newfileset.logicalBlockNum ++;
8446 + udf_release_data(bh);
8452 + while (newfileset.logicalBlockNum < lastblock &&
8453 + fileset->logicalBlockNum == 0xFFFFFFFF &&
8454 + fileset->partitionReferenceNum == 0xFFFF);
8458 + if ((fileset->logicalBlockNum != 0xFFFFFFFF ||
8459 + fileset->partitionReferenceNum != 0xFFFF) && bh)
8461 + udf_debug("Fileset at block=%d, partition=%d\n",
8462 + fileset->logicalBlockNum, fileset->partitionReferenceNum);
8464 + UDF_SB_PARTITION(sb) = fileset->partitionReferenceNum;
8465 + udf_load_fileset(sb, bh, root);
8466 + udf_release_data(bh);
8473 +udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
8475 + struct PrimaryVolDesc *pvoldesc;
8477 + long recording_usec;
8478 + struct ustr instr;
8479 + struct ustr outstr;
8481 + pvoldesc = (struct PrimaryVolDesc *)bh->b_data;
8483 + if ( udf_stamp_to_time(&recording, &recording_usec,
8484 + lets_to_cpu(pvoldesc->recordingDateAndTime)) )
8487 + ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
8488 + udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
8489 + recording, recording_usec,
8490 + ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone);
8491 + UDF_SB_RECORDTIME(sb) = recording;
8494 + if ( !udf_build_ustr(&instr, pvoldesc->volIdent, 32) )
8496 + if (udf_CS0toUTF8(&outstr, &instr))
8498 + strncpy( UDF_SB_VOLIDENT(sb), outstr.u_name,
8499 + outstr.u_len > 31 ? 31 : outstr.u_len);
8500 + udf_debug("volIdent[] = '%s'\n", UDF_SB_VOLIDENT(sb));
8504 + if ( !udf_build_ustr(&instr, pvoldesc->volSetIdent, 128) )
8506 + if (udf_CS0toUTF8(&outstr, &instr))
8507 + udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
8512 +udf_load_fileset(struct super_block *sb, struct buffer_head *bh, lb_addr *root)
8514 + struct FileSetDesc *fset;
8516 + fset = (struct FileSetDesc *)bh->b_data;
8518 + *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation);
8520 + UDF_SB_SERIALNUM(sb) = le16_to_cpu(fset->descTag.tagSerialNum);
8522 + udf_debug("Rootdir at block=%d, partition=%d\n",
8523 + root->logicalBlockNum, root->partitionReferenceNum);
8527 +udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
8529 + struct PartitionDesc *p;
8532 + p=(struct PartitionDesc *)bh->b_data;
8534 + for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
8536 + udf_debug("Searching map: (%d == %d)\n",
8537 + UDF_SB_PARTMAPS(sb)[i].s_partition_num, le16_to_cpu(p->partitionNumber));
8538 + if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
8540 + UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
8541 + UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb);
8543 + if (UDF_SB_PARTTYPE(sb,i) == UDF_SPARABLE_MAP15)
8544 + udf_fill_spartable(sb, &UDF_SB_TYPESPAR(sb,i), UDF_SB_PARTLEN(sb,i));
8546 + if (!strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR02) ||
8547 + !strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR03))
8549 + struct PartitionHeaderDesc *phd;
8551 + phd = (struct PartitionHeaderDesc *)(p->partitionContentsUse);
8552 + if (phd->unallocatedSpaceTable.extLength)
8554 + lb_addr loc = { i, phd->unallocatedSpaceTable.extPosition };
8556 + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table =
8557 + udf_iget(sb, loc);
8558 + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE;
8559 + udf_debug("unallocatedSpaceTable (part %d) @ %ld\n",
8560 + i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino);
8562 + if (phd->unallocatedSpaceBitmap.extLength)
8564 + UDF_SB_ALLOC_BITMAP(sb, i, s_uspace);
8565 + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extLength =
8566 + le32_to_cpu(phd->unallocatedSpaceBitmap.extLength);
8567 + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition =
8568 + le32_to_cpu(phd->unallocatedSpaceBitmap.extPosition);
8569 + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_BITMAP;
8570 + udf_debug("unallocatedSpaceBitmap (part %d) @ %d\n",
8571 + i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition);
8573 + if (phd->partitionIntegrityTable.extLength)
8574 + udf_debug("partitionIntegrityTable (part %d)\n", i);
8575 + if (phd->freedSpaceTable.extLength)
8577 + lb_addr loc = { i, phd->freedSpaceTable.extPosition };
8579 + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table =
8580 + udf_iget(sb, loc);
8581 + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE;
8582 + udf_debug("freedSpaceTable (part %d) @ %ld\n",
8583 + i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table->i_ino);
8585 + if (phd->freedSpaceBitmap.extLength)
8587 + UDF_SB_ALLOC_BITMAP(sb, i, s_fspace);
8588 + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extLength =
8589 + le32_to_cpu(phd->freedSpaceBitmap.extLength);
8590 + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition =
8591 + le32_to_cpu(phd->freedSpaceBitmap.extPosition);
8592 + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_BITMAP;
8593 + udf_debug("freedSpaceBitmap (part %d) @ %d\n",
8594 + i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition);
8600 + if (i == UDF_SB_NUMPARTS(sb))
8602 + udf_debug("Partition (%d) not found in partition map\n", le16_to_cpu(p->partitionNumber));
8606 + udf_debug("Partition (%d:%d type %x) starts at physical %d, block length %d\n",
8607 + le16_to_cpu(p->partitionNumber), i, UDF_SB_PARTTYPE(sb,i),
8608 + UDF_SB_PARTROOT(sb,i), UDF_SB_PARTLEN(sb,i));
8613 +udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fileset)
8615 + struct LogicalVolDesc *lvd;
8619 + lvd = (struct LogicalVolDesc *)bh->b_data;
8621 + UDF_SB_NUMPARTS(sb) = le32_to_cpu(lvd->numPartitionMaps);
8622 + UDF_SB_ALLOC_PARTMAPS(sb, UDF_SB_NUMPARTS(sb));
8624 + for (i=0,offset=0;
8625 + i<UDF_SB_NUMPARTS(sb) && offset<le32_to_cpu(lvd->mapTableLength);
8626 + i++,offset+=((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapLength)
8628 + type = ((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapType;
8631 + struct GenericPartitionMap1 *gpm1 = (struct GenericPartitionMap1 *)&(lvd->partitionMaps[offset]);
8632 + UDF_SB_PARTTYPE(sb,i) = UDF_TYPE1_MAP15;
8633 + UDF_SB_PARTVSN(sb,i) = le16_to_cpu(gpm1->volSeqNum);
8634 + UDF_SB_PARTNUM(sb,i) = le16_to_cpu(gpm1->partitionNum);
8635 + UDF_SB_PARTFUNC(sb,i) = NULL;
8637 + else if (type == 2)
8639 + struct UdfPartitionMap2 *upm2 = (struct UdfPartitionMap2 *)&(lvd->partitionMaps[offset]);
8640 + if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
8642 + if (le16_to_cpu(((Uint16 *)upm2->partIdent.identSuffix)[0]) == 0x0150)
8644 + UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP15;
8645 + UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt15;
8647 + else if (le16_to_cpu(((Uint16 *)upm2->partIdent.identSuffix)[0]) == 0x0200)
8649 + UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP20;
8650 + UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt20;
8653 + else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE)))
8657 + struct SparablePartitionMap *spm = (struct SparablePartitionMap *)&(lvd->partitionMaps[offset]);
8658 + UDF_SB_PARTTYPE(sb,i) = UDF_SPARABLE_MAP15;
8659 + plen = le16_to_cpu(spm->packetLength);
8660 + UDF_SB_TYPESPAR(sb,i).s_spar_pshift = 0;
8661 + while (plen >>= 1)
8662 + UDF_SB_TYPESPAR(sb,i).s_spar_pshift ++;
8663 + for (j=0; j<spm->numSparingTables; j++)
8664 + UDF_SB_TYPESPAR(sb,i).s_spar_loc[j] = le32_to_cpu(spm->locSparingTable[j]);
8665 + UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_spar15;
8669 + udf_debug("Unknown ident: %s\n", upm2->partIdent.ident);
8672 + UDF_SB_PARTVSN(sb,i) = le16_to_cpu(upm2->volSeqNum);
8673 + UDF_SB_PARTNUM(sb,i) = le16_to_cpu(upm2->partitionNum);
8675 + udf_debug("Partition (%d:%d) type %d on volume %d\n",
8676 + i, UDF_SB_PARTNUM(sb,i), type, UDF_SB_PARTVSN(sb,i));
8681 + long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
8683 + *fileset = lelb_to_cpu(la->extLocation);
8684 + udf_debug("FileSet found in LogicalVolDesc at block=%d, partition=%d\n",
8685 + fileset->logicalBlockNum,
8686 + fileset->partitionReferenceNum);
8688 + if (lvd->integritySeqExt.extLength)
8689 + udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
8694 + * udf_load_logicalvolint
8698 +udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
8700 + struct buffer_head *bh = NULL;
8703 + while ((bh = udf_read_tagged(sb, loc.extLocation, loc.extLocation, &ident)) &&
8704 + ident == TID_LOGICAL_VOL_INTEGRITY_DESC && loc.extLength > 0)
8706 + UDF_SB_LVIDBH(sb) = bh;
8708 + if (UDF_SB_LVID(sb)->nextIntegrityExt.extLength)
8709 + udf_load_logicalvolint(sb, leea_to_cpu(UDF_SB_LVID(sb)->nextIntegrityExt));
8711 + if (UDF_SB_LVIDBH(sb) != bh)
8712 + udf_release_data(bh);
8713 + loc.extLength -= sb->s_blocksize;
8714 + loc.extLocation ++;
8716 + if (UDF_SB_LVIDBH(sb) != bh)
8717 + udf_release_data(bh);
8721 + * udf_process_sequence
8724 + * Process a main/reserve volume descriptor sequence.
8727 + * sb Pointer to _locked_ superblock.
8728 + * block First block of first extent of the sequence.
8729 + * lastblock Lastblock of first extent of the sequence.
8732 + * July 1, 1997 - Andrew E. Mileski
8733 + * Written, tested, and released.
8736 +udf_process_sequence(struct super_block *sb, long block, long lastblock, lb_addr *fileset)
8738 + struct buffer_head *bh = NULL;
8739 + struct udf_vds_record vds[VDS_POS_LENGTH];
8740 + struct GenericDesc *gd;
8746 + memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
8748 + /* Read the main descriptor sequence */
8749 + for (;(!done && block <= lastblock); block++)
8752 + bh = udf_read_tagged(sb, block, block, &ident);
8756 + /* Process each descriptor (ISO 13346 3/8.3-8.4) */
8757 + gd = (struct GenericDesc *)bh->b_data;
8758 + vdsn = le32_to_cpu(gd->volDescSeqNum);
8761 + case TID_PRIMARY_VOL_DESC: /* ISO 13346 3/10.1 */
8762 + if (vdsn >= vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum)
8764 + vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum = vdsn;
8765 + vds[VDS_POS_PRIMARY_VOL_DESC].block = block;
8768 + case TID_VOL_DESC_PTR: /* ISO 13346 3/10.3 */
8769 + if (vdsn >= vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum)
8771 + vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn;
8772 + vds[VDS_POS_VOL_DESC_PTR].block = block;
8775 + case TID_IMP_USE_VOL_DESC: /* ISO 13346 3/10.4 */
8776 + if (vdsn >= vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum)
8778 + vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum = vdsn;
8779 + vds[VDS_POS_IMP_USE_VOL_DESC].block = block;
8782 + case TID_PARTITION_DESC: /* ISO 13346 3/10.5 */
8783 + if (!vds[VDS_POS_PARTITION_DESC].block)
8784 + vds[VDS_POS_PARTITION_DESC].block = block;
8786 + case TID_LOGICAL_VOL_DESC: /* ISO 13346 3/10.6 */
8787 + if (vdsn >= vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum)
8789 + vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum = vdsn;
8790 + vds[VDS_POS_LOGICAL_VOL_DESC].block = block;
8793 + case TID_UNALLOC_SPACE_DESC: /* ISO 13346 3/10.8 */
8794 + if (vdsn >= vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum)
8796 + vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum = vdsn;
8797 + vds[VDS_POS_UNALLOC_SPACE_DESC].block = block;
8800 + case TID_TERMINATING_DESC: /* ISO 13346 3/10.9 */
8801 + vds[VDS_POS_TERMINATING_DESC].block = block;
8805 + udf_release_data(bh);
8807 + for (i=0; i<VDS_POS_LENGTH; i++)
8811 + bh = udf_read_tagged(sb, vds[i].block, vds[i].block, &ident);
8813 + if (i == VDS_POS_PRIMARY_VOL_DESC)
8814 + udf_load_pvoldesc(sb, bh);
8815 + else if (i == VDS_POS_LOGICAL_VOL_DESC)
8816 + udf_load_logicalvol(sb, bh, fileset);
8817 + else if (i == VDS_POS_PARTITION_DESC)
8819 + struct buffer_head *bh2 = NULL;
8820 + udf_load_partdesc(sb, bh);
8821 + for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++)
8823 + bh2 = udf_read_tagged(sb, j, j, &ident);
8824 + gd = (struct GenericDesc *)bh2->b_data;
8825 + if (ident == TID_PARTITION_DESC)
8826 + udf_load_partdesc(sb, bh2);
8827 + udf_release_data(bh2);
8830 + udf_release_data(bh);
8838 + * udf_check_valid()
8841 +udf_check_valid(struct super_block *sb, int novrs, int silent)
8847 + udf_debug("Validity check skipped because of novrs option\n");
8850 + /* Check that it is NSR02 compliant */
8851 + /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
8852 + else if ((block = udf_vrs(sb, silent)) == -1)
8854 + udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n");
8862 +udf_load_partition(struct super_block *sb, lb_addr *fileset)
8864 + struct AnchorVolDescPtr *anchor;
8866 + struct buffer_head *bh;
8867 + long main_s, main_e, reserve_s, reserve_e;
8873 + for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
8875 + if (UDF_SB_ANCHOR(sb)[i] && (bh = udf_read_tagged(sb,
8876 + UDF_SB_ANCHOR(sb)[i], UDF_SB_ANCHOR(sb)[i] - UDF_SB_SESSION(sb), &ident)))
8878 + anchor = (struct AnchorVolDescPtr *)bh->b_data;
8880 + /* Locate the main sequence */
8881 + main_s = le32_to_cpu( anchor->mainVolDescSeqExt.extLocation );
8882 + main_e = le32_to_cpu( anchor->mainVolDescSeqExt.extLength );
8883 + main_e = main_e >> sb->s_blocksize_bits;
8886 + /* Locate the reserve sequence */
8887 + reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation);
8888 + reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength);
8889 + reserve_e = reserve_e >> sb->s_blocksize_bits;
8890 + reserve_e += reserve_s;
8892 + udf_release_data(bh);
8894 + /* Process the main & reserve sequences */
8895 + /* responsible for finding the PartitionDesc(s) */
8896 + if (!(udf_process_sequence(sb, main_s, main_e, fileset) &&
8897 + udf_process_sequence(sb, reserve_s, reserve_e, fileset)))
8904 + if (i == sizeof(UDF_SB_ANCHOR(sb))/sizeof(int))
8906 + udf_debug("No Anchor block found\n");
8910 + udf_debug("Using anchor in block %d\n", UDF_SB_ANCHOR(sb)[i]);
8912 + for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
8914 + switch UDF_SB_PARTTYPE(sb, i)
8916 + case UDF_VIRTUAL_MAP15:
8917 + case UDF_VIRTUAL_MAP20:
8921 + if (!UDF_SB_LASTBLOCK(sb))
8923 + udf_debug("Unable to determine Lastblock (For Virtual Partition)\n");
8927 + for (j=0; j<UDF_SB_NUMPARTS(sb); j++)
8930 + UDF_SB_PARTVSN(sb,i) == UDF_SB_PARTVSN(sb,j) &&
8931 + UDF_SB_PARTNUM(sb,i) == UDF_SB_PARTNUM(sb,j))
8933 + ino.partitionReferenceNum = j;
8934 + ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) -
8935 + UDF_SB_PARTROOT(sb,j);
8940 + if (j == UDF_SB_NUMPARTS(sb))
8943 + if (!(UDF_SB_VAT(sb) = udf_iget(sb, ino)))
8946 + if (UDF_SB_PARTTYPE(sb,i) == UDF_VIRTUAL_MAP15)
8948 + UDF_SB_TYPEVIRT(sb,i).s_start_offset = udf_ext0_offset(UDF_SB_VAT(sb));
8949 + UDF_SB_TYPEVIRT(sb,i).s_num_entries = (UDF_SB_VAT(sb)->i_size - 36) >> 2;
8951 + else if (UDF_SB_PARTTYPE(sb,i) == UDF_VIRTUAL_MAP20)
8953 + struct buffer_head *bh = NULL;
8956 + pos = udf_bmap(UDF_SB_VAT(sb), 0);
8957 + bh = bread(sb->s_dev, pos, sb->s_blocksize);
8958 + UDF_SB_TYPEVIRT(sb,i).s_start_offset =
8959 + le16_to_cpu(((struct VirtualAllocationTable20 *)bh->b_data + udf_ext0_offset(UDF_SB_VAT(sb)))->lengthHeader) +
8960 + udf_ext0_offset(UDF_SB_VAT(sb));
8961 + UDF_SB_TYPEVIRT(sb,i).s_num_entries = (UDF_SB_VAT(sb)->i_size -
8962 + UDF_SB_TYPEVIRT(sb,i).s_start_offset) >> 2;
8963 + udf_release_data(bh);
8965 + UDF_SB_PARTROOT(sb,i) = udf_get_pblock(sb, 0, i, 0);
8966 + UDF_SB_PARTLEN(sb,i) = UDF_SB_PARTLEN(sb,ino.partitionReferenceNum);
8973 +static void udf_open_lvid(struct super_block *sb)
8975 + if (UDF_SB_LVIDBH(sb))
8978 + timestamp cpu_time;
8980 + UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
8981 + UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
8982 + if (udf_time_to_stamp(&cpu_time, CURRENT_TIME, CURRENT_UTIME))
8983 + UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time);
8984 + UDF_SB_LVID(sb)->integrityType = INTEGRITY_TYPE_OPEN;
8986 + UDF_SB_LVID(sb)->descTag.descCRC =
8987 + cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
8988 + le16_to_cpu(UDF_SB_LVID(sb)->descTag.descCRCLength), 0));
8990 + UDF_SB_LVID(sb)->descTag.tagChecksum = 0;
8991 + for (i=0; i<16; i++)
8993 + UDF_SB_LVID(sb)->descTag.tagChecksum +=
8994 + ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i];
8996 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
9000 +static void udf_close_lvid(struct super_block *sb)
9002 + if (UDF_SB_LVIDBH(sb) &&
9003 + UDF_SB_LVID(sb)->integrityType == INTEGRITY_TYPE_OPEN)
9006 + timestamp cpu_time;
9008 + UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
9009 + UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
9010 + if (udf_time_to_stamp(&cpu_time, CURRENT_TIME, CURRENT_UTIME))
9011 + UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time);
9012 + if (UDF_MAX_WRITE_VERSION > le16_to_cpu(UDF_SB_LVIDIU(sb)->maxUDFWriteRev))
9013 + UDF_SB_LVIDIU(sb)->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
9014 + if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev))
9015 + UDF_SB_LVIDIU(sb)->minUDFReadRev = cpu_to_le16(UDF_SB_UDFREV(sb));
9016 + if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev))
9017 + UDF_SB_LVIDIU(sb)->minUDFWriteRev = cpu_to_le16(UDF_SB_UDFREV(sb));
9018 + UDF_SB_LVID(sb)->integrityType = INTEGRITY_TYPE_CLOSE;
9020 + UDF_SB_LVID(sb)->descTag.descCRC =
9021 + cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
9022 + le16_to_cpu(UDF_SB_LVID(sb)->descTag.descCRCLength), 0));
9024 + UDF_SB_LVID(sb)->descTag.tagChecksum = 0;
9025 + for (i=0; i<16; i++)
9027 + UDF_SB_LVID(sb)->descTag.tagChecksum +=
9028 + ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i];
9030 + mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
9038 + * Complete the specified super block.
9041 + * sb Pointer to superblock to complete - never NULL.
9042 + * sb->s_dev Device to read suberblock from.
9043 + * options Pointer to mount options.
9044 + * silent Silent flag.
9047 + * July 1, 1997 - Andrew E. Mileski
9048 + * Written, tested, and released.
9050 +static struct super_block *
9051 +udf_read_super(struct super_block *sb, void *options, int silent)
9053 + struct inode *inode=NULL;
9054 + struct udf_options uopt;
9055 + lb_addr rootdir, fileset;
9057 + uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB);
9062 + /* Lock the module in memory (if applicable) */
9063 + MOD_INC_USE_COUNT;
9066 + UDF_SB_ALLOC(sb); /* kmalloc, if needed */
9067 + memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
9069 +#if CONFIG_UDF_RW != 1
9070 + sb->s_flags |= MS_RDONLY;
9073 + if (!udf_parse_options((char *)options, &uopt))
9076 + fileset.logicalBlockNum = 0xFFFFFFFF;
9077 + fileset.partitionReferenceNum = 0xFFFF;
9079 + UDF_SB(sb)->s_flags = uopt.flags;
9080 + UDF_SB(sb)->s_uid = uopt.uid;
9081 + UDF_SB(sb)->s_gid = uopt.gid;
9082 + UDF_SB(sb)->s_umask = uopt.umask;
9084 + /* Set the block size for all transfers */
9085 + if (!udf_set_blocksize(sb, uopt.blocksize))
9088 + if ( uopt.session == 0xFFFFFFFF )
9089 + UDF_SB_SESSION(sb) = udf_get_last_session(sb);
9091 + UDF_SB_SESSION(sb) = uopt.session;
9093 + udf_debug("Multi-session=%d\n", UDF_SB_SESSION(sb));
9095 + if ( uopt.lastblock == 0xFFFFFFFF )
9096 + UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
9098 + UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
9100 + UDF_SB_LASTBLOCK(sb) = udf_find_anchor(sb, uopt.anchor, UDF_SB_LASTBLOCK(sb));
9102 + udf_debug("Lastblock=%d\n", UDF_SB_LASTBLOCK(sb));
9104 + if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
9106 + printk("UDF-fs: No VRS found\n");
9110 + /* Fill in the rest of the superblock */
9111 + sb->s_op = &udf_sb_ops;
9114 + sb->s_magic = UDF_SUPER_MAGIC;
9116 + if (udf_load_partition(sb, &fileset))
9118 + printk("UDF-fs: No partition found (1)\n");
9122 + if ( UDF_SB_LVIDBH(sb) )
9124 + Uint16 minUDFReadRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev);
9125 + Uint16 minUDFWriteRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev);
9126 + /* Uint16 maxUDFWriteRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->maxUDFWriteRev); */
9128 + if (minUDFReadRev > UDF_MAX_READ_VERSION)
9130 + printk("UDF-fs: minUDFReadRev=%x (max is %x)\n",
9131 + UDF_SB_LVIDIU(sb)->minUDFReadRev, UDF_MAX_READ_VERSION);
9134 + else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
9136 + sb->s_flags |= MS_RDONLY;
9139 + if (minUDFReadRev >= UDF_VERS_USE_EXTENDED_FE)
9140 + UDF_SET_FLAG(sb, UDF_FLAG_USE_EXTENDED_FE);
9141 + if (minUDFReadRev >= UDF_VERS_USE_STREAMS)
9142 + UDF_SET_FLAG(sb, UDF_FLAG_USE_STREAMS);
9145 + if ( !UDF_SB_NUMPARTS(sb) )
9147 + printk("UDF-fs: No partition found (2)\n");
9151 + if ( udf_find_fileset(sb, &fileset, &rootdir) )
9153 + printk("UDF-fs: No fileset found\n");
9160 + udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
9161 + udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
9162 + UDFFS_VERSION, UDFFS_DATE,
9163 + UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
9164 + ts.typeAndTimezone);
9166 + if (!(sb->s_flags & MS_RDONLY))
9167 + udf_open_lvid(sb);
9170 + /* Assign the root inode */
9171 + /* assign inodes by physical block number */
9172 + /* perhaps it's not extensible enough, but for now ... */
9173 + inode = udf_iget(sb, rootdir);
9176 + printk("UDF-fs: Error in udf_iget, block=%d, partition=%d\n",
9177 + rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
9181 + /* Allocate a dentry for the root inode */
9182 + sb->s_root = d_alloc_root(inode, NULL);
9185 + printk("UDF-fs: Couldn't allocate root dentry\n");
9193 + sb->s_dev = NODEV;
9194 + if (UDF_SB_VAT(sb))
9195 + iput(UDF_SB_VAT(sb));
9196 + if (UDF_SB_NUMPARTS(sb))
9198 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE)
9199 + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table);
9200 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
9201 + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
9202 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
9203 + kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
9204 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
9205 + kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
9207 + if (!(sb->s_flags & MS_RDONLY))
9208 + udf_close_lvid(sb);
9209 + udf_release_data(UDF_SB_LVIDBH(sb));
9212 + MOD_DEC_USE_COUNT;
9216 +void udf_error(struct super_block *sb, const char *function,
9217 + const char *fmt, ...)
9221 + if (!(sb->s_flags & MS_RDONLY))
9223 + /* mark sb error */
9226 + va_start(args, fmt);
9227 + vsprintf(error_buf, fmt, args);
9229 + printk (KERN_CRIT "UDF-fs error (device %s): %s: %s\n",
9230 + bdevname(sb->s_dev), function, error_buf);
9233 +void udf_warning(struct super_block *sb, const char *function,
9234 + const char *fmt, ...)
9238 + va_start (args, fmt);
9239 + vsprintf(error_buf, fmt, args);
9241 + printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n",
9242 + bdevname(sb->s_dev), function, error_buf);
9249 + * Prepare for destruction of the superblock.
9252 + * Called before the filesystem is unmounted.
9255 + * July 1, 1997 - Andrew E. Mileski
9256 + * Written, tested, and released.
9259 +udf_put_super(struct super_block *sb)
9263 + if (UDF_SB_VAT(sb))
9264 + iput(UDF_SB_VAT(sb));
9265 + if (UDF_SB_NUMPARTS(sb))
9267 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE)
9268 + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table);
9269 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
9270 + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
9271 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
9273 + for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_uspace); i++)
9275 + if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i))
9276 + udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i));
9278 + kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
9280 + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
9282 + for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_fspace); i++)
9284 + if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i))
9285 + udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i));
9287 + kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
9290 + if (!(sb->s_flags & MS_RDONLY))
9291 + udf_close_lvid(sb);
9292 + udf_release_data(UDF_SB_LVIDBH(sb));
9295 + MOD_DEC_USE_COUNT;
9302 + * Return info about the filesystem.
9305 + * Called by sys_statfs()
9308 + * July 1, 1997 - Andrew E. Mileski
9309 + * Written, tested, and released.
9312 +udf_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
9315 + struct statfs tmp;
9318 + size = (bufsize < sizeof(tmp)) ? bufsize: sizeof(tmp);
9320 + memset(&tmp, 0, sizeof(tmp));
9321 + tmp.f_type = UDF_SUPER_MAGIC;
9322 + tmp.f_bsize = sb->s_blocksize;
9323 + tmp.f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
9324 + tmp.f_bfree = udf_count_free(sb);
9325 + tmp.f_bavail = tmp.f_bfree;
9326 + tmp.f_files = (UDF_SB_LVIDBH(sb) ?
9327 + (le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) +
9328 + le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + tmp.f_bfree;
9329 + tmp.f_ffree = tmp.f_bfree;
9330 + /* __kernel_fsid_t f_fsid */
9331 + tmp.f_namelen = UDF_NAME_LEN;
9333 + rc= copy_to_user(buf, &tmp, size) ? -EFAULT: 0;
9337 +static unsigned char udf_bitmap_lookup[16] = {
9338 + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
9341 +static unsigned int
9342 +udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
9344 + struct buffer_head *bh = NULL;
9345 + unsigned int accum = 0;
9347 + int block = 0, newblock;
9353 + struct SpaceBitmapDesc *bm;
9355 + loc.logicalBlockNum = bitmap->s_extPosition;
9356 + loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
9357 + bh = udf_read_ptagged(sb, loc, 0, &ident);
9361 + printk(KERN_ERR "udf: udf_count_free failed\n");
9364 + else if (ident != TID_SPACE_BITMAP_DESC)
9366 + udf_release_data(bh);
9367 + printk(KERN_ERR "udf: udf_count_free failed\n");
9371 + bm = (struct SpaceBitmapDesc *)bh->b_data;
9372 + bytes = bm->numOfBytes;
9373 + index = sizeof(struct SpaceBitmapDesc); /* offset in first block only */
9374 + ptr = (Uint8 *)bh->b_data;
9376 + while ( bytes > 0 )
9378 + while ((bytes > 0) && (index < sb->s_blocksize))
9380 + value = ptr[index];
9381 + accum += udf_bitmap_lookup[ value & 0x0f ];
9382 + accum += udf_bitmap_lookup[ value >> 4 ];
9388 + udf_release_data(bh);
9389 + newblock = udf_get_lb_pblock(sb, loc, ++block);
9390 + bh = udf_tread(sb, newblock, sb->s_blocksize);
9393 + udf_debug("read failed\n");
9397 + ptr = (Uint8 *)bh->b_data;
9400 + udf_release_data(bh);
9404 +static unsigned int
9405 +udf_count_free_table(struct super_block *sb, struct inode * table)
9407 + unsigned int accum = 0;
9408 + Uint32 extoffset, elen;
9409 + lb_addr bloc, eloc;
9411 + struct buffer_head *bh = NULL;
9413 + bloc = UDF_I_LOCATION(table);
9414 + extoffset = sizeof(struct UnallocatedSpaceEntry);
9416 + while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
9418 + accum += (elen >> table->i_sb->s_blocksize_bits);
9420 + udf_release_data(bh);
9424 +static unsigned int
9425 +udf_count_free(struct super_block *sb)
9427 + unsigned int accum = 0;
9429 + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
9431 + accum += udf_count_free_bitmap(sb,
9432 + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
9434 + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
9436 + accum += udf_count_free_bitmap(sb,
9437 + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
9442 + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE)
9444 + accum += udf_count_free_table(sb,
9445 + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table);
9447 + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
9449 + accum += udf_count_free_table(sb,
9450 + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
9455 + if (UDF_SB_LVIDBH(sb))
9457 + if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb))
9459 + accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]);
9461 + if (accum == 0xFFFFFFFF)
9467 diff -Nru linux/fs/udf/symlink.c linux.new/fs/udf/symlink.c
9468 --- linux/fs/udf/symlink.c Thu Jan 1 01:00:00 1970
9469 +++ linux.new/fs/udf/symlink.c Fri Sep 7 11:32:16 2001
9475 + * Symlink handling routines for the OSTA-UDF(tm) filesystem.
9478 + * E-mail regarding any portion of the Linux UDF file system should be
9479 + * directed to the development team mailing list (run by majordomo):
9480 + * linux_udf@hootie.lvld.hp.com
9483 + * This file is distributed under the terms of the GNU General Public
9484 + * License (GPL). Copies of the GPL can be obtained from:
9485 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
9486 + * Each contributing author retains all rights to their own work.
9488 + * (C) 1998-2000 Ben Fennema
9489 + * (C) 1999 Stelias Computing Inc
9493 + * 04/16/99 blf Created.
9497 +#include "udfdecl.h"
9498 +#include <asm/uaccess.h>
9499 +#include <linux/errno.h>
9500 +#include <linux/fs.h>
9501 +#include <linux/udf_fs.h>
9502 +#include <linux/sched.h>
9503 +#include <linux/mm.h>
9504 +#include <linux/stat.h>
9505 +#include <linux/malloc.h>
9508 +static void udf_pc_to_char(char *from, int fromlen, char *to)
9510 + struct PathComponent *pc;
9514 + while (elen < fromlen)
9516 + pc = (struct PathComponent *)(from + elen);
9517 + switch (pc->componentType)
9520 + if (pc->lengthComponentIdent == 0)
9527 + memcpy(p, "../", 3);
9531 + memcpy(p, "./", 2);
9533 + /* that would be . - just ignore */
9536 + memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
9537 + p += pc->lengthComponentIdent;
9540 + elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
9548 +static struct dentry * udf_follow_link(struct dentry * dentry,
9549 + struct dentry * base, unsigned int follow)
9551 + struct inode *inode = dentry->d_inode;
9552 + struct buffer_head *bh = NULL;
9553 + char *symlink, *tmpbuf;
9555 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
9557 + bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
9562 + symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
9566 + bh = bread(inode->i_dev, udf_bmap(inode, 0), inode->i_sb->s_blocksize);
9571 + symlink = bh->b_data;
9573 + if ((tmpbuf = (char *)kmalloc(inode->i_size, GFP_KERNEL)))
9575 + udf_pc_to_char(symlink, inode->i_size, tmpbuf);
9576 + base = lookup_dentry(tmpbuf, base, follow);
9581 + return ERR_PTR(-ENOMEM);
9584 +static int udf_readlink(struct dentry * dentry, char * buffer, int buflen)
9586 + struct inode *inode = dentry->d_inode;
9587 + struct buffer_head *bh = NULL;
9588 + char *symlink, *tmpbuf;
9591 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
9593 + bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
9598 + symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
9602 + bh = bread(inode->i_dev, udf_bmap(inode, 0), inode->i_sb->s_blocksize);
9607 + symlink = bh->b_data;
9610 + if ((tmpbuf = (char *)kmalloc(inode->i_size, GFP_KERNEL)))
9612 + udf_pc_to_char(symlink, inode->i_size, tmpbuf);
9613 + if ((len = strlen(tmpbuf)) > buflen)
9615 + if (copy_to_user(buffer, tmpbuf, len))
9622 + UPDATE_ATIME(inode);
9624 + udf_release_data(bh);
9629 + * symlinks can't do much...
9631 +struct inode_operations udf_symlink_inode_operations = {
9632 + NULL, /* no file-operations */
9633 + NULL, /* create */
9634 + NULL, /* lookup */
9636 + NULL, /* unlink */
9637 + NULL, /* symlink */
9641 + NULL, /* rename */
9642 + udf_readlink, /* readlink */
9643 + udf_follow_link,/* follow_link */
9644 + NULL, /* readpage */
9645 + NULL, /* writepage */
9647 + NULL, /* truncate */
9648 + NULL, /* permission */
9650 + NULL /* revalidate */
9652 diff -Nru linux/fs/udf/truncate.c linux.new/fs/udf/truncate.c
9653 --- linux/fs/udf/truncate.c Thu Jan 1 01:00:00 1970
9654 +++ linux.new/fs/udf/truncate.c Fri Sep 7 11:32:16 2001
9660 + * Truncate handling routines for the OSTA-UDF(tm) filesystem.
9663 + * E-mail regarding any portion of the Linux UDF file system should be
9664 + * directed to the development team mailing list (run by majordomo):
9665 + * linux_udf@hootie.lvld.hp.com
9668 + * This file is distributed under the terms of the GNU General Public
9669 + * License (GPL). Copies of the GPL can be obtained from:
9670 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
9671 + * Each contributing author retains all rights to their own work.
9673 + * (C) 1999-2000 Ben Fennema
9674 + * (C) 1999 Stelias Computing Inc
9678 + * 02/24/99 blf Created.
9682 +#include "udfdecl.h"
9683 +#include <linux/fs.h>
9684 +#include <linux/mm.h>
9685 +#include <linux/udf_fs.h>
9688 +#include "udf_sb.h"
9690 +static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
9691 + lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head *bh, Uint32 nelen)
9693 + lb_addr neloc = { 0, 0 };
9694 + int blocks = inode->i_sb->s_blocksize / 512;
9695 + int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
9696 + int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
9701 + nelen = (etype << 30) | nelen;
9704 + if (elen != nelen)
9706 + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
9707 + if (last_block - first_block > 0)
9709 + if (etype == EXTENT_RECORDED_ALLOCATED)
9711 + inode->i_blocks -= (blocks * (last_block - first_block));
9712 + mark_inode_dirty(inode);
9714 + if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
9715 + udf_free_blocks(inode, eloc, first_block, last_block - first_block);
9720 +void udf_trunc(struct inode * inode)
9722 + lb_addr bloc, eloc, neloc = { 0, 0 };
9723 + Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
9725 + int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
9726 + struct buffer_head *bh = NULL;
9729 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
9730 + adsize = sizeof(short_ad);
9731 + else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
9732 + adsize = sizeof(long_ad);
9736 + etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
9737 + offset = (offset << inode->i_sb->s_blocksize_bits) |
9738 + (inode->i_size & (inode->i_sb->s_blocksize - 1));
9741 + extoffset -= adsize;
9742 + extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset);
9743 + extoffset += adsize;
9746 + lenalloc = extoffset;
9748 + lenalloc = extoffset - adsize;
9750 + if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9751 + lenalloc -= udf_file_entry_alloc_offset(inode);
9753 + lenalloc -= sizeof(struct AllocExtDesc);
9755 + while ((etype = udf_current_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0)) != -1)
9757 + if (etype == EXTENT_NEXT_EXTENT_ALLOCDECS)
9759 + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
9763 + if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9764 + memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
9766 + memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
9767 + udf_free_blocks(inode, bloc, 0, lelen);
9771 + if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9773 + UDF_I_LENALLOC(inode) = lenalloc;
9774 + mark_inode_dirty(inode);
9778 + struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
9779 + aed->lengthAllocDescs = cpu_to_le32(lenalloc);
9780 + udf_update_tag(bh->b_data, lenalloc +
9781 + sizeof(struct AllocExtDesc));
9782 + mark_buffer_dirty(bh, 1);
9786 + udf_release_data(bh);
9791 + lelen = (elen + inode->i_sb->s_blocksize - 1) >>
9792 + inode->i_sb->s_blocksize_bits;
9798 + extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
9799 + extoffset += adsize;
9805 + if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9806 + memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
9808 + memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
9809 + udf_free_blocks(inode, bloc, 0, lelen);
9813 + if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9815 + UDF_I_LENALLOC(inode) = lenalloc;
9816 + mark_inode_dirty(inode);
9820 + struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
9821 + aed->lengthAllocDescs = cpu_to_le32(lenalloc);
9822 + udf_update_tag(bh->b_data, lenalloc +
9823 + sizeof(struct AllocExtDesc));
9824 + mark_buffer_dirty(bh, 1);
9828 + else if (inode->i_size)
9832 + extoffset -= adsize;
9833 + etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
9835 + if (etype == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
9837 + extoffset -= adsize;
9838 + elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (elen + offset);
9839 + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
9841 + else if (etype == EXTENT_NOT_RECORDED_ALLOCATED)
9843 + lb_addr neloc = { 0, 0 };
9844 + extoffset -= adsize;
9845 + nelen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
9846 + ((elen + offset + inode->i_sb->s_blocksize - 1) &
9847 + ~(inode->i_sb->s_blocksize - 1));
9848 + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
9849 + udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
9853 + if (elen & (inode->i_sb->s_blocksize - 1))
9855 + extoffset -= adsize;
9856 + elen = (EXTENT_RECORDED_ALLOCATED << 30) |
9857 + ((elen + inode->i_sb->s_blocksize - 1) &
9858 + ~(inode->i_sb->s_blocksize - 1));
9859 + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
9861 + memset(&eloc, 0x00, sizeof(lb_addr));
9862 + elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | offset;
9863 + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
9868 + udf_release_data(bh);
9871 +void udf_truncate(struct inode * inode)
9875 + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
9876 + S_ISLNK(inode->i_mode)))
9878 + if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
9883 + offset = (inode->i_size & (inode->i_sb->s_blocksize - 1));
9886 + struct buffer_head *bh;
9887 + bh = bread(inode->i_dev,
9888 + udf_bmap(inode, inode->i_size >> inode->i_sb->s_blocksize_bits),
9889 + inode->i_sb->s_blocksize);
9892 + memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
9893 + mark_buffer_dirty(bh, 0);
9894 + udf_release_data(bh);
9898 + inode->i_mtime = inode->i_ctime = CURRENT_TIME;
9899 + mark_inode_dirty(inode);
9902 +void udf_truncate_adinicb(struct inode * inode)
9905 + struct buffer_head *bh;
9908 + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
9909 + S_ISLNK(inode->i_mode)))
9911 + if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
9914 + if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
9917 + udf_expand_file_adinicb(inode, inode->i_size, &err);
9918 + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
9920 + inode->i_size = UDF_I_LENALLOC(inode);
9924 + return udf_truncate(inode);
9927 + UDF_I_LENALLOC(inode) = inode->i_size;
9929 + offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
9930 + udf_file_entry_alloc_offset(inode);
9932 + if ((bh = udf_tread(inode->i_sb,
9933 + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0),
9934 + inode->i_sb->s_blocksize)))
9936 + memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
9937 + mark_buffer_dirty(bh, 0);
9938 + udf_release_data(bh);
9941 + inode->i_mtime = inode->i_ctime = CURRENT_TIME;
9942 + mark_inode_dirty(inode);
9944 diff -Nru linux/fs/udf/udf_i.h linux.new/fs/udf/udf_i.h
9945 --- linux/fs/udf/udf_i.h Thu Jan 1 01:00:00 1970
9946 +++ linux.new/fs/udf/udf_i.h Fri Sep 7 11:32:16 2001
9948 +#ifndef __LINUX_UDF_I_H
9949 +#define __LINUX_UDF_I_H
9951 +#ifndef CONFIG_UDF_FS_EXT
9953 +#define UDF_I(X) (&((X)->u.udf_i))
9956 +/* we're not compiled in, so we can't expect our stuff in <linux/fs.h> */
9957 +#define UDF_I(X) ( (struct udf_inode_info *) &((X)->u.pipe_i))
9958 + /* god, this is slimy. stealing another filesystem's union area. */
9959 + /* for the record, pipe_i is 9 ints long, we're using 9 */
9962 +#define UDF_I_LOCATION(X) ( UDF_I(X)->i_location )
9963 +#define UDF_I_LENEATTR(X) ( UDF_I(X)->i_lenEAttr )
9964 +#define UDF_I_LENALLOC(X) ( UDF_I(X)->i_lenAlloc )
9965 +#define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique )
9966 +#define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type )
9967 +#define UDF_I_EXTENDED_FE(X)( UDF_I(X)->i_extended_fe )
9968 +#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat_4096 )
9969 +#define UDF_I_NEW_INODE(X) ( UDF_I(X)->i_new_inode )
9970 +#define UDF_I_NEXT_ALLOC_BLOCK(X) ( UDF_I(X)->i_next_alloc_block )
9971 +#define UDF_I_NEXT_ALLOC_GOAL(X) ( UDF_I(X)->i_next_alloc_goal )
9972 +#define UDF_I_UATIME(X) ( UDF_I(X)->i_uatime )
9973 +#define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime )
9974 +#define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime )
9976 +#endif /* !defined(_LINUX_UDF_I_H) */
9977 diff -Nru linux/fs/udf/udf_sb.h linux.new/fs/udf/udf_sb.h
9978 --- linux/fs/udf/udf_sb.h Thu Jan 1 01:00:00 1970
9979 +++ linux.new/fs/udf/udf_sb.h Fri Sep 7 11:32:16 2001
9981 +#ifndef __LINUX_UDF_SB_H
9982 +#define __LINUX_UDF_SB_H
9984 +/* Since UDF 1.50 is ISO 13346 based... */
9985 +#define UDF_SUPER_MAGIC 0x15013346
9987 +#define UDF_MAX_READ_VERSION 0x0200
9988 +#define UDF_MAX_WRITE_VERSION 0x0200
9990 +#define UDF_FLAG_USE_EXTENDED_FE 0
9991 +#define UDF_VERS_USE_EXTENDED_FE 0x0200
9992 +#define UDF_FLAG_USE_STREAMS 1
9993 +#define UDF_VERS_USE_STREAMS 0x0200
9994 +#define UDF_FLAG_USE_SHORT_AD 2
9995 +#define UDF_FLAG_USE_AD_IN_ICB 3
9996 +#define UDF_FLAG_USE_FILE_CTIME_EA 4
9997 +#define UDF_FLAG_STRICT 5
9998 +#define UDF_FLAG_UNDELETE 6
9999 +#define UDF_FLAG_UNHIDE 7
10000 +#define UDF_FLAG_VARCONV 8
10002 +#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001
10003 +#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002
10004 +#define UDF_PART_FLAG_FREED_BITMAP 0x0004
10005 +#define UDF_PART_FLAG_FREED_TABLE 0x0008
10007 +/* following is set only when compiling outside kernel tree */
10008 +#ifndef CONFIG_UDF_FS_EXT
10010 +#define UDF_SB_ALLOC(X)
10011 +#define UDF_SB_FREE(X)\
10015 + if (UDF_SB_PARTMAPS(X))\
10016 + kfree(UDF_SB_PARTMAPS(X));\
10017 + UDF_SB_PARTMAPS(X) = NULL;\
10020 +#define UDF_SB(X) (&((X)->u.udf_sb))
10023 + /* else we kmalloc a page to hold our stuff */
10024 +#define UDF_SB_ALLOC(X)\
10025 + (UDF_SB(X) = kmalloc(sizeof(struct udf_sb_info), GFP_KERNEL))
10026 +#define UDF_SB_FREE(X)\
10030 + if (UDF_SB_PARTMAPS(X))\
10031 + kfree(UDF_SB_PARTMAPS(X));\
10032 + kfree(UDF_SB(X));\
10033 + UDF_SB(X) = NULL;\
10037 +#define UDF_SB(X) ((struct udf_sb_info *) ((X)->u.generic_sbp))
10040 +#define UDF_SB_ALLOC_PARTMAPS(X,Y)\
10042 + UDF_SB_NUMPARTS(X) = Y;\
10043 + UDF_SB_PARTMAPS(X) = kmalloc(sizeof(struct udf_part_map) * Y, GFP_KERNEL);\
10044 + memset(UDF_SB_PARTMAPS(X), 0x00, sizeof(struct udf_part_map) * Y);\
10047 +#define UDF_SB_ALLOC_BITMAP(X,Y,Z)\
10049 + int nr_groups = ((UDF_SB_PARTLEN((X),(Y)) + (sizeof(struct SpaceBitmapDesc) << 3) +\
10050 + ((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\
10051 + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(sizeof(struct udf_bitmap) +\
10052 + sizeof(struct buffer_head *) * nr_groups,\
10054 + memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00,\
10055 + sizeof(struct udf_bitmap) + sizeof(struct buffer_head *) * nr_groups);\
10056 + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\
10057 + (struct buffer_head **)(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap + 1);\
10058 + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups = nr_groups;\
10062 +#define UDF_QUERY_FLAG(X,Y) ( UDF_SB(X)->s_flags & ( 1 << (Y) ) )
10063 +#define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) )
10064 +#define UDF_CLEAR_FLAG(X,Y) ( UDF_SB(X)->s_flags &= ~( 1 << (Y) ) )
10066 +#define UDF_UPDATE_UDFREV(X,Y) ( ((Y) > UDF_SB_UDFREV(X)) ? UDF_SB_UDFREV(X) = (Y) : UDF_SB_UDFREV(X) )
10068 +#define UDF_SB_PARTMAPS(X) ( UDF_SB(X)->s_partmaps )
10069 +#define UDF_SB_PARTTYPE(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_type )
10070 +#define UDF_SB_PARTROOT(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_root )
10071 +#define UDF_SB_PARTLEN(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_len )
10072 +#define UDF_SB_PARTVSN(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_volumeseqnum )
10073 +#define UDF_SB_PARTNUM(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_num )
10074 +#define UDF_SB_TYPESPAR(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_sparing )
10075 +#define UDF_SB_TYPEVIRT(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_virtual )
10076 +#define UDF_SB_PARTFUNC(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func )
10077 +#define UDF_SB_PARTFLAGS(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_flags )
10078 +#define UDF_SB_BITMAP(X,Y,Z,I) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap[I] )
10079 +#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups )
10081 +#define UDF_SB_VOLIDENT(X) ( UDF_SB(X)->s_volident )
10082 +#define UDF_SB_NUMPARTS(X) ( UDF_SB(X)->s_partitions )
10083 +#define UDF_SB_PARTITION(X) ( UDF_SB(X)->s_partition )
10084 +#define UDF_SB_SESSION(X) ( UDF_SB(X)->s_session )
10085 +#define UDF_SB_ANCHOR(X) ( UDF_SB(X)->s_anchor )
10086 +#define UDF_SB_LASTBLOCK(X) ( UDF_SB(X)->s_lastblock )
10087 +#define UDF_SB_LVIDBH(X) ( UDF_SB(X)->s_lvidbh )
10088 +#define UDF_SB_LVID(X) ( (struct LogicalVolIntegrityDesc *)UDF_SB_LVIDBH(X)->b_data )
10089 +#define UDF_SB_LVIDIU(X) ( (struct LogicalVolIntegrityDescImpUse *)&(UDF_SB_LVID(X)->impUse[UDF_SB_LVID(X)->numOfPartitions * 2 * sizeof(Uint32)/sizeof(Uint8)]) )
10091 +#define UDF_SB_UMASK(X) ( UDF_SB(X)->s_umask )
10092 +#define UDF_SB_GID(X) ( UDF_SB(X)->s_gid )
10093 +#define UDF_SB_UID(X) ( UDF_SB(X)->s_uid )
10094 +#define UDF_SB_RECORDTIME(X) ( UDF_SB(X)->s_recordtime )
10095 +#define UDF_SB_SERIALNUM(X) ( UDF_SB(X)->s_serialnum )
10096 +#define UDF_SB_UDFREV(X) ( UDF_SB(X)->s_udfrev )
10097 +#define UDF_SB_FLAGS(X) ( UDF_SB(X)->s_flags )
10098 +#define UDF_SB_VAT(X) ( UDF_SB(X)->s_vat )
10100 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
10101 +#define UDF_SB_RENAME_LOCK(X) ( UDF_SB(X)->s_rename_lock )
10102 +#define UDF_SB_RENAME_WAIT(X) ( UDF_SB(X)->s_rename_wait )
10105 +#endif /* __LINUX_UDF_SB_H */
10106 diff -Nru linux/fs/udf/udfdecl.h linux.new/fs/udf/udfdecl.h
10107 --- linux/fs/udf/udfdecl.h Thu Jan 1 01:00:00 1970
10108 +++ linux.new/fs/udf/udfdecl.h Fri Sep 7 11:32:16 2001
10110 +#ifndef __UDF_DECL_H
10111 +#define __UDF_DECL_H
10113 +#include <linux/udf_167.h>
10114 +#include <linux/udf_udf.h>
10115 +#include "udfend.h"
10117 +#include <linux/udf_fs.h>
10121 +#include <linux/config.h>
10122 +#include <linux/fs.h>
10123 +#include <linux/types.h>
10125 +#ifndef LINUX_VERSION_CODE
10126 +#include <linux/version.h>
10129 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,70)
10130 +#error "The UDF Module Current Requires Kernel Version 2.1.70 or greater"
10133 +#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
10134 +#define CONFIG_UDF_FS_MODULE
10135 +#include <linux/udf_fs_sb.h>
10136 +#include <linux/udf_fs_i.h>
10139 +#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
10140 +#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
10142 +#define CURRENT_UTIME (xtime.tv_usec)
10144 +#define udf_file_entry_alloc_offset(inode)\
10145 + ((UDF_I_EXTENDED_FE(inode) ?\
10146 + sizeof(struct ExtendedFileEntry) :\
10147 + sizeof(struct FileEntry)) + UDF_I_LENEATTR(inode))
10149 +#define udf_ext0_offset(inode)\
10150 + (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB ?\
10151 + udf_file_entry_alloc_offset(inode) : 0)
10153 +#define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset))
10157 +#include <sys/types.h>
10159 +#endif /* __KERNEL__ */
10167 +struct task_struct;
10168 +struct buffer_head;
10169 +struct super_block;
10171 +extern struct inode_operations udf_dir_inode_operations;
10172 +extern struct inode_operations udf_file_inode_operations;
10173 +extern struct inode_operations udf_file_inode_operations_adinicb;
10174 +extern struct inode_operations udf_symlink_inode_operations;
10176 +struct udf_fileident_bh
10178 + struct buffer_head *sbh;
10179 + struct buffer_head *ebh;
10184 +#endif /* __KERNEL__ */
10186 +struct udf_directory_record
10190 + Uint32 d_name[255];
10194 +struct udf_vds_record
10197 + Uint32 volDescSeqNum;
10214 + Uint8 u_name[UDF_NAME_LEN];
10217 + unsigned long u_hash;
10223 +extern void udf_error(struct super_block *, const char *, const char *, ...);
10224 +extern void udf_warning(struct super_block *, const char *, const char *, ...);
10227 +extern int udf_write_fi(struct FileIdentDesc *, struct FileIdentDesc *, struct udf_fileident_bh *, Uint8 *, Uint8 *);
10228 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
10229 +extern int udf_lookup(struct inode *, struct dentry *);
10231 +extern struct dentry * udf_lookup(struct inode *, struct dentry *);
10233 +extern int udf_create(struct inode *, struct dentry *, int);
10234 +extern int udf_mknod(struct inode *, struct dentry *, int, int);
10235 +extern int udf_mkdir(struct inode *, struct dentry *, int);
10236 +extern int udf_rmdir(struct inode *, struct dentry *);
10237 +extern int udf_unlink(struct inode *, struct dentry *);
10238 +extern int udf_symlink(struct inode *, struct dentry *, const char *);
10239 +extern int udf_link(struct dentry *, struct inode *, struct dentry *);
10240 +extern int udf_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
10243 +extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
10246 +extern struct inode *udf_iget(struct super_block *, lb_addr);
10247 +extern int udf_sync_inode(struct inode *);
10248 +extern void udf_expand_file_adinicb(struct inode *, int, int *);
10249 +extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
10250 +extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
10251 +extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
10252 +extern void udf_read_inode(struct inode *);
10253 +extern void udf_put_inode(struct inode *);
10254 +extern void udf_delete_inode(struct inode *);
10255 +extern void udf_write_inode(struct inode *);
10256 +extern int inode_bmap(struct inode *, int, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
10257 +extern int udf_bmap(struct inode *, int);
10258 +extern int udf_readpage_adinicb(struct file *, struct page *);
10259 +extern int udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, Uint32, struct buffer_head **, int);
10260 +extern int udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head *, int);
10261 +extern int udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
10262 +extern int udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
10263 +extern int udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
10264 +extern int udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
10265 +extern void udf_discard_prealloc(struct inode *);
10268 +extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
10269 +extern struct buffer_head *udf_tread(struct super_block *, int, int);
10270 +extern struct GenericAttrFormat *udf_add_extendedattr(struct inode *, Uint32, Uint32, Uint8, struct buffer_head **);
10271 +extern struct GenericAttrFormat *udf_get_extendedattr(struct inode *, Uint32, Uint8, struct buffer_head **);
10272 +extern struct buffer_head *udf_read_tagged(struct super_block *, Uint32, Uint32, Uint16 *);
10273 +extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, Uint32, Uint16 *);
10274 +extern struct buffer_head *udf_read_untagged(struct super_block *, Uint32, Uint32);
10275 +extern void udf_release_data(struct buffer_head *);
10278 +extern unsigned int udf_get_last_session(struct super_block *);
10279 +extern unsigned int udf_get_last_block(struct super_block *);
10282 +extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
10283 +extern Uint32 udf_get_pblock_virt15(struct super_block *, Uint32, Uint16, Uint32);
10284 +extern Uint32 udf_get_pblock_virt20(struct super_block *, Uint32, Uint16, Uint32);
10285 +extern Uint32 udf_get_pblock_spar15(struct super_block *, Uint32, Uint16, Uint32);
10286 +extern void udf_fill_spartable(struct super_block *, struct udf_sparing_data *, int);
10289 +extern int udf_get_filename(Uint8 *, Uint8 *, int);
10292 +extern void udf_free_inode(struct inode *);
10293 +extern struct inode * udf_new_inode (const struct inode *, int, int *);
10296 +extern void udf_trunc(struct inode *);
10297 +extern void udf_truncate(struct inode *);
10298 +extern void udf_truncate_adinicb(struct inode *);
10301 +extern inline void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32);
10302 +extern inline int udf_prealloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
10303 +extern inline int udf_new_block(const struct inode *, Uint16, Uint32, int *);
10306 +extern int udf_sync_file(struct file *, struct dentry *);
10307 +extern int udf_sync_file_adinicb(struct file *, struct dentry *);
10310 +extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *);
10311 +extern struct FileIdentDesc * udf_fileident_read(struct inode *, int *, struct udf_fileident_bh *, struct FileIdentDesc *, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
10313 +#endif /* __KERNEL__ */
10315 +/* Miscellaneous UDF Prototypes */
10318 +extern int udf_ustr_to_dchars(Uint8 *, const struct ustr *, int);
10319 +extern int udf_ustr_to_char(Uint8 *, const struct ustr *, int);
10320 +extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
10321 +extern int udf_dchars_to_ustr(struct ustr *, const Uint8 *, int);
10322 +extern int udf_char_to_ustr(struct ustr *, const Uint8 *, int);
10323 +extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
10324 +extern int udf_translate_to_linux(Uint8 *, Uint8 *, int, Uint8 *, int);
10325 +extern int udf_build_ustr(struct ustr *, dstring *, int);
10326 +extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
10327 +extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
10328 +extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
10331 +extern Uint16 udf_crc(Uint8 *, Uint32, Uint16);
10334 +extern uid_t udf_convert_uid(int);
10335 +extern gid_t udf_convert_gid(int);
10336 +extern Uint32 udf64_low32(Uint64);
10337 +extern Uint32 udf64_high32(Uint64);
10338 +extern void udf_update_tag(char *, int);
10339 +extern void udf_new_tag(char *, Uint16, Uint16, Uint16, Uint32, int);
10342 +extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
10343 +extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
10344 +extern time_t udf_converttime (struct ktm *);
10347 +extern struct FileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
10348 +extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
10349 +extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
10350 +extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
10351 +extern Uint8 * udf_get_filead(struct FileEntry *, Uint8 *, int, int, int, int *);
10353 +#endif /* __UDF_DECL_H */
10354 diff -Nru linux/fs/udf/udfend.h linux.new/fs/udf/udfend.h
10355 --- linux/fs/udf/udfend.h Thu Jan 1 01:00:00 1970
10356 +++ linux.new/fs/udf/udfend.h Fri Sep 7 11:32:16 2001
10358 +#ifndef __UDF_ENDIAN_H
10359 +#define __UDF_ENDIAN_H
10361 +#ifndef __KERNEL__
10363 +#include <sys/types.h>
10365 +#if __BYTE_ORDER == 0
10367 +#error "__BYTE_ORDER must be defined"
10369 +#elif __BYTE_ORDER == __BIG_ENDIAN
10371 +#define le16_to_cpu(x) \
10372 + ((Uint16)((((Uint16)(x) & 0x00FFU) << 8) | \
10373 + (((Uint16)(x) & 0xFF00U) >> 8)))
10375 +#define le32_to_cpu(x) \
10376 + ((Uint32)((((Uint32)(x) & 0x000000FFU) << 24) | \
10377 + (((Uint32)(x) & 0x0000FF00U) << 8) | \
10378 + (((Uint32)(x) & 0x00FF0000U) >> 8) | \
10379 + (((Uint32)(x) & 0xFF000000U) >> 24)))
10381 +#define le64_to_cpu(x) \
10382 + ((Uint64)((((Uint64)(x) & 0x00000000000000FFULL) << 56) | \
10383 + (((Uint64)(x) & 0x000000000000FF00ULL) << 40) | \
10384 + (((Uint64)(x) & 0x0000000000FF0000ULL) << 24) | \
10385 + (((Uint64)(x) & 0x00000000FF000000ULL) << 8) | \
10386 + (((Uint64)(x) & 0x000000FF00000000ULL) >> 8) | \
10387 + (((Uint64)(x) & 0x0000FF0000000000ULL) >> 24) | \
10388 + (((Uint64)(x) & 0x00FF000000000000ULL) >> 40) | \
10389 + (((Uint64)(x) & 0xFF00000000000000ULL) >> 56)))
10391 +#define cpu_to_le16(x) (le16_to_cpu(x))
10392 +#define cpu_to_le32(x) (le32_to_cpu(x))
10393 +#define cpu_to_le64(x) (le64_to_cpu(x))
10395 +#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
10397 +#define le16_to_cpu(x) (x)
10398 +#define le32_to_cpu(x) (x)
10399 +#define le64_to_cpu(x) (x)
10400 +#define cpu_to_le16(x) (x)
10401 +#define cpu_to_le32(x) (x)
10402 +#define cpu_to_le64(x) (x)
10404 +#endif /* __BYTE_ORDER == 0 */
10406 +#include <string.h>
10408 +#else /* __KERNEL__ */
10410 +#include <asm/byteorder.h>
10411 +#include <linux/string.h>
10413 +#endif /* ! __KERNEL__ */
10415 +static inline lb_addr lelb_to_cpu(lb_addr in)
10418 + out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum);
10419 + out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum);
10423 +static inline lb_addr cpu_to_lelb(lb_addr in)
10426 + out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum);
10427 + out.partitionReferenceNum = cpu_to_le16(in.partitionReferenceNum);
10431 +static inline timestamp lets_to_cpu(timestamp in)
10434 + memcpy(&out, &in, sizeof(timestamp));
10435 + out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
10436 + out.year = le16_to_cpu(in.year);
10440 +static inline short_ad lesa_to_cpu(short_ad in)
10443 + out.extLength = le32_to_cpu(in.extLength);
10444 + out.extPosition = le32_to_cpu(in.extPosition);
10448 +static inline short_ad cpu_to_lesa(short_ad in)
10451 + out.extLength = cpu_to_le32(in.extLength);
10452 + out.extPosition = cpu_to_le32(in.extPosition);
10456 +static inline long_ad lela_to_cpu(long_ad in)
10459 + out.extLength = le32_to_cpu(in.extLength);
10460 + out.extLocation = lelb_to_cpu(in.extLocation);
10464 +static inline long_ad cpu_to_lela(long_ad in)
10467 + out.extLength = cpu_to_le32(in.extLength);
10468 + out.extLocation = cpu_to_lelb(in.extLocation);
10472 +static inline extent_ad leea_to_cpu(extent_ad in)
10475 + out.extLength = le32_to_cpu(in.extLength);
10476 + out.extLocation = le32_to_cpu(in.extLocation);
10480 +static inline timestamp cpu_to_lets(timestamp in)
10483 + memcpy(&out, &in, sizeof(timestamp));
10484 + out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone);
10485 + out.year = cpu_to_le16(in.year);
10489 +#endif /* __UDF_ENDIAN_H */
10490 diff -Nru linux/fs/udf/udftime.c linux.new/fs/udf/udftime.c
10491 --- linux/fs/udf/udftime.c Thu Jan 1 01:00:00 1970
10492 +++ linux.new/fs/udf/udftime.c Fri Sep 7 11:32:16 2001
10494 +/* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
10495 + This file is part of the GNU C Library.
10496 + Contributed by Paul Eggert (eggert@twinsun.com).
10498 + The GNU C Library is free software; you can redistribute it and/or
10499 + modify it under the terms of the GNU Library General Public License as
10500 + published by the Free Software Foundation; either version 2 of the
10501 + License, or (at your option) any later version.
10503 + The GNU C Library is distributed in the hope that it will be useful,
10504 + but WITHOUT ANY WARRANTY; without even the implied warranty of
10505 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10506 + Library General Public License for more details.
10508 + You should have received a copy of the GNU Library General Public
10509 + License along with the GNU C Library; see the file COPYING.LIB. If not,
10510 + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
10511 + Boston, MA 02111-1307, USA. */
10514 + * dgb 10/02/98: ripped this from glibc source to help convert timestamps to unix time
10515 + * 10/04/98: added new table-based lookup after seeing how ugly the gnu code is
10516 + * blf 09/27/99: ripped out all the old code and inserted new table from
10517 + * John Brockmeyer (without leap second corrections)
10518 + * rewrote udf_stamp_to_time and fixed timezone accounting in
10519 + udf_time_to_stamp.
10523 + * We don't take into account leap seconds. This may be correct or incorrect.
10524 + * For more NIST information (especially dealing with leap seconds), see:
10525 + * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm
10528 +#if defined(__linux__) && defined(__KERNEL__)
10529 +#include <linux/types.h>
10530 +#include <linux/kernel.h>
10532 +#include <stdio.h>
10533 +#include <sys/types.h>
10534 +#include <sys/time.h>
10537 +#include "udfdecl.h"
10539 +#define EPOCH_YEAR 1970
10542 +/* Nonzero if YEAR is a leap year (every 4 years,
10543 + except every 100th isn't, and every 400th is). */
10544 +#define __isleap(year) \
10545 + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
10548 +/* How many days come before each month (0-12). */
10549 +const unsigned short int __mon_yday[2][13] =
10551 + /* Normal years. */
10552 + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
10553 + /* Leap years. */
10554 + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
10557 +#define MAX_YEAR_SECONDS 69
10558 +#define SPD 0x15180 /*3600*24*/
10559 +#define SPY(y,l,s) (SPD * (365*y+l)+s)
10561 +time_t year_seconds[MAX_YEAR_SECONDS]= {
10562 +/*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0),
10563 +/*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0),
10564 +/*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0),
10565 +/*1982*/ SPY(12, 3,0), SPY(13, 3,0), SPY(14, 3,0), SPY(15, 4,0),
10566 +/*1986*/ SPY(16, 4,0), SPY(17, 4,0), SPY(18, 4,0), SPY(19, 5,0),
10567 +/*1990*/ SPY(20, 5,0), SPY(21, 5,0), SPY(22, 5,0), SPY(23, 6,0),
10568 +/*1994*/ SPY(24, 6,0), SPY(25, 6,0), SPY(26, 6,0), SPY(27, 7,0),
10569 +/*1998*/ SPY(28, 7,0), SPY(29, 7,0), SPY(30, 7,0), SPY(31, 8,0),
10570 +/*2002*/ SPY(32, 8,0), SPY(33, 8,0), SPY(34, 8,0), SPY(35, 9,0),
10571 +/*2006*/ SPY(36, 9,0), SPY(37, 9,0), SPY(38, 9,0), SPY(39,10,0),
10572 +/*2010*/ SPY(40,10,0), SPY(41,10,0), SPY(42,10,0), SPY(43,11,0),
10573 +/*2014*/ SPY(44,11,0), SPY(45,11,0), SPY(46,11,0), SPY(47,12,0),
10574 +/*2018*/ SPY(48,12,0), SPY(49,12,0), SPY(50,12,0), SPY(51,13,0),
10575 +/*2022*/ SPY(52,13,0), SPY(53,13,0), SPY(54,13,0), SPY(55,14,0),
10576 +/*2026*/ SPY(56,14,0), SPY(57,14,0), SPY(58,14,0), SPY(59,15,0),
10577 +/*2030*/ SPY(60,15,0), SPY(61,15,0), SPY(62,15,0), SPY(63,16,0),
10578 +/*2034*/ SPY(64,16,0), SPY(65,16,0), SPY(66,16,0), SPY(67,17,0),
10579 +/*2038*/ SPY(68,17,0)
10583 +extern struct timezone sys_tz;
10586 +#define SECS_PER_HOUR (60 * 60)
10587 +#define SECS_PER_DAY (SECS_PER_HOUR * 24)
10590 +udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
10593 + Uint8 type = src.typeAndTimezone >> 12;
10598 + offset = src.typeAndTimezone << 4;
10599 + /* sign extent offset */
10600 + offset = (offset >> 4);
10605 + if ((src.year < EPOCH_YEAR) ||
10606 + (src.year > EPOCH_YEAR+MAX_YEAR_SECONDS))
10612 + *dest = year_seconds[src.year - EPOCH_YEAR];
10613 + *dest -= offset * 60;
10615 + yday = ((__mon_yday[__isleap (src.year)]
10616 + [src.month-1]) + (src.day-1));
10617 + *dest += ( ( (yday* 24) + src.hour ) * 60 + src.minute ) * 60 + src.second;
10618 + *dest_usec = src.centiseconds * 10000 + src.hundredsOfMicroseconds * 100 + src.microseconds;
10624 +udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
10626 + long int days, rem, y;
10627 + const unsigned short int *ip;
10629 +#ifndef __KERNEL__
10630 + struct timeval tv;
10631 + struct timezone sys_tz;
10633 + gettimeofday(&tv, &sys_tz);
10635 + offset = -sys_tz.tz_minuteswest;
10640 + dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
10642 + tv_sec += offset * 60;
10643 + days = tv_sec / SECS_PER_DAY;
10644 + rem = tv_sec % SECS_PER_DAY;
10645 + dest->hour = rem / SECS_PER_HOUR;
10646 + rem %= SECS_PER_HOUR;
10647 + dest->minute = rem / 60;
10648 + dest->second = rem % 60;
10651 +#define DIV(a,b) ((a) / (b) - ((a) % (b) < 0))
10652 +#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
10654 + while (days < 0 || days >= (__isleap(y) ? 366 : 365))
10656 + long int yg = y + days / 365 - (days % 365 < 0);
10658 + /* Adjust DAYS and Y to match the guessed year. */
10659 + days -= ((yg - y) * 365
10660 + + LEAPS_THRU_END_OF (yg - 1)
10661 + - LEAPS_THRU_END_OF (y - 1));
10665 + ip = __mon_yday[__isleap(y)];
10666 + for (y = 11; days < (long int) ip[y]; --y)
10669 + dest->month = y + 1;
10670 + dest->day = days + 1;
10672 + dest->centiseconds = tv_usec / 10000;
10673 + dest->hundredsOfMicroseconds = (tv_usec - dest->centiseconds * 10000) / 100;
10674 + dest->microseconds = (tv_usec - dest->centiseconds * 10000 -
10675 + dest->hundredsOfMicroseconds * 100);
10680 diff -Nru linux/fs/udf/unicode.c linux.new/fs/udf/unicode.c
10681 --- linux/fs/udf/unicode.c Thu Jan 1 01:00:00 1970
10682 +++ linux.new/fs/udf/unicode.c Fri Sep 7 11:32:16 2001
10688 + * Routines for converting between UTF-8 and OSTA Compressed Unicode.
10689 + * Also handles filename mangling
10692 + * OSTA Compressed Unicode is explained in the OSTA UDF specification.
10693 + * http://www.osta.org/
10694 + * UTF-8 is explained in the IETF RFC XXXX.
10695 + * ftp://ftp.internic.net/rfc/rfcxxxx.txt
10698 + * E-mail regarding any portion of the Linux UDF file system should be
10699 + * directed to the development team's mailing list (run by majordomo):
10700 + * linux_udf@hootie.lvld.hp.com
10703 + * This file is distributed under the terms of the GNU General Public
10704 + * License (GPL). Copies of the GPL can be obtained from:
10705 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
10706 + * Each contributing author retains all rights to their own work.
10711 +#include <linux/kernel.h>
10712 +#include <linux/string.h> /* for memset */
10713 +#include <linux/udf_fs.h>
10715 +#include <string.h>
10718 +#include "udfdecl.h"
10720 +int udf_ustr_to_dchars(Uint8 *dest, const struct ustr *src, int strlen)
10722 + if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
10724 + memcpy(dest+1, src->u_name, src->u_len);
10725 + dest[0] = src->u_cmpID;
10726 + return src->u_len + 1;
10729 +int udf_ustr_to_char(Uint8 *dest, const struct ustr *src, int strlen)
10731 + if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
10733 + memcpy(dest, src->u_name, src->u_len);
10734 + return src->u_len;
10737 +int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
10739 + if ( udf_ustr_to_dchars(dest, src, dlength-1) )
10741 + dest[dlength-1] = src->u_len + 1;
10748 +int udf_dchars_to_ustr(struct ustr *dest, const Uint8 *src, int strlen)
10750 + if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
10752 + memset(dest, 0, sizeof(struct ustr));
10753 + memcpy(dest->u_name, src+1, strlen-1);
10754 + dest->u_cmpID = src[0];
10755 + dest->u_len = strlen-1;
10759 +int udf_char_to_ustr(struct ustr *dest, const Uint8 *src, int strlen)
10761 + if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
10763 + memset(dest, 0, sizeof(struct ustr));
10764 + memcpy(dest->u_name, src, strlen);
10765 + dest->u_cmpID = 0x08;
10766 + dest->u_len = strlen;
10771 +int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
10773 + if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
10782 +int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
10786 + if ( (!dest) || (!ptr) || (!size) )
10789 + memset(dest, 0, sizeof(struct ustr));
10790 + usesize= (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
10791 + dest->u_cmpID=ptr[0];
10792 + dest->u_len=ptr[size-1];
10793 + memcpy(dest->u_name, ptr+1, usesize-1);
10798 + * udf_build_ustr_exact
10800 +int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
10802 + if ( (!dest) || (!ptr) || (!exactsize) )
10805 + memset(dest, 0, sizeof(struct ustr));
10806 + dest->u_cmpID=ptr[0];
10807 + dest->u_len=exactsize-1;
10808 + memcpy(dest->u_name, ptr+1, exactsize-1);
10813 + * udf_ocu_to_udf8
10816 + * Convert OSTA Compressed Unicode to the UTF-8 equivalent.
10819 + * This routine is only called by udf_filldir().
10822 + * utf Pointer to UTF-8 output buffer.
10823 + * ocu Pointer to OSTA Compressed Unicode input buffer
10824 + * of size UDF_NAME_LEN bytes.
10825 + * both of type "struct ustr *"
10827 + * POST-CONDITIONS
10828 + * <return> Zero on success.
10831 + * November 12, 1997 - Andrew E. Mileski
10832 + * Written, tested, and released.
10834 +int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
10838 + Uint8 cmp_id, ocu_len;
10841 + ocu = ocu_i->u_name;
10843 + ocu_len = ocu_i->u_len;
10844 + cmp_id = ocu_i->u_cmpID;
10845 + utf_o->u_len = 0;
10847 + if (ocu_len == 0)
10849 + memset(utf_o, 0, sizeof(struct ustr));
10850 + utf_o->u_cmpID = 0;
10851 + utf_o->u_len = 0;
10855 + if ((cmp_id != 8) && (cmp_id != 16))
10858 + printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", cmp_id, ocu_i->u_name);
10863 + for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN-3)) ;)
10866 + /* Expand OSTA compressed Unicode to Unicode */
10868 + if (cmp_id == 16)
10869 + c = (c << 8) | ocu[i++];
10871 + /* Compress Unicode to UTF-8 */
10873 + utf_o->u_name[utf_o->u_len++] = (Uint8)c;
10874 + else if (c < 0x800U)
10876 + utf_o->u_name[utf_o->u_len++] = (Uint8)(0xc0 | (c >> 6));
10877 + utf_o->u_name[utf_o->u_len++] = (Uint8)(0x80 | (c & 0x3f));
10881 + utf_o->u_name[utf_o->u_len++] = (Uint8)(0xe0 | (c >> 12));
10882 + utf_o->u_name[utf_o->u_len++] = (Uint8)(0x80 | ((c >> 6) & 0x3f));
10883 + utf_o->u_name[utf_o->u_len++] = (Uint8)(0x80 | (c & 0x3f));
10886 + utf_o->u_cmpID=8;
10887 + utf_o->u_hash=0L;
10888 + utf_o->padding=0;
10890 + return utf_o->u_len;
10895 + * udf_utf8_to_ocu
10898 + * Convert UTF-8 to the OSTA Compressed Unicode equivalent.
10901 + * This routine is only called by udf_lookup().
10904 + * ocu Pointer to OSTA Compressed Unicode output
10905 + * buffer of size UDF_NAME_LEN bytes.
10906 + * utf Pointer to UTF-8 input buffer.
10907 + * utf_len Length of UTF-8 input buffer in bytes.
10909 + * POST-CONDITIONS
10910 + * <return> Zero on success.
10913 + * November 12, 1997 - Andrew E. Mileski
10914 + * Written, tested, and released.
10916 +int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
10918 + unsigned c, i, max_val, utf_char;
10922 + memset(ocu, 0, sizeof(dstring) * length);
10929 + for (i = 0U; i < utf->u_len; i++)
10931 + c = (Uint8)utf->u_name[i];
10933 + /* Complete a multi-byte UTF-8 character */
10936 + utf_char = (utf_char << 6) | (c & 0x3fU);
10942 + /* Check for a multi-byte UTF-8 character */
10945 + /* Start a multi-byte UTF-8 character */
10946 + if ((c & 0xe0U) == 0xc0U)
10948 + utf_char = c & 0x1fU;
10951 + else if ((c & 0xf0U) == 0xe0U)
10953 + utf_char = c & 0x0fU;
10956 + else if ((c & 0xf8U) == 0xf0U)
10958 + utf_char = c & 0x07U;
10961 + else if ((c & 0xfcU) == 0xf8U)
10963 + utf_char = c & 0x03U;
10966 + else if ((c & 0xfeU) == 0xfcU)
10968 + utf_char = c & 0x01U;
10975 + /* Single byte UTF-8 character (most common) */
10979 + /* Choose no compression if necessary */
10980 + if (utf_char > max_val)
10982 + if ( 0xffU == max_val )
10984 + max_val = 0xffffU;
10985 + ocu[0] = (Uint8)0x10U;
10991 + if (max_val == 0xffffU)
10993 + ocu[++u_len] = (Uint8)(utf_char >> 8);
10995 + ocu[++u_len] = (Uint8)(utf_char & 0xffU);
11003 + printk(KERN_ERR "udf: bad UTF-8 character\n");
11008 + ocu[length - 1] = (Uint8)u_len + 1;
11009 + return u_len + 1;
11013 +int udf_get_filename(Uint8 *sname, Uint8 *dname, int flen)
11015 + struct ustr filename, unifilename;
11018 + if (udf_build_ustr_exact(&unifilename, sname, flen))
11023 + if (!udf_CS0toUTF8(&filename, &unifilename) )
11025 + udf_debug("Failed in udf_get_filename: sname = %s\n", sname);
11029 + if ((len = udf_translate_to_linux(dname, filename.u_name, filename.u_len,
11030 + unifilename.u_name, unifilename.u_len)))
11038 +#define ILLEGAL_CHAR_MARK '_'
11039 +#define EXT_MARK '.'
11040 +#define CRC_MARK '#'
11041 +#define EXT_SIZE 5
11043 +int udf_translate_to_linux(Uint8 *newName, Uint8 *udfName, int udfLen, Uint8 *fidName, int fidNameLen)
11045 + int index, newIndex = 0, needsCRC = 0;
11046 + int extIndex = 0, newExtIndex = 0, hasExt = 0;
11047 + unsigned short valueCRC;
11049 + const Uint8 hexChar[] = "0123456789ABCDEF";
11051 + if (udfName[0] == '.' && (udfLen == 1 ||
11052 + (udfLen == 2 && udfName[1] == '.')))
11055 + newIndex = udfLen;
11056 + memcpy(newName, udfName, udfLen);
11060 + for (index = 0; index < udfLen; index++)
11062 + curr = udfName[index];
11063 + if (curr == '/' || curr == 0)
11066 + curr = ILLEGAL_CHAR_MARK;
11067 + while (index+1 < udfLen && (udfName[index+1] == '/' ||
11068 + udfName[index+1] == 0))
11071 + if (curr == EXT_MARK && (udfLen - index - 1) <= EXT_SIZE)
11073 + if (udfLen == index + 1)
11078 + extIndex = index;
11079 + newExtIndex = newIndex;
11082 + if (newIndex < 256)
11083 + newName[newIndex++] = curr;
11090 + Uint8 ext[EXT_SIZE];
11091 + int localExtIndex = 0;
11095 + int maxFilenameLen;
11096 + for(index = 0; index<EXT_SIZE && extIndex + index +1 < udfLen;
11099 + curr = udfName[extIndex + index + 1];
11101 + if (curr == '/' || curr == 0)
11104 + curr = ILLEGAL_CHAR_MARK;
11105 + while(extIndex + index + 2 < udfLen && (index + 1 < EXT_SIZE
11106 + && (udfName[extIndex + index + 2] == '/' ||
11107 + udfName[extIndex + index + 2] == 0)))
11110 + ext[localExtIndex++] = curr;
11112 + maxFilenameLen = 250 - localExtIndex;
11113 + if (newIndex > maxFilenameLen)
11114 + newIndex = maxFilenameLen;
11116 + newIndex = newExtIndex;
11118 + else if (newIndex > 250)
11120 + newName[newIndex++] = CRC_MARK;
11121 + valueCRC = udf_crc(fidName, fidNameLen, 0);
11122 + newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
11123 + newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
11124 + newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
11125 + newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
11129 + newName[newIndex++] = EXT_MARK;
11130 + for (index = 0;index < localExtIndex ;index++ )
11131 + newName[newIndex++] = ext[index];
11136 diff -Nru linux/include/linux/fs.h linux.new/include/linux/fs.h
11137 --- linux/include/linux/fs.h Fri Sep 7 11:17:46 2001
11138 +++ linux.new/include/linux/fs.h Fri Sep 7 11:37:56 2001
11139 @@ -286,6 +286,7 @@
11140 #include <linux/hfs_fs_i.h>
11141 #include <linux/adfs_fs_i.h>
11142 #include <linux/qnx4_fs_i.h>
11143 +#include <linux/udf_fs_i.h>
11144 #include <linux/reiserfs_fs_i.h>
11145 #include <linux/usbdev_fs_i.h>
11146 #include <linux/beos_fs_i.h>
11147 @@ -403,6 +404,7 @@
11148 struct hfs_inode_info hfs_i;
11149 struct adfs_inode_info adfs_i;
11150 struct qnx4_inode_info qnx4_i;
11151 + struct udf_inode_info udf_i;
11152 struct reiserfs_inode_info reiserfs_i;
11153 struct usbdev_inode_info usbdev_i;
11154 struct socket socket_i;
11155 @@ -530,6 +532,7 @@
11156 #include <linux/hfs_fs_sb.h>
11157 #include <linux/adfs_fs_sb.h>
11158 #include <linux/qnx4_fs_sb.h>
11159 +#include <linux/udf_fs_sb.h>
11160 #include <linux/reiserfs_fs_sb.h>
11161 #include <linux/usbdev_fs_sb.h>
11162 #include <linux/beos_fs_sb.h>
11163 @@ -576,7 +579,8 @@
11164 struct hfs_sb_info hfs_sb;
11165 struct adfs_sb_info adfs_sb;
11166 struct qnx4_sb_info qnx4_sb;
11167 - struct reiserfs_sb_info reiserfs_sb;
11168 + struct udf_sb_info udf_sb;
11169 + struct reiserfs_sb_info reiserfs_sb;
11170 struct usbdev_sb_info usbdevfs_sb;
11171 struct beos_sb_info beos_sb;
11173 diff -Nru linux/include/linux/udf_167.h linux.new/include/linux/udf_167.h
11174 --- linux/include/linux/udf_167.h Thu Jan 1 01:00:00 1970
11175 +++ linux.new/include/linux/udf_167.h Fri Sep 7 11:32:16 2001
11177 +#if !defined(_LINUX_UDF_167_H)
11178 +#define _LINUX_UDF_167_H
11183 + * Definitions from the ECMA 167 standard.
11184 + * http://www.ecma.ch/
11186 + * These abbreviations are used to keep the symbols short:
11187 + * Alloc Allocation
11188 + * App Application
11190 + * Char Characters
11191 + * Desc Descriptor
11192 + * Descs Descriptors
11194 + * Ident Identifier
11195 + * Imp Implementation
11202 + * Struct Structure
11204 + * The symbols are otherwise identical to the standard, and the
11205 + * sections of the standard to refer to are indicated.
11208 + * E-mail regarding any portion of the Linux UDF file system should be
11209 + * directed to the development team mailing list (run by majordomo):
11210 + * linux_udf@hootie.lvld.hp.com
11213 + * This file is distributed under the terms of the GNU General Public
11214 + * License (GPL). Copies of the GPL can be obtained from:
11215 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
11216 + * Each contributing author retains all rights to their own work.
11219 + * July 12, 1997 - Andrew E. Mileski
11220 + * Adapted from the ECMA-167 standard.
11222 + * 10/2/98 dgb Adaptation
11223 + * 10/4/98 Changes by HJA Sandkuyl
11224 + * 10/7/98 Changed FILE_EXISTENCE to FILE_HIDDEN, per UDF 2.0 spec
11225 + * 11/26/98 Modifed some entries for UDF 1.5/2.0
11226 + * 11/26/98 bf Fixed typos, non-linux types, more structures
11227 + * 12/5/98 dgb Adjusted structure and content of include files.
11231 +#include <linux/types.h>
11232 +#define Uint8 __u8
11233 +#define Sint8 __s8
11234 +#define Uint16 __u16
11235 +#define Sint16 __s16
11236 +#define Uint32 __u32
11237 +#define Sint32 __s32
11238 +#define Uint64 __u64
11239 +#define Sint64 __s64
11240 +typedef Uint8 dstring;
11242 +#define Uint8 unsigned char
11243 +#define Sint8 char
11244 +#define Uint16 unsigned short
11245 +#define Sint16 short
11246 +#define Uint32 unsigned int
11247 +#define Sint32 int
11248 +#define Uint64 unsigned long long
11249 +#define Sint64 long long
11250 +typedef Uint8 dstring;
11253 +/* make sure all structures are packed! */
11256 +/* CS0 Charspec (ECMA 167 1/7.2.1) */
11258 + Uint8 charSetType;
11259 + Uint8 charSetInfo[63];
11262 +/* Timestamp (ECMA 167 1/7.3) */
11264 + Uint16 typeAndTimezone;
11271 + Uint8 centiseconds;
11272 + Uint8 hundredsOfMicroseconds;
11273 + Uint8 microseconds;
11276 +/* Timestamp types (ECMA 167 1/7.3.1) */
11277 +#define TIMESTAMP_TYPE_CUT 0x0000U
11278 +#define TIMESTAMP_TYPE_LOCAL 0x0001U
11279 +#define TIMESTAMP_TYPE_AGREEMENT 0x0002U
11281 +/* Entity Identifier (ECMA 167 1/7.4) */
11285 + Uint8 identSuffix[8];
11287 +#define regid EntityID
11289 +/* Entity identifier flags (ECMA 167 1/7.4.1) */
11290 +#define ENTITYID_FLAGS_DIRTY 0x01U
11291 +#define ENTITYID_FLAGS_PROTECTED 0x02U
11293 +/* Volume Structure Descriptor (ECMA 167 2/9.1) */
11294 +#define STD_ID_LEN 5
11295 +struct VolStructDesc {
11296 + Uint8 structType;
11297 + Uint8 stdIdent[STD_ID_LEN];
11298 + Uint8 structVersion;
11299 + Uint8 structData[2041];
11302 +/* Std structure identifiers (ECMA 167 2/9.1.2) */
11303 +#define STD_ID_BEA01 "BEA01"
11304 +#define STD_ID_BOOT2 "BOOT2"
11305 +#define STD_ID_CD001 "CD001"
11306 +#define STD_ID_CDW02 "CDW02"
11307 +#define STD_ID_NSR02 "NSR02"
11308 +#define STD_ID_NSR03 "NSR03"
11309 +#define STD_ID_TEA01 "TEA01"
11311 +/* Beginning Extended Area Descriptor (ECMA 167 2/9.2) */
11312 +struct BeginningExtendedAreaDesc {
11313 + Uint8 structType;
11314 + Uint8 stdIdent[STD_ID_LEN];
11315 + Uint8 structVersion;
11316 + Uint8 structData[2041];
11319 +/* Terminating Extended Area Descriptor (ECMA 167 2/9.3) */
11320 +struct TerminatingExtendedAreaDesc {
11321 + Uint8 structType;
11322 + Uint8 stdIdent[STD_ID_LEN];
11323 + Uint8 structVersion;
11324 + Uint8 structData[2041];
11327 +/* Boot Descriptor (ECMA 167 2/9.4) */
11329 + Uint8 structType;
11330 + Uint8 stdIdent[STD_ID_LEN];
11331 + Uint8 structVersion;
11333 + EntityID architectureType;
11334 + EntityID bootIdent;
11335 + Uint32 bootExtLocation;
11336 + Uint32 bootExtLength;
11337 + Uint64 loadAddress;
11338 + Uint64 startAddress;
11339 + timestamp descCreationDateAndTime;
11341 + Uint8 reserved2[32];
11342 + Uint8 bootUse[1906];
11345 +/* Boot flags (ECMA 167 2/9.4.12) */
11346 +#define BOOT_FLAGS_ERASE 1
11348 +/* Extent Descriptor (ECMA 167 3/7.1) */
11350 + Uint32 extLength;
11351 + Uint32 extLocation;
11354 +/* Descriptor Tag (ECMA 167 3/7.2) */
11357 + Uint16 descVersion;
11358 + Uint8 tagChecksum;
11360 + Uint16 tagSerialNum;
11362 + Uint16 descCRCLength;
11363 + Uint32 tagLocation;
11366 +/* Tag Identifiers (ECMA 167 3/7.2.1) */
11367 +#define TID_UNUSED_DESC 0x0000U
11368 +#define TID_PRIMARY_VOL_DESC 0x0001U
11369 +#define TID_ANCHOR_VOL_DESC_PTR 0x0002U
11370 +#define TID_VOL_DESC_PTR 0x0003U
11371 +#define TID_IMP_USE_VOL_DESC 0x0004U
11372 +#define TID_PARTITION_DESC 0x0005U
11373 +#define TID_LOGICAL_VOL_DESC 0x0006U
11374 +#define TID_UNALLOC_SPACE_DESC 0x0007U
11375 +#define TID_TERMINATING_DESC 0x0008U
11376 +#define TID_LOGICAL_VOL_INTEGRITY_DESC 0x0009U
11378 +/* Tag Identifiers (ECMA 167 4/7.2.1) */
11379 +#define TID_FILE_SET_DESC 0x0100U
11380 +#define TID_FILE_IDENT_DESC 0x0101U
11381 +#define TID_ALLOC_EXTENT_DESC 0x0102U
11382 +#define TID_INDIRECT_ENTRY 0x0103U
11383 +#define TID_TERMINAL_ENTRY 0x0104U
11384 +#define TID_FILE_ENTRY 0x0105U
11385 +#define TID_EXTENDED_ATTRE_HEADER_DESC 0x0106U
11386 +#define TID_UNALLOCATED_SPACE_ENTRY 0x0107U
11387 +#define TID_SPACE_BITMAP_DESC 0x0108U
11388 +#define TID_PARTITION_INTEGRITY_ENTRY 0x0109U
11389 +#define TID_EXTENDED_FILE_ENTRY 0x010AU
11391 +/* NSR Descriptor (ECMA 167 3/9.1) */
11393 + Uint8 structType;
11394 + Uint8 stdIdent[STD_ID_LEN];
11395 + Uint8 structVersion;
11397 + Uint8 structData[2040];
11400 +/* Primary Volume Descriptor (ECMA 167 3/10.1) */
11401 +struct PrimaryVolDesc {
11403 + Uint32 volDescSeqNum;
11404 + Uint32 primaryVolDescNum;
11405 + dstring volIdent[32];
11406 + Uint16 volSeqNum;
11407 + Uint16 maxVolSeqNum;
11408 + Uint16 interchangeLvl;
11409 + Uint16 maxInterchangeLvl;
11410 + Uint32 charSetList;
11411 + Uint32 maxCharSetList;
11412 + dstring volSetIdent[128];
11413 + charspec descCharSet;
11414 + charspec explanatoryCharSet;
11415 + extent_ad volAbstract;
11416 + extent_ad volCopyright;
11417 + EntityID appIdent;
11418 + timestamp recordingDateAndTime;
11419 + EntityID impIdent;
11420 + Uint8 impUse[64];
11421 + Uint32 predecessorVolDescSeqLocation;
11423 + Uint8 reserved[22];
11426 +/* Primary volume descriptor flags (ECMA 167 3/10.1.21) */
11427 +#define VOL_SET_IDENT 1
11429 +/* Anchor Volume Descriptor Pointer (ECMA 167 3/10.2) */
11430 +struct AnchorVolDescPtr {
11432 + extent_ad mainVolDescSeqExt;
11433 + extent_ad reserveVolDescSeqExt;
11434 + Uint8 reserved[480];
11437 +/* Volume Descriptor Pointer (ECMA 167 3/10.3) */
11438 +struct VolDescPtr {
11440 + Uint32 volDescSeqNum;
11441 + extent_ad nextVolDescSeqExt;
11442 + Uint8 reserved[484];
11445 +/* Implementation Use Volume Descriptor (ECMA 167 3/10.4) */
11446 +struct ImpUseVolDesc {
11448 + Uint32 volDescSeqNum;
11449 + EntityID impIdent;
11450 + Uint8 impUse[460];
11453 +/* Partition Descriptor (ECMA 167 3/10.5) */
11454 +struct PartitionDesc {
11456 + Uint32 volDescSeqNum;
11457 + Uint16 partitionFlags;
11458 + Uint16 partitionNumber;
11459 + EntityID partitionContents;
11460 + Uint8 partitionContentsUse[128];
11461 + Uint32 accessType;
11462 + Uint32 partitionStartingLocation;
11463 + Uint32 partitionLength;
11464 + EntityID impIdent;
11465 + Uint8 impUse[128];
11466 + Uint8 reserved[156];
11469 +/* Partition Flags (ECMA 167 3/10.5.3) */
11470 +#define PARTITION_FLAGS_ALLOC 1
11472 +/* Partition Contents (ECMA 167 3/10.5.5) */
11473 +#define PARTITION_CONTENTS_FDC01 "+FDC01"
11474 +#define PARTITION_CONTENTS_CD001 "+CD001"
11475 +#define PARTITION_CONTENTS_CDW02 "+CDW02"
11476 +#define PARTITION_CONTENTS_NSR02 "+NSR02"
11477 +#define PARTITION_CONTENTS_NSR03 "+NSR03"
11479 +/* Partition Access Types (ECMA 167 3/10.5.7) */
11480 +#define PARTITION_ACCESS_NONE 0
11481 +#define PARTITION_ACCESS_R 1
11482 +#define PARTITION_ACCESS_WO 2
11483 +#define PARTITION_ACCESS_RW 3
11484 +#define PARTITION_ACCESS_OW 4
11486 +/* Logical Volume Descriptor (ECMA 167 3/10.6) */
11487 +struct LogicalVolDesc {
11489 + Uint32 volDescSeqNum;
11490 + charspec descCharSet;
11491 + dstring logicalVolIdent[128];
11492 + Uint32 logicalBlockSize;
11493 + EntityID domainIdent;
11494 + Uint8 logicalVolContentsUse[16]; /* used to find fileset */
11495 + Uint32 mapTableLength;
11496 + Uint32 numPartitionMaps;
11497 + EntityID impIdent;
11498 + Uint8 impUse[128];
11499 + extent_ad integritySeqExt;
11500 + Uint8 partitionMaps[0];
11503 +/* Generic Partition Map (ECMA 167 3/10.7.1) */
11504 +struct GenericPartitionMap {
11505 + Uint8 partitionMapType;
11506 + Uint8 partitionMapLength;
11507 + Uint8 partitionMapping[0];
11510 +/* Partition Map Type (ECMA 167 3/10.7.1.1) */
11511 +#define PARTITION_MAP_TYPE_NONE 0
11512 +#define PARTITION_MAP_TYPE_1 1
11513 +#define PARTITION_MAP_TYPE_2 2
11515 +/* Type 1 Partition Map (ECMA 167 3/10.7.2) */
11516 +struct GenericPartitionMap1 {
11517 + Uint8 partitionMapType;
11518 + Uint8 partitionMapLength;
11519 + Uint16 volSeqNum;
11520 + Uint16 partitionNum;
11523 +/* Type 2 Partition Map (ECMA 167 3/10.7.3) */
11524 +struct GenericPartitionMap2 {
11525 + Uint8 partitionMapType; /* 2 */
11526 + Uint8 partitionMapLength;
11527 + Uint8 partitionIdent[62];
11530 +/* Unallocated Space Descriptor (ECMA 167 3/10.8) */
11531 +struct UnallocatedSpaceDesc {
11533 + Uint32 volDescSeqNum;
11534 + Uint32 numAllocDescs;
11535 + extent_ad allocDescs[0];
11538 +/* Terminating Descriptor (ECMA 3/10.9) */
11539 +struct TerminatingDesc {
11541 + Uint8 reserved[496];
11544 +struct GenericDesc
11547 + Uint32 volDescSeqNum;
11550 +/* Logical Volume Integrity Descriptor (ECMA 167 3/10.10) */
11551 +struct LogicalVolIntegrityDesc {
11553 + timestamp recordingDateAndTime;
11554 + Uint32 integrityType;
11555 + extent_ad nextIntegrityExt;
11556 + Uint8 logicalVolContentsUse[32];
11557 + Uint32 numOfPartitions;
11558 + Uint32 lengthOfImpUse;
11559 + Uint32 freeSpaceTable[0];
11560 + Uint32 sizeTable[0];
11564 +/* Integrity Types (ECMA 167 3/10.10.3) */
11565 +#define INTEGRITY_TYPE_OPEN 0
11566 +#define INTEGRITY_TYPE_CLOSE 1
11568 +/* Recorded Address (ECMA 167 4/7.1) */
11570 + Uint32 logicalBlockNum;
11571 + Uint16 partitionReferenceNum;
11574 +/* Extent interpretation (ECMA 167 4/14.14.1.1) */
11575 +#define EXTENT_RECORDED_ALLOCATED 0x00
11576 +#define EXTENT_NOT_RECORDED_ALLOCATED 0x01
11577 +#define EXTENT_NOT_RECORDED_NOT_ALLOCATED 0x02
11578 +#define EXTENT_NEXT_EXTENT_ALLOCDECS 0x03
11580 +/* Long Allocation Descriptor (ECMA 167 4/14.14.2) */
11582 + Uint32 extLength;
11583 + lb_addr extLocation;
11586 + /* upper 2 bits of extLength indicate type */
11588 +/* File Set Descriptor (ECMA 167 4/14.1) */
11589 +struct FileSetDesc {
11591 + timestamp recordingDateAndTime;
11592 + Uint16 interchangeLvl;
11593 + Uint16 maxInterchangeLvl;
11594 + Uint32 charSetList;
11595 + Uint32 maxCharSetList;
11596 + Uint32 fileSetNum;
11597 + Uint32 fileSetDescNum;
11598 + charspec logicalVolIdentCharSet;
11599 + dstring logicalVolIdent[128];
11600 + charspec fileSetCharSet;
11601 + dstring fileSetIdent[32];
11602 + dstring copyrightFileIdent[32];
11603 + dstring abstractFileIdent[32];
11604 + long_ad rootDirectoryICB;
11605 + EntityID domainIdent;
11607 + long_ad streamDirectoryICB;
11608 + Uint8 reserved[32];
11611 +/* Short Allocation Descriptor (ECMA 167 4/14.14.1) */
11613 + Uint32 extLength;
11614 + Uint32 extPosition;
11617 +/* Partition Header Descriptor (ECMA 167 4/14.3) */
11618 +struct PartitionHeaderDesc {
11619 + short_ad unallocatedSpaceTable;
11620 + short_ad unallocatedSpaceBitmap;
11621 + short_ad partitionIntegrityTable;
11622 + short_ad freedSpaceTable;
11623 + short_ad freedSpaceBitmap;
11624 + Uint8 reserved[88];
11627 +/* File Identifier Descriptor (ECMA 167 4/14.4) */
11628 +struct FileIdentDesc
11631 + Uint16 fileVersionNum; /* 1 */
11632 + Uint8 fileCharacteristics;
11633 + Uint8 lengthFileIdent;
11635 + Uint16 lengthOfImpUse;
11637 + Uint8 fileIdent[0];
11638 + Uint8 padding[0];
11641 +/* File Characteristics (ECMA 167 4/14.4.3) */
11642 +#define FILE_HIDDEN 1
11643 +#define FILE_DIRECTORY 2
11644 +#define FILE_DELETED 4
11645 +#define FILE_PARENT 8
11646 +#define FILE_METADATA 0x10 /* UDF 2.0 */
11648 +/* Allocation Ext Descriptor (ECMA 167 4/14.5) */
11649 +struct AllocExtDesc
11652 + Uint32 previousAllocExtLocation;
11653 + Uint32 lengthAllocDescs;
11656 +/* ICB Tag (ECMA 167 4/14.6) */
11658 + Uint32 priorRecordedNumDirectEntries;
11659 + Uint16 strategyType;
11660 + Uint16 strategyParameter;
11661 + Uint16 numEntries;
11664 + lb_addr parentICBLocation;
11668 +/* ICB File Type (ECMA 167 4/14.6.6) */
11669 +#define FILE_TYPE_NONE 0x00U
11670 +#define FILE_TYPE_UNALLOC 0x01U
11671 +#define FILE_TYPE_INTEGRITY 0x02U
11672 +#define FILE_TYPE_INDIRECT 0x03U
11673 +#define FILE_TYPE_DIRECTORY 0x04U
11674 +#define FILE_TYPE_REGULAR 0x05U
11675 +#define FILE_TYPE_BLOCK 0x06U
11676 +#define FILE_TYPE_CHAR 0x07U
11677 +#define FILE_TYPE_EXTENDED 0x08U
11678 +#define FILE_TYPE_FIFO 0x09U
11679 +#define FILE_TYPE_SOCKET 0x0aU
11680 +#define FILE_TYPE_TERMINAL 0x0bU
11681 +#define FILE_TYPE_SYMLINK 0x0cU
11682 +#define FILE_TYPE_STREAMDIR 0x0dU /* ECMA 167 4/13 */
11684 +/* ICB Flags (ECMA 167 4/14.6.8) */
11685 +#define ICB_FLAG_ALLOC_MASK 0x0007U
11686 +#define ICB_FLAG_SORTED 0x0008U
11687 +#define ICB_FLAG_NONRELOCATABLE 0x0010U
11688 +#define ICB_FLAG_ARCHIVE 0x0020U
11689 +#define ICB_FLAG_SETUID 0x0040U
11690 +#define ICB_FLAG_SETGID 0x0080U
11691 +#define ICB_FLAG_STICKY 0x0100U
11692 +#define ICB_FLAG_CONTIGUOUS 0x0200U
11693 +#define ICB_FLAG_SYSTEM 0x0400U
11694 +#define ICB_FLAG_TRANSFORMED 0x0800U
11695 +#define ICB_FLAG_MULTIVERSIONS 0x1000U
11697 +/* ICB Flags Allocation type(ECMA 167 4/14.6.8) */
11698 +#define ICB_FLAG_AD_SHORT 0
11699 +#define ICB_FLAG_AD_LONG 1
11700 +#define ICB_FLAG_AD_EXTENDED 2
11701 +#define ICB_FLAG_AD_IN_ICB 3
11703 +/* Indirect Entry (ECMA 167 4/14.7) */
11704 +struct IndirectEntry {
11707 + long_ad indirectICB;
11710 +/* Terminal Entry (ECMA 167 4/14.8) */
11711 +struct TerminalEntry {
11716 +/* File Entry (ECMA 167 4/14.9) */
11717 +struct FileEntry {
11722 + Uint32 permissions;
11723 + Uint16 fileLinkCount;
11724 + Uint8 recordFormat;
11725 + Uint8 recordDisplayAttr;
11726 + Uint32 recordLength;
11727 + Uint64 informationLength;
11728 + Uint64 logicalBlocksRecorded;
11729 + timestamp accessTime;
11730 + timestamp modificationTime;
11731 + timestamp attrTime;
11732 + Uint32 checkpoint;
11733 + long_ad extendedAttrICB;
11734 + EntityID impIdent;
11735 + Uint64 uniqueID; /* 0= root, 16- (2^32-1) */
11736 + Uint32 lengthExtendedAttr;
11737 + Uint32 lengthAllocDescs;
11738 + Uint8 extendedAttr[0];
11739 + Uint8 allocDescs[0];
11742 +/* File Permissions (ECMA 167 4/14.9.5) */
11743 +#define PERM_O_EXEC 0x00000001U
11744 +#define PERM_O_WRITE 0x00000002U
11745 +#define PERM_O_READ 0x00000004U
11746 +#define PERM_O_CHATTR 0x00000008U
11747 +#define PERM_O_DELETE 0x00000010U
11748 +#define PERM_G_EXEC 0x00000020U
11749 +#define PERM_G_WRITE 0x00000040U
11750 +#define PERM_G_READ 0x00000080U
11751 +#define PERM_G_CHATTR 0x00000100U
11752 +#define PERM_G_DELETE 0x00000200U
11753 +#define PERM_U_EXEC 0x00000400U
11754 +#define PERM_U_WRITE 0x00000800U
11755 +#define PERM_U_READ 0x00001000U
11756 +#define PERM_U_CHATTR 0x00002000U
11757 +#define PERM_U_DELETE 0x00004000U
11759 +/* File Record Format (ECMA 167 4/14.9.7) */
11760 +#define RECORD_FMT_NONE 0
11761 +#define RECORD_FMT_FIXED_PAD 1
11762 +#define RECORD_FMT_FIXED 2
11763 +#define RECORD_FMT_VARIABLE8 3
11764 +#define RECORD_FMT_VARIABLE16 4
11765 +#define RECORD_FMT_VARIABLE16_MSB 5
11766 +#define RECORD_FMT_VARIABLE32 6
11767 +#define RECORD_FMT_PRINT 7
11768 +#define RECORD_FMT_LF 8
11769 +#define RECORD_FMT_CR 9
11770 +#define RECORD_FMT_CRLF 10
11771 +#define RECORD_FMT_LFCR 10
11773 +/* Extended Attribute Header Descriptor (ECMA 167 4/14.10.1) */
11774 +struct ExtendedAttrHeaderDesc {
11776 + Uint32 impAttrLocation;
11777 + Uint32 appAttrLocation;
11780 +/* Generic Attribute Format (ECMA 4/14.10.2) */
11781 +struct GenericAttrFormat {
11783 + Uint8 attrSubtype;
11784 + Uint8 reserved[3];
11785 + Uint32 attrLength;
11786 + Uint8 attrData[0];
11789 +/* Character Set Attribute Format (ECMA 4/14.10.3) */
11790 +struct CharSetAttrFormat {
11791 + Uint32 attrType; /* 1 */
11792 + Uint8 attrSubtype; /* 1 */
11793 + Uint8 reserved[3];
11794 + Uint32 attrLength;
11795 + Uint32 escapeSeqLength;
11796 + Uint8 charSetType;
11797 + Uint8 escapeSeq[0];
11800 +/* Alternate Permissions (ECMA 167 4/14.10.4) */
11801 +struct AlternatePermissionsExtendedAttr {
11802 + Uint32 attrType; /* 3 */
11803 + Uint8 attrSubtype; /* 1 */
11804 + Uint8 reserved[3];
11805 + Uint32 attrLength;
11806 + Uint16 ownerIdent;
11807 + Uint16 groupIdent;
11808 + Uint16 permission;
11811 +/* File Times Extended Attribute (ECMA 167 4/14.10.5) */
11812 +struct FileTimesExtendedAttr {
11813 + Uint32 attrType; /* 5 */
11814 + Uint8 attrSubtype; /* 1 */
11815 + Uint8 reserved[3];
11816 + Uint32 attrLength;
11817 + Uint32 dataLength;
11818 + Uint32 fileTimeExistence;
11822 +/* FileTimeExistence (ECMA 167 4/14.10.5.6) */
11823 +#define FTE_CREATION 0
11824 +#define FTE_DELETION 2
11825 +#define FTE_EFFECTIVE 3
11826 +#define FTE_BACKUP 5
11828 +/* Information Times Extended Attribute (ECMA 167 4/14.10.6) */
11829 +struct InfoTimesExtendedAttr {
11830 + Uint32 attrType; /* 6 */
11831 + Uint8 attrSubtype; /* 1 */
11832 + Uint8 reserved[3];
11833 + Uint32 attrLength;
11834 + Uint32 dataLength;
11835 + Uint32 infoTimeExistence;
11836 + Uint8 infoTimes[0];
11839 +/* Device Specification Extended Attribute (ECMA 167 4/14.10.7) */
11840 +struct DeviceSpecificationExtendedAttr {
11841 + Uint32 attrType; /* 12 */
11842 + Uint8 attrSubtype; /* 1 */
11843 + Uint8 reserved[3];
11844 + Uint32 attrLength;
11845 + Uint32 impUseLength;
11846 + Uint32 majorDeviceIdent;
11847 + Uint32 minorDeviceIdent;
11851 +/* Implementation Use Extended Attr (ECMA 167 4/14.10.8) */
11852 +struct ImpUseExtendedAttr {
11853 + Uint32 attrType; /* 2048 */
11854 + Uint8 attrSubtype; /* 1 */
11855 + Uint8 reserved[3];
11856 + Uint32 attrLength;
11857 + Uint32 impUseLength;
11858 + EntityID impIdent;
11862 +/* Application Use Extended Attribute (ECMA 167 4/14.10.9) */
11863 +struct AppUseExtendedAttr {
11864 + Uint32 attrType; /* 65536 */
11865 + Uint8 attrSubtype; /* 1 */
11866 + Uint8 reserved[3];
11867 + Uint32 attrLength;
11868 + Uint32 appUseLength;
11869 + EntityID appIdent;
11873 +#define EXTATTR_CHAR_SET 1
11874 +#define EXTATTR_ALT_PERMS 3
11875 +#define EXTATTR_FILE_TIMES 5
11876 +#define EXTATTR_INFO_TIMES 6
11877 +#define EXTATTR_DEV_SPEC 12
11878 +#define EXTATTR_IMP_USE 2048
11879 +#define EXTATTR_APP_USE 65536
11882 +/* Unallocated Space Entry (ECMA 167 4/14.11) */
11883 +struct UnallocatedSpaceEntry {
11886 + Uint32 lengthAllocDescs;
11887 + Uint8 allocDescs[0];
11890 +/* Space Bitmap Descriptor (ECMA 167 4/14.12) */
11891 +struct SpaceBitmapDesc {
11893 + Uint32 numOfBits;
11894 + Uint32 numOfBytes;
11898 +/* Partition Integrity Entry (ECMA 167 4/14.13) */
11899 +struct PartitionIntegrityEntry {
11902 + timestamp recordingDateAndTime;
11903 + Uint8 integrityType;
11904 + Uint8 reserved[175];
11905 + EntityID impIdent;
11906 + Uint8 impUse[256];
11909 +/* Extended Allocation Descriptor (ECMA 167 4/14.14.3) */
11910 +typedef struct { /* ECMA 167 4/14.14.3 */
11911 + Uint32 extLength;
11912 + Uint32 recordedLength;
11913 + Uint32 informationLength;
11914 + lb_addr extLocation;
11917 +/* Logical Volume Header Descriptor (ECMA 167 4/14.5) */
11918 +struct LogicalVolHeaderDesc {
11920 + Uint8 reserved[24];
11923 +/* Path Component (ECMA 167 4/14.16.1) */
11924 +struct PathComponent {
11925 + Uint8 componentType;
11926 + Uint8 lengthComponentIdent;
11927 + Uint16 componentFileVersionNum;
11928 + dstring componentIdent[0];
11931 +/* File Entry (ECMA 167 4/14.17) */
11932 +struct ExtendedFileEntry {
11937 + Uint32 permissions;
11938 + Uint16 fileLinkCount;
11939 + Uint8 recordFormat;
11940 + Uint8 recordDisplayAttr;
11941 + Uint32 recordLength;
11942 + Uint64 informationLength;
11943 + Uint64 objectSize;
11944 + Uint64 logicalBlocksRecorded;
11945 + timestamp accessTime;
11946 + timestamp modificationTime;
11947 + timestamp createTime;
11948 + timestamp attrTime;
11949 + Uint32 checkpoint;
11951 + long_ad extendedAttrICB;
11952 + long_ad streamDirectoryICB;
11953 + EntityID impIdent;
11955 + Uint32 lengthExtendedAttr;
11956 + Uint32 lengthAllocDescs;
11957 + Uint8 extendedAttr[0];
11958 + Uint8 allocDescs[0];
11962 +#endif /* !defined(_LINUX_UDF_167_H) */
11963 diff -Nru linux/include/linux/udf_fs.h linux.new/include/linux/udf_fs.h
11964 --- linux/include/linux/udf_fs.h Thu Jan 1 01:00:00 1970
11965 +++ linux.new/include/linux/udf_fs.h Fri Sep 7 11:32:16 2001
11971 + * Included by fs/filesystems.c
11974 + * OSTA-UDF(tm) = Optical Storage Technology Association
11975 + * Universal Disk Format.
11977 + * This code is based on version 2.00 of the UDF specification,
11978 + * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
11979 + * http://www.osta.org/ * http://www.ecma.ch/
11980 + * http://www.iso.org/
11983 + * E-mail regarding any portion of the Linux UDF file system should be
11984 + * directed to the development team mailing list (run by majordomo):
11985 + * linux_udf@hootie.lvld.hp.com
11988 + * This file is distributed under the terms of the GNU General Public
11989 + * License (GPL). Copies of the GPL can be obtained from:
11990 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
11991 + * Each contributing author retains all rights to their own work.
11993 + * (C) 1999-2000 Ben Fennema
11994 + * (C) 1999-2000 Stelias Computing Inc
12000 +#if !defined(_LINUX_UDF_FS_H)
12001 +#define _LINUX_UDF_FS_H
12004 +#define UDF_PREALLOCATE
12005 +#define UDF_DEFAULT_PREALLOC_BLOCKS 8
12007 +#define UDFFS_DATE "2000/05/10"
12008 +#define UDFFS_VERSION "0.9.2.1"
12010 +#define UDFFS_DEBUG
12012 +#ifdef UDFFS_DEBUG
12013 +#define udf_debug(f, a...) \
12015 + printk (KERN_DEBUG "UDF-fs DEBUG (%s, %d): %s: ", \
12016 + __FILE__, __LINE__, __FUNCTION__); \
12017 + printk (## f, ## a); \
12020 +#define udf_debug(f, a...) /**/
12023 +#define udf_info(f, a...) \
12024 + printk (KERN_INFO "UDF-fs INFO " ## f, ## a);
12028 +#ifndef LINUX_VERSION_CODE
12029 +#include <linux/version.h>
12032 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
12033 +extern int init_udf_fs(void);
12034 +#endif /* 2.2.XX */
12036 +#endif /* __KERNEL__ */
12038 +#endif /* !defined(_LINUX_UDF_FS_H) */
12039 diff -Nru linux/include/linux/udf_fs_i.h linux.new/include/linux/udf_fs_i.h
12040 --- linux/include/linux/udf_fs_i.h Thu Jan 1 01:00:00 1970
12041 +++ linux.new/include/linux/udf_fs_i.h Fri Sep 7 11:32:16 2001
12046 + * This file is intended for the Linux kernel/module.
12049 + * E-mail regarding any portion of the Linux UDF file system should be
12050 + * directed to the development team mailing list (run by majordomo):
12051 + * linux_udf@hootie.lvld.hp.com
12054 + * This file is distributed under the terms of the GNU General Public
12055 + * License (GPL). Copies of the GPL can be obtained from:
12056 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
12057 + * Each contributing author retains all rights to their own work.
12060 +#if !defined(_LINUX_UDF_FS_I_H)
12061 +#define _LINUX_UDF_FS_I_H
12065 +#ifndef _LINUX_UDF_167_H
12068 + __u32 logicalBlockNum;
12069 + __u16 partitionReferenceNum;
12073 +struct udf_inode_info
12078 + /* Physical address of inode */
12079 + lb_addr i_location;
12081 + __u32 i_lenEAttr;
12082 + __u32 i_lenAlloc;
12083 + __u32 i_next_alloc_block;
12084 + __u32 i_next_alloc_goal;
12085 + unsigned i_alloc_type : 3;
12086 + unsigned i_extended_fe : 1;
12087 + unsigned i_strat_4096 : 1;
12088 + unsigned i_new_inode : 1;
12089 + unsigned reserved : 26;
12094 +/* exported IOCTLs, we have 'l', 0x40-0x7f */
12096 +#define UDF_GETEASIZE _IOR('l', 0x40, int)
12097 +#define UDF_GETEABLOCK _IOR('l', 0x41, void *)
12098 +#define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
12100 +#endif /* !defined(_LINUX_UDF_FS_I_H) */
12101 diff -Nru linux/include/linux/udf_fs_sb.h linux.new/include/linux/udf_fs_sb.h
12102 --- linux/include/linux/udf_fs_sb.h Thu Jan 1 01:00:00 1970
12103 +++ linux.new/include/linux/udf_fs_sb.h Fri Sep 7 11:32:16 2001
12108 + * This include file is for the Linux kernel/module.
12111 + * E-mail regarding any portion of the Linux UDF file system should be
12112 + * directed to the development team mailing list (run by majordomo):
12113 + * linux_udf@hootie.lvld.hp.com
12116 + * This file is distributed under the terms of the GNU General Public
12117 + * License (GPL). Copies of the GPL can be obtained from:
12118 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
12119 + * Each contributing author retains all rights to their own work.
12122 +#if !defined(_LINUX_UDF_FS_SB_H)
12123 +#define _LINUX_UDF_FS_SB_H
12127 +#define UDF_MAX_BLOCK_LOADED 8
12129 +#define UDF_TYPE1_MAP15 0x1511U
12130 +#define UDF_VIRTUAL_MAP15 0x1512U
12131 +#define UDF_VIRTUAL_MAP20 0x2012U
12132 +#define UDF_SPARABLE_MAP15 0x1522U
12134 +struct udf_sparing_data
12136 + __u32 s_spar_loc[4];
12137 + __u8 s_spar_pshift;
12138 + __u8 s_spar_indexsize;
12139 + __u32 *s_spar_map;
12142 + __u8 *s_spar_remap8;
12143 + __u16 *s_spar_remap16;
12144 + __u32 *s_spar_remap32;
12148 +struct udf_virtual_data
12150 + __u32 s_num_entries;
12151 + __u16 s_start_offset;
12156 + __u32 s_extLength;
12157 + __u32 s_extPosition;
12158 + __u16 s_nr_groups;
12159 + struct buffer_head **s_block_bitmap;
12162 +struct udf_part_map
12166 + struct udf_bitmap *s_bitmap;
12167 + struct inode *s_table;
12171 + struct udf_bitmap *s_bitmap;
12172 + struct inode *s_table;
12174 + __u32 s_partition_root;
12175 + __u32 s_partition_len;
12176 + __u16 s_partition_type;
12177 + __u16 s_partition_num;
12180 + struct udf_sparing_data s_sparing;
12181 + struct udf_virtual_data s_virtual;
12182 + } s_type_specific;
12183 + __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
12184 + __u16 s_volumeseqnum;
12185 + __u16 s_partition_flags;
12190 +struct udf_sb_info
12192 + struct udf_part_map *s_partmaps;
12193 + __u8 s_volident[32];
12195 + /* Overall info */
12196 + __u16 s_partitions;
12197 + __u16 s_partition;
12199 + /* Sector headers */
12201 + __u32 s_anchor[4];
12202 + __u32 s_lastblock;
12204 + struct buffer_head *s_lvidbh;
12206 + /* Default permissions */
12212 + time_t s_recordtime;
12214 + /* Fileset Info */
12215 + __u16 s_serialnum;
12217 + /* highest UDF revision we have recorded to this media */
12220 + /* Miscellaneous flags */
12224 + struct inode *s_vat;
12228 +#endif /* !defined(_LINUX_UDF_FS_SB_H) */
12229 diff -Nru linux/include/linux/udf_udf.h linux.new/include/linux/udf_udf.h
12230 --- linux/include/linux/udf_udf.h Thu Jan 1 01:00:00 1970
12231 +++ linux.new/include/linux/udf_udf.h Fri Sep 7 11:32:16 2001
12233 +#if !defined(_LINUX_UDF_UDF_H)
12234 +#define _LINUX_UDF_UDF_H
12239 + * OSTA-UDF(tm) format specification [based on ECMA 167 standard].
12240 + * http://www.osta.org/
12243 + * E-mail regarding any portion of the Linux UDF file system should be
12244 + * directed to the development team mailing list (run by majordomo):
12245 + * linux_udf@hootie.lvld.hp.com
12248 + * This file is distributed under the terms of the GNU General Public
12249 + * License (GPL). Copies of the GPL can be obtained from:
12250 + * ftp://prep.ai.mit.edu/pub/gnu/GPL
12251 + * Each contributing author retains all rights to their own work.
12254 + * July 1, 1997 - Andrew E. Mileski
12255 + * Written, tested, and released.
12257 + * 10/2/98 dgb changed UDF_ID_DEVELOPER
12258 + * 11/26/98 bf changed UDF_ID_DEVELOPER,
12259 + * 12/5/98 dgb updated include file hierarchy, more UDF definitions
12262 +/* based on ECMA 167 structure definitions */
12263 +#include <linux/udf_167.h>
12267 +/* -------- Basic types and constants ----------- */
12268 +/* UDF character set (UDF 1.50 2.1.2) */
12269 +#define UDF_CHAR_SET_TYPE 0
12270 +#define UDF_CHAR_SET_INFO "OSTA Compressed Unicode"
12272 +#define UDF_ID_DEVELOPER "*Linux UDFFS"
12274 +/* UDF 1.02 2.2.6.4 */
12275 +struct LogicalVolIntegrityDescImpUse
12277 + EntityID impIdent;
12280 + Uint16 minUDFReadRev;
12281 + Uint16 minUDFWriteRev;
12282 + Uint16 maxUDFWriteRev;
12285 +/* UDF 1.02 2.2.7.2 */
12286 +/* LVInformation may be present in ImpUseVolDesc.impUse */
12287 +struct ImpUseVolDescImpUse
12289 + charspec LVICharset;
12290 + dstring logicalVolIdent[128];
12291 + dstring LVInfo1[36];
12292 + dstring LVInfo2[36];
12293 + dstring LVInfo3[36];
12294 + EntityID impIdent;
12295 + Uint8 impUse[128];
12298 +struct UdfPartitionMap2
12300 + Uint8 partitionMapType;
12301 + Uint8 partitionMapLength;
12302 + Uint8 reserved1[2];
12303 + EntityID partIdent;
12304 + Uint16 volSeqNum;
12305 + Uint16 partitionNum;
12306 + Uint8 reserved2[24];
12309 +/* UDF 1.5 2.2.8 */
12310 +struct VirtualPartitionMap
12312 + Uint8 partitionMapType; /* 2 */
12313 + Uint8 partitionMapLength; /* 64 */
12314 + Uint8 reserved1[2]; /* #00 */
12315 + EntityID partIdent;
12316 + Uint16 volSeqNum;
12317 + Uint16 partitionNum;
12318 + Uint8 reserved2[24]; /* #00 */
12321 +/* UDF 1.5 2.2.9 */
12322 +struct SparablePartitionMap
12324 + Uint8 partitionMapType; /* 2 */
12325 + Uint8 partitionMapLength; /* 64 */
12326 + Uint8 reserved1[2]; /* #00 */
12327 + EntityID partIdent; /* Flags = 0 */
12328 + /* Id = UDF_ID_SPARABLE */
12329 + /* IdSuf = 2.1.5.3 */
12330 + Uint16 volSeqNum;
12331 + Uint16 partitionNum;
12332 + Uint16 packetLength; /* 32 */
12333 + Uint8 numSparingTables;
12334 + Uint8 reserved2[1]; /* #00 */
12335 + Uint32 sizeSparingTable;
12336 + Uint32 locSparingTable[4];
12339 +/* DVD Copyright Management Info, see UDF 1.02 3.3.4.5.1.2 */
12340 +/* when ImpUseExtendedAttr.impIdent= "*UDF DVD CGMS Info" */
12341 +struct DVDCopyrightImpUse {
12342 + Uint16 headerChecksum;
12345 + Uint8 protectionSystemInfo[4];
12348 +/* the impUse of long_ad used in AllocDescs - UDF 1.02 2.3.10.1 */
12355 +/* UDF 1.02 2.3.10.1 */
12356 +#define UDF_EXTENT_LENGTH_MASK 0x3FFFFFFF
12357 +#define UDF_EXTENT_FLAG_MASK 0xc0000000
12358 +#define UDF_EXTENT_FLAG_ERASED 0x40000000
12361 + * Important! VirtualAllocationTables are
12362 + * very different between 1.5 and 2.0!
12365 +/* ----------- 1.5 ------------- */
12366 +/* UDF 1.5 2.2.10 */
12367 +#define FILE_TYPE_VAT15 0x0U
12369 +/* UDF 1.5 2.2.10 - VAT layout: */
12370 +struct VirutalAllocationTable15 {
12371 + Uint32 VirtualSector[0];
12373 + Uint32 previousVATICB;
12375 +/* where number of VirtualSector's is (VATSize-36)/4 */
12377 +/* ----------- 2.0 ------------- */
12378 +/* UDF 2.0 2.2.10 */
12379 +#define FILE_TYPE_VAT20 0xf8U
12381 +/* UDF 2.0 2.2.10 (different from 1.5!) */
12382 +struct VirtualAllocationTable20 {
12383 + Uint16 lengthHeader;
12384 + Uint16 lengthImpUse;
12385 + dstring logicalVolIdent[128];
12386 + Uint32 previousVatICBLoc;
12387 + Uint32 numFIDSFiles;
12388 + Uint32 numFIDSDirectories; /* non-parent */
12389 + Uint16 minReadRevision;
12390 + Uint16 minWriteRevision;
12391 + Uint16 maxWriteRevision;
12394 + Uint32 vatEntry[0];
12397 +/* Sparing maps, see UDF 1.5 2.2.11 */
12399 + Uint32 origLocation;
12400 + Uint32 mappedLocation;
12403 +/* sparing maps, see UDF 2.0 2.2.11 */
12404 +struct SparingTable {
12406 + EntityID sparingIdent; /* *UDF Sparing Table */
12407 + Uint16 reallocationTableLen;
12408 + Uint16 reserved; /* #00 */
12409 + Uint32 sequenceNum;
12410 + SparingEntry mapEntry[0];
12413 +/* Entity Identifiers (UDF 1.50 6.1) */
12414 +#define UDF_ID_COMPLIANT "*OSTA UDF Compliant"
12415 +#define UDF_ID_LV_INFO "*UDF LV Info"
12416 +#define UDF_ID_FREE_EA "*UDF FreeEASpace"
12417 +#define UDF_ID_FREE_APP_EA "*UDF FreeAppEASpace"
12418 +#define UDF_ID_DVD_CGMS "*UDF DVD CGMS Info"
12419 +#define UDF_ID_OS2_EA "*UDF OS/2 EA"
12420 +#define UDF_ID_OS2_EA_LENGTH "*UDF OS/2 EALength"
12421 +#define UDF_ID_MAC_VOLUME "*UDF Mac VolumeInfo"
12422 +#define UDF_ID_MAC_FINDER "*UDF Mac FinderInfo"
12423 +#define UDF_ID_MAC_UNIQUE "*UDF Mac UniqueIDTable"
12424 +#define UDF_ID_MAC_RESOURCE "*UDF Mac ResourceFork"
12425 +#define UDF_ID_VIRTUAL "*UDF Virtual Partition"
12426 +#define UDF_ID_SPARABLE "*UDF Sparable Partition"
12427 +#define UDF_ID_ALLOC "*UDF Virtual Alloc Tbl"
12428 +#define UDF_ID_SPARING "*UDF Sparing Table"
12430 +/* Operating System Identifiers (UDF 1.50 6.3) */
12431 +#define UDF_OS_CLASS_UNDEF 0x00U
12432 +#define UDF_OS_CLASS_DOS 0x01U
12433 +#define UDF_OS_CLASS_OS2 0x02U
12434 +#define UDF_OS_CLASS_MAC 0x03U
12435 +#define UDF_OS_CLASS_UNIX 0x04U
12436 +#define UDF_OS_CLASS_WIN95 0x05U
12437 +#define UDF_OS_CLASS_WINNT 0x06U
12438 +#define UDF_OS_ID_UNDEF 0x00U
12439 +#define UDF_OS_ID_DOS 0x00U
12440 +#define UDF_OS_ID_OS2 0x00U
12441 +#define UDF_OS_ID_MAC 0x00U
12442 +#define UDF_OS_ID_UNIX 0x00U
12443 +#define UDF_OS_ID_WIN95 0x00U
12444 +#define UDF_OS_ID_WINNT 0x00U
12445 +#define UDF_OS_ID_AIX 0x01U
12446 +#define UDF_OS_ID_SOLARIS 0x02U
12447 +#define UDF_OS_ID_HPUX 0x03U
12448 +#define UDF_OS_ID_IRIX 0x04U
12449 +#define UDF_OS_ID_LINUX 0x05U
12450 +#define UDF_OS_ID_MKLINUX 0x06U
12451 +#define UDF_OS_ID_FREEBSD 0x07U
12453 +#define UDF_NAME_PAD 4
12454 +#define UDF_NAME_LEN 255
12455 +#define UDF_PATH_LEN 1023
12459 +#endif /* !defined(_LINUX_UDF_FMT_H) */