]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-udf.patch
- added CONFIG_PDC202XXX_FORCE, for new ide drivers
[packages/kernel.git] / kernel-udf.patch
CommitLineData
7416c8cd 1diff -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
4@@ -9538,6 +9538,26 @@
5 like lynx or netscape). Say Y here if you want to be able to read
6 Joliet CDROMs under Linux.
7
8+UDF Filesystem support (EXPERIMENTAL)
9+CONFIG_UDF_FS
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
14+
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.
19+
20+ If unsure, say N.
21+
22+UDF read-write support (FOR TESTING ONLY)
23+CONFIG_UDF_RW
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.
27+
28 fat fs support
29 CONFIG_FAT_FS
30 If you want to use one of the FAT-based filesystems (the MS-DOS,
31diff -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
34@@ -22,6 +22,8 @@
35 - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
36 sysv-fs.txt
37 - info on the SystemV/Coherent filesystem.
38+udf.txt
39+ - info and mount options for the UDF filesystem.
40 ufs.txt
41 - info on the ufs filesystem.
42 umsdos.txt
43diff -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
46@@ -0,0 +1,60 @@
47+*
48+* ./Documentation/filesystems/udf.txt
49+*
50+UDF Filesystem version 0.9.2.1
51+
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
54+developer's list.
55+
56+Write support requires a block driver which supports writing. The current
57+scsi and ide cdrom drivers do not support writing.
58+
59+-------------------------------------------------------------------------------
60+The following mount options are supported:
61+
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)
73+
74+The remaining are for debugging and disaster recovery:
75+
76+ novrs Skip volume sequence recognition
77+
78+The following expect a offset from 0.
79+
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/
85+
86+The following expect a offset from the partition root.
87+
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+-------------------------------------------------------------------------------
93+
94+
95+For more information see:
96+ http://www.trylinux.com/projects/udf/index.html
97+
98+For the latest version and toolset see:
99+ http://www.csc.calpoly.edu/~bfennema/udf.html
100+ http://linux-udf.sourceforge.net/
101+
102+Documentation on UDF and ECMA 167 is available FREE from:
103+ http://www.osta.org/
104+ http://www.ecma.ch/
105+
106+Ben Fennema <bfennema@falcon.csc.calpoly.edu>
107diff -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
110@@ -96,6 +96,8 @@
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
119diff -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
124 S: Maintained
125
126+UDF FILESYSTEM
127+P: Ben Fennema
128+M: bfennema@falcon.csc.calpoly.edu
129+P: Dave Boynton
130+M: dave@trylinux.com
131+L: linux_udf@hootie.lvld.hp.com
132+W: http://www.trylinux.com/projects/udf/index.html
133+S: Maintained
134+
135 UMSDOS FILESYSTEM
136 P: Matija Nalis
137 M: mnalis-umsdos@voyager.hr
138diff -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
141@@ -31,6 +31,13 @@
142 # needed by nls/Config.in
143 define_bool CONFIG_JOLIET n
144 fi
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
149+ fi
150+fi
151+
152
153 tristate 'Minix fs support' CONFIG_MINIX_FS
154 tristate 'NTFS filesystem support (read only)' CONFIG_NTFS_FS
c10d8420
KT
155diff -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
7416c8cd 158@@ -19,7 +19,7 @@
159 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
160 reiserfs \
161 hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd \
c10d8420
KT
162- nfsd nls devpts adfs qnx4 efs
163+ nfsd nls devpts adfs qnx4 udf efs
7416c8cd 164
165 ifeq ($(CONFIG_QUOTA),y)
166 O_OBJS += dquot.o
167@@ -232,6 +232,14 @@
168 endif
169 endif
170
171+ifeq ($(CONFIG_UDF_FS),y)
172+SUB_DIRS += udf
173+else
174+ ifeq ($(CONFIG_UDF_FS),m)
175+ MOD_SUB_DIRS += udf
176+ endif
177+endif
178+
179 ifeq ($(CONFIG_AUTOFS_FS),y)
180 SUB_DIRS += autofs
181 else
182diff -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
185@@ -26,6 +26,7 @@
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>
193@@ -163,6 +164,9 @@
194 init_qnx4_fs();
195 #endif
196
197+#ifdef CONFIG_UDF_FS
198+ init_udf_fs();
199+#endif
200 #ifdef CONFIG_NLS
201 init_nls();
202 #endif
203diff -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
206@@ -0,0 +1,16 @@
207+#
208+# Makefile for the linux udf-filesystem routines.
209+#
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).
213+#
214+# Note 2! The CFLAGS definitions are now in the main makefile..
215+
216+O_TARGET := udf.o
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)
221+
222+include $(TOPDIR)/Rules.make
223diff -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
226@@ -0,0 +1,1008 @@
227+/*
228+ * balloc.c
229+ *
230+ * PURPOSE
231+ * Block allocation handling routines for the OSTA-UDF(tm) filesystem.
232+ *
233+ * CONTACTS
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
237+ *
238+ * COPYRIGHT
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.
243+ *
244+ * (C) 1999-2000 Ben Fennema
245+ * (C) 1999 Stelias Computing Inc
246+ *
247+ * HISTORY
248+ *
249+ * 02/24/99 blf Created.
250+ *
251+ */
252+
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>
258+
259+#include <asm/bitops.h>
260+
261+#include "udf_i.h"
262+#include "udf_sb.h"
263+
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)
269+
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))
273+
274+extern inline int find_next_one_bit (void * addr, int size, int offset)
275+{
276+ unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
277+ unsigned long result = offset & ~(BITS_PER_LONG-1);
278+ unsigned long tmp;
279+
280+ if (offset >= size)
281+ return size;
282+ size -= result;
283+ offset &= (BITS_PER_LONG-1);
284+ if (offset)
285+ {
286+ tmp = leBPL_to_cpup(p++);
287+ tmp &= ~0UL << offset;
288+ if (size < BITS_PER_LONG)
289+ goto found_first;
290+ if (tmp)
291+ goto found_middle;
292+ size -= BITS_PER_LONG;
293+ result += BITS_PER_LONG;
294+ }
295+ while (size & ~(BITS_PER_LONG-1))
296+ {
297+ if ((tmp = leBPL_to_cpup(p++)))
298+ goto found_middle;
299+ result += BITS_PER_LONG;
300+ size -= BITS_PER_LONG;
301+ }
302+ if (!size)
303+ return result;
304+ tmp = leBPL_to_cpup(p);
305+found_first:
306+ tmp &= ~0UL >> (BITS_PER_LONG-size);
307+found_middle:
308+ return result + ffz(~tmp);
309+}
310+
311+#define find_first_one_bit(addr, size)\
312+ find_next_one_bit((addr), (size), 0)
313+
314+static int read_block_bitmap(struct super_block * sb,
315+ struct udf_bitmap *bitmap, unsigned int block, unsigned long bitmap_nr)
316+{
317+ struct buffer_head *bh = NULL;
318+ int retval = 0;
319+ lb_addr loc;
320+
321+ loc.logicalBlockNum = bitmap->s_extPosition;
322+ loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
323+
324+ bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block), sb->s_blocksize);
325+ if (!bh)
326+ {
327+ retval = -EIO;
328+ }
329+ bitmap->s_block_bitmap[bitmap_nr] = bh;
330+ return retval;
331+}
332+
333+static int __load_block_bitmap(struct super_block * sb,
334+ struct udf_bitmap *bitmap, unsigned int block_group)
335+{
336+ int retval = 0;
337+ int nr_groups = bitmap->s_nr_groups;
338+
339+ if (block_group >= nr_groups)
340+ {
341+ udf_debug("block_group (%d) > nr_groups (%d)\n", block_group, nr_groups);
342+ }
343+
344+ if (bitmap->s_block_bitmap[block_group])
345+ return block_group;
346+ else
347+ {
348+ retval = read_block_bitmap(sb, bitmap, block_group, block_group);
349+ if (retval < 0)
350+ return retval;
351+ return block_group;
352+ }
353+}
354+
355+static inline int load_block_bitmap(struct super_block *sb,
356+ struct udf_bitmap *bitmap, unsigned int block_group)
357+{
358+ int slot;
359+
360+ if (bitmap->s_block_bitmap[block_group])
361+ return 0;
362+ else
363+ slot = __load_block_bitmap(sb, bitmap, block_group);
364+
365+ if (slot < 0)
366+ return slot;
367+
368+ if (!bitmap->s_block_bitmap[slot])
369+ return -EIO;
370+
371+ return slot;
372+}
373+
374+static void udf_bitmap_free_blocks(const struct inode * inode,
375+ struct udf_bitmap *bitmap, lb_addr bloc, Uint32 offset, Uint32 count)
376+{
377+ struct buffer_head * bh = NULL;
378+ unsigned long block;
379+ unsigned long block_group;
380+ unsigned long bit;
381+ unsigned long i;
382+ int bitmap_nr;
383+ unsigned long overflow;
384+ struct super_block * sb;
385+
386+ sb = inode->i_sb;
387+ if (!sb)
388+ {
389+ udf_debug("nonexistent device");
390+ return;
391+ }
392+
393+ lock_super(sb);
394+ if (bloc.logicalBlockNum < 0 ||
395+ (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum))
396+ {
397+ udf_debug("%d < %d || %d + %d > %d\n",
398+ bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count,
399+ UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum));
400+ goto error_return;
401+ }
402+
403+ block = bloc.logicalBlockNum + offset + (sizeof(struct SpaceBitmapDesc) << 3);
404+
405+do_more:
406+ overflow = 0;
407+ block_group = block >> (sb->s_blocksize_bits + 3);
408+ bit = block % (sb->s_blocksize << 3);
409+
410+ /*
411+ * Check to see if we are freeing blocks across a group boundary.
412+ */
413+ if (bit + count > (sb->s_blocksize << 3))
414+ {
415+ overflow = bit + count - (sb->s_blocksize << 3);
416+ count -= overflow;
417+ }
418+ bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
419+ if (bitmap_nr < 0)
420+ goto error_return;
421+
422+ bh = bitmap->s_block_bitmap[bitmap_nr];
423+ for (i=0; i < count; i++)
424+ {
425+ if (udf_set_bit(bit + i, bh->b_data))
426+ {
427+ udf_debug("bit %ld already set\n", bit + i);
428+ udf_debug("byte=%2x\n", ((char *)bh->b_data)[(bit + i) >> 3]);
429+ }
430+ else
431+ {
432+ DQUOT_FREE_BLOCK(sb, inode, 1);
433+ if (UDF_SB_LVIDBH(sb))
434+ {
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);
437+ }
438+ }
439+ }
440+ mark_buffer_dirty(bh, 1);
441+ if (overflow)
442+ {
443+ block += count;
444+ count = overflow;
445+ goto do_more;
446+ }
447+error_return:
448+ sb->s_dirt = 1;
449+ if (UDF_SB_LVIDBH(sb))
450+ mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
451+ unlock_super(sb);
452+ return;
453+}
454+
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)
458+{
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;
464+
465+ sb = inode->i_sb;
466+ if (!sb)
467+ {
468+ udf_debug("nonexistent device\n");
469+ return 0;
470+ }
471+ lock_super(sb);
472+
473+ if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
474+ goto out;
475+
476+repeat:
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);
482+
483+ bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
484+ if (bitmap_nr < 0)
485+ goto out;
486+ bh = bitmap->s_block_bitmap[bitmap_nr];
487+
488+ bit = block % (sb->s_blocksize << 3);
489+
490+ while (bit < (sb->s_blocksize << 3) && block_count > 0)
491+ {
492+ if (!udf_test_bit(bit, bh->b_data))
493+ goto out;
494+ else if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))
495+ goto out;
496+ else if (!udf_clear_bit(bit, bh->b_data))
497+ {
498+ udf_debug("bit already cleared for block %d\n", bit);
499+ DQUOT_FREE_BLOCK(sb, inode, 1);
500+ goto out;
501+ }
502+ block_count --;
503+ alloc_count ++;
504+ bit ++;
505+ block ++;
506+ }
507+ mark_buffer_dirty(bh, 1);
508+ if (block_count > 0)
509+ goto repeat;
510+out:
511+ if (UDF_SB_LVIDBH(sb))
512+ {
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);
516+ }
517+ sb->s_dirt = 1;
518+ unlock_super(sb);
519+ return alloc_count;
520+}
521+
522+static int udf_bitmap_new_block(const struct inode * inode,
523+ struct udf_bitmap *bitmap,Uint16 partition, Uint32 goal, int *err)
524+{
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;
529+ char *ptr;
530+ int newblock = 0;
531+
532+ *err = -ENOSPC;
533+ sb = inode->i_sb;
534+ if (!sb)
535+ {
536+ udf_debug("nonexistent device\n");
537+ return newblock;
538+ }
539+ lock_super(sb);
540+
541+repeat:
542+ if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition))
543+ goal = 0;
544+
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);
549+
550+ bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
551+ if (bitmap_nr < 0)
552+ goto error_return;
553+ bh = bitmap->s_block_bitmap[bitmap_nr];
554+ ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start);
555+
556+ if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize)
557+ {
558+ bit = block % (sb->s_blocksize << 3);
559+
560+ if (udf_test_bit(bit, bh->b_data))
561+ {
562+ goto got_block;
563+ }
564+ end_goal = (bit + 63) & ~63;
565+ bit = udf_find_next_one_bit(bh->b_data, end_goal, bit);
566+ if (bit < end_goal)
567+ goto got_block;
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)
571+ {
572+ bit = newbit;
573+ goto search_back;
574+ }
575+ newbit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, bit);
576+ if (newbit < sb->s_blocksize << 3)
577+ {
578+ bit = newbit;
579+ goto got_block;
580+ }
581+ }
582+
583+ for (i=0; i<(nr_groups*2); i++)
584+ {
585+ block_group ++;
586+ if (block_group >= nr_groups)
587+ block_group = 0;
588+ group_start = block_group ? 0 : sizeof(struct SpaceBitmapDesc);
589+
590+ bitmap_nr = load_block_bitmap(sb,bitmap, block_group);
591+ if (bitmap_nr < 0)
592+ goto error_return;
593+ bh = bitmap->s_block_bitmap[bitmap_nr];
594+ if (i < nr_groups)
595+ {
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)
598+ {
599+ bit = (ptr - ((char *)bh->b_data)) << 3;
600+ break;
601+ }
602+ }
603+ else
604+ {
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)
607+ break;
608+ }
609+ }
610+ if (i >= (nr_groups*2))
611+ {
612+ unlock_super(sb);
613+ return newblock;
614+ }
615+ if (bit < sb->s_blocksize << 3)
616+ goto search_back;
617+ else
618+ bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, group_start << 3);
619+ if (bit >= sb->s_blocksize << 3)
620+ {
621+ unlock_super(sb);
622+ return 0;
623+ }
624+
625+search_back:
626+ for (i=0; i<7 && bit > (group_start << 3) && udf_test_bit(bit - 1, bh->b_data); i++, bit--);
627+
628+got_block:
629+
630+ /*
631+ * Check quota for allocation of this block.
632+ */
633+ if (DQUOT_ALLOC_BLOCK(sb, inode, 1))
634+ {
635+ unlock_super(sb);
636+ *err = -EDQUOT;
637+ return 0;
638+ }
639+
640+ newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
641+ (sizeof(struct SpaceBitmapDesc) << 3);
642+
643+ tmp = udf_get_pblock(sb, newblock, partition, 0);
644+ if (!udf_clear_bit(bit, bh->b_data))
645+ {
646+ udf_debug("bit already cleared for block %d\n", bit);
647+ goto repeat;
648+ }
649+
650+ mark_buffer_dirty(bh, 1);
651+ if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize)))
652+ {
653+ udf_debug("cannot get block %d\n", tmp);
654+ unlock_super(sb);
655+ return 0;
656+ }
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);
661+
662+ if (UDF_SB_LVIDBH(sb))
663+ {
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);
667+ }
668+ sb->s_dirt = 1;
669+ unlock_super(sb);
670+ *err = 0;
671+ return newblock;
672+
673+error_return:
674+ *err = -EIO;
675+ unlock_super(sb);
676+ return 0;
677+}
678+
679+static void udf_table_free_blocks(const struct inode * inode,
680+ struct inode * table, lb_addr bloc, Uint32 offset, Uint32 count)
681+{
682+ struct super_block * sb;
683+ Uint32 start, end;
684+ Uint32 nextoffset, oextoffset, elen;
685+ lb_addr nbloc, obloc, eloc;
686+ struct buffer_head *obh, *nbh;
687+ char etype;
688+ int i;
689+
690+ udf_debug("ino=%ld, bloc=%d, offset=%d, count=%d\n",
691+ inode->i_ino, bloc.logicalBlockNum, offset, count);
692+
693+ sb = inode->i_sb;
694+ if (!sb)
695+ {
696+ udf_debug("nonexistent device");
697+ return;
698+ }
699+
700+ if (table == NULL)
701+ return;
702+
703+ lock_super(sb);
704+ if (bloc.logicalBlockNum < 0 ||
705+ (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum))
706+ {
707+ udf_debug("%d < %d || %d + %d > %d\n",
708+ bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count,
709+ UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum));
710+ goto error_return;
711+ }
712+
713+ /* We do this up front - There are some error conditions that could occure,
714+ but.. oh well */
715+ DQUOT_FREE_BLOCK(sb, inode, count);
716+ if (UDF_SB_LVIDBH(sb))
717+ {
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);
721+ }
722+
723+ start = bloc.logicalBlockNum + offset;
724+ end = bloc.logicalBlockNum + offset + count - 1;
725+
726+ oextoffset = nextoffset = sizeof(struct UnallocatedSpaceEntry);
727+ elen = 0;
728+ obloc = nbloc = UDF_I_LOCATION(table);
729+
730+ obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0), sb->s_blocksize);
731+ nbh->b_count ++;
732+
733+ while (count && (etype =
734+ udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
735+ {
736+ if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) ==
737+ start))
738+ {
739+ if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits))
740+ {
741+ count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
742+ start += ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);
743+ elen = (etype << 30) | (0x40000000 - sb->s_blocksize);
744+ }
745+ else
746+ {
747+ elen = (etype << 30) |
748+ (elen + (count << sb->s_blocksize_bits));
749+ start += count;
750+ count = 0;
751+ }
752+ udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
753+ }
754+ else if (eloc.logicalBlockNum == (end + 1))
755+ {
756+ if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits))
757+ {
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);
763+ }
764+ else
765+ {
766+ eloc.logicalBlockNum = start;
767+ elen = (etype << 30) |
768+ (elen + (count << sb->s_blocksize_bits));
769+ end -= count;
770+ count = 0;
771+ }
772+ udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
773+ }
774+
775+ if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
776+ {
777+ i = -1;
778+ obloc = nbloc;
779+ udf_release_data(obh);
780+ nbh->b_count ++;
781+ obh = nbh;
782+ oextoffset = 0;
783+ }
784+ else
785+ oextoffset = nextoffset;
786+ }
787+
788+ if (count)
789+ {
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 :)
793+
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.
797+
798+ It would be nice if the blocks were close together, but it
799+ isn't required.
800+ */
801+
802+ int adsize;
803+ short_ad *sad = NULL;
804+ long_ad *lad = NULL;
805+ struct AllocExtDesc *aed;
806+
807+ eloc.logicalBlockNum = start;
808+ elen = (EXTENT_RECORDED_ALLOCATED << 30) |
809+ (count << sb->s_blocksize_bits);
810+
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);
815+ else
816+ {
817+ udf_release_data(obh);
818+ udf_release_data(nbh);
819+ goto error_return;
820+ }
821+
822+ if (nextoffset + (2 * adsize) > sb->s_blocksize)
823+ {
824+ char *sptr, *dptr;
825+ int loffset;
826+
827+ udf_release_data(obh);
828+ obh = nbh;
829+ obloc = nbloc;
830+ oextoffset = nextoffset;
831+
832+ /* Steal a block from the extent being free'd */
833+ nbloc.logicalBlockNum = eloc.logicalBlockNum;
834+ eloc.logicalBlockNum ++;
835+ elen -= sb->s_blocksize;
836+
837+ if (!(nbh = udf_tread(sb,
838+ udf_get_lb_pblock(sb, nbloc, 0),
839+ sb->s_blocksize)))
840+ {
841+ udf_release_data(obh);
842+ goto error_return;
843+ }
844+ aed = (struct AllocExtDesc *)(nbh->b_data);
845+ aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
846+ if (nextoffset + adsize > sb->s_blocksize)
847+ {
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;
854+ }
855+ else
856+ {
857+ loffset = nextoffset + adsize;
858+ aed->lengthAllocDescs = cpu_to_le32(0);
859+ sptr = (obh)->b_data + nextoffset;
860+ nextoffset = sizeof(struct AllocExtDesc);
861+
862+ if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
863+ {
864+ aed = (struct AllocExtDesc *)(obh)->b_data;
865+ aed->lengthAllocDescs =
866+ cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
867+ }
868+ else
869+ {
870+ UDF_I_LENALLOC(table) += adsize;
871+ mark_inode_dirty(table);
872+ }
873+ }
874+ udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1,
875+ nbloc.logicalBlockNum, sizeof(tag));
876+ switch (UDF_I_ALLOCTYPE(table))
877+ {
878+ case ICB_FLAG_AD_SHORT:
879+ {
880+ sad = (short_ad *)sptr;
881+ sad->extLength = cpu_to_le32(
882+ EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
883+ sb->s_blocksize);
884+ sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum);
885+ break;
886+ }
887+ case ICB_FLAG_AD_LONG:
888+ {
889+ lad = (long_ad *)sptr;
890+ lad->extLength = cpu_to_le32(
891+ EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
892+ sb->s_blocksize);
893+ lad->extLocation = cpu_to_lelb(nbloc);
894+ break;
895+ }
896+ }
897+ udf_update_tag(obh->b_data, loffset);
898+ mark_buffer_dirty(obh, 1);
899+ }
900+
901+ if (elen) /* It's possible that stealing the block emptied the extent */
902+ {
903+ udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
904+
905+ if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
906+ {
907+ UDF_I_LENALLOC(table) += adsize;
908+ mark_inode_dirty(table);
909+ }
910+ else
911+ {
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);
917+ }
918+ }
919+ }
920+
921+ udf_release_data(nbh);
922+ udf_release_data(obh);
923+
924+error_return:
925+ sb->s_dirt = 1;
926+ unlock_super(sb);
927+ return;
928+}
929+
930+static int udf_table_prealloc_blocks(const struct inode * inode,
931+ struct inode *table, Uint16 partition, Uint32 first_block,
932+ Uint32 block_count)
933+{
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;
939+ char etype = -1;
940+
941+ udf_debug("ino=%ld, partition=%d, first_block=%d, block_count=%d\n",
942+ inode->i_ino, partition, first_block, block_count);
943+
944+ sb = inode->i_sb;
945+ if (!sb)
946+ {
947+ udf_debug("nonexistent device\n");
948+ return 0;
949+ }
950+
951+ if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
952+ return 0;
953+
954+ if (table == NULL)
955+ return 0;
956+
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);
961+ else
962+ return 0;
963+
964+ lock_super(sb);
965+
966+ extoffset = sizeof(struct UnallocatedSpaceEntry);
967+ bloc = UDF_I_LOCATION(table);
968+
969+ bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize);
970+ eloc.logicalBlockNum = 0xFFFFFFFF;
971+
972+ while (first_block != eloc.logicalBlockNum && (etype =
973+ udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
974+ {
975+ udf_debug("eloc=%d, elen=%d, first_block=%d\n",
976+ eloc.logicalBlockNum, elen, first_block);
977+ ; /* empty loop body */
978+ }
979+
980+ if (first_block == eloc.logicalBlockNum)
981+ {
982+ extoffset -= adsize;
983+
984+ alloc_count = (elen >> sb->s_blocksize_bits);
985+ if (alloc_count > block_count)
986+ {
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);
991+ }
992+ else
993+ udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);
994+ }
995+ else
996+ alloc_count = 0;
997+
998+ udf_release_data(bh);
999+
1000+ if (alloc_count && UDF_SB_LVIDBH(sb))
1001+ {
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);
1005+ }
1006+ sb->s_dirt = 1;
1007+ unlock_super(sb);
1008+ udf_debug("alloc_count=%d\n", alloc_count);
1009+ return alloc_count;
1010+}
1011+
1012+static int udf_table_new_block(const struct inode * inode,
1013+ struct inode *table, Uint16 partition, Uint32 goal, int *err)
1014+{
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;
1021+ char etype;
1022+
1023+ udf_debug("ino=%ld, partition=%d, goal=%d\n",
1024+ inode->i_ino, partition, goal);
1025+
1026+ *err = -ENOSPC;
1027+ sb = inode->i_sb;
1028+ if (!sb)
1029+ {
1030+ udf_debug("nonexistent device\n");
1031+ return newblock;
1032+ }
1033+
1034+ if (table == NULL)
1035+ return newblock;
1036+
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);
1041+ else
1042+ return newblock;
1043+
1044+ lock_super(sb);
1045+
1046+ if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition))
1047+ goal = 0;
1048+
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.
1052+ */
1053+
1054+ extoffset = sizeof(struct UnallocatedSpaceEntry);
1055+ bloc = UDF_I_LOCATION(table);
1056+
1057+ goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize);
1058+ goal_bh->b_count ++;
1059+
1060+ while (spread && (etype =
1061+ udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
1062+ {
1063+ if (goal >= eloc.logicalBlockNum)
1064+ {
1065+ if (goal < eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits))
1066+ nspread = 0;
1067+ else
1068+ nspread = goal - eloc.logicalBlockNum -
1069+ (elen >> sb->s_blocksize_bits);
1070+ }
1071+ else
1072+ nspread = eloc.logicalBlockNum - goal;
1073+
1074+ if (nspread < spread)
1075+ {
1076+ spread = nspread;
1077+ if (goal_bh != bh)
1078+ {
1079+ udf_release_data(goal_bh);
1080+ goal_bh = bh;
1081+ goal_bh->b_count ++;
1082+ }
1083+ goal_bloc = bloc;
1084+ goal_extoffset = extoffset - adsize;
1085+ goal_eloc = eloc;
1086+ goal_elen = (etype << 30) | elen;
1087+ }
1088+ }
1089+
1090+ udf_release_data(bh);
1091+
1092+ if (spread == 0xFFFFFFFF)
1093+ {
1094+ udf_release_data(goal_bh);
1095+ unlock_super(sb);
1096+ return 0;
1097+ }
1098+
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.... */
1103+
1104+ newblock = goal_eloc.logicalBlockNum;
1105+ goal_eloc.logicalBlockNum ++;
1106+ goal_elen -= sb->s_blocksize;
1107+
1108+ tmp = udf_get_pblock(sb, newblock, partition, 0);
1109+ if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize)))
1110+ {
1111+ udf_debug("cannot get block %d\n", tmp);
1112+ udf_release_data(bh);
1113+ unlock_super(sb);
1114+ return 0;
1115+ }
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);
1120+
1121+ if (goal_elen)
1122+ udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);
1123+ else
1124+ udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh);
1125+ udf_release_data(goal_bh);
1126+
1127+ if (UDF_SB_LVIDBH(sb))
1128+ {
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);
1132+ }
1133+
1134+ sb->s_dirt = 1;
1135+ unlock_super(sb);
1136+ *err = 0;
1137+ return newblock;
1138+}
1139+
1140+inline void udf_free_blocks(const struct inode * inode, lb_addr bloc,
1141+ Uint32 offset, Uint32 count)
1142+{
1143+ if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_BITMAP)
1144+ {
1145+ return udf_bitmap_free_blocks(inode,
1146+ UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_bitmap,
1147+ bloc, offset, count);
1148+ }
1149+ else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_TABLE)
1150+ {
1151+ return udf_table_free_blocks(inode,
1152+ UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_table,
1153+ bloc, offset, count);
1154+ }
1155+ else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_BITMAP)
1156+ {
1157+ return udf_bitmap_free_blocks(inode,
1158+ UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_bitmap,
1159+ bloc, offset, count);
1160+ }
1161+ else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_TABLE)
1162+ {
1163+ return udf_table_free_blocks(inode,
1164+ UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_table,
1165+ bloc, offset, count);
1166+ }
1167+ else
1168+ return;
1169+}
1170+
1171+inline int udf_prealloc_blocks(const struct inode * inode, Uint16 partition,
1172+ Uint32 first_block, Uint32 block_count)
1173+{
1174+ if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
1175+ {
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);
1179+ }
1180+ else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
1181+ {
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);
1185+ }
1186+ else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
1187+ {
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);
1191+ }
1192+ else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE)
1193+ {
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);
1197+ }
1198+ else
1199+ return 0;
1200+}
1201+
1202+inline int udf_new_block(const struct inode * inode, Uint16 partition,
1203+ Uint32 goal, int *err)
1204+{
1205+ if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
1206+ {
1207+ return udf_bitmap_new_block(inode,
1208+ UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap,
1209+ partition, goal, err);
1210+ }
1211+ else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
1212+ {
1213+ return udf_table_new_block(inode,
1214+ UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table,
1215+ partition, goal, err);
1216+ }
1217+ else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
1218+ {
1219+ return udf_bitmap_new_block(inode,
1220+ UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap,
1221+ partition, goal, err);
1222+ }
1223+ else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE)
1224+ {
1225+ return udf_table_new_block(inode,
1226+ UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table,
1227+ partition, goal, err);
1228+ }
1229+ else
1230+ {
1231+ *err = -EIO;
1232+ return 0;
1233+ }
1234+}
1235diff -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
1238@@ -0,0 +1,178 @@
1239+/*
1240+ * crc.c
1241+ *
1242+ * PURPOSE
1243+ * Routines to generate, calculate, and test a 16-bit CRC.
1244+ *
1245+ * DESCRIPTION
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.
1250+ *
1251+ * Copyright is held by AT&T.
1252+ *
1253+ * AT&T gives permission for the free use of the CRC source code.
1254+ *
1255+ * CONTACTS
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
1259+ *
1260+ * COPYRIGHT
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.
1265+ */
1266+
1267+#include "udfdecl.h"
1268+
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
1302+};
1303+
1304+/*
1305+ * udf_crc
1306+ *
1307+ * PURPOSE
1308+ * Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial.
1309+ *
1310+ * DESCRIPTION
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
1313+ *
1314+ * PRE-CONDITIONS
1315+ * data Pointer to the data block.
1316+ * size Size of the data block.
1317+ *
1318+ * POST-CONDITIONS
1319+ * <return> CRC of the data block.
1320+ *
1321+ * HISTORY
1322+ * July 21, 1997 - Andrew E. Mileski
1323+ * Adapted from OSTA-UDF(tm) 1.50 standard.
1324+ */
1325+extern Uint16
1326+udf_crc(Uint8 *data, Uint32 size, Uint16 crc)
1327+{
1328+ while (size--)
1329+ crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8);
1330+
1331+ return crc;
1332+}
1333+
1334+/****************************************************************************/
1335+#if defined(TEST)
1336+
1337+/*
1338+ * PURPOSE
1339+ * Test udf_crc()
1340+ *
1341+ * HISTORY
1342+ * July 21, 1997 - Andrew E. Mileski
1343+ * Adapted from OSTA-UDF(tm) 1.50 standard.
1344+ */
1345+
1346+unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U };
1347+
1348+int main(void)
1349+{
1350+ unsigned short x;
1351+
1352+ x = udf_crc16(bytes, sizeof bytes);
1353+ printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
1354+
1355+ return 0;
1356+}
1357+
1358+#endif /* defined(TEST) */
1359+
1360+/****************************************************************************/
1361+#if defined(GENERATE)
1362+
1363+/*
1364+ * PURPOSE
1365+ * Generate a table for fast 16-bit CRC calculations (any polynomial).
1366+ *
1367+ * DESCRIPTION
1368+ * The ITU-T V.41 polynomial is 010041.
1369+ *
1370+ * HISTORY
1371+ * July 21, 1997 - Andrew E. Mileski
1372+ * Adapted from OSTA-UDF(tm) 1.50 standard.
1373+ */
1374+
1375+#include <stdio.h>
1376+
1377+int main(int argc, char **argv)
1378+{
1379+ unsigned long crc, poly;
1380+ int n, i;
1381+
1382+ /* Get the polynomial */
1383+ sscanf(argv[1], "%lo", &poly);
1384+ if (poly & 0xffff0000U){
1385+ fprintf(stderr, "polynomial is too large\en");
1386+ exit(1);
1387+ }
1388+
1389+ printf("/* CRC 0%o */\n", poly);
1390+
1391+ /* Create a table */
1392+ printf("static unsigned short crc_table[256] = {\n");
1393+ for (n = 0; n < 256; n++){
1394+ if (n % 8 == 0)
1395+ printf("\t");
1396+ crc = n << 8;
1397+ for (i = 0; i < 8; i++){
1398+ if(crc & 0x8000U)
1399+ crc = (crc << 1) ^ poly;
1400+ else
1401+ crc <<= 1;
1402+ crc &= 0xFFFFU;
1403+ }
1404+ if (n == 255)
1405+ printf("0x%04xU ", crc);
1406+ else
1407+ printf("0x%04xU, ", crc);
1408+ if(n % 8 == 7)
1409+ printf("\n");
1410+ }
1411+ printf("};\n");
1412+
1413+ return 0;
1414+}
1415+
1416+#endif /* defined(GENERATE) */
1417diff -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
1420@@ -0,0 +1,283 @@
1421+/*
1422+ * dir.c
1423+ *
1424+ * PURPOSE
1425+ * Directory handling routines for the OSTA-UDF(tm) filesystem.
1426+ *
1427+ * CONTACTS
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
1431+ *
1432+ * COPYRIGHT
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.
1437+ *
1438+ * (C) 1998-2000 Ben Fennema
1439+ *
1440+ * HISTORY
1441+ *
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
1447+ * across blocks.
1448+ * 12/12/98 Split out the lookup code to namei.c. bulk of directory
1449+ * code now in directory.c:udf_fileident_read.
1450+ */
1451+
1452+#include "udfdecl.h"
1453+
1454+#if defined(__linux__) && defined(__KERNEL__)
1455+#include <linux/version.h>
1456+#include "udf_i.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>
1463+#endif
1464+
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 *);
1468+
1469+/* readdir and lookup functions */
1470+
1471+static struct file_operations udf_dir_operations = {
1472+ NULL, /* lllseek */
1473+ NULL, /* read */
1474+ NULL, /* write */
1475+ udf_readdir, /* readdir */
1476+ NULL, /* poll */
1477+ udf_ioctl, /* ioctl */
1478+ NULL, /* mmap */
1479+ NULL, /* open */
1480+ NULL, /* flush */
1481+ NULL, /* release */
1482+ udf_sync_file, /* fsync */
1483+ NULL, /* fasync */
1484+ NULL, /* check_media_change */
1485+ NULL, /* revalidate */
1486+ NULL /* lock */
1487+};
1488+
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 */
1504+ NULL, /* bmap */
1505+ NULL, /* truncate */
1506+ NULL, /* permission */
1507+ NULL, /* smap */
1508+ NULL, /* updatepage */
1509+ NULL /* revalidate */
1510+};
1511+
1512+/*
1513+ * udf_readdir
1514+ *
1515+ * PURPOSE
1516+ * Read a directory entry.
1517+ *
1518+ * DESCRIPTION
1519+ * Optional - sys_getdents() will return -ENOTDIR if this routine is not
1520+ * available.
1521+ *
1522+ * Refer to sys_getdents() in fs/readdir.c
1523+ * sys_getdents() -> .
1524+ *
1525+ * PRE-CONDITIONS
1526+ * filp Pointer to directory file.
1527+ * buf Pointer to directory entry buffer.
1528+ * filldir Pointer to filldir function.
1529+ *
1530+ * POST-CONDITIONS
1531+ * <return> >=0 on success.
1532+ *
1533+ * HISTORY
1534+ * July 1, 1997 - Andrew E. Mileski
1535+ * Written, tested, and released.
1536+ */
1537+
1538+int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
1539+{
1540+ struct inode *dir = filp->f_dentry->d_inode;
1541+ int result;
1542+
1543+ if (!dir)
1544+ return -EBADF;
1545+
1546+ if (!S_ISDIR(dir->i_mode))
1547+ return -ENOTDIR;
1548+
1549+ if ( filp->f_pos == 0 )
1550+ {
1551+ if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino))
1552+ return 0;
1553+ }
1554+
1555+ result = do_udf_readdir(dir, filp, filldir, dirent);
1556+ UPDATE_ATIME(dir);
1557+ return result;
1558+}
1559+
1560+static int
1561+do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *dirent)
1562+{
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;
1568+ int flen;
1569+ char fname[255];
1570+ char *nameptr;
1571+ Uint16 liu;
1572+ Uint8 lfi;
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;
1577+
1578+ if (nf_pos >= size)
1579+ return 1;
1580+
1581+ if (nf_pos == 0)
1582+ nf_pos = (udf_ext0_offset(dir) >> 2);
1583+
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)
1587+ {
1588+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
1589+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
1590+ {
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);
1595+ }
1596+ else
1597+ offset = 0;
1598+ }
1599+ else
1600+ {
1601+ udf_release_data(bh);
1602+ return 0;
1603+ }
1604+
1605+ if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1606+ {
1607+ udf_release_data(bh);
1608+ return 0;
1609+ }
1610+
1611+ while ( nf_pos < size )
1612+ {
1613+ filp->f_pos = nf_pos;
1614+
1615+ fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
1616+
1617+ if (!fi)
1618+ {
1619+ if (fibh.sbh != fibh.ebh)
1620+ udf_release_data(fibh.ebh);
1621+ udf_release_data(fibh.sbh);
1622+ udf_release_data(bh);
1623+ return 1;
1624+ }
1625+
1626+ liu = le16_to_cpu(cfi.lengthOfImpUse);
1627+ lfi = cfi.lengthFileIdent;
1628+
1629+ if (fibh.sbh == fibh.ebh)
1630+ nameptr = fi->fileIdent + liu;
1631+ else
1632+ {
1633+ int poffset; /* Unpaded ending offset */
1634+
1635+ poffset = fibh.soffset + sizeof(struct FileIdentDesc) + liu + lfi;
1636+
1637+ if (poffset >= lfi)
1638+ nameptr = (char *)(fibh.ebh->b_data + poffset - lfi);
1639+ else
1640+ {
1641+ nameptr = fname;
1642+ memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
1643+ memcpy(nameptr + lfi - poffset, fibh.ebh->b_data, poffset);
1644+ }
1645+ }
1646+
1647+ if ( (cfi.fileCharacteristics & FILE_DELETED) != 0 )
1648+ {
1649+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
1650+ continue;
1651+ }
1652+
1653+ if ( (cfi.fileCharacteristics & FILE_HIDDEN) != 0 )
1654+ {
1655+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
1656+ continue;
1657+ }
1658+
1659+ iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
1660+
1661+ if (!lfi) /* parent directory */
1662+ {
1663+ if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino))
1664+ {
1665+ if (fibh.sbh != fibh.ebh)
1666+ udf_release_data(fibh.ebh);
1667+ udf_release_data(fibh.sbh);
1668+ udf_release_data(bh);
1669+ return 1;
1670+ }
1671+ }
1672+ else
1673+ {
1674+ if ((flen = udf_get_filename(nameptr, fname, lfi)))
1675+ {
1676+ if (filldir(dirent, fname, flen, filp->f_pos, iblock))
1677+ {
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 */
1683+ }
1684+ }
1685+ else
1686+ {
1687+ udf_debug("size=%d, nf_pos=%d, liu=%d, lfi=%d\n", size, nf_pos, liu, lfi);
1688+ }
1689+ }
1690+ } /* end while */
1691+
1692+ filp->f_pos = nf_pos;
1693+
1694+ if (fibh.sbh != fibh.ebh)
1695+ udf_release_data(fibh.ebh);
1696+ udf_release_data(fibh.sbh);
1697+ udf_release_data(bh);
1698+
1699+ if ( filp->f_pos >= size)
1700+ return 1;
1701+ else
1702+ return 0;
1703+}
1704diff -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
1707@@ -0,0 +1,330 @@
1708+/*
1709+ * directory.c
1710+ *
1711+ * PURPOSE
1712+ * Directory related functions
1713+ *
1714+ * CONTACTS
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
1718+ *
1719+ * COPYRIGHT
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.
1724+ */
1725+
1726+#include "udfdecl.h"
1727+
1728+#if defined(__linux__) && defined(__KERNEL__)
1729+
1730+#include <linux/fs.h>
1731+#include <linux/string.h>
1732+#include <linux/udf_fs.h>
1733+
1734+#else
1735+
1736+#include <sys/types.h>
1737+#include <stdio.h>
1738+#include <unistd.h>
1739+
1740+#endif
1741+
1742+#ifdef __KERNEL__
1743+
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)
1746+{
1747+ int loffset = *offset;
1748+ int block;
1749+ Uint8 *ad;
1750+ int remainder;
1751+
1752+ *error = 0;
1753+
1754+ ad = (Uint8 *)(*bh)->b_data + *offset;
1755+ *offset += ad_size;
1756+
1757+ if (!ad)
1758+ {
1759+ udf_release_data(*bh);
1760+ *error = 1;
1761+ return NULL;
1762+ }
1763+
1764+ if (*offset == dir->i_sb->s_blocksize)
1765+ {
1766+ udf_release_data(*bh);
1767+ block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
1768+ if (!block)
1769+ return NULL;
1770+ if (!(*bh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1771+ return NULL;
1772+ }
1773+ else if (*offset > dir->i_sb->s_blocksize)
1774+ {
1775+ ad = tmpad;
1776+
1777+ remainder = dir->i_sb->s_blocksize - loffset;
1778+ memcpy((Uint8 *)ad, (*bh)->b_data + loffset, remainder);
1779+
1780+ udf_release_data(*bh);
1781+ block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
1782+ if (!block)
1783+ return NULL;
1784+ if (!((*bh) = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1785+ return NULL;
1786+
1787+ memcpy((Uint8 *)ad + remainder, (*bh)->b_data, ad_size - remainder);
1788+ *offset = ad_size - remainder;
1789+ }
1790+ return ad;
1791+}
1792+
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)
1800+{
1801+ struct FileIdentDesc *fi;
1802+ int block;
1803+
1804+ fibh->soffset = fibh->eoffset;
1805+
1806+ if (fibh->eoffset == dir->i_sb->s_blocksize)
1807+ {
1808+ int lextoffset = *extoffset;
1809+
1810+ if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
1811+ EXTENT_RECORDED_ALLOCATED)
1812+ {
1813+ return NULL;
1814+ }
1815+
1816+ block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
1817+
1818+ (*offset) ++;
1819+
1820+ if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
1821+ *offset = 0;
1822+ else
1823+ *extoffset = lextoffset;
1824+
1825+ udf_release_data(fibh->sbh);
1826+ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1827+ return NULL;
1828+ fibh->soffset = fibh->eoffset = 0;
1829+ }
1830+ else if (fibh->sbh != fibh->ebh)
1831+ {
1832+ udf_release_data(fibh->sbh);
1833+ fibh->sbh = fibh->ebh;
1834+ }
1835+
1836+ fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
1837+ &(fibh->eoffset));
1838+
1839+ if (!fi)
1840+ return NULL;
1841+
1842+ *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
1843+
1844+ if (fibh->eoffset <= dir->i_sb->s_blocksize)
1845+ {
1846+ memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
1847+ }
1848+ else if (fibh->eoffset > dir->i_sb->s_blocksize)
1849+ {
1850+ int lextoffset = *extoffset;
1851+
1852+ if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
1853+ EXTENT_RECORDED_ALLOCATED)
1854+ {
1855+ return NULL;
1856+ }
1857+
1858+ block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
1859+
1860+ (*offset) ++;
1861+
1862+ if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
1863+ *offset = 0;
1864+ else
1865+ *extoffset = lextoffset;
1866+
1867+ fibh->soffset -= dir->i_sb->s_blocksize;
1868+ fibh->eoffset -= dir->i_sb->s_blocksize;
1869+
1870+ if (!(fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
1871+ return NULL;
1872+
1873+ if (sizeof(struct FileIdentDesc) > - fibh->soffset)
1874+ {
1875+ int fi_len;
1876+
1877+ memcpy((Uint8 *)cfi, (Uint8 *)fi, - fibh->soffset);
1878+ memcpy((Uint8 *)cfi - fibh->soffset, fibh->ebh->b_data,
1879+ sizeof(struct FileIdentDesc) + fibh->soffset);
1880+
1881+ fi_len = (sizeof(struct FileIdentDesc) + cfi->lengthFileIdent +
1882+ le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
1883+
1884+ *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
1885+ fibh->eoffset = fibh->soffset + fi_len;
1886+ }
1887+ else
1888+ {
1889+ memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
1890+ }
1891+ }
1892+ return fi;
1893+}
1894+#endif
1895+
1896+struct FileIdentDesc *
1897+udf_get_fileident(void * buffer, int bufsize, int * offset)
1898+{
1899+ struct FileIdentDesc *fi;
1900+ int lengthThisIdent;
1901+ Uint8 * ptr;
1902+ int padlen;
1903+
1904+ if ( (!buffer) || (!offset) ) {
1905+#ifdef __KERNEL__
1906+ udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
1907+#endif
1908+ return NULL;
1909+ }
1910+
1911+ ptr = buffer;
1912+
1913+ if ( (*offset > 0) && (*offset < bufsize) ) {
1914+ ptr += *offset;
1915+ }
1916+ fi=(struct FileIdentDesc *)ptr;
1917+ if (le16_to_cpu(fi->descTag.tagIdent) != TID_FILE_IDENT_DESC)
1918+ {
1919+#ifdef __KERNEL__
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);
1924+#endif
1925+ return NULL;
1926+ }
1927+ if ( (*offset + sizeof(struct FileIdentDesc)) > bufsize )
1928+ {
1929+ lengthThisIdent = sizeof(struct FileIdentDesc);
1930+ }
1931+ else
1932+ lengthThisIdent = sizeof(struct FileIdentDesc) +
1933+ fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
1934+
1935+ /* we need to figure padding, too! */
1936+ padlen = lengthThisIdent % UDF_NAME_PAD;
1937+ if (padlen)
1938+ lengthThisIdent += (UDF_NAME_PAD - padlen);
1939+ *offset = *offset + lengthThisIdent;
1940+
1941+ return fi;
1942+}
1943+
1944+extent_ad *
1945+udf_get_fileextent(void * buffer, int bufsize, int * offset)
1946+{
1947+ extent_ad * ext;
1948+ struct FileEntry *fe;
1949+ Uint8 * ptr;
1950+
1951+ if ( (!buffer) || (!offset) )
1952+ {
1953+#ifdef __KERNEL__
1954+ printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
1955+#endif
1956+ return NULL;
1957+ }
1958+
1959+ fe = (struct FileEntry *)buffer;
1960+
1961+ if ( le16_to_cpu(fe->descTag.tagIdent) != TID_FILE_ENTRY )
1962+ {
1963+#ifdef __KERNEL__
1964+ udf_debug("0x%x != TID_FILE_ENTRY\n",
1965+ le16_to_cpu(fe->descTag.tagIdent));
1966+#endif
1967+ return NULL;
1968+ }
1969+
1970+ ptr=(Uint8 *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
1971+
1972+ if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
1973+ {
1974+ ptr += *offset;
1975+ }
1976+
1977+ ext = (extent_ad *)ptr;
1978+
1979+ *offset = *offset + sizeof(extent_ad);
1980+ return ext;
1981+}
1982+
1983+short_ad *
1984+udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
1985+{
1986+ short_ad * sa;
1987+ Uint8 * ptr;
1988+
1989+ if ( (!buffer) || (!offset) )
1990+ {
1991+#ifdef __KERNEL__
1992+ printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
1993+#endif
1994+ return NULL;
1995+ }
1996+
1997+ ptr = (Uint8 *)buffer;
1998+
1999+ if ( (*offset > 0) && (*offset < maxoffset) )
2000+ ptr += *offset;
2001+ else
2002+ return NULL;
2003+
2004+ if ((sa = (short_ad *)ptr)->extLength == 0)
2005+ return NULL;
2006+ else if (inc)
2007+ (*offset) += sizeof(short_ad);
2008+ return sa;
2009+}
2010+
2011+long_ad *
2012+udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
2013+{
2014+ long_ad * la;
2015+ Uint8 * ptr;
2016+
2017+ if ( (!buffer) || !(offset) )
2018+ {
2019+#ifdef __KERNEL__
2020+ printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
2021+#endif
2022+ return NULL;
2023+ }
2024+
2025+ ptr = (Uint8 *)buffer;
2026+
2027+ if ( (*offset > 0) && (*offset < maxoffset) )
2028+ ptr += *offset;
2029+ else
2030+ return NULL;
2031+
2032+ if ((la = (long_ad *)ptr)->extLength == 0)
2033+ return NULL;
2034+ else if (inc)
2035+ (*offset) += sizeof(long_ad);
2036+ return la;
2037+}
2038diff -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
2041@@ -0,0 +1,549 @@
2042+/*
2043+ * file.c
2044+ *
2045+ * PURPOSE
2046+ * File handling routines for the OSTA-UDF(tm) filesystem.
2047+ *
2048+ * CONTACTS
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
2052+ *
2053+ * COPYRIGHT
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.
2058+ *
2059+ * (C) 1998-1999 Dave Boynton
2060+ * (C) 1998-2000 Ben Fennema
2061+ * (C) 1999-2000 Stelias Computing Inc
2062+ *
2063+ * HISTORY
2064+ *
2065+ * 10/02/98 dgb Attempt to integrate into udf.o
2066+ * 10/07/98 Switched to using generic_readpage, etc., like isofs
2067+ * And it works!
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
2072+ */
2073+
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>
2082+
2083+#include "udf_i.h"
2084+#include "udf_sb.h"
2085+
2086+#define NBUF 32
2087+
2088+typedef void * poll_table;
2089+
2090+/*
2091+ * Make sure the offset never goes beyond the 32-bit mark..
2092+ */
2093+static long long udf_file_llseek(struct file * file, long long offset, int origin)
2094+{
2095+ struct inode * inode = file->f_dentry->d_inode;
2096+
2097+ switch (origin)
2098+ {
2099+ case 2:
2100+ {
2101+ offset += inode->i_size;
2102+ break;
2103+ }
2104+ case 1:
2105+ {
2106+ offset += file->f_pos;
2107+ break;
2108+ }
2109+ }
2110+#if BITS_PER_LONG < 64
2111+ if (((unsigned long long) offset >> 32) != 0)
2112+ {
2113+ return -EINVAL;
2114+ }
2115+#endif
2116+ if (offset != file->f_pos)
2117+ {
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;
2122+#else
2123+ file->f_version = ++global_event;
2124+#endif
2125+ }
2126+ return offset;
2127+}
2128+
2129+static inline void remove_suid(struct inode * inode)
2130+{
2131+ unsigned int mode;
2132+
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;
2135+
2136+ /* was any of the uid bits set? */
2137+ mode &= inode->i_mode;
2138+ if (mode && !capable(CAP_FSETID))
2139+ {
2140+ inode->i_mode &= ~mode;
2141+ mark_inode_dirty(inode);
2142+ }
2143+}
2144+
2145+static ssize_t udf_file_write(struct file * filp, const char * buf,
2146+ size_t count, loff_t *ppos)
2147+{
2148+ struct inode * inode = filp->f_dentry->d_inode;
2149+ off_t pos;
2150+ long block;
2151+ int offset;
2152+ int written, c;
2153+ struct buffer_head * bh, * bufferlist[NBUF];
2154+ struct super_block * sb;
2155+ int err;
2156+ int i, buffercount, write_error, new_buffer;
2157+ unsigned long limit;
2158+
2159+ /* POSIX: mtime/ctime may not change for 0 count */
2160+ if (!count)
2161+ return 0;
2162+ /* This makes the bounds-checking arithmetic later on much more
2163+ * sane. */
2164+ write_error = buffercount = 0;
2165+ if (!inode)
2166+ {
2167+ printk("udf_file_write: inode = NULL\n");
2168+ return -EINVAL;
2169+ }
2170+ sb = inode->i_sb;
2171+ if (sb->s_flags & MS_RDONLY)
2172+ {
2173+ return -ENOSPC;
2174+ }
2175+
2176+ if (!S_ISREG(inode->i_mode))
2177+ {
2178+ udf_warning(sb, "udf_file_write", "mode = %07o", inode->i_mode);
2179+ return -EINVAL;
2180+ }
2181+ remove_suid(inode);
2182+
2183+ if (filp->f_flags & O_APPEND)
2184+ pos = inode->i_size;
2185+ else
2186+ {
2187+ pos = *ppos;
2188+ if (pos != *ppos)
2189+ return -EINVAL;
2190+ }
2191+
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)
2197+ return -EFBIG;
2198+
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)
2203+ {
2204+ count = 0x7FFFFFFFL - pos;
2205+ if (((ssize_t) count) < 0)
2206+ return -EFBIG;
2207+ }
2208+#endif
2209+
2210+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
2211+ if (limit < RLIM_INFINITY)
2212+ {
2213+ if (((off_t) pos + count) >= limit)
2214+ {
2215+ count = limit - pos;
2216+ if (((ssize_t) count) <= 0)
2217+ {
2218+ send_sig(SIGXFSZ, current, 0);
2219+ return -EFBIG;
2220+ }
2221+ }
2222+ }
2223+
2224+
2225+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
2226+ {
2227+ if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
2228+ pos + count))
2229+ {
2230+ udf_expand_file_adinicb(inode, pos + count, &err);
2231+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
2232+ {
2233+ udf_debug("udf_expand_file_adinicb: err=%d\n", err);
2234+ return err;
2235+ }
2236+ }
2237+ else
2238+ {
2239+ if (pos + count > inode->i_size)
2240+ UDF_I_LENALLOC(inode) = pos + count;
2241+ else
2242+ UDF_I_LENALLOC(inode) = inode->i_size;
2243+ pos += udf_file_entry_alloc_offset(inode);
2244+ }
2245+ }
2246+
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;
2252+ written = 0;
2253+ do
2254+ {
2255+ bh = udf_getblk(inode, block, 1, &err);
2256+ if (!bh)
2257+ {
2258+ if (!written)
2259+ written = err;
2260+ break;
2261+ }
2262+ if (c > count)
2263+ c = count;
2264+
2265+ new_buffer = (!buffer_uptodate(bh) && !buffer_locked(bh) &&
2266+ c == sb->s_blocksize);
2267+
2268+ if (new_buffer)
2269+ {
2270+
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)
2274+ {
2275+ c = 0;
2276+ unlock_buffer(bh);
2277+ brelse(bh);
2278+ if (!written)
2279+ written = -EFAULT;
2280+ break;
2281+ }
2282+ mark_buffer_uptodate(bh, 1);
2283+ unlock_buffer(bh);
2284+ }
2285+ else
2286+ {
2287+ if (!buffer_uptodate(bh))
2288+ {
2289+ ll_rw_block(READ, 1, &bh);
2290+ wait_on_buffer(bh);
2291+ if (!buffer_uptodate(bh))
2292+ {
2293+ brelse(bh);
2294+ if (!written)
2295+ written = -EIO;
2296+ break;
2297+ }
2298+ }
2299+ c -= copy_from_user(bh->b_data + offset, buf, c);
2300+ }
2301+ if (!c)
2302+ {
2303+ brelse(bh);
2304+ if (!written)
2305+ written = -EFAULT;
2306+ break;
2307+ }
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);
2311+#else
2312+ update_vm_cache_conditional(inode, pos, bh->b_data + offset, c,
2313+ (unsigned long) buf);
2314+#endif
2315+ pos += c;
2316+ written += c;
2317+ buf += c;
2318+ count -= c;
2319+
2320+ if (filp->f_flags & O_SYNC)
2321+ bufferlist[buffercount++] = bh;
2322+ else
2323+ brelse(bh);
2324+ if (buffercount == NBUF)
2325+ {
2326+ ll_rw_block(WRITE, buffercount, bufferlist);
2327+ for (i=0; i<buffercount; i++)
2328+ {
2329+ wait_on_buffer(bufferlist[i]);
2330+ if (!buffer_uptodate(bufferlist[i]))
2331+ write_error = 1;
2332+ brelse(bufferlist[i]);
2333+ }
2334+ buffercount = 0;
2335+ }
2336+ if (write_error)
2337+ break;
2338+ block++;
2339+ offset = 0;
2340+ c = sb->s_blocksize;
2341+ } while (count);
2342+
2343+ if (buffercount)
2344+ {
2345+ ll_rw_block(WRITE, buffercount, bufferlist);
2346+ for (i=0; i<buffercount; i++)
2347+ {
2348+ wait_on_buffer(bufferlist[i]);
2349+ if (!buffer_uptodate(bufferlist[i]))
2350+ write_error = 1;
2351+ brelse(bufferlist[i]);
2352+ }
2353+ }
2354+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
2355+ pos -= udf_file_entry_alloc_offset(inode);
2356+
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;
2363+ *ppos = pos;
2364+ mark_inode_dirty(inode);
2365+ return written;
2366+}
2367+
2368+/*
2369+ * udf_ioctl
2370+ *
2371+ * PURPOSE
2372+ * Issue an ioctl.
2373+ *
2374+ * DESCRIPTION
2375+ * Optional - sys_ioctl() will return -ENOTTY if this routine is not
2376+ * available, and the ioctl cannot be handled without filesystem help.
2377+ *
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.
2383+ *
2384+ * Refer to sys_ioctl() in fs/ioctl.c
2385+ * sys_ioctl() -> .
2386+ *
2387+ * PRE-CONDITIONS
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].
2393+ *
2394+ * POST-CONDITIONS
2395+ * <return> Success (>=0) or an error code (<=0) that
2396+ * sys_ioctl() will return.
2397+ *
2398+ * HISTORY
2399+ * July 1, 1997 - Andrew E. Mileski
2400+ * Written, tested, and released.
2401+ */
2402+int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
2403+ unsigned long arg)
2404+{
2405+ int result = -1;
2406+ struct buffer_head *bh = NULL;
2407+ Uint16 ident;
2408+ long_ad eaicb;
2409+ Uint8 *ea = NULL;
2410+
2411+ if ( permission(inode, MAY_READ) != 0 )
2412+ {
2413+ udf_debug("no permission to access inode %lu\n",
2414+ inode->i_ino);
2415+ return -EPERM;
2416+ }
2417+
2418+ if ( !arg )
2419+ {
2420+ udf_debug("invalid argument to udf_ioctl\n");
2421+ return -EINVAL;
2422+ }
2423+
2424+ /* first, do ioctls that don't need to udf_read */
2425+ switch (cmd)
2426+ {
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);
2430+ return result;
2431+
2432+ }
2433+
2434+ /* ok, we need to read the inode */
2435+ bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
2436+
2437+ if (!bh || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))
2438+ {
2439+ udf_debug("bread failed (ino=%ld) or ident (%d) != TID_(EXTENDED_)FILE_ENTRY",
2440+ inode->i_ino, ident);
2441+ return -EFAULT;
2442+ }
2443+
2444+ if (UDF_I_EXTENDED_FE(inode) == 0)
2445+ {
2446+ struct FileEntry *fe;
2447+
2448+ fe = (struct FileEntry *)bh->b_data;
2449+ eaicb = lela_to_cpu(fe->extendedAttrICB);
2450+ if (UDF_I_LENEATTR(inode))
2451+ ea = fe->extendedAttr;
2452+ }
2453+ else
2454+ {
2455+ struct ExtendedFileEntry *efe;
2456+
2457+ efe = (struct ExtendedFileEntry *)bh->b_data;
2458+ eaicb = lela_to_cpu(efe->extendedAttrICB);
2459+ if (UDF_I_LENEATTR(inode))
2460+ ea = efe->extendedAttr;
2461+ }
2462+
2463+ switch (cmd)
2464+ {
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);
2468+ break;
2469+
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));
2473+ break;
2474+
2475+ default:
2476+ udf_debug("ino=%ld, cmd=%d\n", inode->i_ino, cmd);
2477+ break;
2478+ }
2479+
2480+ udf_release_data(bh);
2481+ return result;
2482+}
2483+
2484+/*
2485+ * udf_release_file
2486+ *
2487+ * PURPOSE
2488+ * Called when all references to the file are closed
2489+ *
2490+ * DESCRIPTION
2491+ * Discard prealloced blocks
2492+ *
2493+ * HISTORY
2494+ *
2495+ */
2496+static int udf_release_file(struct inode * inode, struct file * filp)
2497+{
2498+ if (filp->f_mode & FMODE_WRITE)
2499+ udf_discard_prealloc(inode);
2500+ return 0;
2501+}
2502+
2503+#if BITS_PER_LONG < 64
2504+/*
2505+ * udf_open_file
2506+ *
2507+ * PURPOSE
2508+ * Called when an inode is about to be open.
2509+ *
2510+ * DESCRIPTION
2511+ * Use this to disallow opening RW large files on 32 bit systems.
2512+ *
2513+ * HISTORY
2514+ *
2515+ */
2516+static int udf_open_file(struct inode * inode, struct file * filp)
2517+{
2518+ if (inode->i_size == (Uint32)-1 && (filp->f_mode & FMODE_WRITE))
2519+ return -EFBIG;
2520+ return 0;
2521+}
2522+#endif
2523+
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 */
2529+ NULL, /* poll */
2530+ udf_ioctl, /* ioctl */
2531+ generic_file_mmap, /* mmap */
2532+#if BITS_PER_LONG == 64
2533+ NULL, /* open */
2534+#else
2535+ udf_open_file, /* open */
2536+#endif
2537+ NULL, /* flush */
2538+ udf_release_file, /* release */
2539+ udf_sync_file, /* fsync */
2540+ NULL, /* fasync */
2541+ NULL, /* check_media_change */
2542+ NULL, /* revalidate */
2543+ NULL /* lock */
2544+};
2545+
2546+struct inode_operations udf_file_inode_operations = {
2547+ &udf_file_operations,
2548+ NULL, /* create */
2549+ NULL, /* lookup */
2550+ NULL, /* link */
2551+ NULL, /* unlink */
2552+ NULL, /* symlink */
2553+ NULL, /* mkdir */
2554+ NULL, /* rmdir */
2555+ NULL, /* mknod */
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 */
2564+ NULL, /* smap */
2565+ NULL, /* updatepage */
2566+ NULL /* revalidate */
2567+};
2568+
2569+struct inode_operations udf_file_inode_operations_adinicb = {
2570+ &udf_file_operations,
2571+ NULL, /* create */
2572+ NULL, /* lookup */
2573+ NULL, /* link */
2574+ NULL, /* unlink */
2575+ NULL, /* symlink */
2576+ NULL, /* mkdir */
2577+ NULL, /* rmdir */
2578+ NULL, /* mknod */
2579+ NULL, /* rename */
2580+ NULL, /* readlink */
2581+ NULL, /* follow_link */
2582+ udf_readpage_adinicb, /* readpage */
2583+ NULL, /* writepage */
2584+ NULL, /* bmap */
2585+ udf_truncate_adinicb, /* truncate */
2586+ NULL, /* permission */
2587+ NULL, /* smap */
2588+ NULL, /* updatepage */
2589+ NULL /* revalidate */
2590+};
2591diff -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
2594@@ -0,0 +1,115 @@
2595+/*
2596+ * fsync.c
2597+ *
2598+ * PURPOSE
2599+ * Fsync handling routines for the OSTA-UDF(tm) filesystem.
2600+ *
2601+ * CONTACTS
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
2605+ *
2606+ * COPYRIGHT
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.
2611+ *
2612+ * (C) 1999-2000 Ben Fennema
2613+ * (C) 1999-2000 Stelias Computing Inc
2614+ *
2615+ * HISTORY
2616+ *
2617+ * 05/22/99 blf Created.
2618+ */
2619+
2620+#include "udfdecl.h"
2621+
2622+#include <linux/fs.h>
2623+#include <linux/udf_fs.h>
2624+#include "udf_i.h"
2625+
2626+static int sync_block (struct inode * inode, Uint32 * block, int wait)
2627+{
2628+ struct buffer_head * bh;
2629+
2630+ if (!*block)
2631+ return 0;
2632+ bh = get_hash_table (inode->i_dev, *block, inode->i_sb->s_blocksize);
2633+ if (!bh)
2634+ return 0;
2635+ if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
2636+ brelse (bh);
2637+ return -1;
2638+ }
2639+ if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
2640+ brelse (bh);
2641+ return 0;
2642+ }
2643+ ll_rw_block (WRITE, 1, &bh);
2644+ bh->b_count--;
2645+ return 0;
2646+}
2647+
2648+static int sync_extent (struct inode * inode, lb_addr *loc, Uint32 *len, int wait)
2649+{
2650+ Uint32 i, block;
2651+ int rc, err = 0;
2652+
2653+ for (i = 0; i < *len; i++)
2654+ {
2655+ block = udf_get_lb_pblock(inode->i_sb, *loc, i);
2656+ rc = sync_block (inode, &block, wait);
2657+ if (rc)
2658+ err = rc;
2659+ }
2660+ return err;
2661+}
2662+
2663+static int sync_all_extents(struct inode * inode, int wait)
2664+{
2665+ lb_addr bloc, eloc;
2666+ Uint32 extoffset, elen, offset;
2667+ int err = 0, etype;
2668+ struct buffer_head *bh = NULL;
2669+
2670+ if ((etype = inode_bmap(inode, 0, &bloc, &extoffset, &eloc, &elen, &offset, &bh)) != -1)
2671+ {
2672+ err |= sync_extent(inode, &eloc, &elen, wait);
2673+
2674+ while ((etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
2675+ {
2676+ if (etype == EXTENT_RECORDED_ALLOCATED)
2677+ err |= sync_extent(inode, &eloc, &elen, wait);
2678+ }
2679+ }
2680+ udf_release_data(bh);
2681+ return err;
2682+}
2683+
2684+/*
2685+ * File may be NULL when we are called. Perhaps we shouldn't
2686+ * even pass file to fsync ?
2687+ */
2688+
2689+int udf_sync_file(struct file * file, struct dentry *dentry)
2690+{
2691+ int wait, err = 0;
2692+ struct inode *inode = dentry->d_inode;
2693+
2694+ if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
2695+ {
2696+ /*
2697+ * Don't sync fast links! or ICB_FLAG_AD_IN_ICB
2698+ */
2699+ goto skip;
2700+ }
2701+
2702+ for (wait=0; wait<=1; wait++)
2703+ {
2704+ err |= sync_all_extents (inode, wait);
2705+ }
2706+skip:
2707+ err |= udf_sync_inode (inode);
2708+ return err ? -EIO : 0;
2709+}
2710diff -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
2713@@ -0,0 +1,195 @@
2714+/*
2715+ * ialloc.c
2716+ *
2717+ * PURPOSE
2718+ * Inode allocation handling routines for the OSTA-UDF(tm) filesystem.
2719+ *
2720+ * CONTACTS
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
2724+ *
2725+ * COPYRIGHT
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.
2730+ *
2731+ * (C) 1998-2000 Ben Fennema
2732+ *
2733+ * HISTORY
2734+ *
2735+ * 02/24/99 blf Created.
2736+ *
2737+ */
2738+
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>
2745+
2746+#include "udf_i.h"
2747+#include "udf_sb.h"
2748+
2749+void udf_free_inode(struct inode * inode)
2750+{
2751+ struct super_block * sb = inode->i_sb;
2752+ int is_directory;
2753+ unsigned long ino;
2754+
2755+ if (!inode->i_dev)
2756+ {
2757+ udf_debug("inode has no device\n");
2758+ return;
2759+ }
2760+ if (inode->i_count > 1)
2761+ {
2762+ udf_debug("inode has count=%d\n", inode->i_count);
2763+ return;
2764+ }
2765+ if (inode->i_nlink)
2766+ {
2767+ udf_debug("inode has nlink=%d\n", inode->i_nlink);
2768+ return;
2769+ }
2770+ if (!sb)
2771+ {
2772+ udf_debug("inode on nonexistent device\n");
2773+ return;
2774+ }
2775+
2776+ ino = inode->i_ino;
2777+
2778+ /*
2779+ * Note: we must free any quota before locking the superblock,
2780+ * as writing the quota to disk may need the lock as well.
2781+ */
2782+ DQUOT_FREE_INODE(sb, inode);
2783+ DQUOT_DROP(inode);
2784+
2785+ lock_super(sb);
2786+
2787+ is_directory = S_ISDIR(inode->i_mode);
2788+
2789+ clear_inode(inode);
2790+
2791+ if (UDF_SB_LVIDBH(sb))
2792+ {
2793+ if (is_directory)
2794+ UDF_SB_LVIDIU(sb)->numDirs =
2795+ cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs) - 1);
2796+ else
2797+ UDF_SB_LVIDIU(sb)->numFiles =
2798+ cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1);
2799+
2800+ mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
2801+ }
2802+
2803+ unlock_super(sb);
2804+
2805+ udf_free_blocks(inode, UDF_I_LOCATION(inode), 0, 1);
2806+}
2807+
2808+struct inode * udf_new_inode (const struct inode *dir, int mode, int * err)
2809+{
2810+ struct super_block *sb;
2811+ struct inode * inode;
2812+ int block;
2813+ Uint32 start = UDF_I_LOCATION(dir).logicalBlockNum;
2814+
2815+ inode = get_empty_inode();
2816+ if (!inode)
2817+ {
2818+ *err = -ENOMEM;
2819+ return NULL;
2820+ }
2821+ sb = dir->i_sb;
2822+ inode->i_sb = sb;
2823+ inode->i_flags = 0;
2824+ *err = -ENOSPC;
2825+
2826+ block = udf_new_block(dir, UDF_I_LOCATION(dir).partitionReferenceNum,
2827+ start, err);
2828+ if (*err)
2829+ {
2830+ iput(inode);
2831+ return NULL;
2832+ }
2833+ lock_super(sb);
2834+
2835+ if (UDF_SB_LVIDBH(sb))
2836+ {
2837+ struct LogicalVolHeaderDesc *lvhd;
2838+ Uint64 uniqueID;
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);
2843+ else
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))
2848+ uniqueID += 16;
2849+ lvhd->uniqueID = cpu_to_le64(uniqueID);
2850+ mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
2851+ }
2852+ inode->i_mode = mode;
2853+ inode->i_sb = sb;
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)
2860+ {
2861+ inode->i_gid = dir->i_gid;
2862+ if (S_ISDIR(mode))
2863+ mode |= S_ISGID;
2864+ }
2865+ else
2866+ inode->i_gid = current->fsgid;
2867+
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))
2877+ {
2878+ UDF_I_EXTENDED_FE(inode) = 1;
2879+ UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
2880+ }
2881+ else
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;
2887+ else
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);
2895+
2896+ unlock_super(sb);
2897+ if (DQUOT_ALLOC_INODE(sb, inode))
2898+ {
2899+ sb->dq_op->drop(inode);
2900+ inode->i_nlink = 0;
2901+ iput(inode);
2902+ *err = -EDQUOT;
2903+ return NULL;
2904+ }
2905+
2906+ *err = 0;
2907+ return inode;
2908+}
2909diff -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
2912@@ -0,0 +1,2022 @@
2913+/*
2914+ * inode.c
2915+ *
2916+ * PURPOSE
2917+ * Inode handling routines for the OSTA-UDF(tm) filesystem.
2918+ *
2919+ * CONTACTS
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
2923+ *
2924+ * COPYRIGHT
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.
2929+ *
2930+ * (C) 1998 Dave Boynton
2931+ * (C) 1998-2000 Ben Fennema
2932+ * (C) 1999-2000 Stelias Computing Inc
2933+ *
2934+ * HISTORY
2935+ *
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 #
2946+ */
2947+
2948+#include "udfdecl.h"
2949+#include <linux/locks.h>
2950+#include <linux/mm.h>
2951+
2952+#include "udf_i.h"
2953+#include "udf_sb.h"
2954+
2955+#define EXTENT_MERGE_SIZE 5
2956+
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 **);
2970+
2971+/*
2972+ * udf_put_inode
2973+ *
2974+ * PURPOSE
2975+ *
2976+ * DESCRIPTION
2977+ * This routine is called whenever the kernel no longer needs the inode.
2978+ *
2979+ * HISTORY
2980+ * July 1, 1997 - Andrew E. Mileski
2981+ * Written, tested, and released.
2982+ *
2983+ * Called at each iput()
2984+ */
2985+void udf_put_inode(struct inode * inode)
2986+{
2987+ if (!(inode->i_sb->s_flags & MS_RDONLY))
2988+ {
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));
2993+ }
2994+}
2995+
2996+/*
2997+ * udf_delete_inode
2998+ *
2999+ * PURPOSE
3000+ * Clean-up before the specified inode is destroyed.
3001+ *
3002+ * DESCRIPTION
3003+ * This routine is called when the kernel destroys an inode structure
3004+ * ie. when iput() finds i_count == 0.
3005+ *
3006+ * HISTORY
3007+ * July 1, 1997 - Andrew E. Mileski
3008+ * Written, tested, and released.
3009+ *
3010+ * Called at the last iput() if i_nlink is zero.
3011+ */
3012+void udf_delete_inode(struct inode * inode)
3013+{
3014+ if (is_bad_inode(inode))
3015+ return;
3016+ inode->i_size = 0;
3017+ if (inode->i_blocks)
3018+ {
3019+ if (inode->i_op && inode->i_op->truncate)
3020+ inode->i_op->truncate(inode);
3021+ else
3022+ udf_truncate(inode);
3023+ }
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);
3028+}
3029+
3030+void udf_discard_prealloc(struct inode * inode)
3031+{
3032+ if (inode->i_size && UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
3033+ udf_trunc(inode);
3034+}
3035+
3036+void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
3037+{
3038+ int block, newblock;
3039+ struct buffer_head *sbh = NULL, *dbh = NULL;
3040+ lb_addr bloc, eloc;
3041+ Uint32 elen, extoffset;
3042+
3043+ if (!UDF_I_LENALLOC(inode))
3044+ {
3045+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
3046+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
3047+ else
3048+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
3049+ mark_inode_dirty(inode);
3050+ inode->i_op = &udf_file_inode_operations;
3051+ return;
3052+ }
3053+
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);
3058+
3059+ if (!(block))
3060+ return;
3061+ newblock = udf_get_pblock(inode->i_sb, block,
3062+ UDF_I_LOCATION(inode).partitionReferenceNum, 0);
3063+ if (!newblock)
3064+ return;
3065+ sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
3066+ if (!sbh)
3067+ return;
3068+ dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize);
3069+ if (!dbh)
3070+ return;
3071+
3072+ memcpy(dbh->b_data, sbh->b_data + udf_file_entry_alloc_offset(inode),
3073+ UDF_I_LENALLOC(inode));
3074+
3075+ mark_buffer_dirty(dbh, 1);
3076+ udf_release_data(dbh);
3077+
3078+ memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
3079+ 0, UDF_I_LENALLOC(inode));
3080+
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;
3084+ else
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 */
3094+
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;
3101+}
3102+
3103+struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
3104+{
3105+ int newblock;
3106+ struct buffer_head *sbh = NULL, *dbh = NULL;
3107+ lb_addr bloc, eloc;
3108+ Uint32 elen, extoffset;
3109+
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;
3114+
3115+ if (!inode->i_size)
3116+ {
3117+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
3118+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
3119+ else
3120+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
3121+ mark_inode_dirty(inode);
3122+ return NULL;
3123+ }
3124+
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);
3129+
3130+ if (!(*block))
3131+ return NULL;
3132+ newblock = udf_get_pblock(inode->i_sb, *block,
3133+ UDF_I_LOCATION(inode).partitionReferenceNum, 0);
3134+ if (!newblock)
3135+ return NULL;
3136+ sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
3137+ if (!sbh)
3138+ return NULL;
3139+ dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize);
3140+ if (!dbh)
3141+ return NULL;
3142+
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) )
3148+ {
3149+ sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
3150+ if (!sfi)
3151+ {
3152+ udf_release_data(sbh);
3153+ udf_release_data(dbh);
3154+ return NULL;
3155+ }
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))
3162+ {
3163+ udf_release_data(sbh);
3164+ udf_release_data(dbh);
3165+ return NULL;
3166+ }
3167+ }
3168+ mark_buffer_dirty(dbh, 1);
3169+
3170+ memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
3171+ 0, UDF_I_LENALLOC(inode));
3172+
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;
3176+ else
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 */
3185+
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 ++;
3191+ return dbh;
3192+}
3193+
3194+struct buffer_head * udf_getblk(struct inode * inode, long block,
3195+ int create, int * err)
3196+{
3197+ *err = -EIO;
3198+ if (block < 0)
3199+ {
3200+ udf_warning(inode->i_sb, "udf_getblk", "block < 0");
3201+ return NULL;
3202+ }
3203+
3204+ if (block == UDF_I_NEXT_ALLOC_BLOCK(inode) + 1)
3205+ {
3206+ UDF_I_NEXT_ALLOC_BLOCK(inode) ++;
3207+ UDF_I_NEXT_ALLOC_GOAL(inode) ++;
3208+ }
3209+
3210+ *err = -ENOSPC;
3211+ return inode_getblk(inode, block, create, err);
3212+}
3213+
3214+static struct buffer_head * inode_getblk(struct inode * inode, long block,
3215+ int create, int * err)
3216+{
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;
3221+ Uint32 elen = 0;
3222+ lb_addr eloc, pbloc = UDF_I_LOCATION(inode), cbloc = UDF_I_LOCATION(inode);
3223+ int c = 1;
3224+ int lbcount = 0, b_off = 0, offset = 0;
3225+ Uint32 newblocknum, newblock;
3226+ char etype;
3227+ int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
3228+ char lastblock = 0;
3229+
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);
3233+
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 */
3237+ do
3238+ {
3239+ if (pbh != cbh)
3240+ {
3241+ udf_release_data(pbh);
3242+ pbh = cbh;
3243+ cbh->b_count ++;
3244+ pbloc = cbloc;
3245+ }
3246+
3247+ lbcount += elen;
3248+
3249+ pextoffset = cextoffset;
3250+ cextoffset = nextoffset;
3251+
3252+ if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1)
3253+ break;
3254+
3255+ c = !c;
3256+
3257+ laarr[c].extLength = (etype << 30) | elen;
3258+ laarr[c].extLocation = eloc;
3259+
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);
3264+
3265+ count ++;
3266+ } while (lbcount + elen <= b_off);
3267+
3268+ b_off -= lbcount;
3269+ offset = b_off >> inode->i_sb->s_blocksize_bits;
3270+
3271+ /* if the extent is allocated and recorded, return the block
3272+ if the extent is not a multiple of the blocksize, round up */
3273+
3274+ if (etype == EXTENT_RECORDED_ALLOCATED)
3275+ {
3276+ if (elen & (inode->i_sb->s_blocksize - 1))
3277+ {
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);
3282+ }
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);
3287+ }
3288+
3289+ if (etype == -1)
3290+ {
3291+ endnum = startnum = ((count > 1) ? 1 : count);
3292+ if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
3293+ {
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));
3299+ }
3300+ c = !c;
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));
3304+ count ++;
3305+ endnum ++;
3306+ lastblock = 1;
3307+ }
3308+ else
3309+ endnum = startnum = ((count > 2) ? 2 : count);
3310+
3311+ /* if the current extent is in position 0, swap it with the previous */
3312+ if (!c && count != 1)
3313+ {
3314+ laarr[2] = laarr[0];
3315+ laarr[0] = laarr[1];
3316+ laarr[1] = laarr[2];
3317+ c = 1;
3318+ }
3319+
3320+ /* if the current block is located in a extent, read the next extent */
3321+ if (etype != -1)
3322+ {
3323+ if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 0)) != -1)
3324+ {
3325+ laarr[c+1].extLength = (etype << 30) | elen;
3326+ laarr[c+1].extLocation = eloc;
3327+ count ++;
3328+ startnum ++;
3329+ endnum ++;
3330+ }
3331+ else
3332+ lastblock = 1;
3333+ }
3334+ udf_release_data(cbh);
3335+
3336+ *err = -EFBIG;
3337+ if (!create && etype != EXTENT_NOT_RECORDED_ALLOCATED)
3338+ goto dont_create;
3339+
3340+ {
3341+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
3342+ if (limit < RLIM_INFINITY)
3343+ {
3344+ limit >>= inode->i_sb->s_blocksize_bits;
3345+ if (block >= limit)
3346+ {
3347+ send_sig(SIGXFSZ, current, 0);
3348+dont_create:
3349+ *err = -EFBIG;
3350+ return NULL;
3351+ }
3352+ }
3353+ }
3354+
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 */
3360+ {
3361+ if (UDF_I_NEXT_ALLOC_BLOCK(inode) == block)
3362+ goal = UDF_I_NEXT_ALLOC_GOAL(inode);
3363+
3364+ if (!goal)
3365+ {
3366+ if (!(goal = pgoal))
3367+ goal = UDF_I_LOCATION(inode).logicalBlockNum + 1;
3368+ }
3369+
3370+ if (!(newblocknum = udf_new_block(inode,
3371+ UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
3372+ {
3373+ udf_release_data(pbh);
3374+ *err = -ENOSPC;
3375+ return NULL;
3376+ }
3377+ }
3378+
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);
3383+
3384+#ifdef UDF_PREALLOCATE
3385+ /* preallocate blocks */
3386+ udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
3387+#endif
3388+
3389+ /* merge any continuous blocks in laarr */
3390+ udf_merge_extents(inode, laarr, &endnum);
3391+
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);
3396+
3397+ udf_release_data(pbh);
3398+
3399+ if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
3400+ UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
3401+ {
3402+ return NULL;
3403+ }
3404+ if ((result = getblk(inode->i_dev, newblock, inode->i_sb->s_blocksize)))
3405+ {
3406+ memset(result->b_data, 0x00, inode->i_sb->s_blocksize);
3407+ mark_buffer_uptodate(result, 1);
3408+ mark_buffer_dirty(result, 1);
3409+ }
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);
3417+ else
3418+ mark_inode_dirty(inode);
3419+ return result;
3420+}
3421+
3422+static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum,
3423+ long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
3424+{
3425+ if ((laarr[*c].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED ||
3426+ (laarr[*c].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
3427+ {
3428+ int curr = *c;
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;
3432+
3433+ if (blen == 1)
3434+ ;
3435+ else if (!offset || blen == offset + 1)
3436+ {
3437+ laarr[curr+2] = laarr[curr+1];
3438+ laarr[curr+1] = laarr[curr];
3439+ }
3440+ else
3441+ {
3442+ laarr[curr+3] = laarr[curr+1];
3443+ laarr[curr+2] = laarr[curr+1] = laarr[curr];
3444+ }
3445+
3446+ if (offset)
3447+ {
3448+ laarr[curr].extLength = type |
3449+ (offset << inode->i_sb->s_blocksize_bits);
3450+ curr ++;
3451+ (*c) ++;
3452+ (*endnum) ++;
3453+ }
3454+
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;
3461+ curr ++;
3462+
3463+ if (blen != offset + 1)
3464+ {
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);
3469+ curr ++;
3470+ (*endnum) ++;
3471+ }
3472+ }
3473+}
3474+
3475+static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
3476+ long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
3477+{
3478+ int start, length = 0, currlength = 0, i;
3479+
3480+ if (*endnum >= (c+1) && !lastblock)
3481+ return;
3482+
3483+ if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
3484+ {
3485+ start = c+1;
3486+ length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) +
3487+ inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
3488+ }
3489+ else
3490+ start = c;
3491+
3492+ for (i=start+1; i<=*endnum; i++)
3493+ {
3494+ if (i == *endnum)
3495+ {
3496+ if (lastblock)
3497+ length += UDF_DEFAULT_PREALLOC_BLOCKS;
3498+ }
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);
3502+ else
3503+ break;
3504+ }
3505+
3506+ if (length)
3507+ {
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);
3515+
3516+ if (numalloc)
3517+ {
3518+ if (start == (c+1))
3519+ laarr[start].extLength +=
3520+ (numalloc << inode->i_sb->s_blocksize_bits);
3521+ else
3522+ {
3523+ memmove(&laarr[c+2], &laarr[c+1],
3524+ sizeof(long_ad) * (*endnum - (c+1)));
3525+ (*endnum) ++;
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);
3531+ start = c+1;
3532+ }
3533+
3534+ for (i=start+1; numalloc && i<*endnum; i++)
3535+ {
3536+ int elen = ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
3537+ inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
3538+
3539+ if (elen > numalloc)
3540+ {
3541+ laarr[c+1].extLength -=
3542+ (numalloc << inode->i_sb->s_blocksize_bits);
3543+ numalloc = 0;
3544+ }
3545+ else
3546+ {
3547+ numalloc -= elen;
3548+ if (*endnum > (i+1))
3549+ memmove(&laarr[i], &laarr[i+1],
3550+ sizeof(long_ad) * (*endnum - (i+1)));
3551+ i --;
3552+ (*endnum) --;
3553+ }
3554+ }
3555+ }
3556+ }
3557+}
3558+
3559+static void udf_merge_extents(struct inode *inode,
3560+ long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
3561+{
3562+ int i;
3563+
3564+ for (i=0; i<(*endnum-1); i++)
3565+ {
3566+ if ((laarr[i].extLength >> 30) == (laarr[i+1].extLength >> 30))
3567+ {
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)))
3572+ {
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)
3576+ {
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);
3586+ }
3587+ else
3588+ {
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)));
3595+ i --;
3596+ (*endnum) --;
3597+ }
3598+ }
3599+ }
3600+ }
3601+}
3602+
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)
3606+{
3607+ int start = 0, i;
3608+ lb_addr tmploc;
3609+ Uint32 tmplen;
3610+
3611+ if (startnum > endnum)
3612+ {
3613+ for (i=0; i<(startnum-endnum); i++)
3614+ {
3615+ udf_delete_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
3616+ laarr[i].extLength, *pbh);
3617+ }
3618+ }
3619+ else if (startnum < endnum)
3620+ {
3621+ for (i=0; i<(endnum-startnum); i++)
3622+ {
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);
3627+ start ++;
3628+ }
3629+ }
3630+
3631+ for (i=start; i<endnum; i++)
3632+ {
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);
3636+ }
3637+}
3638+
3639+struct buffer_head * udf_bread(struct inode * inode, int block,
3640+ int create, int * err)
3641+{
3642+ struct buffer_head * bh = NULL;
3643+ int prev_blocks;
3644+
3645+ prev_blocks = inode->i_blocks;
3646+
3647+ bh = udf_getblk(inode, block, create, err);
3648+ if (!bh)
3649+ return NULL;
3650+
3651+#if 0
3652+ if (create &&
3653+ S_ISDIR(inode->i_mode) &&
3654+ inode->i_blocks > prev_blocks)
3655+ {
3656+ int i;
3657+ struct buffer_head *tmp_bh = NULL;
3658+
3659+ for (i=1;
3660+ i < UDF_DEFAULT_PREALLOC_DIR_BLOCKS;
3661+ i++)
3662+ {
3663+ tmp_bh = udf_getblk(inode, block+i, create, err);
3664+ if (!tmp_bh)
3665+ {
3666+ udf_release_data(bh);
3667+ return 0;
3668+ }
3669+ udf_release_data(tmp_bh);
3670+ }
3671+ }
3672+#endif
3673+
3674+ if (buffer_uptodate(bh))
3675+ return bh;
3676+ ll_rw_block(READ, 1, &bh);
3677+ wait_on_buffer(bh);
3678+ if (buffer_uptodate(bh))
3679+ return bh;
3680+ brelse(bh);
3681+ *err = -EIO;
3682+ return NULL;
3683+}
3684+
3685+/*
3686+ * udf_read_inode
3687+ *
3688+ * PURPOSE
3689+ * Read an inode.
3690+ *
3691+ * DESCRIPTION
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.
3695+ *
3696+ * HISTORY
3697+ * July 1, 1997 - Andrew E. Mileski
3698+ * Written, tested, and released.
3699+ *
3700+ * 12/19/98 dgb Updated to fix size problems.
3701+ */
3702+void
3703+udf_read_inode(struct inode *inode)
3704+{
3705+ memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(lb_addr));
3706+}
3707+
3708+void
3709+__udf_read_inode(struct inode *inode)
3710+{
3711+ struct buffer_head *bh = NULL;
3712+ struct FileEntry *fe;
3713+ Uint16 ident;
3714+
3715+ /*
3716+ * Set defaults, but the inode is still incomplete!
3717+ * Note: get_new_inode() sets the following on a new inode:
3718+ * i_sb = sb
3719+ * i_dev = sb->s_dev;
3720+ * i_no = ino
3721+ * i_flags = sb->s_flags
3722+ * i_state = 0
3723+ * clean_inode(): zero fills and sets
3724+ * i_count = 1
3725+ * i_nlink = 1
3726+ * i_op = NULL;
3727+ */
3728+
3729+ inode->i_blksize = PAGE_SIZE;
3730+
3731+ bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
3732+
3733+ if (!bh)
3734+ {
3735+ printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",
3736+ inode->i_ino);
3737+ make_bad_inode(inode);
3738+ return;
3739+ }
3740+
3741+ if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY &&
3742+ ident != TID_UNALLOCATED_SPACE_ENTRY)
3743+ {
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);
3748+ return;
3749+ }
3750+
3751+ fe = (struct FileEntry *)bh->b_data;
3752+
3753+ if (le16_to_cpu(fe->icbTag.strategyType) == 4096)
3754+ {
3755+ struct buffer_head *ibh = NULL, *nbh = NULL;
3756+ struct IndirectEntry *ie;
3757+
3758+ ibh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1, &ident);
3759+ if (ident == TID_INDIRECT_ENTRY)
3760+ {
3761+ if (ibh)
3762+ {
3763+ lb_addr loc;
3764+ ie = (struct IndirectEntry *)ibh->b_data;
3765+
3766+ loc = lelb_to_cpu(ie->indirectICB.extLocation);
3767+
3768+ if (ie->indirectICB.extLength &&
3769+ (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident)))
3770+ {
3771+ if (ident == TID_FILE_ENTRY ||
3772+ ident == TID_EXTENDED_FILE_ENTRY)
3773+ {
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);
3779+ return;
3780+ }
3781+ else
3782+ {
3783+ udf_release_data(nbh);
3784+ udf_release_data(ibh);
3785+ }
3786+ }
3787+ else
3788+ udf_release_data(ibh);
3789+ }
3790+ }
3791+ else
3792+ udf_release_data(ibh);
3793+ }
3794+ else if (le16_to_cpu(fe->icbTag.strategyType) != 4)
3795+ {
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);
3800+ return;
3801+ }
3802+ udf_fill_inode(inode, bh);
3803+ udf_release_data(bh);
3804+}
3805+
3806+static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
3807+{
3808+ struct FileEntry *fe;
3809+ struct ExtendedFileEntry *efe;
3810+ time_t convtime;
3811+ long convtime_usec;
3812+ int offset, alen;
3813+
3814+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
3815+ inode->i_version = ++event;
3816+#else
3817+ inode->i_version = ++global_event;
3818+#endif
3819+ UDF_I_NEW_INODE(inode) = 0;
3820+
3821+ fe = (struct FileEntry *)bh->b_data;
3822+ efe = (struct ExtendedFileEntry *)bh->b_data;
3823+
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;
3828+
3829+ UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK;
3830+
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)
3836+ {
3837+ UDF_I_LENALLOC(inode) =
3838+ le32_to_cpu(
3839+ ((struct UnallocatedSpaceEntry *)bh->b_data)->lengthAllocDescs);
3840+ return;
3841+ }
3842+
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;
3845+
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;
3848+
3849+ inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
3850+ if (!inode->i_nlink)
3851+ inode->i_nlink = 1;
3852+
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;
3857+#endif
3858+
3859+ inode->i_mode = udf_convert_permissions(fe);
3860+ inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
3861+
3862+ UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
3863+ UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
3864+
3865+ if (UDF_I_EXTENDED_FE(inode) == 0)
3866+ {
3867+ inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
3868+ (inode->i_sb->s_blocksize_bits - 9);
3869+
3870+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
3871+ lets_to_cpu(fe->modificationTime)) )
3872+ {
3873+ inode->i_mtime = convtime;
3874+ UDF_I_UMTIME(inode) = convtime_usec;
3875+ inode->i_ctime = convtime;
3876+ UDF_I_UCTIME(inode) = convtime_usec;
3877+ }
3878+ else
3879+ {
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;
3884+ }
3885+
3886+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
3887+ lets_to_cpu(fe->accessTime)) )
3888+ {
3889+ inode->i_atime = convtime;
3890+ UDF_I_UATIME(inode) = convtime_usec;
3891+ }
3892+ else
3893+ {
3894+ inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
3895+ UDF_I_UATIME(inode) = convtime_usec;
3896+ }
3897+
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);
3903+ }
3904+ else
3905+ {
3906+ inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
3907+ (inode->i_sb->s_blocksize_bits - 9);
3908+
3909+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
3910+ lets_to_cpu(efe->modificationTime)) )
3911+ {
3912+ inode->i_mtime = convtime;
3913+ UDF_I_UMTIME(inode) = convtime_usec;
3914+ }
3915+ else
3916+ {
3917+ inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
3918+ UDF_I_UMTIME(inode) = 0;
3919+ }
3920+
3921+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
3922+ lets_to_cpu(efe->accessTime)) )
3923+ {
3924+ inode->i_atime = convtime;
3925+ UDF_I_UATIME(inode) = convtime_usec;
3926+ }
3927+ else
3928+ {
3929+ inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
3930+ UDF_I_UATIME(inode) = 0;
3931+ }
3932+
3933+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
3934+ lets_to_cpu(efe->createTime)) )
3935+ {
3936+ inode->i_ctime = convtime;
3937+ UDF_I_UCTIME(inode) = convtime_usec;
3938+ }
3939+ else
3940+ {
3941+ inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
3942+ UDF_I_UCTIME(inode) = 0;
3943+ }
3944+
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);
3950+ }
3951+
3952+ switch (fe->icbTag.fileType)
3953+ {
3954+ case FILE_TYPE_DIRECTORY:
3955+ {
3956+ inode->i_op = &udf_dir_inode_operations;
3957+ inode->i_mode |= S_IFDIR;
3958+ inode->i_nlink ++;
3959+ break;
3960+ }
3961+ case FILE_TYPE_REGULAR:
3962+ case FILE_TYPE_NONE:
3963+ {
3964+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
3965+ inode->i_op = &udf_file_inode_operations_adinicb;
3966+ else
3967+ inode->i_op = &udf_file_inode_operations;
3968+ inode->i_mode |= S_IFREG;
3969+ break;
3970+ }
3971+ case FILE_TYPE_BLOCK:
3972+ {
3973+ inode->i_op = &blkdev_inode_operations;
3974+ inode->i_mode |= S_IFBLK;
3975+ break;
3976+ }
3977+ case FILE_TYPE_CHAR:
3978+ {
3979+ inode->i_op = &chrdev_inode_operations;
3980+ inode->i_mode |= S_IFCHR;
3981+ break;
3982+ }
3983+ case FILE_TYPE_FIFO:
3984+ {
3985+ init_fifo(inode);
3986+ break;
3987+ }
3988+ case FILE_TYPE_SYMLINK:
3989+ {
3990+ /* untested! */
3991+ inode->i_op = &udf_symlink_inode_operations;
3992+ inode->i_mode = S_IFLNK|S_IRWXUGO;
3993+ break;
3994+ }
3995+ default:
3996+ {
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);
4000+ return;
4001+ }
4002+ }
4003+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
4004+ {
4005+ struct buffer_head *tbh = NULL;
4006+ struct DeviceSpecificationExtendedAttr *dsea =
4007+ (struct DeviceSpecificationExtendedAttr *)
4008+ udf_get_extendedattr(inode, 12, 1, &tbh);
4009+
4010+ if (dsea)
4011+ {
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);
4017+ }
4018+ else
4019+ {
4020+ make_bad_inode(inode);
4021+ }
4022+ }
4023+}
4024+
4025+static mode_t
4026+udf_convert_permissions(struct FileEntry *fe)
4027+{
4028+ mode_t mode;
4029+ Uint32 permissions;
4030+ Uint32 flags;
4031+
4032+ permissions = le32_to_cpu(fe->permissions);
4033+ flags = le16_to_cpu(fe->icbTag.flags);
4034+
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);
4041+
4042+ return mode;
4043+}
4044+
4045+/*
4046+ * udf_write_inode
4047+ *
4048+ * PURPOSE
4049+ * Write out the specified inode.
4050+ *
4051+ * DESCRIPTION
4052+ * This routine is called whenever an inode is synced.
4053+ * Currently this routine is just a placeholder.
4054+ *
4055+ * HISTORY
4056+ * July 1, 1997 - Andrew E. Mileski
4057+ * Written, tested, and released.
4058+ */
4059+
4060+void udf_write_inode(struct inode * inode)
4061+{
4062+ udf_update_inode(inode, 0);
4063+}
4064+
4065+int udf_sync_inode(struct inode * inode)
4066+{
4067+ return udf_update_inode(inode, 1);
4068+}
4069+
4070+static int
4071+udf_update_inode(struct inode *inode, int do_sync)
4072+{
4073+ struct buffer_head *bh = NULL;
4074+ struct FileEntry *fe;
4075+ struct ExtendedFileEntry *efe;
4076+ Uint32 udfperms;
4077+ Uint16 icbflags;
4078+ Uint16 crclen;
4079+ int i;
4080+ timestamp cpu_time;
4081+ int err = 0;
4082+
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);
4086+ if (!bh)
4087+ {
4088+ udf_debug("bread failure\n");
4089+ return -EIO;
4090+ }
4091+ fe = (struct FileEntry *)bh->b_data;
4092+ efe = (struct ExtendedFileEntry *)bh->b_data;
4093+ if (UDF_I_NEW_INODE(inode) == 1)
4094+ {
4095+ if (UDF_I_EXTENDED_FE(inode) == 0)
4096+ memset(bh->b_data, 0x0, sizeof(struct FileEntry));
4097+ else
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;
4103+ }
4104+
4105+ if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
4106+ {
4107+ struct UnallocatedSpaceEntry *use =
4108+ (struct UnallocatedSpaceEntry *)bh->b_data;
4109+
4110+ use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
4111+ crclen = sizeof(struct UnallocatedSpaceEntry) + UDF_I_LENALLOC(inode) -
4112+ sizeof(tag);
4113+ use->descTag.descCRCLength = cpu_to_le16(crclen);
4114+ use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0));
4115+
4116+ use->descTag.tagChecksum = 0;
4117+ for (i=0; i<16; i++)
4118+ if (i != 4)
4119+ use->descTag.tagChecksum += ((Uint8 *)&(use->descTag))[i];
4120+
4121+ mark_buffer_dirty(bh, 1);
4122+ udf_release_data(bh);
4123+ return err;
4124+ }
4125+
4126+ if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
4127+ fe->uid = cpu_to_le32(inode->i_uid);
4128+
4129+ if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid)
4130+ fe->gid = cpu_to_le32(inode->i_gid);
4131+
4132+ udfperms = ((inode->i_mode & S_IRWXO) ) |
4133+ ((inode->i_mode & S_IRWXG) << 2) |
4134+ ((inode->i_mode & S_IRWXU) << 4);
4135+
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);
4141+
4142+ if (S_ISDIR(inode->i_mode))
4143+ fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
4144+ else
4145+ fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
4146+
4147+ fe->informationLength = cpu_to_le64(inode->i_size);
4148+
4149+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
4150+ {
4151+ EntityID *eid;
4152+ struct buffer_head *tbh = NULL;
4153+ struct DeviceSpecificationExtendedAttr *dsea =
4154+ (struct DeviceSpecificationExtendedAttr *)
4155+ udf_get_extendedattr(inode, 12, 1, &tbh);
4156+
4157+ if (!dsea)
4158+ {
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) +
4166+ sizeof(EntityID);
4167+ dsea->impUseLength = sizeof(EntityID);
4168+ }
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);
4178+ }
4179+
4180+ if (UDF_I_EXTENDED_FE(inode) == 0)
4181+ {
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));
4185+
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);
4199+ }
4200+ else
4201+ {
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));
4205+
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);
4221+ }
4222+ if (UDF_I_STRAT4096(inode))
4223+ {
4224+ fe->icbTag.strategyType = cpu_to_le16(4096);
4225+ fe->icbTag.strategyParameter = cpu_to_le16(1);
4226+ fe->icbTag.numEntries = cpu_to_le16(2);
4227+ }
4228+ else
4229+ {
4230+ fe->icbTag.strategyType = cpu_to_le16(4);
4231+ fe->icbTag.numEntries = cpu_to_le16(1);
4232+ }
4233+
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;
4246+
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));
4254+
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));
4262+
4263+ fe->descTag.tagChecksum = 0;
4264+ for (i=0; i<16; i++)
4265+ if (i != 4)
4266+ fe->descTag.tagChecksum += ((Uint8 *)&(fe->descTag))[i];
4267+
4268+ /* write the data blocks */
4269+ mark_buffer_dirty(bh, 1);
4270+ if (do_sync)
4271+ {
4272+ ll_rw_block(WRITE, 1, &bh);
4273+ wait_on_buffer(bh);
4274+ if (buffer_req(bh) && !buffer_uptodate(bh))
4275+ {
4276+ printk("IO error syncing udf inode [%s:%08lx]\n",
4277+ bdevname(inode->i_dev), inode->i_ino);
4278+ err = -EIO;
4279+ }
4280+ }
4281+ udf_release_data(bh);
4282+ return err;
4283+}
4284+
4285+/*
4286+ * udf_iget
4287+ *
4288+ * PURPOSE
4289+ * Get an inode.
4290+ *
4291+ * DESCRIPTION
4292+ * This routine replaces iget() and read_inode().
4293+ *
4294+ * HISTORY
4295+ * October 3, 1997 - Andrew E. Mileski
4296+ * Written, tested, and released.
4297+ *
4298+ * 12/19/98 dgb Added semaphore and changed to be a wrapper of iget
4299+ */
4300+struct inode *
4301+udf_iget(struct super_block *sb, lb_addr ino)
4302+{
4303+ struct inode *inode;
4304+ unsigned long block;
4305+
4306+ block = udf_get_lb_pblock(sb, ino, 0);
4307+
4308+ /* Get the inode */
4309+
4310+ inode = iget(sb, block);
4311+ /* calls udf_read_inode() ! */
4312+
4313+ if (!inode)
4314+ {
4315+ printk(KERN_ERR "udf: iget() failed\n");
4316+ return NULL;
4317+ }
4318+ else if (is_bad_inode(inode))
4319+ {
4320+ iput(inode);
4321+ return NULL;
4322+ }
4323+ else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&
4324+ UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)
4325+ {
4326+ memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
4327+ __udf_read_inode(inode);
4328+ }
4329+
4330+ if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) )
4331+ {
4332+ udf_debug("block=%d, partition=%d out of range\n",
4333+ ino.logicalBlockNum, ino.partitionReferenceNum);
4334+ return NULL;
4335+ }
4336+
4337+ return inode;
4338+}
4339+
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)
4342+{
4343+ int adsize;
4344+ short_ad *sad = NULL;
4345+ long_ad *lad = NULL;
4346+ struct AllocExtDesc *aed;
4347+ int ret;
4348+
4349+ if (!(*bh))
4350+ {
4351+ if (!(*bh = udf_tread(inode->i_sb,
4352+ udf_get_lb_pblock(inode->i_sb, *bloc, 0),
4353+ inode->i_sb->s_blocksize)))
4354+ {
4355+ udf_debug("reading block %d failed!\n",
4356+ udf_get_lb_pblock(inode->i_sb, *bloc, 0));
4357+ return -1;
4358+ }
4359+ }
4360+
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);
4365+ else
4366+ return -1;
4367+
4368+ if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)
4369+ {
4370+ char *sptr, *dptr;
4371+ struct buffer_head *nbh;
4372+ int err, loffset;
4373+ lb_addr obloc = *bloc;
4374+
4375+ if (!(bloc->logicalBlockNum = udf_new_block(inode,
4376+ obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
4377+ {
4378+ return -1;
4379+ }
4380+ if (!(nbh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
4381+ *bloc, 0), inode->i_sb->s_blocksize)))
4382+ {
4383+ return -1;
4384+ }
4385+ aed = (struct AllocExtDesc *)(nbh->b_data);
4386+ aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
4387+ if (*extoffset + adsize > inode->i_sb->s_blocksize)
4388+ {
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;
4395+ }
4396+ else
4397+ {
4398+ loffset = *extoffset + adsize;
4399+ aed->lengthAllocDescs = cpu_to_le32(0);
4400+ sptr = (*bh)->b_data + *extoffset;
4401+ *extoffset = sizeof(struct AllocExtDesc);
4402+
4403+ if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
4404+ {
4405+ aed = (struct AllocExtDesc *)(*bh)->b_data;
4406+ aed->lengthAllocDescs =
4407+ cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
4408+ }
4409+ else
4410+ {
4411+ UDF_I_LENALLOC(inode) += adsize;
4412+ mark_inode_dirty(inode);
4413+ }
4414+ }
4415+ udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1,
4416+ bloc->logicalBlockNum, sizeof(tag));
4417+ switch (UDF_I_ALLOCTYPE(inode))
4418+ {
4419+ case ICB_FLAG_AD_SHORT:
4420+ {
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);
4426+ break;
4427+ }
4428+ case ICB_FLAG_AD_LONG:
4429+ {
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);
4435+ break;
4436+ }
4437+ }
4438+ udf_update_tag((*bh)->b_data, loffset);
4439+ mark_buffer_dirty(*bh, 1);
4440+ udf_release_data(*bh);
4441+ *bh = nbh;
4442+ }
4443+
4444+ ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
4445+
4446+ if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
4447+ {
4448+ UDF_I_LENALLOC(inode) += adsize;
4449+ mark_inode_dirty(inode);
4450+ }
4451+ else
4452+ {
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);
4458+ }
4459+
4460+ return ret;
4461+}
4462+
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)
4465+{
4466+ int adsize;
4467+ short_ad *sad = NULL;
4468+ long_ad *lad = NULL;
4469+
4470+ if (!(bh))
4471+ {
4472+ if (!(bh = udf_tread(inode->i_sb,
4473+ udf_get_lb_pblock(inode->i_sb, bloc, 0),
4474+ inode->i_sb->s_blocksize)))
4475+ {
4476+ udf_debug("reading block %d failed!\n",
4477+ udf_get_lb_pblock(inode->i_sb, bloc, 0));
4478+ return -1;
4479+ }
4480+ }
4481+ else
4482+ bh->b_count ++;
4483+
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);
4488+ else
4489+ return -1;
4490+
4491+ switch (UDF_I_ALLOCTYPE(inode))
4492+ {
4493+ case ICB_FLAG_AD_SHORT:
4494+ {
4495+ sad = (short_ad *)((bh)->b_data + *extoffset);
4496+ sad->extLength = cpu_to_le32(elen);
4497+ sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
4498+ break;
4499+ }
4500+ case ICB_FLAG_AD_LONG:
4501+ {
4502+ lad = (long_ad *)((bh)->b_data + *extoffset);
4503+ lad->extLength = cpu_to_le32(elen);
4504+ lad->extLocation = cpu_to_lelb(eloc);
4505+ break;
4506+ }
4507+ }
4508+
4509+ if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
4510+ {
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));
4514+ }
4515+ else
4516+ mark_inode_dirty(inode);
4517+
4518+ mark_buffer_dirty(bh, 1);
4519+
4520+ if (inc)
4521+ *extoffset += adsize;
4522+ udf_release_data(bh);
4523+ return (elen >> 30);
4524+}
4525+
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)
4528+{
4529+ Uint16 tagIdent;
4530+ int pos, alen;
4531+ Uint8 etype;
4532+
4533+ if (!(*bh))
4534+ {
4535+ if (!(*bh = udf_tread(inode->i_sb,
4536+ udf_get_lb_pblock(inode->i_sb, *bloc, 0),
4537+ inode->i_sb->s_blocksize)))
4538+ {
4539+ udf_debug("reading block %d failed!\n",
4540+ udf_get_lb_pblock(inode->i_sb, *bloc, 0));
4541+ return -1;
4542+ }
4543+ }
4544+
4545+ tagIdent = ((tag *)(*bh)->b_data)->tagIdent;
4546+
4547+ if (tagIdent == TID_FILE_ENTRY || tagIdent == TID_EXTENDED_FILE_ENTRY ||
4548+ UDF_I_NEW_INODE(inode))
4549+ {
4550+ pos = udf_file_entry_alloc_offset(inode);
4551+ alen = UDF_I_LENALLOC(inode) + pos;
4552+ }
4553+ else if (tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
4554+ {
4555+ pos = sizeof(struct UnallocatedSpaceEntry);
4556+ alen = UDF_I_LENALLOC(inode) + pos;
4557+ }
4558+ else if (tagIdent == TID_ALLOC_EXTENT_DESC)
4559+ {
4560+ struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data;
4561+
4562+ pos = sizeof(struct AllocExtDesc);
4563+ alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
4564+ }
4565+ else
4566+ return -1;
4567+
4568+ if (!(*extoffset))
4569+ *extoffset = pos;
4570+
4571+ switch (UDF_I_ALLOCTYPE(inode))
4572+ {
4573+ case ICB_FLAG_AD_SHORT:
4574+ {
4575+ short_ad *sad;
4576+
4577+ if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
4578+ return -1;
4579+
4580+ if ((etype = le32_to_cpu(sad->extLength) >> 30) == EXTENT_NEXT_EXTENT_ALLOCDECS)
4581+ {
4582+ bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
4583+ *extoffset = 0;
4584+ udf_release_data(*bh);
4585+ *bh = NULL;
4586+ return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
4587+ }
4588+ else
4589+ {
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;
4593+ }
4594+ break;
4595+ }
4596+ case ICB_FLAG_AD_LONG:
4597+ {
4598+ long_ad *lad;
4599+
4600+ if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
4601+ return -1;
4602+
4603+ if ((etype = le32_to_cpu(lad->extLength) >> 30) == EXTENT_NEXT_EXTENT_ALLOCDECS)
4604+ {
4605+ *bloc = lelb_to_cpu(lad->extLocation);
4606+ *extoffset = 0;
4607+ udf_release_data(*bh);
4608+ *bh = NULL;
4609+ return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
4610+ }
4611+ else
4612+ {
4613+ *eloc = lelb_to_cpu(lad->extLocation);
4614+ *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
4615+ }
4616+ break;
4617+ }
4618+ case ICB_FLAG_AD_IN_ICB:
4619+ {
4620+ if (UDF_I_LENALLOC(inode) == 0)
4621+ return -1;
4622+ etype = EXTENT_RECORDED_ALLOCATED;
4623+ *eloc = UDF_I_LOCATION(inode);
4624+ *elen = UDF_I_LENALLOC(inode);
4625+ break;
4626+ }
4627+ default:
4628+ {
4629+ udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
4630+ return -1;
4631+ }
4632+ }
4633+ if (*elen)
4634+ return etype;
4635+
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);
4642+ return -1;
4643+}
4644+
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)
4647+{
4648+ int pos, alen;
4649+ Uint8 etype;
4650+
4651+ if (!(*bh))
4652+ {
4653+ if (!(*bh = udf_tread(inode->i_sb,
4654+ udf_get_lb_pblock(inode->i_sb, *bloc, 0),
4655+ inode->i_sb->s_blocksize)))
4656+ {
4657+ udf_debug("reading block %d failed!\n",
4658+ udf_get_lb_pblock(inode->i_sb, *bloc, 0));
4659+ return -1;
4660+ }
4661+ udf_debug("new bh, count=%d\n", (*bh)->b_count);
4662+ }
4663+
4664+ if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
4665+ {
4666+ if (!(UDF_I_EXTENDED_FE(inode)))
4667+ pos = sizeof(struct FileEntry) + UDF_I_LENEATTR(inode);
4668+ else
4669+ pos = sizeof(struct ExtendedFileEntry) + UDF_I_LENEATTR(inode);
4670+ alen = UDF_I_LENALLOC(inode) + pos;
4671+ }
4672+ else
4673+ {
4674+ struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data;
4675+
4676+ pos = sizeof(struct AllocExtDesc);
4677+ alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
4678+ }
4679+
4680+ if (!(*extoffset))
4681+ *extoffset = pos;
4682+
4683+ switch (UDF_I_ALLOCTYPE(inode))
4684+ {
4685+ case ICB_FLAG_AD_SHORT:
4686+ {
4687+ short_ad *sad;
4688+
4689+ if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
4690+ return -1;
4691+
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;
4696+ break;
4697+ }
4698+ case ICB_FLAG_AD_LONG:
4699+ {
4700+ long_ad *lad;
4701+
4702+ if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
4703+ return -1;
4704+
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;
4708+ break;
4709+ }
4710+ default:
4711+ {
4712+ udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
4713+ return -1;
4714+ }
4715+ }
4716+ if (*elen)
4717+ return etype;
4718+
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);
4724+ return -1;
4725+}
4726+
4727+int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
4728+ lb_addr neloc, Uint32 nelen, struct buffer_head *bh)
4729+{
4730+ lb_addr oeloc;
4731+ Uint32 oelen;
4732+ int type;
4733+
4734+ if (!bh)
4735+ {
4736+ if (!(bh = udf_tread(inode->i_sb,
4737+ udf_get_lb_pblock(inode->i_sb, bloc, 0),
4738+ inode->i_sb->s_blocksize)))
4739+ {
4740+ udf_debug("reading block %d failed!\n",
4741+ udf_get_lb_pblock(inode->i_sb, bloc, 0));
4742+ return -1;
4743+ }
4744+ }
4745+ else
4746+ bh->b_count ++;
4747+
4748+ while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
4749+ {
4750+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
4751+
4752+ neloc = oeloc;
4753+ nelen = (type << 30) | oelen;
4754+ }
4755+ udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
4756+ udf_release_data(bh);
4757+ return (nelen >> 30);
4758+}
4759+
4760+int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
4761+ lb_addr eloc, Uint32 elen, struct buffer_head *nbh)
4762+{
4763+ struct buffer_head *obh;
4764+ lb_addr obloc;
4765+ int oextoffset, adsize;
4766+ char type;
4767+ struct AllocExtDesc *aed;
4768+
4769+ if (!(nbh))
4770+ {
4771+ if (!(nbh = udf_tread(inode->i_sb,
4772+ udf_get_lb_pblock(inode->i_sb, nbloc, 0),
4773+ inode->i_sb->s_blocksize)))
4774+ {
4775+ udf_debug("reading block %d failed!\n",
4776+ udf_get_lb_pblock(inode->i_sb, nbloc, 0));
4777+ return -1;
4778+ }
4779+ }
4780+ else
4781+ nbh->b_count ++;
4782+ nbh->b_count ++;
4783+
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);
4788+ else
4789+ adsize = 0;
4790+
4791+ obh = nbh;
4792+ obloc = nbloc;
4793+ oextoffset = nextoffset;
4794+
4795+ if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)
4796+ return -1;
4797+
4798+ while ((type = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
4799+ {
4800+ udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, obh, 1);
4801+ if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
4802+ {
4803+ obloc = nbloc;
4804+ udf_release_data(obh);
4805+ nbh->b_count ++;
4806+ obh = nbh;
4807+ oextoffset = nextoffset - adsize;
4808+ }
4809+ }
4810+ memset(&eloc, 0x00, sizeof(lb_addr));
4811+ elen = 0;
4812+
4813+ if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
4814+ {
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)))
4819+ {
4820+ UDF_I_LENALLOC(inode) -= (adsize * 2);
4821+ mark_inode_dirty(inode);
4822+ }
4823+ else
4824+ {
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);
4830+ }
4831+ }
4832+ else
4833+ {
4834+ udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
4835+ if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
4836+ {
4837+ UDF_I_LENALLOC(inode) -= adsize;
4838+ mark_inode_dirty(inode);
4839+ }
4840+ else
4841+ {
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);
4847+ }
4848+ }
4849+
4850+ udf_release_data(nbh);
4851+ udf_release_data(obh);
4852+ return (elen >> 30);
4853+}
4854+
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)
4857+{
4858+ int etype, lbcount = 0;
4859+
4860+ if (block < 0)
4861+ {
4862+ printk(KERN_ERR "udf: inode_bmap: block < 0\n");
4863+ return -1;
4864+ }
4865+ if (!inode)
4866+ {
4867+ printk(KERN_ERR "udf: inode_bmap: NULL inode\n");
4868+ return -1;
4869+ }
4870+
4871+ *extoffset = 0;
4872+ *elen = 0;
4873+ *bloc = UDF_I_LOCATION(inode);
4874+
4875+ do
4876+ {
4877+ if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
4878+ {
4879+ *offset = block - lbcount;
4880+ return -1;
4881+ }
4882+ lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >>
4883+ inode->i_sb->s_blocksize_bits);
4884+ } while (lbcount <= block);
4885+
4886+ *offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >>
4887+ inode->i_sb->s_blocksize_bits) - lbcount;
4888+
4889+ return etype;
4890+}
4891+
4892+int udf_bmap(struct inode *inode, int block)
4893+{
4894+ lb_addr eloc, bloc;
4895+ Uint32 offset, extoffset, elen;
4896+ struct buffer_head *bh = NULL;
4897+ int ret;
4898+
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);
4901+ else
4902+ ret = 0;
4903+
4904+ if (bh)
4905+ udf_release_data(bh);
4906+
4907+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
4908+ return udf_fixed_to_variable(ret);
4909+ else
4910+ return ret;
4911+}
4912+
4913+int udf_readpage_adinicb (struct file * file, struct page * page)
4914+{
4915+ struct inode * inode;
4916+ struct buffer_head *bh;
4917+ int block;
4918+
4919+ inode = file->f_dentry->d_inode;
4920+
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))
4925+ {
4926+ ll_rw_block (READ, 1, &bh);
4927+ wait_on_buffer(bh);
4928+ }
4929+ memcpy((char *)page_address(page), bh->b_data + udf_ext0_offset(inode),
4930+ inode->i_size);
4931+ brelse(bh);
4932+ set_bit(PG_uptodate, &page->flags);
4933+ return 0;
4934+}
4935diff -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
4938@@ -0,0 +1,390 @@
4939+/*
4940+ * lowlevel.c
4941+ *
4942+ * PURPOSE
4943+ * Low Level Device Routines for the UDF filesystem
4944+ *
4945+ * CONTACTS
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
4949+ *
4950+ * COPYRIGHT
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.
4955+ *
4956+ * (C) 1999-2000 Ben Fennema
4957+ *
4958+ * HISTORY
4959+ *
4960+ * 03/26/99 blf Created.
4961+ */
4962+
4963+#include "udfdecl.h"
4964+
4965+#include <linux/blkdev.h>
4966+#include <linux/cdrom.h>
4967+#include <asm/uaccess.h>
4968+#include <scsi/scsi.h>
4969+
4970+typedef struct scsi_device Scsi_Device;
4971+typedef struct scsi_cmnd Scsi_Cmnd;
4972+
4973+#include <scsi/scsi_ioctl.h>
4974+
4975+#include <linux/udf_fs.h>
4976+#include "udf_sb.h"
4977+
4978+unsigned int
4979+udf_get_last_session(struct super_block *sb)
4980+{
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);
4986+ int i;
4987+
4988+ vol_desc_start=0;
4989+ if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
4990+ {
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]
4994+ */
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,
5000+ NULL,
5001+ CDROMMULTISESSION,
5002+ (unsigned long) &ms_info);
5003+ set_fs(old_fs);
5004+
5005+#define WE_OBEY_THE_WRITTEN_STANDARDS 1
5006+
5007+ if (i == 0)
5008+ {
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 */
5013+#endif
5014+ vol_desc_start = ms_info.addr.lba;
5015+ }
5016+ else
5017+ {
5018+ udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i);
5019+ }
5020+ }
5021+ else
5022+ {
5023+ udf_debug("Device doesn't know how to ioctl?\n");
5024+ }
5025+ return vol_desc_start;
5026+}
5027+
5028+#ifdef CDROM_LAST_WRITTEN
5029+
5030+static unsigned int
5031+udf_get_last_written(kdev_t dev, struct inode *inode_fake)
5032+{
5033+ extern struct file_operations * get_blkfops(unsigned int);
5034+ unsigned long lastsector;
5035+
5036+ if (!(get_blkfops(MAJOR(dev))->ioctl(inode_fake,
5037+ NULL,
5038+ CDROM_LAST_WRITTEN,
5039+ (unsigned long) &lastsector)))
5040+ {
5041+ return lastsector - 1;
5042+ }
5043+ else
5044+ return 0;
5045+}
5046+
5047+#else
5048+
5049+static int
5050+do_scsi(kdev_t dev, struct inode *inode_fake, Uint8 *command, int cmd_len,
5051+ Uint8 *buffer, Uint32 in_len, Uint32 out_len)
5052+{
5053+ extern struct file_operations * get_blkfops(unsigned int);
5054+ Uint32 *ip;
5055+
5056+ ip = (Uint32 *)buffer;
5057+ ip[0] = in_len;
5058+ ip[1] = out_len;
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);
5062+}
5063+
5064+static unsigned int
5065+udf_get_last_rti(kdev_t dev, struct inode *inode_fake)
5066+{
5067+ char buffer[128];
5068+ int result = 0;
5069+ int *ip;
5070+ int track_no;
5071+ Uint32 trackstart, tracklength, freeblocks;
5072+ Uint8 cdb[10];
5073+ unsigned long lastsector = 0;
5074+ int len;
5075+
5076+ ip = (int *)(buffer + 8);
5077+ memset(cdb, 0, 10);
5078+ cdb[0] = 0x51;
5079+ cdb[8] = 32;
5080+ result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, 32);
5081+ if (!result)
5082+ {
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);
5087+ cdb[0] = 0x52;
5088+ cdb[1] = 1;
5089+ cdb[4] = (track_no & 0xFF00) >> 8;
5090+ cdb[5] = track_no & 0xFF;
5091+ cdb[8] = 8;
5092+ result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, 8);
5093+ if (!result)
5094+ {
5095+ len = cdb[8] = ((buffer[8] << 8) | (buffer[9] & 0xFF)) + 2;
5096+ result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, len);
5097+ if (!result)
5098+ {
5099+ if (buffer[14] & 0x40)
5100+ {
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);
5104+ }
5105+ if (!result)
5106+ {
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)
5112+ {
5113+ if (buffer[14] & 0x10)
5114+ {
5115+ udf_debug("Packet size is %d.\n", be32_to_cpu(ip[5]));
5116+ lastsector = trackstart + tracklength - 1;
5117+ }
5118+ else
5119+ {
5120+ udf_debug("Variable packet written track.\n");
5121+ lastsector = trackstart + tracklength - 1;
5122+ if (freeblocks)
5123+ {
5124+ lastsector = lastsector - freeblocks - 7;
5125+ }
5126+ }
5127+ }
5128+ }
5129+ }
5130+ }
5131+ }
5132+ return lastsector;
5133+}
5134+
5135+static unsigned int
5136+udf_get_toc_entry(kdev_t dev, struct inode *inode_fake)
5137+{
5138+ extern struct file_operations * get_blkfops(unsigned int);
5139+ struct cdrom_tocentry toc;
5140+ int res, lastsector = 0;
5141+
5142+ toc.cdte_format = CDROM_LBA;
5143+ toc.cdte_track = 0xAA;
5144+
5145+ if (!(res = get_blkfops(MAJOR(dev))->ioctl(inode_fake,
5146+ NULL,
5147+ CDROMREADTOCENTRY,
5148+ (unsigned long) &toc)))
5149+ {
5150+ lastsector = toc.cdte_addr.lba - 1;
5151+ }
5152+
5153+ return lastsector;
5154+}
5155+
5156+static unsigned int
5157+udf_get_capacity(kdev_t dev, struct inode *inode_fake)
5158+{
5159+ char buffer[128];
5160+ int result = 0;
5161+ int *ip;
5162+ Uint8 cdb[10];
5163+ unsigned long lastsector = 0;
5164+
5165+ ip = (int *)(buffer + 8);
5166+ memset(cdb, 0, 10);
5167+
5168+ cdb[0] = READ_CAPACITY;
5169+ result = do_scsi(dev, inode_fake, cdb, 10, buffer, 0, 8);
5170+ if (!result)
5171+ lastsector = be32_to_cpu(ip[0]);
5172+
5173+ return lastsector;
5174+}
5175+
5176+static int
5177+is_mmc(kdev_t dev, struct inode *inode_fake)
5178+{
5179+ Uint8 buffer[142];
5180+ int result = 0, n;
5181+ Uint8 cdb[6];
5182+ Uint8 *data = &buffer[8];
5183+ int len = 4;
5184+
5185+ cdb[0] = MODE_SENSE;
5186+ cdb[2] = 0x2A;
5187+ cdb[4] = len;
5188+ cdb[1] = cdb[3] = cdb[5] = 0;
5189+
5190+ memset(buffer, 0, 142);
5191+ result = do_scsi(dev, inode_fake, cdb, 6, buffer, 0, len);
5192+ if (!result)
5193+ {
5194+ len = cdb[4] = data[3] + 4 + 2;
5195+ result = do_scsi(dev, inode_fake, cdb, 6, buffer, 0, len);
5196+ if (!result)
5197+ {
5198+ n = data[3] + 4;
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))
5202+ {
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));
5254+ }
5255+ else
5256+ return 0;
5257+ }
5258+ }
5259+ return !result;
5260+}
5261+
5262+#endif
5263+
5264+unsigned int
5265+udf_get_last_block(struct super_block *sb)
5266+{
5267+ kdev_t dev = sb->s_dev;
5268+ struct inode inode_fake;
5269+ extern struct file_operations * get_blkfops(unsigned int);
5270+ int ret;
5271+ unsigned long lblock;
5272+ int accurate = 0;
5273+
5274+ if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
5275+ {
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]
5279+ */
5280+ mm_segment_t old_fs=get_fs();
5281+ inode_fake.i_rdev=dev;
5282+ set_fs(KERNEL_DS);
5283+
5284+ lblock = 0;
5285+ ret = get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
5286+ NULL,
5287+ BLKGETSIZE,
5288+ (unsigned long) &lblock);
5289+
5290+ if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
5291+ {
5292+ udf_debug("BLKGETSIZE lblock=%ld\n", lblock);
5293+ lblock = ((512 * lblock) / sb->s_blocksize) - 1;
5294+ accurate = 1;
5295+ }
5296+ else /* CDROM */
5297+ {
5298+#ifdef CDROM_LAST_WRITTEN
5299+ if ((lblock = udf_get_last_written(dev, &inode_fake)))
5300+ {
5301+ udf_debug("last_written lblock=%ld\n", lblock);
5302+ accurate = 1;
5303+ }
5304+#else
5305+ if (is_mmc(dev, &inode_fake) &&
5306+ (lblock = udf_get_last_rti(dev, &inode_fake)))
5307+ {
5308+ udf_debug("LAST_RTI lblock=%ld\n", lblock);
5309+ }
5310+ else if ((lblock = udf_get_toc_entry(dev, &inode_fake)))
5311+ {
5312+ udf_debug("TOC_ENTRY lblock=%ld\n", lblock);
5313+ }
5314+ else if ((lblock = udf_get_capacity(dev, &inode_fake)))
5315+ {
5316+ udf_debug("READ_CAPACITY lblock=%ld\n", lblock);
5317+ }
5318+#endif
5319+ }
5320+ set_fs(old_fs);
5321+ return lblock;
5322+ }
5323+ else
5324+ {
5325+ udf_debug("Device doesn't know how to ioctl?\n");
5326+ }
5327+ return 0;
5328+}
5329diff -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
5332@@ -0,0 +1,515 @@
5333+/*
5334+ * misc.c
5335+ *
5336+ * PURPOSE
5337+ * Miscellaneous routines for the OSTA-UDF(tm) filesystem.
5338+ *
5339+ * CONTACTS
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
5343+ *
5344+ * COPYRIGHT
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.
5349+ *
5350+ * (C) 1998 Dave Boynton
5351+ * (C) 1998-2000 Ben Fennema
5352+ * (C) 1999-2000 Stelias Computing Inc
5353+ *
5354+ * HISTORY
5355+ *
5356+ * 04/19/99 blf partial support for reading/writing specific EA's
5357+ */
5358+
5359+#include "udfdecl.h"
5360+
5361+#if defined(__linux__) && defined(__KERNEL__)
5362+
5363+#include "udf_sb.h"
5364+#include "udf_i.h"
5365+
5366+#include <linux/fs.h>
5367+#include <linux/string.h>
5368+#include <linux/udf_fs.h>
5369+
5370+#else
5371+
5372+#include <sys/types.h>
5373+#include <stdio.h>
5374+#include <unistd.h>
5375+#include <string.h>
5376+
5377+int udf_blocksize=0;
5378+int udf_errno=0;
5379+
5380+void
5381+udf_setblocksize(int size)
5382+{
5383+ udf_blocksize=size;
5384+}
5385+#endif
5386+
5387+Uint32
5388+udf64_low32(Uint64 indat)
5389+{
5390+ return indat & 0x00000000FFFFFFFFULL;
5391+}
5392+
5393+Uint32
5394+udf64_high32(Uint64 indat)
5395+{
5396+ return indat >> 32;
5397+}
5398+
5399+uid_t udf_convert_uid(int uidin)
5400+{
5401+ if ( uidin == -1 )
5402+ return 0;
5403+ if ( uidin > (64*1024U - 1) ) /* 16 bit UID */
5404+ return 0;
5405+ return uidin;
5406+}
5407+
5408+gid_t udf_convert_gid(int gidin)
5409+{
5410+ if ( gidin == -1 )
5411+ return 0;
5412+ if ( gidin > (64*1024U - 1) ) /* 16 bit GID */
5413+ return 0;
5414+ return gidin;
5415+}
5416+
5417+#if defined(__linux__) && defined(__KERNEL__)
5418+
5419+extern struct buffer_head *
5420+udf_tread(struct super_block *sb, int block, int size)
5421+{
5422+ if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
5423+ return bread(sb->s_dev, udf_fixed_to_variable(block), size);
5424+ else
5425+ return bread(sb->s_dev, block, size);
5426+}
5427+
5428+extern struct GenericAttrFormat *
5429+udf_add_extendedattr(struct inode * inode, Uint32 size, Uint32 type,
5430+ Uint8 loc, struct buffer_head **bh)
5431+{
5432+ Uint8 *ea = NULL, *ad = NULL;
5433+ long_ad eaicb;
5434+ int offset;
5435+
5436+ *bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
5437+
5438+ if (UDF_I_EXTENDED_FE(inode) == 0)
5439+ {
5440+ struct FileEntry *fe;
5441+
5442+ fe = (struct FileEntry *)(*bh)->b_data;
5443+ eaicb = lela_to_cpu(fe->extendedAttrICB);
5444+ offset = sizeof(struct FileEntry);
5445+ }
5446+ else
5447+ {
5448+ struct ExtendedFileEntry *efe;
5449+
5450+ efe = (struct ExtendedFileEntry *)(*bh)->b_data;
5451+ eaicb = lela_to_cpu(efe->extendedAttrICB);
5452+ offset = sizeof(struct ExtendedFileEntry);
5453+ }
5454+
5455+ ea = &(*bh)->b_data[offset];
5456+ if (UDF_I_LENEATTR(inode))
5457+ offset += UDF_I_LENEATTR(inode);
5458+ else
5459+ size += sizeof(struct ExtendedAttrHeaderDesc);
5460+
5461+ ad = &(*bh)->b_data[offset];
5462+ if (UDF_I_LENALLOC(inode))
5463+ offset += UDF_I_LENALLOC(inode);
5464+
5465+ offset = inode->i_sb->s_blocksize - offset;
5466+
5467+ /* TODO - Check for FreeEASpace */
5468+
5469+ if (loc & 0x01 && offset >= size)
5470+ {
5471+ struct ExtendedAttrHeaderDesc *eahd;
5472+ eahd = (struct ExtendedAttrHeaderDesc *)ea;
5473+
5474+ if (UDF_I_LENALLOC(inode))
5475+ {
5476+ memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
5477+ }
5478+
5479+ if (UDF_I_LENEATTR(inode))
5480+ {
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)
5484+ {
5485+ udf_release_data(*bh);
5486+ return NULL;
5487+ }
5488+ }
5489+ else
5490+ {
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);
5499+ }
5500+
5501+ offset = UDF_I_LENEATTR(inode);
5502+ if (type < 2048)
5503+ {
5504+ if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
5505+ {
5506+ Uint32 aal = le32_to_cpu(eahd->appAttrLocation);
5507+ memmove(&ea[offset - aal + size],
5508+ &ea[aal], offset - aal);
5509+ offset -= aal;
5510+ eahd->appAttrLocation = cpu_to_le32(aal + size);
5511+ }
5512+ if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode))
5513+ {
5514+ Uint32 ial = le32_to_cpu(eahd->impAttrLocation);
5515+ memmove(&ea[offset - ial + size],
5516+ &ea[ial], offset - ial);
5517+ offset -= ial;
5518+ eahd->impAttrLocation = cpu_to_le32(ial + size);
5519+ }
5520+ }
5521+ else if (type < 65536)
5522+ {
5523+ if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
5524+ {
5525+ Uint32 aal = le32_to_cpu(eahd->appAttrLocation);
5526+ memmove(&ea[offset - aal + size],
5527+ &ea[aal], offset - aal);
5528+ offset -= aal;
5529+ eahd->appAttrLocation = cpu_to_le32(aal + size);
5530+ }
5531+ }
5532+ /* rewrite CRC + checksum of eahd */
5533+ UDF_I_LENEATTR(inode) += size;
5534+ return (struct GenericAttrFormat *)&ea[offset];
5535+ }
5536+ if (loc & 0x02)
5537+ {
5538+ }
5539+ udf_release_data(*bh);
5540+ return NULL;
5541+}
5542+
5543+extern struct GenericAttrFormat *
5544+udf_get_extendedattr(struct inode * inode, Uint32 type, Uint8 subtype,
5545+ struct buffer_head **bh)
5546+{
5547+ struct GenericAttrFormat *gaf;
5548+ Uint8 *ea = NULL;
5549+ long_ad eaicb;
5550+ Uint32 offset;
5551+
5552+ *bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
5553+
5554+ if (UDF_I_EXTENDED_FE(inode) == 0)
5555+ {
5556+ struct FileEntry *fe;
5557+
5558+ fe = (struct FileEntry *)(*bh)->b_data;
5559+ eaicb = lela_to_cpu(fe->extendedAttrICB);
5560+ if (UDF_I_LENEATTR(inode))
5561+ ea = fe->extendedAttr;
5562+ }
5563+ else
5564+ {
5565+ struct ExtendedFileEntry *efe;
5566+
5567+ efe = (struct ExtendedFileEntry *)(*bh)->b_data;
5568+ eaicb = lela_to_cpu(efe->extendedAttrICB);
5569+ if (UDF_I_LENEATTR(inode))
5570+ ea = efe->extendedAttr;
5571+ }
5572+
5573+ if (UDF_I_LENEATTR(inode))
5574+ {
5575+ struct ExtendedAttrHeaderDesc *eahd;
5576+ eahd = (struct ExtendedAttrHeaderDesc *)ea;
5577+
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)
5581+ {
5582+ udf_release_data(*bh);
5583+ return NULL;
5584+ }
5585+
5586+ if (type < 2048)
5587+ offset = sizeof(struct ExtendedAttrHeaderDesc);
5588+ else if (type < 65536)
5589+ offset = le32_to_cpu(eahd->impAttrLocation);
5590+ else
5591+ offset = le32_to_cpu(eahd->appAttrLocation);
5592+
5593+ while (offset < UDF_I_LENEATTR(inode))
5594+ {
5595+ gaf = (struct GenericAttrFormat *)&ea[offset];
5596+ if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
5597+ return gaf;
5598+ else
5599+ offset += le32_to_cpu(gaf->attrLength);
5600+ }
5601+ }
5602+
5603+ udf_release_data(*bh);
5604+ if (eaicb.extLength)
5605+ {
5606+ /* TODO */
5607+ }
5608+ return NULL;
5609+}
5610+
5611+extern struct buffer_head *
5612+udf_read_untagged(struct super_block *sb, Uint32 block, Uint32 offset)
5613+{
5614+ struct buffer_head *bh = NULL;
5615+
5616+ /* Read the block */
5617+ bh = udf_tread(sb, block+offset, sb->s_blocksize);
5618+ if (!bh)
5619+ {
5620+ printk(KERN_ERR "udf: udf_read_untagged(%p,%d,%d) failed\n",
5621+ sb, block, offset);
5622+ return NULL;
5623+ }
5624+ return bh;
5625+}
5626+
5627+/*
5628+ * udf_read_tagged
5629+ *
5630+ * PURPOSE
5631+ * Read the first block of a tagged descriptor.
5632+ *
5633+ * HISTORY
5634+ * July 1, 1997 - Andrew E. Mileski
5635+ * Written, tested, and released.
5636+ */
5637+extern struct buffer_head *
5638+udf_read_tagged(struct super_block *sb, Uint32 block, Uint32 location, Uint16 *ident)
5639+{
5640+ tag *tag_p;
5641+ struct buffer_head *bh = NULL;
5642+ register Uint8 checksum;
5643+ register int i;
5644+
5645+ /* Read the block */
5646+ if (block == 0xFFFFFFFF)
5647+ return NULL;
5648+
5649+ bh = udf_tread(sb, block, sb->s_blocksize);
5650+ if (!bh)
5651+ {
5652+ udf_debug("block=%d, location=%d: read failed\n", block, location);
5653+ return NULL;
5654+ }
5655+
5656+ tag_p = (tag *)(bh->b_data);
5657+
5658+ *ident = le16_to_cpu(tag_p->tagIdent);
5659+
5660+ if ( location != le32_to_cpu(tag_p->tagLocation) )
5661+ {
5662+ udf_debug("location mismatch block %d, tag %d != %d\n",
5663+ block, le32_to_cpu(tag_p->tagLocation), location);
5664+ goto error_out;
5665+ }
5666+
5667+ /* Verify the tag checksum */
5668+ checksum = 0U;
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);
5675+ goto error_out;
5676+ }
5677+
5678+ /* Verify the tag version */
5679+ if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
5680+ le16_to_cpu(tag_p->descVersion) != 0x0003U)
5681+ {
5682+ udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
5683+ le16_to_cpu(tag_p->descVersion), block);
5684+ goto error_out;
5685+ }
5686+
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))
5691+ {
5692+ return bh;
5693+ }
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));
5696+
5697+error_out:
5698+ brelse(bh);
5699+ return NULL;
5700+}
5701+
5702+extern struct buffer_head *
5703+udf_read_ptagged(struct super_block *sb, lb_addr loc, Uint32 offset, Uint16 *ident)
5704+{
5705+ return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
5706+ loc.logicalBlockNum + offset, ident);
5707+}
5708+
5709+void udf_release_data(struct buffer_head *bh)
5710+{
5711+ if (bh)
5712+ brelse(bh);
5713+}
5714+
5715+#endif
5716+
5717+void udf_update_tag(char *data, int length)
5718+{
5719+ tag *tptr = (tag *)data;
5720+ int i;
5721+
5722+ length -= sizeof(tag);
5723+
5724+ tptr->tagChecksum = 0;
5725+ tptr->descCRCLength = le16_to_cpu(length);
5726+ tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0));
5727+
5728+ for (i=0; i<16; i++)
5729+ if (i != 4)
5730+ tptr->tagChecksum += (Uint8)(data[i]);
5731+}
5732+
5733+void udf_new_tag(char *data, Uint16 ident, Uint16 version, Uint16 snum,
5734+ Uint32 loc, int length)
5735+{
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);
5742+}
5743+
5744+#ifndef __KERNEL__
5745+/*
5746+ * udf_read_tagged_data
5747+ *
5748+ * PURPOSE
5749+ * Read the first block of a tagged descriptor.
5750+ * Usable from user-land.
5751+ *
5752+ * HISTORY
5753+ * 10/4/98 dgb: written
5754+ */
5755+int
5756+udf_read_tagged_data(char *buffer, int size, int fd, int block, int offset)
5757+{
5758+ tag *tag_p;
5759+ register Uint8 checksum;
5760+ register int i;
5761+ unsigned long offs;
5762+
5763+ if (!buffer)
5764+ {
5765+ udf_errno = 1;
5766+ return -1;
5767+ }
5768+
5769+ if ( !udf_blocksize )
5770+ {
5771+ udf_errno = 2;
5772+ return -1;
5773+ }
5774+
5775+ if ( size < udf_blocksize )
5776+ {
5777+ udf_errno=3;
5778+ return -1;
5779+ }
5780+ udf_errno=0;
5781+
5782+ offs=(long)block * udf_blocksize;
5783+ if ( lseek(fd, offs, SEEK_SET) != offs ) {
5784+ udf_errno=4;
5785+ return -1;
5786+ }
5787+
5788+ i=read(fd, buffer, udf_blocksize);
5789+ if ( i < udf_blocksize ) {
5790+ udf_errno=5;
5791+ return -1;
5792+ }
5793+
5794+ tag_p = (tag *)(buffer);
5795+
5796+ /* Verify the tag location */
5797+ if ((block-offset) != tag_p->tagLocation) {
5798+#ifdef __KERNEL__
5799+ printk(KERN_ERR "udf: location mismatch block %d, tag %d\n",
5800+ block, tag_p->tagLocation);
5801+#else
5802+ udf_errno=6;
5803+#endif
5804+ goto error_out;
5805+ }
5806+
5807+ /* Verify the tag checksum */
5808+ checksum = 0U;
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) {
5814+#ifdef __KERNEL__
5815+ printk(KERN_ERR "udf: tag checksum failed\n");
5816+#else
5817+ udf_errno=7;
5818+#endif
5819+ goto error_out;
5820+ }
5821+
5822+ /* Verify the tag version */
5823+ if (tag_p->descVersion != 0x0002U) {
5824+#ifdef __KERNEL__
5825+ printk(KERN_ERR "udf: tag version 0x%04x != 0x0002U\n",
5826+ tag_p->descVersion);
5827+#else
5828+ udf_errno=8;
5829+#endif
5830+ goto error_out;
5831+ }
5832+
5833+ /* Verify the descriptor CRC */
5834+ if (tag_p->descCRC == udf_crc(buffer + 16, tag_p->descCRCLength, 0)) {
5835+ udf_errno=0;
5836+ return 0;
5837+ }
5838+#ifdef __KERNEL__
5839+ printk(KERN_ERR "udf: crc failure in udf_read_tagged\n");
5840+#else
5841+ udf_errno=9;
5842+#endif
5843+
5844+error_out:
5845+ return -1;
5846+}
5847+#endif
5848diff -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
5851@@ -0,0 +1,1609 @@
5852+/*
5853+ * namei.c
5854+ *
5855+ * PURPOSE
5856+ * Inode name handling routines for the OSTA-UDF(tm) filesystem.
5857+ *
5858+ * CONTACTS
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
5862+ *
5863+ * COPYRIGHT
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.
5868+ *
5869+ * (C) 1998-2000 Ben Fennema
5870+ * (C) 1999-2000 Stelias Computing Inc
5871+ *
5872+ * HISTORY
5873+ *
5874+ * 12/12/98 blf Created. Split out the lookup code from dir.c
5875+ * 04/19/99 blf link, mknod, symlink support
5876+ */
5877+
5878+#include "udfdecl.h"
5879+
5880+#if defined(__linux__) && defined(__KERNEL__)
5881+#include <linux/version.h>
5882+#include "udf_i.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>
5890+#endif
5891+
5892+static inline int udf_match(int len, const char * const name, struct qstr *qs)
5893+{
5894+ if (len != qs->len)
5895+ return 0;
5896+ return !memcmp(name, qs->name, len);
5897+}
5898+
5899+int udf_write_fi(struct FileIdentDesc *cfi, struct FileIdentDesc *sfi,
5900+ struct udf_fileident_bh *fibh,
5901+ Uint8 *impuse, Uint8 *fileident)
5902+{
5903+ Uint16 crclen = fibh->eoffset - fibh->soffset - sizeof(tag);
5904+ Uint16 crc;
5905+ Uint8 checksum = 0;
5906+ int i;
5907+ int offset;
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);
5912+
5913+
5914+ offset = fibh->soffset + sizeof(struct FileIdentDesc);
5915+
5916+ if (impuse)
5917+ {
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);
5922+ else
5923+ {
5924+ memcpy((Uint8 *)sfi->impUse, impuse, -offset);
5925+ memcpy(fibh->ebh->b_data, impuse - offset, liu + offset);
5926+ }
5927+ }
5928+
5929+ offset += liu;
5930+
5931+ if (fileident)
5932+ {
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);
5937+ else
5938+ {
5939+ memcpy((Uint8 *)sfi->fileIdent + liu, fileident, -offset);
5940+ memcpy(fibh->ebh->b_data, fileident - offset, lfi + offset);
5941+ }
5942+ }
5943+
5944+ offset += lfi;
5945+
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);
5950+ else
5951+ {
5952+ memset((Uint8 *)sfi->padding + liu + lfi, 0x00, -offset);
5953+ memset(fibh->ebh->b_data, 0x00, padlen + offset);
5954+ }
5955+
5956+ crc = udf_crc((Uint8 *)cfi + sizeof(tag), sizeof(struct FileIdentDesc) -
5957+ sizeof(tag), 0);
5958+
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);
5965+ else
5966+ {
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);
5970+ }
5971+
5972+ cfi->descTag.descCRC = cpu_to_le32(crc);
5973+ cfi->descTag.descCRCLength = cpu_to_le16(crclen);
5974+
5975+ for (i=0; i<16; i++)
5976+ if (i != 4)
5977+ checksum += ((Uint8 *)&cfi->descTag)[i];
5978+
5979+ cfi->descTag.tagChecksum = checksum;
5980+ if (sizeof(struct FileIdentDesc) <= -fibh->soffset)
5981+ memcpy((Uint8 *)sfi, (Uint8 *)cfi, sizeof(struct FileIdentDesc));
5982+ else
5983+ {
5984+ memcpy((Uint8 *)sfi, (Uint8 *)cfi, -fibh->soffset);
5985+ memcpy(fibh->ebh->b_data, (Uint8 *)cfi - fibh->soffset,
5986+ sizeof(struct FileIdentDesc) + fibh->soffset);
5987+ }
5988+
5989+ if (fibh->sbh != fibh->ebh)
5990+ mark_buffer_dirty(fibh->ebh, 1);
5991+ mark_buffer_dirty(fibh->sbh, 1);
5992+ return 0;
5993+}
5994+
5995+static struct FileIdentDesc *
5996+udf_find_entry(struct inode *dir, struct dentry *dentry,
5997+ struct udf_fileident_bh *fibh,
5998+ struct FileIdentDesc *cfi)
5999+{
6000+ struct FileIdentDesc *fi=NULL;
6001+ int f_pos, block;
6002+ int flen;
6003+ char fname[255];
6004+ char *nameptr;
6005+ Uint8 lfi;
6006+ Uint16 liu;
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;
6011+
6012+ if (!dir)
6013+ return NULL;
6014+
6015+ f_pos = (udf_ext0_offset(dir) >> 2);
6016+
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)
6020+ {
6021+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
6022+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
6023+ {
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);
6028+ }
6029+ else
6030+ offset = 0;
6031+ }
6032+ else
6033+ {
6034+ udf_release_data(bh);
6035+ return NULL;
6036+ }
6037+
6038+ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
6039+ {
6040+ udf_debug("udf_tread failed: block=%d\n", block);
6041+ udf_release_data(bh);
6042+ return NULL;
6043+ }
6044+
6045+ while ( (f_pos < size) )
6046+ {
6047+ fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
6048+
6049+ if (!fi)
6050+ {
6051+ if (fibh->sbh != fibh->ebh)
6052+ udf_release_data(fibh->ebh);
6053+ udf_release_data(fibh->sbh);
6054+ udf_release_data(bh);
6055+ return NULL;
6056+ }
6057+
6058+ liu = le16_to_cpu(cfi->lengthOfImpUse);
6059+ lfi = cfi->lengthFileIdent;
6060+
6061+ if (fibh->sbh == fibh->ebh)
6062+ {
6063+ nameptr = fi->fileIdent + liu;
6064+ }
6065+ else
6066+ {
6067+ int poffset; /* Unpaded ending offset */
6068+
6069+ poffset = fibh->soffset + sizeof(struct FileIdentDesc) + liu + lfi;
6070+
6071+ if (poffset >= lfi)
6072+ nameptr = (Uint8 *)(fibh->ebh->b_data + poffset - lfi);
6073+ else
6074+ {
6075+ nameptr = fname;
6076+ memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
6077+ memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
6078+ }
6079+ }
6080+
6081+ if ( (cfi->fileCharacteristics & FILE_DELETED) != 0 )
6082+ {
6083+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
6084+ continue;
6085+ }
6086+
6087+ if ( (cfi->fileCharacteristics & FILE_HIDDEN) != 0 )
6088+ {
6089+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
6090+ continue;
6091+ }
6092+
6093+ if (!lfi)
6094+ continue;
6095+
6096+ if ((flen = udf_get_filename(nameptr, fname, lfi)))
6097+ {
6098+ if (udf_match(flen, fname, &(dentry->d_name)))
6099+ {
6100+ udf_release_data(bh);
6101+ return fi;
6102+ }
6103+ }
6104+ }
6105+ if (fibh->sbh != fibh->ebh)
6106+ udf_release_data(fibh->ebh);
6107+ udf_release_data(fibh->sbh);
6108+ udf_release_data(bh);
6109+ return NULL;
6110+}
6111+
6112+/*
6113+ * udf_lookup
6114+ *
6115+ * PURPOSE
6116+ * Look-up the inode for a given name.
6117+ *
6118+ * DESCRIPTION
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.
6122+ *
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.
6128+ *
6129+ * Refer to lookup_dentry() in fs/namei.c
6130+ * lookup_dentry() -> lookup() -> real_lookup() -> .
6131+ *
6132+ * PRE-CONDITIONS
6133+ * dir Pointer to inode of parent directory.
6134+ * dentry Pointer to dentry to complete.
6135+ *
6136+ * POST-CONDITIONS
6137+ * <return> Zero on success.
6138+ *
6139+ * HISTORY
6140+ * July 1, 1997 - Andrew E. Mileski
6141+ * Written, tested, and released.
6142+ */
6143+
6144+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6145+int
6146+#else
6147+struct dentry *
6148+#endif
6149+udf_lookup(struct inode *dir, struct dentry *dentry)
6150+{
6151+ struct inode *inode = NULL;
6152+ struct FileIdentDesc cfi, *fi;
6153+ struct udf_fileident_bh fibh;
6154+
6155+ if (dentry->d_name.len > UDF_NAME_LEN)
6156+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6157+ return -ENAMETOOLONG;
6158+#else
6159+ return ERR_PTR(-ENAMETOOLONG);
6160+#endif
6161+
6162+#ifdef UDF_RECOVERY
6163+ /* temporary shorthand for specifying files by inode number */
6164+ if (!strncmp(dentry->d_name.name, ".B=", 3) )
6165+ {
6166+ lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
6167+ inode = udf_iget(dir->i_sb, lb);
6168+ if (!inode)
6169+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6170+ return -EACCES;
6171+#else
6172+ return ERR_PTR(-EACCES);
6173+#endif
6174+ }
6175+ else
6176+#endif /* UDF_RECOVERY */
6177+
6178+ if ((fi = udf_find_entry(dir, dentry, &fibh, &cfi)))
6179+ {
6180+ if (fibh.sbh != fibh.ebh)
6181+ udf_release_data(fibh.ebh);
6182+ udf_release_data(fibh.sbh);
6183+
6184+ inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
6185+ if ( !inode )
6186+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6187+ return -EACCES;
6188+#else
6189+ return ERR_PTR(-EACCES);
6190+#endif
6191+ }
6192+ d_add(dentry, inode);
6193+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,7)
6194+ return 0;
6195+#else
6196+ return NULL;
6197+#endif
6198+}
6199+
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)
6204+{
6205+ struct super_block *sb;
6206+ struct FileIdentDesc *fi=NULL;
6207+ struct ustr unifilename;
6208+ char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
6209+ int namelen;
6210+ int f_pos;
6211+ int flen;
6212+ char *nameptr;
6213+ int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
6214+ int nfidlen;
6215+ Uint8 lfi;
6216+ Uint16 liu;
6217+ int block;
6218+ lb_addr bloc, eloc;
6219+ Uint32 extoffset, elen, offset;
6220+ struct buffer_head *bh = NULL;
6221+
6222+ if (!dir || !dir->i_nlink)
6223+ return NULL;
6224+ sb = dir->i_sb;
6225+
6226+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6227+ if (dentry->d_name.len >= UDF_NAME_LEN)
6228+ {
6229+ *err = -ENAMETOOLONG;
6230+ return NULL;
6231+ }
6232+#endif
6233+
6234+ if (dentry->d_name.len)
6235+ {
6236+ if (!dentry->d_name.len)
6237+ {
6238+ *err = -EINVAL;
6239+ return NULL;
6240+ }
6241+
6242+ if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
6243+ {
6244+ *err = -ENAMETOOLONG;
6245+ return NULL;
6246+ }
6247+
6248+ if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
6249+ {
6250+ *err = -ENAMETOOLONG;
6251+ return NULL;
6252+ }
6253+ }
6254+ else
6255+ namelen = 0;
6256+
6257+ nfidlen = (sizeof(struct FileIdentDesc) + namelen + 3) & ~3;
6258+
6259+ f_pos = (udf_ext0_offset(dir) >> 2);
6260+
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)
6264+ {
6265+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
6266+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
6267+ {
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);
6272+ }
6273+ else
6274+ offset = 0;
6275+
6276+ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
6277+ {
6278+ udf_release_data(bh);
6279+ *err = -EIO;
6280+ return NULL;
6281+ }
6282+
6283+ block = UDF_I_LOCATION(dir).logicalBlockNum;
6284+
6285+ while ( (f_pos < size) )
6286+ {
6287+ fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
6288+
6289+ if (!fi)
6290+ {
6291+ if (fibh->sbh != fibh->ebh)
6292+ udf_release_data(fibh->ebh);
6293+ udf_release_data(fibh->sbh);
6294+ udf_release_data(bh);
6295+ *err = -EIO;
6296+ return NULL;
6297+ }
6298+
6299+ liu = le16_to_cpu(cfi->lengthOfImpUse);
6300+ lfi = cfi->lengthFileIdent;
6301+
6302+ if (fibh->sbh == fibh->ebh)
6303+ nameptr = fi->fileIdent + liu;
6304+ else
6305+ {
6306+ int poffset; /* Unpaded ending offset */
6307+
6308+ poffset = fibh->soffset + sizeof(struct FileIdentDesc) + liu + lfi;
6309+
6310+ if (poffset >= lfi)
6311+ nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
6312+ else
6313+ {
6314+ nameptr = fname;
6315+ memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
6316+ memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
6317+ }
6318+ }
6319+
6320+ if ( (cfi->fileCharacteristics & FILE_DELETED) != 0 )
6321+ {
6322+ if (((sizeof(struct FileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
6323+ {
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))
6331+ return fi;
6332+ else
6333+ {
6334+ *err = -EIO;
6335+ return NULL;
6336+ }
6337+ }
6338+ }
6339+
6340+ if (!lfi)
6341+ continue;
6342+
6343+ if ((flen = udf_get_filename(nameptr, fname, lfi)))
6344+ {
6345+ if (udf_match(flen, fname, &(dentry->d_name)))
6346+ {
6347+ if (fibh->sbh != fibh->ebh)
6348+ udf_release_data(fibh->ebh);
6349+ udf_release_data(fibh->sbh);
6350+ udf_release_data(bh);
6351+ *err = -EEXIST;
6352+ return NULL;
6353+ }
6354+ }
6355+ }
6356+ }
6357+ else
6358+ {
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)
6361+ {
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);
6364+ }
6365+ else
6366+ {
6367+ fibh->sbh = fibh->ebh = NULL;
6368+ fibh->soffset = fibh->eoffset = sb->s_blocksize;
6369+ }
6370+ }
6371+
6372+ f_pos += nfidlen;
6373+
6374+ if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB &&
6375+ sb->s_blocksize - fibh->eoffset < nfidlen)
6376+ {
6377+ udf_release_data(bh);
6378+ bh = NULL;
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)))
6386+ return NULL;
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);
6396+ }
6397+
6398+ if (sb->s_blocksize - fibh->eoffset >= nfidlen)
6399+ {
6400+ fibh->soffset = fibh->eoffset;
6401+ fibh->eoffset += nfidlen;
6402+ if (fibh->sbh != fibh->ebh)
6403+ {
6404+ udf_release_data(fibh->sbh);
6405+ fibh->sbh = fibh->ebh;
6406+ }
6407+
6408+ if (UDF_I_ALLOCTYPE(dir) != ICB_FLAG_AD_IN_ICB)
6409+ block = eloc.logicalBlockNum + ((elen - 1) >>
6410+ dir->i_sb->s_blocksize_bits);
6411+ else
6412+ block = UDF_I_LOCATION(dir).logicalBlockNum;
6413+
6414+ fi = (struct FileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
6415+ }
6416+ else
6417+ {
6418+ fibh->soffset = fibh->eoffset - sb->s_blocksize;
6419+ fibh->eoffset += nfidlen - sb->s_blocksize;
6420+ if (fibh->sbh != fibh->ebh)
6421+ {
6422+ udf_release_data(fibh->sbh);
6423+ fibh->sbh = fibh->ebh;
6424+ }
6425+
6426+ block = eloc.logicalBlockNum + ((elen - 1) >>
6427+ dir->i_sb->s_blocksize_bits);
6428+
6429+ if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
6430+ {
6431+ udf_release_data(bh);
6432+ udf_release_data(fibh->sbh);
6433+ return NULL;
6434+ }
6435+
6436+ if (!(fibh->soffset))
6437+ {
6438+ if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==
6439+ EXTENT_RECORDED_ALLOCATED)
6440+ {
6441+ block = eloc.logicalBlockNum + ((elen - 1) >>
6442+ dir->i_sb->s_blocksize_bits);
6443+ }
6444+ else
6445+ block ++;
6446+
6447+ udf_release_data(fibh->sbh);
6448+ fibh->sbh = fibh->ebh;
6449+ fi = (struct FileIdentDesc *)(fibh->sbh->b_data);
6450+ }
6451+ else
6452+ {
6453+ fi = (struct FileIdentDesc *)
6454+ (fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
6455+ }
6456+ }
6457+
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))
6464+ {
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;
6471+#else
6472+ dir->i_version = ++global_event;
6473+#endif
6474+ mark_inode_dirty(dir);
6475+ return fi;
6476+ }
6477+ else
6478+ {
6479+ udf_release_data(bh);
6480+ if (fibh->sbh != fibh->ebh)
6481+ udf_release_data(fibh->ebh);
6482+ udf_release_data(fibh->sbh);
6483+ *err = -EIO;
6484+ return NULL;
6485+ }
6486+}
6487+
6488+static int udf_delete_entry(struct FileIdentDesc *fi,
6489+ struct udf_fileident_bh *fibh,
6490+ struct FileIdentDesc *cfi)
6491+{
6492+ cfi->fileCharacteristics |= FILE_DELETED;
6493+ return udf_write_fi(cfi, fi, fibh, NULL, NULL);
6494+}
6495+
6496+int udf_create(struct inode *dir, struct dentry *dentry, int mode)
6497+{
6498+ struct udf_fileident_bh fibh;
6499+ struct inode *inode;
6500+ struct FileIdentDesc cfi, *fi;
6501+ int err;
6502+
6503+ inode = udf_new_inode(dir, mode, &err);
6504+ if (!inode)
6505+ {
6506+ udf_debug("udf_new_inode failure, err=%d\n", err);
6507+ return err;
6508+ }
6509+
6510+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
6511+ inode->i_op = &udf_file_inode_operations_adinicb;
6512+ else
6513+ inode->i_op = &udf_file_inode_operations;
6514+ inode->i_mode = mode;
6515+ mark_inode_dirty(inode);
6516+
6517+ if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
6518+ {
6519+ udf_debug("udf_add_entry failure!\n");
6520+ inode->i_nlink --;
6521+ mark_inode_dirty(inode);
6522+ iput(inode);
6523+ return err;
6524+ }
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)
6531+ {
6532+ mark_inode_dirty(dir);
6533+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6534+ dir->i_version = ++event;
6535+#else
6536+ dir->i_version = ++global_event;
6537+#endif
6538+ }
6539+ if (fibh.sbh != fibh.ebh)
6540+ udf_release_data(fibh.ebh);
6541+ udf_release_data(fibh.sbh);
6542+ d_instantiate(dentry, inode);
6543+ return 0;
6544+}
6545+
6546+int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
6547+{
6548+ struct inode * inode;
6549+ struct udf_fileident_bh fibh;
6550+ int err;
6551+ struct FileIdentDesc cfi, *fi;
6552+
6553+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6554+ err = -ENAMETOOLONG;
6555+ if (dentry->d_name.len >= UDF_NAME_LEN)
6556+ goto out;
6557+#endif
6558+
6559+ err = -EIO;
6560+ inode = udf_new_inode(dir, mode, &err);
6561+ if (!inode)
6562+ goto out;
6563+
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)))
6568+ {
6569+ udf_debug("udf_add_entry failure!\n");
6570+ inode->i_nlink --;
6571+ mark_inode_dirty(inode);
6572+ iput(inode);
6573+ return err;
6574+ }
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)
6581+ {
6582+ mark_inode_dirty(dir);
6583+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6584+ dir->i_version = ++event;
6585+#else
6586+ dir->i_version = ++global_event;
6587+#endif
6588+ }
6589+ if (S_ISREG(inode->i_mode))
6590+ {
6591+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
6592+ inode->i_op = &udf_file_inode_operations_adinicb;
6593+ else
6594+ inode->i_op = &udf_file_inode_operations;
6595+ }
6596+ else if (S_ISCHR(inode->i_mode))
6597+ {
6598+ inode->i_op = &chrdev_inode_operations;
6599+ }
6600+ else if (S_ISBLK(inode->i_mode))
6601+ {
6602+ inode->i_op = &blkdev_inode_operations;
6603+ }
6604+ else if (S_ISFIFO(inode->i_mode))
6605+ {
6606+ init_fifo(inode);
6607+ }
6608+ if (S_ISBLK(mode) || S_ISCHR(mode))
6609+ inode->i_rdev = to_kdev_t(rdev);
6610+ mark_inode_dirty(inode);
6611+
6612+ if (fibh.sbh != fibh.ebh)
6613+ udf_release_data(fibh.ebh);
6614+ udf_release_data(fibh.sbh);
6615+ d_instantiate(dentry, inode);
6616+ err = 0;
6617+out:
6618+ return err;
6619+}
6620+
6621+int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
6622+{
6623+ struct inode * inode;
6624+ struct udf_fileident_bh fibh;
6625+ int err;
6626+ struct FileIdentDesc cfi, *fi;
6627+
6628+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6629+ err = -ENAMETOOLONG;
6630+ if (dentry->d_name.len >= UDF_NAME_LEN)
6631+ goto out;
6632+#endif
6633+
6634+ err = -EMLINK;
6635+ if (dir->i_nlink >= (256<<sizeof(dir->i_nlink))-1)
6636+ goto out;
6637+
6638+ err = -EIO;
6639+ inode = udf_new_inode(dir, S_IFDIR, &err);
6640+ if (!inode)
6641+ goto out;
6642+
6643+ inode->i_op = &udf_dir_inode_operations;
6644+ if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err)))
6645+ {
6646+ inode->i_nlink--;
6647+ mark_inode_dirty(inode);
6648+ iput(inode);
6649+ goto out;
6650+ }
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);
6663+
6664+ if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
6665+ {
6666+ udf_debug("udf_add_entry failure!\n");
6667+ inode->i_nlink = 0;
6668+ mark_inode_dirty(inode);
6669+ iput(inode);
6670+ goto out;
6671+ }
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;
6680+#else
6681+ dir->i_version = ++global_event;
6682+#endif
6683+ dir->i_nlink++;
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);
6689+ err = 0;
6690+out:
6691+ return err;
6692+}
6693+
6694+static int empty_dir(struct inode *dir)
6695+{
6696+ struct FileIdentDesc *fi, cfi;
6697+ struct udf_fileident_bh fibh;
6698+ int f_pos;
6699+ int size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
6700+ int block;
6701+ lb_addr bloc, eloc;
6702+ Uint32 extoffset, elen, offset;
6703+ struct buffer_head *bh = NULL;
6704+
6705+ f_pos = (udf_ext0_offset(dir) >> 2);
6706+
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)
6710+ {
6711+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
6712+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
6713+ {
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);
6718+ }
6719+ else
6720+ offset = 0;
6721+ }
6722+ else
6723+ {
6724+ udf_release_data(bh);
6725+ return 0;
6726+ }
6727+
6728+ if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
6729+ return 0;
6730+
6731+ while ( (f_pos < size) )
6732+ {
6733+ fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
6734+
6735+ if (!fi)
6736+ {
6737+ if (fibh.sbh != fibh.ebh)
6738+ udf_release_data(fibh.ebh);
6739+ udf_release_data(fibh.sbh);
6740+ udf_release_data(bh);
6741+ return 0;
6742+ }
6743+
6744+ if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FILE_DELETED) == 0)
6745+ {
6746+ udf_release_data(bh);
6747+ return 0;
6748+ }
6749+ }
6750+ if (fibh.sbh != fibh.ebh)
6751+ udf_release_data(fibh.ebh);
6752+ udf_release_data(fibh.sbh);
6753+ udf_release_data(bh);
6754+ return 1;
6755+}
6756+
6757+int udf_rmdir(struct inode * dir, struct dentry * dentry)
6758+{
6759+ int retval;
6760+ struct inode * inode;
6761+ struct udf_fileident_bh fibh;
6762+ struct FileIdentDesc *fi, cfi;
6763+
6764+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6765+ retval = -ENAMETOOLONG;
6766+ if (dentry->d_name.len >= UDF_NAME_LEN)
6767+ goto out;
6768+#endif
6769+
6770+ retval = -ENOENT;
6771+ fi = udf_find_entry(dir, dentry, &fibh, &cfi);
6772+ if (!fi)
6773+ goto out;
6774+
6775+ inode = dentry->d_inode;
6776+ DQUOT_INIT(inode);
6777+
6778+ retval = -EIO;
6779+ if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino)
6780+ goto end_rmdir;
6781+
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) !=
6786+ inode->i_ino)
6787+ {
6788+ retval = -ENOENT;
6789+ }
6790+ else
6791+ {
6792+ retval = udf_delete_entry(fi, &fibh, &cfi);
6793+ dir->i_version = ++event;
6794+ }
6795+#else
6796+ retval = -ENOTEMPTY;
6797+ if (!empty_dir(inode))
6798+ goto end_rmdir;
6799+ retval = udf_delete_entry(fi, &fibh, &cfi);
6800+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6801+ dir->i_version = ++event;
6802+#else
6803+ dir->i_version = ++global_event;
6804+#endif
6805+#endif
6806+ if (retval)
6807+ goto end_rmdir;
6808+ if (inode->i_nlink != 2)
6809+ udf_warning(inode->i_sb, "udf_rmdir",
6810+ "empty directory has nlink != 2 (%d)",
6811+ inode->i_nlink);
6812+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
6813+ inode->i_version = ++event;
6814+#else
6815+ inode->i_version = ++global_event;
6816+#endif
6817+ inode->i_nlink = 0;
6818+ inode->i_size = 0;
6819+ mark_inode_dirty(inode);
6820+ dir->i_nlink --;
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);
6824+ d_delete(dentry);
6825+
6826+end_rmdir:
6827+ if (fibh.sbh != fibh.ebh)
6828+ udf_release_data(fibh.ebh);
6829+ udf_release_data(fibh.sbh);
6830+out:
6831+ return retval;
6832+}
6833+
6834+int udf_unlink(struct inode * dir, struct dentry * dentry)
6835+{
6836+ int retval;
6837+ struct inode * inode;
6838+ struct udf_fileident_bh fibh;
6839+ struct FileIdentDesc *fi;
6840+ struct FileIdentDesc cfi;
6841+
6842+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
6843+ retval = -ENAMETOOLONG;
6844+ if (dentry->d_name.len >= UDF_NAME_LEN)
6845+ goto out;
6846+#endif
6847+
6848+ retval = -ENOENT;
6849+ fi = udf_find_entry(dir, dentry, &fibh, &cfi);
6850+ if (!fi)
6851+ goto out;
6852+
6853+ inode = dentry->d_inode;
6854+ DQUOT_INIT(inode);
6855+
6856+ retval = -EIO;
6857+
6858+ if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) !=
6859+ inode->i_ino)
6860+ {
6861+ goto end_unlink;
6862+ }
6863+
6864+ if (!inode->i_nlink)
6865+ {
6866+ udf_debug("Deleting nonexistent file (%lu), %d\n",
6867+ inode->i_ino, inode->i_nlink);
6868+ inode->i_nlink = 1;
6869+ }
6870+ retval = udf_delete_entry(fi, &fibh, &cfi);
6871+ if (retval)
6872+ goto end_unlink;
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);
6876+ inode->i_nlink--;
6877+ mark_inode_dirty(inode);
6878+ inode->i_ctime = dir->i_ctime;
6879+ retval = 0;
6880+ d_delete(dentry); /* This also frees the inode */
6881+
6882+end_unlink:
6883+ if (fibh.sbh != fibh.ebh)
6884+ udf_release_data(fibh.ebh);
6885+ udf_release_data(fibh.sbh);
6886+out:
6887+ return retval;
6888+}
6889+
6890+int udf_symlink(struct inode * dir, struct dentry * dentry, const char * symname)
6891+{
6892+ struct inode * inode;
6893+ struct PathComponent *pc;
6894+ char *compstart;
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;
6900+ char *ea;
6901+ int err;
6902+ int block;
6903+
6904+ if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
6905+ goto out;
6906+
6907+ inode->i_mode = S_IFLNK | S_IRWXUGO;
6908+ inode->i_op = &udf_symlink_inode_operations;
6909+
6910+ if (UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
6911+ {
6912+ struct buffer_head *bh = NULL;
6913+ lb_addr bloc, eloc;
6914+ Uint32 elen, extoffset;
6915+
6916+ block = udf_new_block(inode,
6917+ UDF_I_LOCATION(inode).partitionReferenceNum,
6918+ UDF_I_LOCATION(inode).logicalBlockNum, &err);
6919+ if (!block)
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);
6928+
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);
6932+ }
6933+ else
6934+ block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
6935+
6936+ bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize);
6937+ ea = bh->b_data + udf_ext0_offset(inode);
6938+
6939+ eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
6940+ pc = (struct PathComponent *)ea;
6941+
6942+ if (*symname == '/')
6943+ {
6944+ do
6945+ {
6946+ symname++;
6947+ } while (*symname == '/');
6948+
6949+ pc->componentType = 1;
6950+ pc->lengthComponentIdent = 0;
6951+ pc->componentFileVersionNum = 0;
6952+ pc += sizeof(struct PathComponent);
6953+ elen += sizeof(struct PathComponent);
6954+ }
6955+
6956+ err = -ENAMETOOLONG;
6957+
6958+ while (*symname)
6959+ {
6960+ if (elen + sizeof(struct PathComponent) > eoffset)
6961+ goto out_no_entry;
6962+
6963+ pc = (struct PathComponent *)(ea + elen);
6964+
6965+ compstart = (char *)symname;
6966+
6967+ do
6968+ {
6969+ symname++;
6970+ } while (*symname && *symname != '/');
6971+
6972+ pc->componentType = 5;
6973+ pc->lengthComponentIdent = 0;
6974+ pc->componentFileVersionNum = 0;
6975+ if (pc->componentIdent[0] == '.')
6976+ {
6977+ if (pc->lengthComponentIdent == 1)
6978+ pc->componentType = 4;
6979+ else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
6980+ pc->componentType = 3;
6981+ }
6982+
6983+ if (pc->componentType == 5)
6984+ {
6985+ if (elen + sizeof(struct PathComponent) + symname - compstart > eoffset)
6986+ goto out_no_entry;
6987+ else
6988+ pc->lengthComponentIdent = symname - compstart;
6989+
6990+ memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
6991+ }
6992+
6993+ elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
6994+
6995+ if (*symname)
6996+ {
6997+ do
6998+ {
6999+ symname++;
7000+ } while (*symname == '/');
7001+ }
7002+ }
7003+
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);
7009+
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))
7015+ {
7016+ struct LogicalVolHeaderDesc *lvhd;
7017+ Uint64 uniqueID;
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))
7023+ uniqueID += 16;
7024+ lvhd->uniqueID = cpu_to_le64(uniqueID);
7025+ mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
7026+ }
7027+ udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
7028+ if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
7029+ {
7030+ mark_inode_dirty(dir);
7031+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7032+ dir->i_version = ++event;
7033+#else
7034+ dir->i_version = ++global_event;
7035+#endif
7036+ }
7037+ if (fibh.sbh != fibh.ebh)
7038+ udf_release_data(fibh.ebh);
7039+ udf_release_data(fibh.sbh);
7040+ d_instantiate(dentry, inode);
7041+ err = 0;
7042+
7043+out:
7044+ return err;
7045+
7046+out_no_entry:
7047+ inode->i_nlink--;
7048+ mark_inode_dirty(inode);
7049+ iput(inode);
7050+ goto out;
7051+}
7052+
7053+int udf_link(struct dentry * old_dentry, struct inode * dir,
7054+ struct dentry *dentry)
7055+{
7056+ struct inode *inode = old_dentry->d_inode;
7057+ struct udf_fileident_bh fibh;
7058+ int err;
7059+ struct FileIdentDesc cfi, *fi;
7060+
7061+ if (S_ISDIR(inode->i_mode))
7062+ return -EPERM;
7063+
7064+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
7065+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
7066+ return -EPERM;
7067+#endif
7068+
7069+ if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
7070+ return -EMLINK;
7071+
7072+ if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
7073+ return 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))
7077+ {
7078+ struct LogicalVolHeaderDesc *lvhd;
7079+ Uint64 uniqueID;
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))
7085+ uniqueID += 16;
7086+ lvhd->uniqueID = cpu_to_le64(uniqueID);
7087+ mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
7088+ }
7089+ udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
7090+ if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
7091+ {
7092+ mark_inode_dirty(dir);
7093+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7094+ dir->i_version = ++event;
7095+#else
7096+ dir->i_version = ++global_event;
7097+#endif
7098+ }
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);
7108+ return 0;
7109+}
7110+
7111+
7112+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)
7113+
7114+/*
7115+ * rename uses retrying to avoid race-conditions: at least they should be
7116+ * minimal.
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.
7121+ *
7122+ * Anybody can rename anything with this: the permission checks are left to the
7123+ * higher-level routines.
7124+ */
7125+static int do_udf_rename(struct inode *old_dir, struct dentry *old_dentry,
7126+ struct inode *new_dir, struct dentry *new_dentry)
7127+{
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;
7133+
7134+ if (old_dentry->d_name.len > UDF_NAME_LEN)
7135+ goto end_rename;
7136+
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) !=
7140+ old_inode->i_ino)
7141+ {
7142+ goto end_rename;
7143+ }
7144+
7145+ new_inode = new_dentry->d_inode;
7146+ nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
7147+ if (nfi)
7148+ {
7149+ if (!new_inode)
7150+ {
7151+ if (nfibh.sbh != nfibh.ebh)
7152+ udf_release_data(nfibh.ebh);
7153+ udf_release_data(nfibh.sbh);
7154+ nfi = NULL;
7155+ }
7156+ else
7157+ {
7158+ DQUOT_INIT(new_inode);
7159+ }
7160+ }
7161+ retval = 0;
7162+ if (new_inode == old_inode)
7163+ goto end_rename;
7164+ if (S_ISDIR(old_inode->i_mode))
7165+ {
7166+ Uint32 offset = udf_ext0_offset(old_inode);
7167+ retval = -EINVAL;
7168+ if (is_subdir(new_dentry, old_dentry))
7169+ goto end_rename;
7170+
7171+ if (new_inode)
7172+ {
7173+ /* Prune any children before testing for busy */
7174+ if (new_dentry->d_count > 1)
7175+ shrink_dcache_parent(new_dentry);
7176+ retval = -EBUSY;
7177+ if (new_dentry->d_count > 1)
7178+ goto end_rename;
7179+ retval = -ENOTEMPTY;
7180+ if (!empty_dir(new_inode))
7181+ goto end_rename;
7182+ }
7183+ dir_bh = udf_bread(old_inode, 0, 0, &retval);
7184+ if (!dir_bh)
7185+ goto end_rename;
7186+ dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
7187+ if (!dir_fi)
7188+ goto end_rename;
7189+ if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
7190+ old_dir->i_ino)
7191+ {
7192+ goto end_rename;
7193+ }
7194+ retval = -EMLINK;
7195+ if (!new_inode && new_dir->i_nlink >= (256<<sizeof(new_dir->i_nlink))-1)
7196+ goto end_rename;
7197+ }
7198+ if (!nfi)
7199+ {
7200+ nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);
7201+ if (!nfi)
7202+ goto end_rename;
7203+ }
7204+ new_dir->i_version = ++event;
7205+
7206+ /*
7207+ * Like most other Unix systems, set the ctime for inodes on a
7208+ * rename.
7209+ */
7210+ old_inode->i_ctime = CURRENT_TIME;
7211+ UDF_I_UCTIME(old_inode) = CURRENT_UTIME;
7212+ mark_inode_dirty(old_inode);
7213+
7214+ /*
7215+ * ok, that's it
7216+ */
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);
7221+
7222+ udf_delete_entry(ofi, &ofibh, &ocfi);
7223+
7224+ old_dir->i_version = ++event;
7225+ if (new_inode)
7226+ {
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);
7231+ }
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);
7235+
7236+ if (dir_bh)
7237+ {
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)
7242+ {
7243+ mark_inode_dirty(old_inode);
7244+ old_inode->i_version = ++event;
7245+ }
7246+ else
7247+ mark_buffer_dirty(dir_bh, 1);
7248+ old_dir->i_nlink --;
7249+ mark_inode_dirty(old_dir);
7250+ if (new_inode)
7251+ {
7252+ new_inode->i_nlink --;
7253+ mark_inode_dirty(new_inode);
7254+ }
7255+ else
7256+ {
7257+ new_dir->i_nlink ++;
7258+ mark_inode_dirty(new_dir);
7259+ }
7260+ }
7261+
7262+ /* Update the dcache */
7263+ d_move(old_dentry, new_dentry);
7264+ retval = 0;
7265+
7266+end_rename:
7267+ udf_release_data(dir_bh);
7268+ if (ofi)
7269+ {
7270+ if (ofibh.sbh != ofibh.ebh)
7271+ udf_release_data(ofibh.ebh);
7272+ udf_release_data(ofibh.sbh);
7273+ }
7274+ if (nfi)
7275+ {
7276+ if (nfibh.sbh != nfibh.ebh)
7277+ udf_release_data(nfibh.ebh);
7278+ udf_release_data(nfibh.sbh);
7279+ }
7280+ return retval;
7281+}
7282+
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.
7286+ *
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.
7290+ *
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
7294+ */
7295+
7296+int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
7297+ struct inode *new_dir, struct dentry *new_dentry)
7298+{
7299+ int result;
7300+
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));
7307+ return result;
7308+}
7309+
7310+#else
7311+
7312+/* Anybody can rename anything with this: the permission checks are left to the
7313+ * higher-level routines.
7314+ */
7315+int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
7316+ struct inode * new_dir, struct dentry * new_dentry)
7317+{
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;
7323+
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) !=
7327+ old_inode->i_ino)
7328+ {
7329+ goto end_rename;
7330+ }
7331+
7332+ new_inode = new_dentry->d_inode;
7333+ nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
7334+ if (nfi)
7335+ {
7336+ if (!new_inode)
7337+ {
7338+ if (nfibh.sbh != nfibh.ebh)
7339+ udf_release_data(nfibh.ebh);
7340+ udf_release_data(nfibh.sbh);
7341+ nfi = NULL;
7342+ }
7343+ else
7344+ {
7345+ DQUOT_INIT(new_inode);
7346+ }
7347+ }
7348+ if (S_ISDIR(old_inode->i_mode))
7349+ {
7350+ Uint32 offset = udf_ext0_offset(old_inode);
7351+
7352+ if (new_inode)
7353+ {
7354+ retval = -ENOTEMPTY;
7355+ if (!empty_dir(new_inode))
7356+ goto end_rename;
7357+ }
7358+ retval = -EIO;
7359+ dir_bh = udf_bread(old_inode, 0, 0, &retval);
7360+ if (!dir_bh)
7361+ goto end_rename;
7362+ dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
7363+ if (!dir_fi)
7364+ goto end_rename;
7365+ if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
7366+ old_dir->i_ino)
7367+ {
7368+ goto end_rename;
7369+ }
7370+ retval = -EMLINK;
7371+ if (!new_inode && new_dir->i_nlink >= (256<<sizeof(new_dir->i_nlink))-1)
7372+ goto end_rename;
7373+ }
7374+ if (!nfi)
7375+ {
7376+ nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);
7377+ if (!nfi)
7378+ goto end_rename;
7379+ }
7380+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7381+ new_dir->i_version = ++event;
7382+#else
7383+ new_dir->i_version = ++global_event;
7384+#endif
7385+
7386+ /*
7387+ * ok, that's it
7388+ */
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);
7393+
7394+ udf_delete_entry(ofi, &ofibh, &ocfi);
7395+
7396+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7397+ old_dir->i_version = ++event;
7398+#else
7399+ old_dir->i_version = ++global_event;
7400+#endif
7401+ if (new_inode)
7402+ {
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);
7407+ }
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);
7411+
7412+ if (dir_bh)
7413+ {
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)
7418+ {
7419+ mark_inode_dirty(old_inode);
7420+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14)
7421+ old_inode->i_version = ++event;
7422+#else
7423+ old_inode->i_version = ++global_event;
7424+#endif
7425+ }
7426+ else
7427+ mark_buffer_dirty(dir_bh, 1);
7428+ old_dir->i_nlink --;
7429+ mark_inode_dirty(old_dir);
7430+ if (new_inode)
7431+ {
7432+ new_inode->i_nlink --;
7433+ mark_inode_dirty(new_inode);
7434+ }
7435+ else
7436+ {
7437+ new_dir->i_nlink ++;
7438+ mark_inode_dirty(new_dir);
7439+ }
7440+ }
7441+
7442+ retval = 0;
7443+
7444+end_rename:
7445+ udf_release_data(dir_bh);
7446+ if (ofi)
7447+ {
7448+ if (ofibh.sbh != ofibh.ebh)
7449+ udf_release_data(ofibh.ebh);
7450+ udf_release_data(ofibh.sbh);
7451+ }
7452+ if (nfi)
7453+ {
7454+ if (nfibh.sbh != nfibh.ebh)
7455+ udf_release_data(nfibh.ebh);
7456+ udf_release_data(nfibh.sbh);
7457+ }
7458+ return retval;
7459+}
7460+#endif
7461diff -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
7464@@ -0,0 +1,233 @@
7465+/*
7466+ * partition.c
7467+ *
7468+ * PURPOSE
7469+ * Partition handling routines for the OSTA-UDF(tm) filesystem.
7470+ *
7471+ * CONTACTS
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
7475+ *
7476+ * COPYRIGHT
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.
7481+ *
7482+ * (C) 1998-2000 Ben Fennema
7483+ *
7484+ * HISTORY
7485+ *
7486+ * 12/06/98 blf Created file.
7487+ *
7488+ */
7489+
7490+#include "udfdecl.h"
7491+#include "udf_sb.h"
7492+#include "udf_i.h"
7493+
7494+#include <linux/fs.h>
7495+#include <linux/string.h>
7496+#include <linux/udf_fs.h>
7497+#include <linux/malloc.h>
7498+
7499+inline Uint32 udf_get_pblock(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7500+{
7501+ if (partition >= UDF_SB_NUMPARTS(sb))
7502+ {
7503+ udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
7504+ block, partition, offset);
7505+ return 0xFFFFFFFF;
7506+ }
7507+ if (UDF_SB_PARTFUNC(sb, partition))
7508+ return UDF_SB_PARTFUNC(sb, partition)(sb, block, partition, offset);
7509+ else
7510+ return UDF_SB_PARTROOT(sb, partition) + block + offset;
7511+}
7512+
7513+Uint32 udf_get_pblock_virt15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7514+{
7515+ struct buffer_head *bh = NULL;
7516+ Uint32 newblock;
7517+ Uint32 index;
7518+ Uint32 loc;
7519+
7520+ index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(Uint32);
7521+
7522+ if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries)
7523+ {
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;
7527+ }
7528+
7529+ if (block >= index)
7530+ {
7531+ block -= index;
7532+ newblock = 1 + (block / (sb->s_blocksize / sizeof(Uint32)));
7533+ index = block % (sb->s_blocksize / sizeof(Uint32));
7534+ }
7535+ else
7536+ {
7537+ newblock = 0;
7538+ index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block;
7539+ }
7540+
7541+ loc = udf_bmap(UDF_SB_VAT(sb), newblock);
7542+
7543+ if (!(bh = bread(sb->s_dev, loc, sb->s_blocksize)))
7544+ {
7545+ udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
7546+ sb, block, partition, loc, index);
7547+ return 0xFFFFFFFF;
7548+ }
7549+
7550+ loc = le32_to_cpu(((Uint32 *)bh->b_data)[index]);
7551+
7552+ udf_release_data(bh);
7553+
7554+ if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
7555+ {
7556+ udf_debug("recursive call to udf_get_pblock!\n");
7557+ return 0xFFFFFFFF;
7558+ }
7559+
7560+ return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset);
7561+}
7562+
7563+inline Uint32 udf_get_pblock_virt20(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7564+{
7565+ return udf_get_pblock_virt15(sb, block, partition, offset);
7566+}
7567+
7568+Uint32 udf_get_pblock_spar15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
7569+{
7570+ Uint32 packet = (block + offset) >> UDF_SB_TYPESPAR(sb,partition).s_spar_pshift;
7571+ Uint32 index = 0;
7572+
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];
7579+
7580+ if (index == ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize)-1))
7581+ return UDF_SB_PARTROOT(sb,partition) + block + offset;
7582+
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));
7585+}
7586+
7587+void udf_fill_spartable(struct super_block *sb, struct udf_sparing_data *sdata, int partlen)
7588+{
7589+ Uint16 ident;
7590+ Uint32 spartable;
7591+ int i;
7592+ struct buffer_head *bh;
7593+ struct SparingTable *st;
7594+
7595+ for (i=0; i<4; i++)
7596+ {
7597+ if (!(spartable = sdata->s_spar_loc[i]))
7598+ continue;
7599+
7600+ bh = udf_read_tagged(sb, spartable, spartable, &ident);
7601+
7602+ if (!bh)
7603+ {
7604+ sdata->s_spar_loc[i] = 0;
7605+ continue;
7606+ }
7607+
7608+ if (ident == 0)
7609+ {
7610+ st = (struct SparingTable *)bh->b_data;
7611+ if (!strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)))
7612+ {
7613+ SparingEntry *se;
7614+ Uint16 rtl = le16_to_cpu(st->reallocationTableLen);
7615+ int index;
7616+
7617+ if (!sdata->s_spar_map)
7618+ {
7619+ int num = 1, mapsize;
7620+ sdata->s_spar_indexsize = 8;
7621+ while (rtl*sizeof(Uint32) >= (1 << sdata->s_spar_indexsize))
7622+ {
7623+ num ++;
7624+ sdata->s_spar_indexsize <<= 1;
7625+ }
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);
7631+ }
7632+
7633+ index = sizeof(struct SparingTable);
7634+ for (i=0; i<rtl; i++)
7635+ {
7636+ if (index > sb->s_blocksize)
7637+ {
7638+ udf_release_data(bh);
7639+ bh = udf_tread(sb, ++spartable, sb->s_blocksize);
7640+ if (!bh)
7641+ {
7642+ sdata->s_spar_loc[i] = 0;
7643+ continue;
7644+ }
7645+ index = 0;
7646+ }
7647+ se = (SparingEntry *)&(bh->b_data[index]);
7648+ index += sizeof(SparingEntry);
7649+
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))
7653+ {
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);
7656+ }
7657+
7658+ if (le32_to_cpu(se->origLocation) < 0xFFFFFFF0)
7659+ {
7660+ int packet = le32_to_cpu(se->origLocation) >> sdata->s_spar_pshift;
7661+ if (sdata->s_spar_indexsize == 8)
7662+ {
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)
7666+ {
7667+ udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
7668+ sdata->s_spar_remap.s_spar_remap8[packet], i);
7669+ }
7670+ }
7671+ else if (sdata->s_spar_indexsize == 16)
7672+ {
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)
7676+ {
7677+ udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
7678+ sdata->s_spar_remap.s_spar_remap16[packet], i);
7679+ }
7680+ }
7681+ else if (sdata->s_spar_indexsize == 32)
7682+ {
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)
7686+ {
7687+ udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
7688+ sdata->s_spar_remap.s_spar_remap32[packet], i);
7689+ }
7690+ }
7691+ }
7692+ }
7693+ }
7694+ }
7695+ udf_release_data(bh);
7696+ }
7697+}
7698diff -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
7701@@ -0,0 +1,1765 @@
7702+/*
7703+ * super.c
7704+ *
7705+ * PURPOSE
7706+ * Super block routines for the OSTA-UDF(tm) filesystem.
7707+ *
7708+ * DESCRIPTION
7709+ * OSTA-UDF(tm) = Optical Storage Technology Association
7710+ * Universal Disk Format.
7711+ *
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/
7717+ *
7718+ * CONTACTS
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
7722+ *
7723+ * COPYRIGHT
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.
7728+ *
7729+ * (C) 1998 Dave Boynton
7730+ * (C) 1998-2000 Ben Fennema
7731+ * (C) 2000 Stelias Computing Inc
7732+ *
7733+ * HISTORY
7734+ *
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)
7745+ */
7746+
7747+#include "udfdecl.h"
7748+
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>
7760+
7761+#include <linux/udf_fs.h>
7762+#include "udf_sb.h"
7763+#include "udf_i.h"
7764+
7765+#include <linux/init.h>
7766+#include <asm/uaccess.h>
7767+
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
7776+
7777+static char error_buf[1024];
7778+
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);
7798+
7799+/* UDF filesystem type */
7800+static struct file_system_type udf_fstype = {
7801+ "udf", /* name */
7802+ FS_REQUIRES_DEV, /* fs_flags */
7803+ udf_read_super, /* read_super */
7804+ NULL /* next */
7805+};
7806+
7807+/* Superblock operations */
7808+static struct super_operations udf_sb_ops =
7809+{
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 */
7821+};
7822+
7823+struct udf_options
7824+{
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;
7835+ mode_t umask;
7836+ gid_t gid;
7837+ uid_t uid;
7838+};
7839+
7840+#if defined(MODULE)
7841+
7842+/*
7843+ * cleanup_module
7844+ *
7845+ * PURPOSE
7846+ * Unregister the UDF filesystem type.
7847+ *
7848+ * DESCRIPTION
7849+ * Clean-up before the module is unloaded.
7850+ * This routine only applies when compiled as a module.
7851+ *
7852+ * HISTORY
7853+ * July 1, 1997 - Andrew E. Mileski
7854+ * Written, tested, and released.
7855+ */
7856+int
7857+cleanup_module(void)
7858+{
7859+ printk(KERN_NOTICE "udf: unregistering filesystem\n");
7860+ return unregister_filesystem(&udf_fstype);
7861+}
7862+
7863+/*
7864+ * init_module / init_udf_fs
7865+ *
7866+ * PURPOSE
7867+ * Register the UDF filesystem type.
7868+ *
7869+ * HISTORY
7870+ * July 1, 1997 - Andrew E. Mileski
7871+ * Written, tested, and released.
7872+ */
7873+int init_module(void)
7874+#else /* if !defined(MODULE) */
7875+__initfunc(int init_udf_fs(void))
7876+#endif
7877+{
7878+ printk(KERN_NOTICE "udf: registering filesystem\n");
7879+ {
7880+ struct super_block sb;
7881+ int size;
7882+
7883+ size = sizeof(struct super_block) +
7884+ (long)&sb.u - (long)&sb;
7885+ if ( size < sizeof(struct udf_sb_info) )
7886+ {
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));
7890+ return 0;
7891+ }
7892+ }
7893+ return register_filesystem(&udf_fstype);
7894+}
7895+
7896+/*
7897+ * udf_parse_options
7898+ *
7899+ * PURPOSE
7900+ * Parse mount options.
7901+ *
7902+ * DESCRIPTION
7903+ * The following mount options are supported:
7904+ *
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)
7916+ *
7917+ * The remaining are for debugging and disaster recovery:
7918+ *
7919+ * novrs Skip volume sequence recognition
7920+ *
7921+ * The following expect a offset from 0.
7922+ *
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/
7928+ *
7929+ * The following expect a offset from the partition root.
7930+ *
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.
7935+ *
7936+ * PRE-CONDITIONS
7937+ * options Pointer to mount options string.
7938+ * uopts Pointer to mount options variable.
7939+ *
7940+ * POST-CONDITIONS
7941+ * <return> 0 Mount options parsed okay.
7942+ * <return> -1 Error parsing mount options.
7943+ *
7944+ * HISTORY
7945+ * July 1, 1997 - Andrew E. Mileski
7946+ * Written, tested, and released.
7947+ */
7948+
7949+static int
7950+udf_parse_options(char *options, struct udf_options *uopt)
7951+{
7952+ char *opt, *val;
7953+
7954+ uopt->novrs = 0;
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;
7963+
7964+ if (!options)
7965+ return 1;
7966+
7967+ for (opt = strtok(options, ","); opt; opt = strtok(NULL, ","))
7968+ {
7969+ /* Make "opt=val" into two strings */
7970+ val = strchr(opt, '=');
7971+ if (val)
7972+ *(val++) = 0;
7973+ if (!strcmp(opt, "novrs") && !val)
7974+ uopt->novrs = 1;
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);
8011+ else if (val)
8012+ {
8013+ printk(KERN_ERR "udf: bad mount option \"%s=%s\"\n",
8014+ opt, val);
8015+ return 0;
8016+ }
8017+ else
8018+ {
8019+ printk(KERN_ERR "udf: bad mount option \"%s\"\n",
8020+ opt);
8021+ return 0;
8022+ }
8023+ }
8024+ return 1;
8025+}
8026+
8027+void
8028+udf_write_super(struct super_block *sb)
8029+{
8030+ if (!(sb->s_flags & MS_RDONLY))
8031+ udf_open_lvid(sb);
8032+ sb->s_dirt = 0;
8033+}
8034+
8035+static int
8036+udf_remount_fs(struct super_block *sb, int *flags, char *options)
8037+{
8038+ struct udf_options uopt;
8039+
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 ;
8044+
8045+ if ( !udf_parse_options(options, &uopt) )
8046+ return -EINVAL;
8047+
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;
8052+
8053+#if CONFIG_UDF_RW != 1
8054+ *flags |= MS_RDONLY;
8055+#endif
8056+
8057+ if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
8058+ return 0;
8059+ if (*flags & MS_RDONLY)
8060+ udf_close_lvid(sb);
8061+ else
8062+ udf_open_lvid(sb);
8063+
8064+ return 0;
8065+}
8066+
8067+/*
8068+ * udf_set_blocksize
8069+ *
8070+ * PURPOSE
8071+ * Set the block size to be used in all transfers.
8072+ *
8073+ * DESCRIPTION
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.
8077+ *
8078+ * Note that the Linux kernel can currently only deal with blocksizes of
8079+ * 512, 1024, 2048, 4096, and 8192 bytes.
8080+ *
8081+ * PRE-CONDITIONS
8082+ * sb Pointer to _locked_ superblock.
8083+ *
8084+ * POST-CONDITIONS
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.
8089+ *
8090+ * HISTORY
8091+ * July 1, 1997 - Andrew E. Mileski
8092+ * Written, tested, and released.
8093+ */
8094+static int
8095+udf_set_blocksize(struct super_block *sb, int bsize)
8096+{
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;
8102+
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;
8110+ default:
8111+ {
8112+ udf_debug("Bad block size (%ld)\n", sb->s_blocksize);
8113+ printk(KERN_ERR "udf: bad block size (%ld)\n", sb->s_blocksize);
8114+ return 0;
8115+ }
8116+ }
8117+
8118+ /* Set the block size */
8119+ set_blocksize(sb->s_dev, sb->s_blocksize);
8120+ return sb->s_blocksize;
8121+}
8122+
8123+static int
8124+udf_vrs(struct super_block *sb, int silent)
8125+{
8126+ struct VolStructDesc *vsd = NULL;
8127+ int sector = 32768;
8128+ struct buffer_head *bh = NULL;
8129+ int iso9660=0;
8130+ int nsr02=0;
8131+ int nsr03=0;
8132+
8133+ /* Block size must be a multiple of 512 */
8134+ if (sb->s_blocksize & 511)
8135+ return sector;
8136+
8137+ sector += (UDF_SB_SESSION(sb) << sb->s_blocksize_bits);
8138+
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)
8143+ {
8144+ /* Read a block */
8145+ bh = udf_tread(sb, sector >> sb->s_blocksize_bits, sb->s_blocksize);
8146+ if (!bh)
8147+ break;
8148+
8149+ /* Look for ISO descriptors */
8150+ vsd = (struct VolStructDesc *)(bh->b_data +
8151+ (sector & (sb->s_blocksize - 1)));
8152+
8153+ if (vsd->stdIdent[0] == 0)
8154+ {
8155+ udf_release_data(bh);
8156+ break;
8157+ }
8158+ else if (!strncmp(vsd->stdIdent, STD_ID_CD001, STD_ID_LEN))
8159+ {
8160+ iso9660 = sector;
8161+ switch (vsd->structType)
8162+ {
8163+ case 0:
8164+ udf_debug("ISO9660 Boot Record found\n");
8165+ break;
8166+ case 1:
8167+ udf_debug("ISO9660 Primary Volume Descriptor found\n");
8168+ break;
8169+ case 2:
8170+ udf_debug("ISO9660 Supplementary Volume Descriptor found\n");
8171+ break;
8172+ case 3:
8173+ udf_debug("ISO9660 Volume Partition Descriptor found\n");
8174+ break;
8175+ case 255:
8176+ udf_debug("ISO9660 Volume Descriptor Set Terminator found\n");
8177+ break;
8178+ default:
8179+ udf_debug("ISO9660 VRS (%u) found\n", vsd->structType);
8180+ break;
8181+ }
8182+ }
8183+ else if (!strncmp(vsd->stdIdent, STD_ID_BEA01, STD_ID_LEN))
8184+ {
8185+ }
8186+ else if (!strncmp(vsd->stdIdent, STD_ID_TEA01, STD_ID_LEN))
8187+ {
8188+ udf_release_data(bh);
8189+ break;
8190+ }
8191+ else if (!strncmp(vsd->stdIdent, STD_ID_NSR02, STD_ID_LEN))
8192+ {
8193+ nsr02 = sector;
8194+ }
8195+ else if (!strncmp(vsd->stdIdent, STD_ID_NSR03, STD_ID_LEN))
8196+ {
8197+ nsr03 = sector;
8198+ }
8199+ udf_release_data(bh);
8200+ }
8201+
8202+ if (nsr03)
8203+ return nsr03;
8204+ else if (nsr02)
8205+ return nsr02;
8206+ else if (sector - (UDF_SB_SESSION(sb) << sb->s_blocksize_bits) == 32768)
8207+ return -1;
8208+ else
8209+ return 0;
8210+}
8211+
8212+/*
8213+ * udf_find_anchor
8214+ *
8215+ * PURPOSE
8216+ * Find an anchor volume descriptor.
8217+ *
8218+ * PRE-CONDITIONS
8219+ * sb Pointer to _locked_ superblock.
8220+ * lastblock Last block on media.
8221+ *
8222+ * POST-CONDITIONS
8223+ * <return> 1 if not found, 0 if ok
8224+ *
8225+ * HISTORY
8226+ * July 1, 1997 - Andrew E. Mileski
8227+ * Written, tested, and released.
8228+ */
8229+static int
8230+udf_find_anchor(struct super_block *sb, int useranchor, int lastblock)
8231+{
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;
8238+ Uint16 ident;
8239+ Uint32 location;
8240+ int i;
8241+
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);
8246+
8247+ lastblock = 0;
8248+
8249+ /* Search for an anchor volume descriptor pointer */
8250+
8251+ /* according to spec, anchor is in either:
8252+ * block 256
8253+ * lastblock-256
8254+ * lastblock
8255+ * however, if the disc isn't closed, it could be 512 */
8256+
8257+ for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++)
8258+ {
8259+ if (!(bh = bread(sb->s_dev, last[i], sb->s_blocksize)))
8260+ {
8261+ ident = location = 0;
8262+ }
8263+ else
8264+ {
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);
8268+ }
8269+
8270+ if (ident == TID_ANCHOR_VOL_DESC_PTR)
8271+ {
8272+ if (location == last[i] - UDF_SB_SESSION(sb))
8273+ {
8274+ lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
8275+ UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
8276+ }
8277+ else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
8278+ {
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;
8282+ }
8283+ else
8284+ udf_debug("Anchor found at block %d, location mismatch %d.\n",
8285+ last[i], location);
8286+ }
8287+ else if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY)
8288+ {
8289+ lastblock = last[i];
8290+ UDF_SB_ANCHOR(sb)[2] = 512 + UDF_SB_SESSION(sb);
8291+ }
8292+ else
8293+ {
8294+ if (!(bh = bread(sb->s_dev, last[i] - 256, sb->s_blocksize)))
8295+ {
8296+ ident = location = 0;
8297+ }
8298+ else
8299+ {
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);
8303+ }
8304+
8305+ if (ident == TID_ANCHOR_VOL_DESC_PTR &&
8306+ location == last[i] - 256 - UDF_SB_SESSION(sb))
8307+ {
8308+ lastblock = last[i];
8309+ UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
8310+ }
8311+ else
8312+ {
8313+ if (!(bh = bread(sb->s_dev, last[i] - 312 - UDF_SB_SESSION(sb),
8314+ sb->s_blocksize)))
8315+ {
8316+ ident = location = 0;
8317+ }
8318+ else
8319+ {
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);
8323+ }
8324+
8325+ if (ident == TID_ANCHOR_VOL_DESC_PTR &&
8326+ location == udf_variable_to_fixed(last[i]) - 256)
8327+ {
8328+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
8329+ lastblock = udf_variable_to_fixed(last[i]);
8330+ UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
8331+ }
8332+ }
8333+ }
8334+ }
8335+
8336+ if (!lastblock)
8337+ {
8338+ /* We havn't found the lastblock. check 312 */
8339+ if ((bh = bread(sb->s_dev, 312 + UDF_SB_SESSION(sb), sb->s_blocksize)))
8340+ {
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);
8344+
8345+ if (ident == TID_ANCHOR_VOL_DESC_PTR && location == 256)
8346+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
8347+ }
8348+ }
8349+
8350+ for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
8351+ {
8352+ if (UDF_SB_ANCHOR(sb)[i])
8353+ {
8354+ if (!(bh = udf_read_tagged(sb,
8355+ UDF_SB_ANCHOR(sb)[i], UDF_SB_ANCHOR(sb)[i], &ident)))
8356+ {
8357+ UDF_SB_ANCHOR(sb)[i] = 0;
8358+ }
8359+ else
8360+ {
8361+ udf_release_data(bh);
8362+ if ((ident != TID_ANCHOR_VOL_DESC_PTR) && (i ||
8363+ (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY)))
8364+ {
8365+ UDF_SB_ANCHOR(sb)[i] = 0;
8366+ }
8367+ }
8368+ }
8369+ else if (useranchor != 0xFFFFFFFF)
8370+ {
8371+ UDF_SB_ANCHOR(sb)[i] = useranchor;
8372+ useranchor = 0xFFFFFFFF;
8373+ i --;
8374+ }
8375+ }
8376+
8377+ return lastblock;
8378+}
8379+
8380+static int
8381+udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
8382+{
8383+ struct buffer_head *bh = NULL;
8384+ long lastblock;
8385+ Uint16 ident;
8386+
8387+ if (fileset->logicalBlockNum != 0xFFFFFFFF ||
8388+ fileset->partitionReferenceNum != 0xFFFF)
8389+ {
8390+ bh = udf_read_ptagged(sb, *fileset, 0, &ident);
8391+
8392+ if (!bh)
8393+ return 1;
8394+ else if (ident != TID_FILE_SET_DESC)
8395+ {
8396+ udf_release_data(bh);
8397+ return 1;
8398+ }
8399+
8400+ }
8401+
8402+ if (!bh) /* Search backwards through the partitions */
8403+ {
8404+ lb_addr newfileset;
8405+
8406+ return 1;
8407+
8408+ for (newfileset.partitionReferenceNum=UDF_SB_NUMPARTS(sb)-1;
8409+ (newfileset.partitionReferenceNum != 0xFFFF &&
8410+ fileset->logicalBlockNum == 0xFFFFFFFF &&
8411+ fileset->partitionReferenceNum == 0xFFFF);
8412+ newfileset.partitionReferenceNum--)
8413+ {
8414+ lastblock = UDF_SB_PARTLEN(sb, newfileset.partitionReferenceNum);
8415+ newfileset.logicalBlockNum = 0;
8416+
8417+ do
8418+ {
8419+ bh = udf_read_ptagged(sb, newfileset, 0, &ident);
8420+ if (!bh)
8421+ {
8422+ newfileset.logicalBlockNum ++;
8423+ continue;
8424+ }
8425+
8426+ switch (ident)
8427+ {
8428+ case TID_SPACE_BITMAP_DESC:
8429+ {
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);
8436+ break;
8437+ }
8438+ case TID_FILE_SET_DESC:
8439+ {
8440+ *fileset = newfileset;
8441+ break;
8442+ }
8443+ default:
8444+ {
8445+ newfileset.logicalBlockNum ++;
8446+ udf_release_data(bh);
8447+ bh = NULL;
8448+ break;
8449+ }
8450+ }
8451+ }
8452+ while (newfileset.logicalBlockNum < lastblock &&
8453+ fileset->logicalBlockNum == 0xFFFFFFFF &&
8454+ fileset->partitionReferenceNum == 0xFFFF);
8455+ }
8456+ }
8457+
8458+ if ((fileset->logicalBlockNum != 0xFFFFFFFF ||
8459+ fileset->partitionReferenceNum != 0xFFFF) && bh)
8460+ {
8461+ udf_debug("Fileset at block=%d, partition=%d\n",
8462+ fileset->logicalBlockNum, fileset->partitionReferenceNum);
8463+
8464+ UDF_SB_PARTITION(sb) = fileset->partitionReferenceNum;
8465+ udf_load_fileset(sb, bh, root);
8466+ udf_release_data(bh);
8467+ return 0;
8468+ }
8469+ return 1;
8470+}
8471+
8472+static void
8473+udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
8474+{
8475+ struct PrimaryVolDesc *pvoldesc;
8476+ time_t recording;
8477+ long recording_usec;
8478+ struct ustr instr;
8479+ struct ustr outstr;
8480+
8481+ pvoldesc = (struct PrimaryVolDesc *)bh->b_data;
8482+
8483+ if ( udf_stamp_to_time(&recording, &recording_usec,
8484+ lets_to_cpu(pvoldesc->recordingDateAndTime)) )
8485+ {
8486+ timestamp ts;
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;
8492+ }
8493+
8494+ if ( !udf_build_ustr(&instr, pvoldesc->volIdent, 32) )
8495+ {
8496+ if (udf_CS0toUTF8(&outstr, &instr))
8497+ {
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));
8501+ }
8502+ }
8503+
8504+ if ( !udf_build_ustr(&instr, pvoldesc->volSetIdent, 128) )
8505+ {
8506+ if (udf_CS0toUTF8(&outstr, &instr))
8507+ udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
8508+ }
8509+}
8510+
8511+static void
8512+udf_load_fileset(struct super_block *sb, struct buffer_head *bh, lb_addr *root)
8513+{
8514+ struct FileSetDesc *fset;
8515+
8516+ fset = (struct FileSetDesc *)bh->b_data;
8517+
8518+ *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation);
8519+
8520+ UDF_SB_SERIALNUM(sb) = le16_to_cpu(fset->descTag.tagSerialNum);
8521+
8522+ udf_debug("Rootdir at block=%d, partition=%d\n",
8523+ root->logicalBlockNum, root->partitionReferenceNum);
8524+}
8525+
8526+static void
8527+udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
8528+{
8529+ struct PartitionDesc *p;
8530+ int i;
8531+
8532+ p=(struct PartitionDesc *)bh->b_data;
8533+
8534+ for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
8535+ {
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))
8539+ {
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);
8542+
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));
8545+
8546+ if (!strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR02) ||
8547+ !strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR03))
8548+ {
8549+ struct PartitionHeaderDesc *phd;
8550+
8551+ phd = (struct PartitionHeaderDesc *)(p->partitionContentsUse);
8552+ if (phd->unallocatedSpaceTable.extLength)
8553+ {
8554+ lb_addr loc = { i, phd->unallocatedSpaceTable.extPosition };
8555+
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);
8561+ }
8562+ if (phd->unallocatedSpaceBitmap.extLength)
8563+ {
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);
8572+ }
8573+ if (phd->partitionIntegrityTable.extLength)
8574+ udf_debug("partitionIntegrityTable (part %d)\n", i);
8575+ if (phd->freedSpaceTable.extLength)
8576+ {
8577+ lb_addr loc = { i, phd->freedSpaceTable.extPosition };
8578+
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);
8584+ }
8585+ if (phd->freedSpaceBitmap.extLength)
8586+ {
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);
8595+ }
8596+ }
8597+ break;
8598+ }
8599+ }
8600+ if (i == UDF_SB_NUMPARTS(sb))
8601+ {
8602+ udf_debug("Partition (%d) not found in partition map\n", le16_to_cpu(p->partitionNumber));
8603+ }
8604+ else
8605+ {
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));
8609+ }
8610+}
8611+
8612+static int
8613+udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fileset)
8614+{
8615+ struct LogicalVolDesc *lvd;
8616+ int i, j, offset;
8617+ Uint8 type;
8618+
8619+ lvd = (struct LogicalVolDesc *)bh->b_data;
8620+
8621+ UDF_SB_NUMPARTS(sb) = le32_to_cpu(lvd->numPartitionMaps);
8622+ UDF_SB_ALLOC_PARTMAPS(sb, UDF_SB_NUMPARTS(sb));
8623+
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)
8627+ {
8628+ type = ((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapType;
8629+ if (type == 1)
8630+ {
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;
8636+ }
8637+ else if (type == 2)
8638+ {
8639+ struct UdfPartitionMap2 *upm2 = (struct UdfPartitionMap2 *)&(lvd->partitionMaps[offset]);
8640+ if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
8641+ {
8642+ if (le16_to_cpu(((Uint16 *)upm2->partIdent.identSuffix)[0]) == 0x0150)
8643+ {
8644+ UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP15;
8645+ UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt15;
8646+ }
8647+ else if (le16_to_cpu(((Uint16 *)upm2->partIdent.identSuffix)[0]) == 0x0200)
8648+ {
8649+ UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP20;
8650+ UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt20;
8651+ }
8652+ }
8653+ else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE)))
8654+ {
8655+ int plen;
8656+
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;
8666+ }
8667+ else
8668+ {
8669+ udf_debug("Unknown ident: %s\n", upm2->partIdent.ident);
8670+ continue;
8671+ }
8672+ UDF_SB_PARTVSN(sb,i) = le16_to_cpu(upm2->volSeqNum);
8673+ UDF_SB_PARTNUM(sb,i) = le16_to_cpu(upm2->partitionNum);
8674+ }
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));
8677+ }
8678+
8679+ if (fileset)
8680+ {
8681+ long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
8682+
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);
8687+ }
8688+ if (lvd->integritySeqExt.extLength)
8689+ udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
8690+ return 0;
8691+}
8692+
8693+/*
8694+ * udf_load_logicalvolint
8695+ *
8696+ */
8697+static void
8698+udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
8699+{
8700+ struct buffer_head *bh = NULL;
8701+ Uint16 ident;
8702+
8703+ while ((bh = udf_read_tagged(sb, loc.extLocation, loc.extLocation, &ident)) &&
8704+ ident == TID_LOGICAL_VOL_INTEGRITY_DESC && loc.extLength > 0)
8705+ {
8706+ UDF_SB_LVIDBH(sb) = bh;
8707+
8708+ if (UDF_SB_LVID(sb)->nextIntegrityExt.extLength)
8709+ udf_load_logicalvolint(sb, leea_to_cpu(UDF_SB_LVID(sb)->nextIntegrityExt));
8710+
8711+ if (UDF_SB_LVIDBH(sb) != bh)
8712+ udf_release_data(bh);
8713+ loc.extLength -= sb->s_blocksize;
8714+ loc.extLocation ++;
8715+ }
8716+ if (UDF_SB_LVIDBH(sb) != bh)
8717+ udf_release_data(bh);
8718+}
8719+
8720+/*
8721+ * udf_process_sequence
8722+ *
8723+ * PURPOSE
8724+ * Process a main/reserve volume descriptor sequence.
8725+ *
8726+ * PRE-CONDITIONS
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.
8730+ *
8731+ * HISTORY
8732+ * July 1, 1997 - Andrew E. Mileski
8733+ * Written, tested, and released.
8734+ */
8735+static int
8736+udf_process_sequence(struct super_block *sb, long block, long lastblock, lb_addr *fileset)
8737+{
8738+ struct buffer_head *bh = NULL;
8739+ struct udf_vds_record vds[VDS_POS_LENGTH];
8740+ struct GenericDesc *gd;
8741+ int done=0;
8742+ int i,j;
8743+ Uint32 vdsn;
8744+ Uint16 ident;
8745+
8746+ memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
8747+
8748+ /* Read the main descriptor sequence */
8749+ for (;(!done && block <= lastblock); block++)
8750+ {
8751+
8752+ bh = udf_read_tagged(sb, block, block, &ident);
8753+ if (!bh)
8754+ break;
8755+
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);
8759+ switch (ident)
8760+ {
8761+ case TID_PRIMARY_VOL_DESC: /* ISO 13346 3/10.1 */
8762+ if (vdsn >= vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum)
8763+ {
8764+ vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum = vdsn;
8765+ vds[VDS_POS_PRIMARY_VOL_DESC].block = block;
8766+ }
8767+ break;
8768+ case TID_VOL_DESC_PTR: /* ISO 13346 3/10.3 */
8769+ if (vdsn >= vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum)
8770+ {
8771+ vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn;
8772+ vds[VDS_POS_VOL_DESC_PTR].block = block;
8773+ }
8774+ break;
8775+ case TID_IMP_USE_VOL_DESC: /* ISO 13346 3/10.4 */
8776+ if (vdsn >= vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum)
8777+ {
8778+ vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum = vdsn;
8779+ vds[VDS_POS_IMP_USE_VOL_DESC].block = block;
8780+ }
8781+ break;
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;
8785+ break;
8786+ case TID_LOGICAL_VOL_DESC: /* ISO 13346 3/10.6 */
8787+ if (vdsn >= vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum)
8788+ {
8789+ vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum = vdsn;
8790+ vds[VDS_POS_LOGICAL_VOL_DESC].block = block;
8791+ }
8792+ break;
8793+ case TID_UNALLOC_SPACE_DESC: /* ISO 13346 3/10.8 */
8794+ if (vdsn >= vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum)
8795+ {
8796+ vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum = vdsn;
8797+ vds[VDS_POS_UNALLOC_SPACE_DESC].block = block;
8798+ }
8799+ break;
8800+ case TID_TERMINATING_DESC: /* ISO 13346 3/10.9 */
8801+ vds[VDS_POS_TERMINATING_DESC].block = block;
8802+ done = 1;
8803+ break;
8804+ }
8805+ udf_release_data(bh);
8806+ }
8807+ for (i=0; i<VDS_POS_LENGTH; i++)
8808+ {
8809+ if (vds[i].block)
8810+ {
8811+ bh = udf_read_tagged(sb, vds[i].block, vds[i].block, &ident);
8812+
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)
8818+ {
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++)
8822+ {
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);
8828+ }
8829+ }
8830+ udf_release_data(bh);
8831+ }
8832+ }
8833+
8834+ return 0;
8835+}
8836+
8837+/*
8838+ * udf_check_valid()
8839+ */
8840+static int
8841+udf_check_valid(struct super_block *sb, int novrs, int silent)
8842+{
8843+ long block;
8844+
8845+ if (novrs)
8846+ {
8847+ udf_debug("Validity check skipped because of novrs option\n");
8848+ return 0;
8849+ }
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)
8853+ {
8854+ udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n");
8855+ return 0;
8856+ }
8857+ else
8858+ return !block;
8859+}
8860+
8861+static int
8862+udf_load_partition(struct super_block *sb, lb_addr *fileset)
8863+{
8864+ struct AnchorVolDescPtr *anchor;
8865+ Uint16 ident;
8866+ struct buffer_head *bh;
8867+ long main_s, main_e, reserve_s, reserve_e;
8868+ int i, j;
8869+
8870+ if (!sb)
8871+ return 1;
8872+
8873+ for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
8874+ {
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)))
8877+ {
8878+ anchor = (struct AnchorVolDescPtr *)bh->b_data;
8879+
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;
8884+ main_e += main_s;
8885+
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;
8891+
8892+ udf_release_data(bh);
8893+
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)))
8898+ {
8899+ break;
8900+ }
8901+ }
8902+ }
8903+
8904+ if (i == sizeof(UDF_SB_ANCHOR(sb))/sizeof(int))
8905+ {
8906+ udf_debug("No Anchor block found\n");
8907+ return 1;
8908+ }
8909+ else
8910+ udf_debug("Using anchor in block %d\n", UDF_SB_ANCHOR(sb)[i]);
8911+
8912+ for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
8913+ {
8914+ switch UDF_SB_PARTTYPE(sb, i)
8915+ {
8916+ case UDF_VIRTUAL_MAP15:
8917+ case UDF_VIRTUAL_MAP20:
8918+ {
8919+ lb_addr ino;
8920+
8921+ if (!UDF_SB_LASTBLOCK(sb))
8922+ {
8923+ udf_debug("Unable to determine Lastblock (For Virtual Partition)\n");
8924+ return 1;
8925+ }
8926+
8927+ for (j=0; j<UDF_SB_NUMPARTS(sb); j++)
8928+ {
8929+ if (j != i &&
8930+ UDF_SB_PARTVSN(sb,i) == UDF_SB_PARTVSN(sb,j) &&
8931+ UDF_SB_PARTNUM(sb,i) == UDF_SB_PARTNUM(sb,j))
8932+ {
8933+ ino.partitionReferenceNum = j;
8934+ ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) -
8935+ UDF_SB_PARTROOT(sb,j);
8936+ break;
8937+ }
8938+ }
8939+
8940+ if (j == UDF_SB_NUMPARTS(sb))
8941+ return 1;
8942+
8943+ if (!(UDF_SB_VAT(sb) = udf_iget(sb, ino)))
8944+ return 1;
8945+
8946+ if (UDF_SB_PARTTYPE(sb,i) == UDF_VIRTUAL_MAP15)
8947+ {
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;
8950+ }
8951+ else if (UDF_SB_PARTTYPE(sb,i) == UDF_VIRTUAL_MAP20)
8952+ {
8953+ struct buffer_head *bh = NULL;
8954+ Uint32 pos;
8955+
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);
8964+ }
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);
8967+ }
8968+ }
8969+ }
8970+ return 0;
8971+}
8972+
8973+static void udf_open_lvid(struct super_block *sb)
8974+{
8975+ if (UDF_SB_LVIDBH(sb))
8976+ {
8977+ int i;
8978+ timestamp cpu_time;
8979+
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;
8985+
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));
8989+
8990+ UDF_SB_LVID(sb)->descTag.tagChecksum = 0;
8991+ for (i=0; i<16; i++)
8992+ if (i != 4)
8993+ UDF_SB_LVID(sb)->descTag.tagChecksum +=
8994+ ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i];
8995+
8996+ mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
8997+ }
8998+}
8999+
9000+static void udf_close_lvid(struct super_block *sb)
9001+{
9002+ if (UDF_SB_LVIDBH(sb) &&
9003+ UDF_SB_LVID(sb)->integrityType == INTEGRITY_TYPE_OPEN)
9004+ {
9005+ int i;
9006+ timestamp cpu_time;
9007+
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;
9019+
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));
9023+
9024+ UDF_SB_LVID(sb)->descTag.tagChecksum = 0;
9025+ for (i=0; i<16; i++)
9026+ if (i != 4)
9027+ UDF_SB_LVID(sb)->descTag.tagChecksum +=
9028+ ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i];
9029+
9030+ mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
9031+ }
9032+}
9033+
9034+/*
9035+ * udf_read_super
9036+ *
9037+ * PURPOSE
9038+ * Complete the specified super block.
9039+ *
9040+ * PRE-CONDITIONS
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.
9045+ *
9046+ * HISTORY
9047+ * July 1, 1997 - Andrew E. Mileski
9048+ * Written, tested, and released.
9049+ */
9050+static struct super_block *
9051+udf_read_super(struct super_block *sb, void *options, int silent)
9052+{
9053+ struct inode *inode=NULL;
9054+ struct udf_options uopt;
9055+ lb_addr rootdir, fileset;
9056+
9057+ uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB);
9058+ uopt.uid = 0;
9059+ uopt.gid = 0;
9060+ uopt.umask = 0;
9061+
9062+ /* Lock the module in memory (if applicable) */
9063+ MOD_INC_USE_COUNT;
9064+
9065+ lock_super(sb);
9066+ UDF_SB_ALLOC(sb); /* kmalloc, if needed */
9067+ memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
9068+
9069+#if CONFIG_UDF_RW != 1
9070+ sb->s_flags |= MS_RDONLY;
9071+#endif
9072+
9073+ if (!udf_parse_options((char *)options, &uopt))
9074+ goto error_out;
9075+
9076+ fileset.logicalBlockNum = 0xFFFFFFFF;
9077+ fileset.partitionReferenceNum = 0xFFFF;
9078+
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;
9083+
9084+ /* Set the block size for all transfers */
9085+ if (!udf_set_blocksize(sb, uopt.blocksize))
9086+ goto error_out;
9087+
9088+ if ( uopt.session == 0xFFFFFFFF )
9089+ UDF_SB_SESSION(sb) = udf_get_last_session(sb);
9090+ else
9091+ UDF_SB_SESSION(sb) = uopt.session;
9092+
9093+ udf_debug("Multi-session=%d\n", UDF_SB_SESSION(sb));
9094+
9095+ if ( uopt.lastblock == 0xFFFFFFFF )
9096+ UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
9097+ else
9098+ UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
9099+
9100+ UDF_SB_LASTBLOCK(sb) = udf_find_anchor(sb, uopt.anchor, UDF_SB_LASTBLOCK(sb));
9101+
9102+ udf_debug("Lastblock=%d\n", UDF_SB_LASTBLOCK(sb));
9103+
9104+ if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
9105+ {
9106+ printk("UDF-fs: No VRS found\n");
9107+ goto error_out;
9108+ }
9109+
9110+ /* Fill in the rest of the superblock */
9111+ sb->s_op = &udf_sb_ops;
9112+ sb->dq_op = NULL;
9113+ sb->s_dirt = 0;
9114+ sb->s_magic = UDF_SUPER_MAGIC;
9115+
9116+ if (udf_load_partition(sb, &fileset))
9117+ {
9118+ printk("UDF-fs: No partition found (1)\n");
9119+ goto error_out;
9120+ }
9121+
9122+ if ( UDF_SB_LVIDBH(sb) )
9123+ {
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); */
9127+
9128+ if (minUDFReadRev > UDF_MAX_READ_VERSION)
9129+ {
9130+ printk("UDF-fs: minUDFReadRev=%x (max is %x)\n",
9131+ UDF_SB_LVIDIU(sb)->minUDFReadRev, UDF_MAX_READ_VERSION);
9132+ goto error_out;
9133+ }
9134+ else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
9135+ {
9136+ sb->s_flags |= MS_RDONLY;
9137+ }
9138+
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);
9143+ }
9144+
9145+ if ( !UDF_SB_NUMPARTS(sb) )
9146+ {
9147+ printk("UDF-fs: No partition found (2)\n");
9148+ goto error_out;
9149+ }
9150+
9151+ if ( udf_find_fileset(sb, &fileset, &rootdir) )
9152+ {
9153+ printk("UDF-fs: No fileset found\n");
9154+ goto error_out;
9155+ }
9156+
9157+ if (!silent)
9158+ {
9159+ timestamp ts;
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);
9165+ }
9166+ if (!(sb->s_flags & MS_RDONLY))
9167+ udf_open_lvid(sb);
9168+ unlock_super(sb);
9169+
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);
9174+ if (!inode)
9175+ {
9176+ printk("UDF-fs: Error in udf_iget, block=%d, partition=%d\n",
9177+ rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
9178+ goto error_out;
9179+ }
9180+
9181+ /* Allocate a dentry for the root inode */
9182+ sb->s_root = d_alloc_root(inode, NULL);
9183+ if (!sb->s_root)
9184+ {
9185+ printk("UDF-fs: Couldn't allocate root dentry\n");
9186+ iput(inode);
9187+ goto error_out;
9188+ }
9189+
9190+ return sb;
9191+
9192+error_out:
9193+ sb->s_dev = NODEV;
9194+ if (UDF_SB_VAT(sb))
9195+ iput(UDF_SB_VAT(sb));
9196+ if (UDF_SB_NUMPARTS(sb))
9197+ {
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);
9206+ }
9207+ if (!(sb->s_flags & MS_RDONLY))
9208+ udf_close_lvid(sb);
9209+ udf_release_data(UDF_SB_LVIDBH(sb));
9210+ UDF_SB_FREE(sb);
9211+ unlock_super(sb);
9212+ MOD_DEC_USE_COUNT;
9213+ return NULL;
9214+}
9215+
9216+void udf_error(struct super_block *sb, const char *function,
9217+ const char *fmt, ...)
9218+{
9219+ va_list args;
9220+
9221+ if (!(sb->s_flags & MS_RDONLY))
9222+ {
9223+ /* mark sb error */
9224+ sb->s_dirt = 1;
9225+ }
9226+ va_start(args, fmt);
9227+ vsprintf(error_buf, fmt, args);
9228+ va_end(args);
9229+ printk (KERN_CRIT "UDF-fs error (device %s): %s: %s\n",
9230+ bdevname(sb->s_dev), function, error_buf);
9231+}
9232+
9233+void udf_warning(struct super_block *sb, const char *function,
9234+ const char *fmt, ...)
9235+{
9236+ va_list args;
9237+
9238+ va_start (args, fmt);
9239+ vsprintf(error_buf, fmt, args);
9240+ va_end(args);
9241+ printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n",
9242+ bdevname(sb->s_dev), function, error_buf);
9243+}
9244+
9245+/*
9246+ * udf_put_super
9247+ *
9248+ * PURPOSE
9249+ * Prepare for destruction of the superblock.
9250+ *
9251+ * DESCRIPTION
9252+ * Called before the filesystem is unmounted.
9253+ *
9254+ * HISTORY
9255+ * July 1, 1997 - Andrew E. Mileski
9256+ * Written, tested, and released.
9257+ */
9258+static void
9259+udf_put_super(struct super_block *sb)
9260+{
9261+ int i;
9262+
9263+ if (UDF_SB_VAT(sb))
9264+ iput(UDF_SB_VAT(sb));
9265+ if (UDF_SB_NUMPARTS(sb))
9266+ {
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)
9272+ {
9273+ for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_uspace); i++)
9274+ {
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));
9277+ }
9278+ kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
9279+ }
9280+ if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
9281+ {
9282+ for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_fspace); i++)
9283+ {
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));
9286+ }
9287+ kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
9288+ }
9289+ }
9290+ if (!(sb->s_flags & MS_RDONLY))
9291+ udf_close_lvid(sb);
9292+ udf_release_data(UDF_SB_LVIDBH(sb));
9293+ UDF_SB_FREE(sb);
9294+
9295+ MOD_DEC_USE_COUNT;
9296+}
9297+
9298+/*
9299+ * udf_stat_fs
9300+ *
9301+ * PURPOSE
9302+ * Return info about the filesystem.
9303+ *
9304+ * DESCRIPTION
9305+ * Called by sys_statfs()
9306+ *
9307+ * HISTORY
9308+ * July 1, 1997 - Andrew E. Mileski
9309+ * Written, tested, and released.
9310+ */
9311+static int
9312+udf_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
9313+{
9314+ int size;
9315+ struct statfs tmp;
9316+ int rc;
9317+
9318+ size = (bufsize < sizeof(tmp)) ? bufsize: sizeof(tmp);
9319+
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;
9332+
9333+ rc= copy_to_user(buf, &tmp, size) ? -EFAULT: 0;
9334+ return rc;
9335+}
9336+
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
9339+};
9340+
9341+static unsigned int
9342+udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
9343+{
9344+ struct buffer_head *bh = NULL;
9345+ unsigned int accum = 0;
9346+ int index;
9347+ int block = 0, newblock;
9348+ lb_addr loc;
9349+ Uint32 bytes;
9350+ Uint8 value;
9351+ Uint8 *ptr;
9352+ Uint16 ident;
9353+ struct SpaceBitmapDesc *bm;
9354+
9355+ loc.logicalBlockNum = bitmap->s_extPosition;
9356+ loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
9357+ bh = udf_read_ptagged(sb, loc, 0, &ident);
9358+
9359+ if (!bh)
9360+ {
9361+ printk(KERN_ERR "udf: udf_count_free failed\n");
9362+ return 0;
9363+ }
9364+ else if (ident != TID_SPACE_BITMAP_DESC)
9365+ {
9366+ udf_release_data(bh);
9367+ printk(KERN_ERR "udf: udf_count_free failed\n");
9368+ return 0;
9369+ }
9370+
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;
9375+
9376+ while ( bytes > 0 )
9377+ {
9378+ while ((bytes > 0) && (index < sb->s_blocksize))
9379+ {
9380+ value = ptr[index];
9381+ accum += udf_bitmap_lookup[ value & 0x0f ];
9382+ accum += udf_bitmap_lookup[ value >> 4 ];
9383+ index++;
9384+ bytes--;
9385+ }
9386+ if ( bytes )
9387+ {
9388+ udf_release_data(bh);
9389+ newblock = udf_get_lb_pblock(sb, loc, ++block);
9390+ bh = udf_tread(sb, newblock, sb->s_blocksize);
9391+ if (!bh)
9392+ {
9393+ udf_debug("read failed\n");
9394+ return accum;
9395+ }
9396+ index = 0;
9397+ ptr = (Uint8 *)bh->b_data;
9398+ }
9399+ }
9400+ udf_release_data(bh);
9401+ return accum;
9402+}
9403+
9404+static unsigned int
9405+udf_count_free_table(struct super_block *sb, struct inode * table)
9406+{
9407+ unsigned int accum = 0;
9408+ Uint32 extoffset, elen;
9409+ lb_addr bloc, eloc;
9410+ char etype;
9411+ struct buffer_head *bh = NULL;
9412+
9413+ bloc = UDF_I_LOCATION(table);
9414+ extoffset = sizeof(struct UnallocatedSpaceEntry);
9415+
9416+ while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
9417+ {
9418+ accum += (elen >> table->i_sb->s_blocksize_bits);
9419+ }
9420+ udf_release_data(bh);
9421+ return accum;
9422+}
9423+
9424+static unsigned int
9425+udf_count_free(struct super_block *sb)
9426+{
9427+ unsigned int accum = 0;
9428+
9429+ if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
9430+ {
9431+ accum += udf_count_free_bitmap(sb,
9432+ UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
9433+ }
9434+ if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
9435+ {
9436+ accum += udf_count_free_bitmap(sb,
9437+ UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
9438+ }
9439+ if (accum)
9440+ return accum;
9441+
9442+ if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE)
9443+ {
9444+ accum += udf_count_free_table(sb,
9445+ UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table);
9446+ }
9447+ if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
9448+ {
9449+ accum += udf_count_free_table(sb,
9450+ UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
9451+ }
9452+ if (accum)
9453+ return accum;
9454+
9455+ if (UDF_SB_LVIDBH(sb))
9456+ {
9457+ if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb))
9458+ {
9459+ accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]);
9460+
9461+ if (accum == 0xFFFFFFFF)
9462+ accum = 0;
9463+ }
9464+ }
9465+ return accum;
9466+}
9467diff -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
9470@@ -0,0 +1,181 @@
9471+/*
9472+ * symlink.c
9473+ *
9474+ * PURPOSE
9475+ * Symlink handling routines for the OSTA-UDF(tm) filesystem.
9476+ *
9477+ * CONTACTS
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
9481+ *
9482+ * COPYRIGHT
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.
9487+ *
9488+ * (C) 1998-2000 Ben Fennema
9489+ * (C) 1999 Stelias Computing Inc
9490+ *
9491+ * HISTORY
9492+ *
9493+ * 04/16/99 blf Created.
9494+ *
9495+ */
9496+
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>
9506+#include "udf_i.h"
9507+
9508+static void udf_pc_to_char(char *from, int fromlen, char *to)
9509+{
9510+ struct PathComponent *pc;
9511+ int elen = 0;
9512+ char *p = to;
9513+
9514+ while (elen < fromlen)
9515+ {
9516+ pc = (struct PathComponent *)(from + elen);
9517+ switch (pc->componentType)
9518+ {
9519+ case 1:
9520+ if (pc->lengthComponentIdent == 0)
9521+ {
9522+ p = to;
9523+ *p++ = '/';
9524+ }
9525+ break;
9526+ case 3:
9527+ memcpy(p, "../", 3);
9528+ p += 3;
9529+ break;
9530+ case 4:
9531+ memcpy(p, "./", 2);
9532+ p += 2;
9533+ /* that would be . - just ignore */
9534+ break;
9535+ case 5:
9536+ memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
9537+ p += pc->lengthComponentIdent;
9538+ *p++ = '/';
9539+ }
9540+ elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
9541+ }
9542+ if (p > to+1)
9543+ p[-1] = '\0';
9544+ else
9545+ p[0] = '\0';
9546+}
9547+
9548+static struct dentry * udf_follow_link(struct dentry * dentry,
9549+ struct dentry * base, unsigned int follow)
9550+{
9551+ struct inode *inode = dentry->d_inode;
9552+ struct buffer_head *bh = NULL;
9553+ char *symlink, *tmpbuf;
9554+
9555+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
9556+ {
9557+ bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
9558+
9559+ if (!bh)
9560+ return 0;
9561+
9562+ symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
9563+ }
9564+ else
9565+ {
9566+ bh = bread(inode->i_dev, udf_bmap(inode, 0), inode->i_sb->s_blocksize);
9567+
9568+ if (!bh)
9569+ return 0;
9570+
9571+ symlink = bh->b_data;
9572+ }
9573+ if ((tmpbuf = (char *)kmalloc(inode->i_size, GFP_KERNEL)))
9574+ {
9575+ udf_pc_to_char(symlink, inode->i_size, tmpbuf);
9576+ base = lookup_dentry(tmpbuf, base, follow);
9577+ kfree(tmpbuf);
9578+ return base;
9579+ }
9580+ else
9581+ return ERR_PTR(-ENOMEM);
9582+}
9583+
9584+static int udf_readlink(struct dentry * dentry, char * buffer, int buflen)
9585+{
9586+ struct inode *inode = dentry->d_inode;
9587+ struct buffer_head *bh = NULL;
9588+ char *symlink, *tmpbuf;
9589+ int len;
9590+
9591+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
9592+ {
9593+ bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
9594+
9595+ if (!bh)
9596+ return 0;
9597+
9598+ symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
9599+ }
9600+ else
9601+ {
9602+ bh = bread(inode->i_dev, udf_bmap(inode, 0), inode->i_sb->s_blocksize);
9603+
9604+ if (!bh)
9605+ return 0;
9606+
9607+ symlink = bh->b_data;
9608+ }
9609+
9610+ if ((tmpbuf = (char *)kmalloc(inode->i_size, GFP_KERNEL)))
9611+ {
9612+ udf_pc_to_char(symlink, inode->i_size, tmpbuf);
9613+ if ((len = strlen(tmpbuf)) > buflen)
9614+ len = buflen;
9615+ if (copy_to_user(buffer, tmpbuf, len))
9616+ len = -EFAULT;
9617+ kfree(tmpbuf);
9618+ }
9619+ else
9620+ len = -ENOMEM;
9621+
9622+ UPDATE_ATIME(inode);
9623+ if (bh)
9624+ udf_release_data(bh);
9625+ return len;
9626+}
9627+
9628+/*
9629+ * symlinks can't do much...
9630+ */
9631+struct inode_operations udf_symlink_inode_operations = {
9632+ NULL, /* no file-operations */
9633+ NULL, /* create */
9634+ NULL, /* lookup */
9635+ NULL, /* link */
9636+ NULL, /* unlink */
9637+ NULL, /* symlink */
9638+ NULL, /* mkdir */
9639+ NULL, /* rmdir */
9640+ NULL, /* mknod */
9641+ NULL, /* rename */
9642+ udf_readlink, /* readlink */
9643+ udf_follow_link,/* follow_link */
9644+ NULL, /* readpage */
9645+ NULL, /* writepage */
9646+ NULL, /* bmap */
9647+ NULL, /* truncate */
9648+ NULL, /* permission */
9649+ NULL, /* smap */
9650+ NULL /* revalidate */
9651+};
9652diff -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
9655@@ -0,0 +1,288 @@
9656+/*
9657+ * truncate.c
9658+ *
9659+ * PURPOSE
9660+ * Truncate handling routines for the OSTA-UDF(tm) filesystem.
9661+ *
9662+ * CONTACTS
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
9666+ *
9667+ * COPYRIGHT
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.
9672+ *
9673+ * (C) 1999-2000 Ben Fennema
9674+ * (C) 1999 Stelias Computing Inc
9675+ *
9676+ * HISTORY
9677+ *
9678+ * 02/24/99 blf Created.
9679+ *
9680+ */
9681+
9682+#include "udfdecl.h"
9683+#include <linux/fs.h>
9684+#include <linux/mm.h>
9685+#include <linux/udf_fs.h>
9686+
9687+#include "udf_i.h"
9688+#include "udf_sb.h"
9689+
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)
9692+{
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;
9697+
9698+ if (nelen)
9699+ {
9700+ neloc = eloc;
9701+ nelen = (etype << 30) | nelen;
9702+ }
9703+
9704+ if (elen != nelen)
9705+ {
9706+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
9707+ if (last_block - first_block > 0)
9708+ {
9709+ if (etype == EXTENT_RECORDED_ALLOCATED)
9710+ {
9711+ inode->i_blocks -= (blocks * (last_block - first_block));
9712+ mark_inode_dirty(inode);
9713+ }
9714+ if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
9715+ udf_free_blocks(inode, eloc, first_block, last_block - first_block);
9716+ }
9717+ }
9718+}
9719+
9720+void udf_trunc(struct inode * inode)
9721+{
9722+ lb_addr bloc, eloc, neloc = { 0, 0 };
9723+ Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
9724+ int etype;
9725+ int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
9726+ struct buffer_head *bh = NULL;
9727+ int adsize;
9728+
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);
9733+ else
9734+ adsize = 0;
9735+
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));
9739+ if (etype != -1)
9740+ {
9741+ extoffset -= adsize;
9742+ extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset);
9743+ extoffset += adsize;
9744+
9745+ if (offset)
9746+ lenalloc = extoffset;
9747+ else
9748+ lenalloc = extoffset - adsize;
9749+
9750+ if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9751+ lenalloc -= udf_file_entry_alloc_offset(inode);
9752+ else
9753+ lenalloc -= sizeof(struct AllocExtDesc);
9754+
9755+ while ((etype = udf_current_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0)) != -1)
9756+ {
9757+ if (etype == EXTENT_NEXT_EXTENT_ALLOCDECS)
9758+ {
9759+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
9760+ extoffset = 0;
9761+ if (lelen)
9762+ {
9763+ if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9764+ memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
9765+ else
9766+ memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
9767+ udf_free_blocks(inode, bloc, 0, lelen);
9768+ }
9769+ else
9770+ {
9771+ if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9772+ {
9773+ UDF_I_LENALLOC(inode) = lenalloc;
9774+ mark_inode_dirty(inode);
9775+ }
9776+ else
9777+ {
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);
9783+ }
9784+ }
9785+
9786+ udf_release_data(bh);
9787+ bh = NULL;
9788+
9789+ bloc = eloc;
9790+ if (elen)
9791+ lelen = (elen + inode->i_sb->s_blocksize - 1) >>
9792+ inode->i_sb->s_blocksize_bits;
9793+ else
9794+ lelen = 1;
9795+ }
9796+ else
9797+ {
9798+ extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
9799+ extoffset += adsize;
9800+ }
9801+ }
9802+
9803+ if (lelen)
9804+ {
9805+ if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9806+ memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
9807+ else
9808+ memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
9809+ udf_free_blocks(inode, bloc, 0, lelen);
9810+ }
9811+ else
9812+ {
9813+ if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
9814+ {
9815+ UDF_I_LENALLOC(inode) = lenalloc;
9816+ mark_inode_dirty(inode);
9817+ }
9818+ else
9819+ {
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);
9825+ }
9826+ }
9827+ }
9828+ else if (inode->i_size)
9829+ {
9830+ if (offset)
9831+ {
9832+ extoffset -= adsize;
9833+ etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
9834+
9835+ if (etype == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
9836+ {
9837+ extoffset -= adsize;
9838+ elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (elen + offset);
9839+ udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
9840+ }
9841+ else if (etype == EXTENT_NOT_RECORDED_ALLOCATED)
9842+ {
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);
9850+ }
9851+ else
9852+ {
9853+ if (elen & (inode->i_sb->s_blocksize - 1))
9854+ {
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);
9860+ }
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);
9864+ }
9865+ }
9866+ }
9867+
9868+ udf_release_data(bh);
9869+}
9870+
9871+void udf_truncate(struct inode * inode)
9872+{
9873+ int offset;
9874+
9875+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
9876+ S_ISLNK(inode->i_mode)))
9877+ return;
9878+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
9879+ return;
9880+
9881+ udf_trunc(inode);
9882+
9883+ offset = (inode->i_size & (inode->i_sb->s_blocksize - 1));
9884+ if (offset)
9885+ {
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);
9890+ if (bh)
9891+ {
9892+ memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
9893+ mark_buffer_dirty(bh, 0);
9894+ udf_release_data(bh);
9895+ }
9896+ }
9897+
9898+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
9899+ mark_inode_dirty(inode);
9900+}
9901+
9902+void udf_truncate_adinicb(struct inode * inode)
9903+{
9904+ int offset;
9905+ struct buffer_head *bh;
9906+ int err;
9907+
9908+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
9909+ S_ISLNK(inode->i_mode)))
9910+ return;
9911+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
9912+ return;
9913+
9914+ if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
9915+ inode->i_size))
9916+ {
9917+ udf_expand_file_adinicb(inode, inode->i_size, &err);
9918+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
9919+ {
9920+ inode->i_size = UDF_I_LENALLOC(inode);
9921+ return;
9922+ }
9923+ else
9924+ return udf_truncate(inode);
9925+ }
9926+ else
9927+ UDF_I_LENALLOC(inode) = inode->i_size;
9928+
9929+ offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
9930+ udf_file_entry_alloc_offset(inode);
9931+
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)))
9935+ {
9936+ memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
9937+ mark_buffer_dirty(bh, 0);
9938+ udf_release_data(bh);
9939+ }
9940+
9941+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
9942+ mark_inode_dirty(inode);
9943+}
9944diff -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
9947@@ -0,0 +1,29 @@
9948+#ifndef __LINUX_UDF_I_H
9949+#define __LINUX_UDF_I_H
9950+
9951+#ifndef CONFIG_UDF_FS_EXT
9952+
9953+#define UDF_I(X) (&((X)->u.udf_i))
9954+
9955+#else
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 */
9960+#endif
9961+
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 )
9975+
9976+#endif /* !defined(_LINUX_UDF_I_H) */
9977diff -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
9980@@ -0,0 +1,125 @@
9981+#ifndef __LINUX_UDF_SB_H
9982+#define __LINUX_UDF_SB_H
9983+
9984+/* Since UDF 1.50 is ISO 13346 based... */
9985+#define UDF_SUPER_MAGIC 0x15013346
9986+
9987+#define UDF_MAX_READ_VERSION 0x0200
9988+#define UDF_MAX_WRITE_VERSION 0x0200
9989+
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
10001+
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
10006+
10007+/* following is set only when compiling outside kernel tree */
10008+#ifndef CONFIG_UDF_FS_EXT
10009+
10010+#define UDF_SB_ALLOC(X)
10011+#define UDF_SB_FREE(X)\
10012+{\
10013+ if (UDF_SB(X))\
10014+ {\
10015+ if (UDF_SB_PARTMAPS(X))\
10016+ kfree(UDF_SB_PARTMAPS(X));\
10017+ UDF_SB_PARTMAPS(X) = NULL;\
10018+ }\
10019+}
10020+#define UDF_SB(X) (&((X)->u.udf_sb))
10021+
10022+#else
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)\
10027+{\
10028+ if (UDF_SB(X))\
10029+ {\
10030+ if (UDF_SB_PARTMAPS(X))\
10031+ kfree(UDF_SB_PARTMAPS(X));\
10032+ kfree(UDF_SB(X));\
10033+ UDF_SB(X) = NULL;\
10034+ }\
10035+}
10036+
10037+#define UDF_SB(X) ((struct udf_sb_info *) ((X)->u.generic_sbp))
10038+#endif
10039+
10040+#define UDF_SB_ALLOC_PARTMAPS(X,Y)\
10041+{\
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);\
10045+}
10046+
10047+#define UDF_SB_ALLOC_BITMAP(X,Y,Z)\
10048+{\
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,\
10053+ GFP_KERNEL);\
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;\
10059+}
10060+
10061+
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) ) )
10065+
10066+#define UDF_UPDATE_UDFREV(X,Y) ( ((Y) > UDF_SB_UDFREV(X)) ? UDF_SB_UDFREV(X) = (Y) : UDF_SB_UDFREV(X) )
10067+
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 )
10080+
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)]) )
10090+
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 )
10099+
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 )
10103+#endif
10104+
10105+#endif /* __LINUX_UDF_SB_H */
10106diff -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
10109@@ -0,0 +1,244 @@
10110+#ifndef __UDF_DECL_H
10111+#define __UDF_DECL_H
10112+
10113+#include <linux/udf_167.h>
10114+#include <linux/udf_udf.h>
10115+#include "udfend.h"
10116+
10117+#include <linux/udf_fs.h>
10118+
10119+#ifdef __KERNEL__
10120+
10121+#include <linux/config.h>
10122+#include <linux/fs.h>
10123+#include <linux/types.h>
10124+
10125+#ifndef LINUX_VERSION_CODE
10126+#include <linux/version.h>
10127+#endif
10128+
10129+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,70)
10130+#error "The UDF Module Current Requires Kernel Version 2.1.70 or greater"
10131+#endif
10132+
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>
10137+#endif
10138+
10139+#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
10140+#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
10141+
10142+#define CURRENT_UTIME (xtime.tv_usec)
10143+
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))
10148+
10149+#define udf_ext0_offset(inode)\
10150+ (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB ?\
10151+ udf_file_entry_alloc_offset(inode) : 0)
10152+
10153+#define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset))
10154+
10155+#else
10156+
10157+#include <sys/types.h>
10158+
10159+#endif /* __KERNEL__ */
10160+
10161+
10162+
10163+#ifdef __KERNEL__
10164+
10165+struct dentry;
10166+struct inode;
10167+struct task_struct;
10168+struct buffer_head;
10169+struct super_block;
10170+
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;
10175+
10176+struct udf_fileident_bh
10177+{
10178+ struct buffer_head *sbh;
10179+ struct buffer_head *ebh;
10180+ int soffset;
10181+ int eoffset;
10182+};
10183+
10184+#endif /* __KERNEL__ */
10185+
10186+struct udf_directory_record
10187+{
10188+ Uint32 d_parent;
10189+ Uint32 d_inode;
10190+ Uint32 d_name[255];
10191+};
10192+
10193+
10194+struct udf_vds_record
10195+{
10196+ Uint32 block;
10197+ Uint32 volDescSeqNum;
10198+};
10199+
10200+struct ktm
10201+{
10202+ int tm_sec;
10203+ int tm_min;
10204+ int tm_hour;
10205+ int tm_mday;
10206+ int tm_mon;
10207+ int tm_year;
10208+ int tm_isdst;
10209+};
10210+
10211+struct ustr
10212+{
10213+ Uint8 u_cmpID;
10214+ Uint8 u_name[UDF_NAME_LEN];
10215+ Uint8 u_len;
10216+ Uint8 padding;
10217+ unsigned long u_hash;
10218+};
10219+
10220+#ifdef __KERNEL__
10221+
10222+/* super.c */
10223+extern void udf_error(struct super_block *, const char *, const char *, ...);
10224+extern void udf_warning(struct super_block *, const char *, const char *, ...);
10225+
10226+/* namei.c */
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 *);
10230+#else
10231+extern struct dentry * udf_lookup(struct inode *, struct dentry *);
10232+#endif
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 *);
10241+
10242+/* file.c */
10243+extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
10244+
10245+/* inode.c */
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 *);
10266+
10267+/* misc.c */
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 *);
10276+
10277+/* lowlevel.c */
10278+extern unsigned int udf_get_last_session(struct super_block *);
10279+extern unsigned int udf_get_last_block(struct super_block *);
10280+
10281+/* partition.c */
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);
10287+
10288+/* unicode.c */
10289+extern int udf_get_filename(Uint8 *, Uint8 *, int);
10290+
10291+/* ialloc.c */
10292+extern void udf_free_inode(struct inode *);
10293+extern struct inode * udf_new_inode (const struct inode *, int, int *);
10294+
10295+/* truncate.c */
10296+extern void udf_trunc(struct inode *);
10297+extern void udf_truncate(struct inode *);
10298+extern void udf_truncate_adinicb(struct inode *);
10299+
10300+/* balloc.c */
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 *);
10304+
10305+/* fsync.c */
10306+extern int udf_sync_file(struct file *, struct dentry *);
10307+extern int udf_sync_file_adinicb(struct file *, struct dentry *);
10308+
10309+/* directory.c */
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 **);
10312+
10313+#endif /* __KERNEL__ */
10314+
10315+/* Miscellaneous UDF Prototypes */
10316+
10317+/* unicode.c */
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);
10329+
10330+/* crc.c */
10331+extern Uint16 udf_crc(Uint8 *, Uint32, Uint16);
10332+
10333+/* misc.c */
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);
10340+
10341+/* udftime.c */
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 *);
10345+
10346+/* directory.c */
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 *);
10352+
10353+#endif /* __UDF_DECL_H */
10354diff -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
10357@@ -0,0 +1,132 @@
10358+#ifndef __UDF_ENDIAN_H
10359+#define __UDF_ENDIAN_H
10360+
10361+#ifndef __KERNEL__
10362+
10363+#include <sys/types.h>
10364+
10365+#if __BYTE_ORDER == 0
10366+
10367+#error "__BYTE_ORDER must be defined"
10368+
10369+#elif __BYTE_ORDER == __BIG_ENDIAN
10370+
10371+#define le16_to_cpu(x) \
10372+ ((Uint16)((((Uint16)(x) & 0x00FFU) << 8) | \
10373+ (((Uint16)(x) & 0xFF00U) >> 8)))
10374+
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)))
10380+
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)))
10390+
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))
10394+
10395+#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
10396+
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)
10403+
10404+#endif /* __BYTE_ORDER == 0 */
10405+
10406+#include <string.h>
10407+
10408+#else /* __KERNEL__ */
10409+
10410+#include <asm/byteorder.h>
10411+#include <linux/string.h>
10412+
10413+#endif /* ! __KERNEL__ */
10414+
10415+static inline lb_addr lelb_to_cpu(lb_addr in)
10416+{
10417+ lb_addr out;
10418+ out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum);
10419+ out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum);
10420+ return out;
10421+}
10422+
10423+static inline lb_addr cpu_to_lelb(lb_addr in)
10424+{
10425+ lb_addr out;
10426+ out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum);
10427+ out.partitionReferenceNum = cpu_to_le16(in.partitionReferenceNum);
10428+ return out;
10429+}
10430+
10431+static inline timestamp lets_to_cpu(timestamp in)
10432+{
10433+ timestamp out;
10434+ memcpy(&out, &in, sizeof(timestamp));
10435+ out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
10436+ out.year = le16_to_cpu(in.year);
10437+ return out;
10438+}
10439+
10440+static inline short_ad lesa_to_cpu(short_ad in)
10441+{
10442+ short_ad out;
10443+ out.extLength = le32_to_cpu(in.extLength);
10444+ out.extPosition = le32_to_cpu(in.extPosition);
10445+ return out;
10446+}
10447+
10448+static inline short_ad cpu_to_lesa(short_ad in)
10449+{
10450+ short_ad out;
10451+ out.extLength = cpu_to_le32(in.extLength);
10452+ out.extPosition = cpu_to_le32(in.extPosition);
10453+ return out;
10454+}
10455+
10456+static inline long_ad lela_to_cpu(long_ad in)
10457+{
10458+ long_ad out;
10459+ out.extLength = le32_to_cpu(in.extLength);
10460+ out.extLocation = lelb_to_cpu(in.extLocation);
10461+ return out;
10462+}
10463+
10464+static inline long_ad cpu_to_lela(long_ad in)
10465+{
10466+ long_ad out;
10467+ out.extLength = cpu_to_le32(in.extLength);
10468+ out.extLocation = cpu_to_lelb(in.extLocation);
10469+ return out;
10470+}
10471+
10472+static inline extent_ad leea_to_cpu(extent_ad in)
10473+{
10474+ extent_ad out;
10475+ out.extLength = le32_to_cpu(in.extLength);
10476+ out.extLocation = le32_to_cpu(in.extLocation);
10477+ return out;
10478+}
10479+
10480+static inline timestamp cpu_to_lets(timestamp in)
10481+{
10482+ timestamp out;
10483+ memcpy(&out, &in, sizeof(timestamp));
10484+ out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone);
10485+ out.year = cpu_to_le16(in.year);
10486+ return out;
10487+}
10488+
10489+#endif /* __UDF_ENDIAN_H */
10490diff -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
10493@@ -0,0 +1,186 @@
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).
10497+
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.
10502+
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.
10507+
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. */
10512+
10513+/*
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.
10520+ */
10521+
10522+/*
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
10526+ */
10527+
10528+#if defined(__linux__) && defined(__KERNEL__)
10529+#include <linux/types.h>
10530+#include <linux/kernel.h>
10531+#else
10532+#include <stdio.h>
10533+#include <sys/types.h>
10534+#include <sys/time.h>
10535+#endif
10536+
10537+#include "udfdecl.h"
10538+
10539+#define EPOCH_YEAR 1970
10540+
10541+#ifndef __isleap
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))
10546+#endif
10547+
10548+/* How many days come before each month (0-12). */
10549+const unsigned short int __mon_yday[2][13] =
10550+{
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 }
10555+};
10556+
10557+#define MAX_YEAR_SECONDS 69
10558+#define SPD 0x15180 /*3600*24*/
10559+#define SPY(y,l,s) (SPD * (365*y+l)+s)
10560+
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)
10580+};
10581+
10582+#ifdef __KERNEL__
10583+extern struct timezone sys_tz;
10584+#endif
10585+
10586+#define SECS_PER_HOUR (60 * 60)
10587+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
10588+
10589+time_t *
10590+udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
10591+{
10592+ int yday;
10593+ Uint8 type = src.typeAndTimezone >> 12;
10594+ Sint16 offset;
10595+
10596+ if (type == 1)
10597+ {
10598+ offset = src.typeAndTimezone << 4;
10599+ /* sign extent offset */
10600+ offset = (offset >> 4);
10601+ }
10602+ else
10603+ offset = 0;
10604+
10605+ if ((src.year < EPOCH_YEAR) ||
10606+ (src.year > EPOCH_YEAR+MAX_YEAR_SECONDS))
10607+ {
10608+ *dest = -1;
10609+ *dest_usec = -1;
10610+ return NULL;
10611+ }
10612+ *dest = year_seconds[src.year - EPOCH_YEAR];
10613+ *dest -= offset * 60;
10614+
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;
10619+ return dest;
10620+}
10621+
10622+
10623+timestamp *
10624+udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
10625+{
10626+ long int days, rem, y;
10627+ const unsigned short int *ip;
10628+ Sint16 offset;
10629+#ifndef __KERNEL__
10630+ struct timeval tv;
10631+ struct timezone sys_tz;
10632+
10633+ gettimeofday(&tv, &sys_tz);
10634+#endif
10635+ offset = -sys_tz.tz_minuteswest;
10636+
10637+ if (!dest)
10638+ return NULL;
10639+
10640+ dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
10641+
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;
10649+ y = 1970;
10650+
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))
10653+
10654+ while (days < 0 || days >= (__isleap(y) ? 366 : 365))
10655+ {
10656+ long int yg = y + days / 365 - (days % 365 < 0);
10657+
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));
10662+ y = yg;
10663+ }
10664+ dest->year = y;
10665+ ip = __mon_yday[__isleap(y)];
10666+ for (y = 11; days < (long int) ip[y]; --y)
10667+ continue;
10668+ days -= ip[y];
10669+ dest->month = y + 1;
10670+ dest->day = days + 1;
10671+
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);
10676+ return dest;
10677+}
10678+
10679+/* EOF */
10680diff -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
10683@@ -0,0 +1,452 @@
10684+/*
10685+ * unicode.c
10686+ *
10687+ * PURPOSE
10688+ * Routines for converting between UTF-8 and OSTA Compressed Unicode.
10689+ * Also handles filename mangling
10690+ *
10691+ * DESCRIPTION
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
10696+ *
10697+ * CONTACTS
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
10701+ *
10702+ * COPYRIGHT
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.
10707+ */
10708+
10709+
10710+#ifdef __KERNEL__
10711+#include <linux/kernel.h>
10712+#include <linux/string.h> /* for memset */
10713+#include <linux/udf_fs.h>
10714+#else
10715+#include <string.h>
10716+#endif
10717+
10718+#include "udfdecl.h"
10719+
10720+int udf_ustr_to_dchars(Uint8 *dest, const struct ustr *src, int strlen)
10721+{
10722+ if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
10723+ return 0;
10724+ memcpy(dest+1, src->u_name, src->u_len);
10725+ dest[0] = src->u_cmpID;
10726+ return src->u_len + 1;
10727+}
10728+
10729+int udf_ustr_to_char(Uint8 *dest, const struct ustr *src, int strlen)
10730+{
10731+ if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
10732+ return 0;
10733+ memcpy(dest, src->u_name, src->u_len);
10734+ return src->u_len;
10735+}
10736+
10737+int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
10738+{
10739+ if ( udf_ustr_to_dchars(dest, src, dlength-1) )
10740+ {
10741+ dest[dlength-1] = src->u_len + 1;
10742+ return dlength;
10743+ }
10744+ else
10745+ return 0;
10746+}
10747+
10748+int udf_dchars_to_ustr(struct ustr *dest, const Uint8 *src, int strlen)
10749+{
10750+ if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
10751+ return 0;
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;
10756+ return strlen-1;
10757+}
10758+
10759+int udf_char_to_ustr(struct ustr *dest, const Uint8 *src, int strlen)
10760+{
10761+ if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
10762+ return 0;
10763+ memset(dest, 0, sizeof(struct ustr));
10764+ memcpy(dest->u_name, src, strlen);
10765+ dest->u_cmpID = 0x08;
10766+ dest->u_len = strlen;
10767+ return strlen;
10768+}
10769+
10770+
10771+int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
10772+{
10773+ if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
10774+ return dlength;
10775+ else
10776+ return 0;
10777+}
10778+
10779+/*
10780+ * udf_build_ustr
10781+ */
10782+int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
10783+{
10784+ int usesize;
10785+
10786+ if ( (!dest) || (!ptr) || (!size) )
10787+ return -1;
10788+
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);
10794+ return 0;
10795+}
10796+
10797+/*
10798+ * udf_build_ustr_exact
10799+ */
10800+int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
10801+{
10802+ if ( (!dest) || (!ptr) || (!exactsize) )
10803+ return -1;
10804+
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);
10809+ return 0;
10810+}
10811+
10812+/*
10813+ * udf_ocu_to_udf8
10814+ *
10815+ * PURPOSE
10816+ * Convert OSTA Compressed Unicode to the UTF-8 equivalent.
10817+ *
10818+ * DESCRIPTION
10819+ * This routine is only called by udf_filldir().
10820+ *
10821+ * PRE-CONDITIONS
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 *"
10826+ *
10827+ * POST-CONDITIONS
10828+ * <return> Zero on success.
10829+ *
10830+ * HISTORY
10831+ * November 12, 1997 - Andrew E. Mileski
10832+ * Written, tested, and released.
10833+ */
10834+int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
10835+{
10836+ Uint8 *ocu;
10837+ Uint32 c;
10838+ Uint8 cmp_id, ocu_len;
10839+ int i;
10840+
10841+ ocu = ocu_i->u_name;
10842+
10843+ ocu_len = ocu_i->u_len;
10844+ cmp_id = ocu_i->u_cmpID;
10845+ utf_o->u_len = 0;
10846+
10847+ if (ocu_len == 0)
10848+ {
10849+ memset(utf_o, 0, sizeof(struct ustr));
10850+ utf_o->u_cmpID = 0;
10851+ utf_o->u_len = 0;
10852+ return 0;
10853+ }
10854+
10855+ if ((cmp_id != 8) && (cmp_id != 16))
10856+ {
10857+#ifdef __KERNEL__
10858+ printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", cmp_id, ocu_i->u_name);
10859+#endif
10860+ return 0;
10861+ }
10862+
10863+ for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN-3)) ;)
10864+ {
10865+
10866+ /* Expand OSTA compressed Unicode to Unicode */
10867+ c = ocu[i++];
10868+ if (cmp_id == 16)
10869+ c = (c << 8) | ocu[i++];
10870+
10871+ /* Compress Unicode to UTF-8 */
10872+ if (c < 0x80U)
10873+ utf_o->u_name[utf_o->u_len++] = (Uint8)c;
10874+ else if (c < 0x800U)
10875+ {
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));
10878+ }
10879+ else
10880+ {
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));
10884+ }
10885+ }
10886+ utf_o->u_cmpID=8;
10887+ utf_o->u_hash=0L;
10888+ utf_o->padding=0;
10889+
10890+ return utf_o->u_len;
10891+}
10892+
10893+/*
10894+ *
10895+ * udf_utf8_to_ocu
10896+ *
10897+ * PURPOSE
10898+ * Convert UTF-8 to the OSTA Compressed Unicode equivalent.
10899+ *
10900+ * DESCRIPTION
10901+ * This routine is only called by udf_lookup().
10902+ *
10903+ * PRE-CONDITIONS
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.
10908+ *
10909+ * POST-CONDITIONS
10910+ * <return> Zero on success.
10911+ *
10912+ * HISTORY
10913+ * November 12, 1997 - Andrew E. Mileski
10914+ * Written, tested, and released.
10915+ */
10916+int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
10917+{
10918+ unsigned c, i, max_val, utf_char;
10919+ int utf_cnt;
10920+ int u_len = 0;
10921+
10922+ memset(ocu, 0, sizeof(dstring) * length);
10923+ ocu[0] = 8;
10924+ max_val = 0xffU;
10925+
10926+try_again:
10927+ utf_char = 0U;
10928+ utf_cnt = 0U;
10929+ for (i = 0U; i < utf->u_len; i++)
10930+ {
10931+ c = (Uint8)utf->u_name[i];
10932+
10933+ /* Complete a multi-byte UTF-8 character */
10934+ if (utf_cnt)
10935+ {
10936+ utf_char = (utf_char << 6) | (c & 0x3fU);
10937+ if (--utf_cnt)
10938+ continue;
10939+ }
10940+ else
10941+ {
10942+ /* Check for a multi-byte UTF-8 character */
10943+ if (c & 0x80U)
10944+ {
10945+ /* Start a multi-byte UTF-8 character */
10946+ if ((c & 0xe0U) == 0xc0U)
10947+ {
10948+ utf_char = c & 0x1fU;
10949+ utf_cnt = 1;
10950+ }
10951+ else if ((c & 0xf0U) == 0xe0U)
10952+ {
10953+ utf_char = c & 0x0fU;
10954+ utf_cnt = 2;
10955+ }
10956+ else if ((c & 0xf8U) == 0xf0U)
10957+ {
10958+ utf_char = c & 0x07U;
10959+ utf_cnt = 3;
10960+ }
10961+ else if ((c & 0xfcU) == 0xf8U)
10962+ {
10963+ utf_char = c & 0x03U;
10964+ utf_cnt = 4;
10965+ }
10966+ else if ((c & 0xfeU) == 0xfcU)
10967+ {
10968+ utf_char = c & 0x01U;
10969+ utf_cnt = 5;
10970+ }
10971+ else
10972+ goto error_out;
10973+ continue;
10974+ } else
10975+ /* Single byte UTF-8 character (most common) */
10976+ utf_char = c;
10977+ }
10978+
10979+ /* Choose no compression if necessary */
10980+ if (utf_char > max_val)
10981+ {
10982+ if ( 0xffU == max_val )
10983+ {
10984+ max_val = 0xffffU;
10985+ ocu[0] = (Uint8)0x10U;
10986+ goto try_again;
10987+ }
10988+ goto error_out;
10989+ }
10990+
10991+ if (max_val == 0xffffU)
10992+ {
10993+ ocu[++u_len] = (Uint8)(utf_char >> 8);
10994+ }
10995+ ocu[++u_len] = (Uint8)(utf_char & 0xffU);
10996+ }
10997+
10998+
10999+ if (utf_cnt)
11000+ {
11001+error_out:
11002+#ifdef __KERNEL__
11003+ printk(KERN_ERR "udf: bad UTF-8 character\n");
11004+#endif
11005+ return 0;
11006+ }
11007+
11008+ ocu[length - 1] = (Uint8)u_len + 1;
11009+ return u_len + 1;
11010+}
11011+
11012+#ifdef __KERNEL__
11013+int udf_get_filename(Uint8 *sname, Uint8 *dname, int flen)
11014+{
11015+ struct ustr filename, unifilename;
11016+ int len;
11017+
11018+ if (udf_build_ustr_exact(&unifilename, sname, flen))
11019+ {
11020+ return 0;
11021+ }
11022+
11023+ if (!udf_CS0toUTF8(&filename, &unifilename) )
11024+ {
11025+ udf_debug("Failed in udf_get_filename: sname = %s\n", sname);
11026+ return 0;
11027+ }
11028+
11029+ if ((len = udf_translate_to_linux(dname, filename.u_name, filename.u_len,
11030+ unifilename.u_name, unifilename.u_len)))
11031+ {
11032+ return len;
11033+ }
11034+ return 0;
11035+}
11036+#endif
11037+
11038+#define ILLEGAL_CHAR_MARK '_'
11039+#define EXT_MARK '.'
11040+#define CRC_MARK '#'
11041+#define EXT_SIZE 5
11042+
11043+int udf_translate_to_linux(Uint8 *newName, Uint8 *udfName, int udfLen, Uint8 *fidName, int fidNameLen)
11044+{
11045+ int index, newIndex = 0, needsCRC = 0;
11046+ int extIndex = 0, newExtIndex = 0, hasExt = 0;
11047+ unsigned short valueCRC;
11048+ Uint8 curr;
11049+ const Uint8 hexChar[] = "0123456789ABCDEF";
11050+
11051+ if (udfName[0] == '.' && (udfLen == 1 ||
11052+ (udfLen == 2 && udfName[1] == '.')))
11053+ {
11054+ needsCRC = 1;
11055+ newIndex = udfLen;
11056+ memcpy(newName, udfName, udfLen);
11057+ }
11058+ else
11059+ {
11060+ for (index = 0; index < udfLen; index++)
11061+ {
11062+ curr = udfName[index];
11063+ if (curr == '/' || curr == 0)
11064+ {
11065+ needsCRC = 1;
11066+ curr = ILLEGAL_CHAR_MARK;
11067+ while (index+1 < udfLen && (udfName[index+1] == '/' ||
11068+ udfName[index+1] == 0))
11069+ index++;
11070+ }
11071+ if (curr == EXT_MARK && (udfLen - index - 1) <= EXT_SIZE)
11072+ {
11073+ if (udfLen == index + 1)
11074+ hasExt = 0;
11075+ else
11076+ {
11077+ hasExt = 1;
11078+ extIndex = index;
11079+ newExtIndex = newIndex;
11080+ }
11081+ }
11082+ if (newIndex < 256)
11083+ newName[newIndex++] = curr;
11084+ else
11085+ needsCRC = 1;
11086+ }
11087+ }
11088+ if (needsCRC)
11089+ {
11090+ Uint8 ext[EXT_SIZE];
11091+ int localExtIndex = 0;
11092+
11093+ if (hasExt)
11094+ {
11095+ int maxFilenameLen;
11096+ for(index = 0; index<EXT_SIZE && extIndex + index +1 < udfLen;
11097+ index++ )
11098+ {
11099+ curr = udfName[extIndex + index + 1];
11100+
11101+ if (curr == '/' || curr == 0)
11102+ {
11103+ needsCRC = 1;
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)))
11108+ index++;
11109+ }
11110+ ext[localExtIndex++] = curr;
11111+ }
11112+ maxFilenameLen = 250 - localExtIndex;
11113+ if (newIndex > maxFilenameLen)
11114+ newIndex = maxFilenameLen;
11115+ else
11116+ newIndex = newExtIndex;
11117+ }
11118+ else if (newIndex > 250)
11119+ 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)];
11126+
11127+ if (hasExt)
11128+ {
11129+ newName[newIndex++] = EXT_MARK;
11130+ for (index = 0;index < localExtIndex ;index++ )
11131+ newName[newIndex++] = ext[index];
11132+ }
11133+ }
11134+ return newIndex;
11135+}
11136diff -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;
11172 void *generic_sbp;
11173diff -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
11176@@ -0,0 +1,786 @@
11177+#if !defined(_LINUX_UDF_167_H)
11178+#define _LINUX_UDF_167_H
11179+/*
11180+ * udf_167.h
11181+ *
11182+ * DESCRIPTION
11183+ * Definitions from the ECMA 167 standard.
11184+ * http://www.ecma.ch/
11185+ *
11186+ * These abbreviations are used to keep the symbols short:
11187+ * Alloc Allocation
11188+ * App Application
11189+ * Attr Attribute
11190+ * Char Characters
11191+ * Desc Descriptor
11192+ * Descs Descriptors
11193+ * Ext Extent
11194+ * Ident Identifier
11195+ * Imp Implementation
11196+ * Lvl Level
11197+ * Max Maximum
11198+ * Num Number
11199+ * Ptr Pointer
11200+ * Seq Sequence
11201+ * Std Standard
11202+ * Struct Structure
11203+ * Vol Volume
11204+ * The symbols are otherwise identical to the standard, and the
11205+ * sections of the standard to refer to are indicated.
11206+ *
11207+ * CONTACTS
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
11211+ *
11212+ * COPYRIGHT
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.
11217+ *
11218+ * HISTORY
11219+ * July 12, 1997 - Andrew E. Mileski
11220+ * Adapted from the ECMA-167 standard.
11221+ *
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.
11228+ */
11229+
11230+#ifdef __KERNEL__
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;
11241+#else
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;
11251+#endif
11252+
11253+/* make sure all structures are packed! */
11254+#pragma pack(1)
11255+
11256+/* CS0 Charspec (ECMA 167 1/7.2.1) */
11257+typedef struct {
11258+ Uint8 charSetType;
11259+ Uint8 charSetInfo[63];
11260+} charspec;
11261+
11262+/* Timestamp (ECMA 167 1/7.3) */
11263+typedef struct {
11264+ Uint16 typeAndTimezone;
11265+ Uint16 year;
11266+ Uint8 month;
11267+ Uint8 day;
11268+ Uint8 hour;
11269+ Uint8 minute;
11270+ Uint8 second;
11271+ Uint8 centiseconds;
11272+ Uint8 hundredsOfMicroseconds;
11273+ Uint8 microseconds;
11274+} timestamp;
11275+
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
11280+
11281+/* Entity Identifier (ECMA 167 1/7.4) */
11282+typedef struct {
11283+ Uint8 flags;
11284+ Uint8 ident[23];
11285+ Uint8 identSuffix[8];
11286+} EntityID;
11287+#define regid EntityID
11288+
11289+/* Entity identifier flags (ECMA 167 1/7.4.1) */
11290+#define ENTITYID_FLAGS_DIRTY 0x01U
11291+#define ENTITYID_FLAGS_PROTECTED 0x02U
11292+
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];
11300+};
11301+
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"
11310+
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];
11317+};
11318+
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];
11325+};
11326+
11327+/* Boot Descriptor (ECMA 167 2/9.4) */
11328+struct BootDesc {
11329+ Uint8 structType;
11330+ Uint8 stdIdent[STD_ID_LEN];
11331+ Uint8 structVersion;
11332+ Uint8 reserved1;
11333+ EntityID architectureType;
11334+ EntityID bootIdent;
11335+ Uint32 bootExtLocation;
11336+ Uint32 bootExtLength;
11337+ Uint64 loadAddress;
11338+ Uint64 startAddress;
11339+ timestamp descCreationDateAndTime;
11340+ Uint16 flags;
11341+ Uint8 reserved2[32];
11342+ Uint8 bootUse[1906];
11343+};
11344+
11345+/* Boot flags (ECMA 167 2/9.4.12) */
11346+#define BOOT_FLAGS_ERASE 1
11347+
11348+/* Extent Descriptor (ECMA 167 3/7.1) */
11349+typedef struct {
11350+ Uint32 extLength;
11351+ Uint32 extLocation;
11352+} extent_ad;
11353+
11354+/* Descriptor Tag (ECMA 167 3/7.2) */
11355+typedef struct {
11356+ Uint16 tagIdent;
11357+ Uint16 descVersion;
11358+ Uint8 tagChecksum;
11359+ Uint8 reserved;
11360+ Uint16 tagSerialNum;
11361+ Uint16 descCRC;
11362+ Uint16 descCRCLength;
11363+ Uint32 tagLocation;
11364+} tag;
11365+
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
11377+
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
11390+
11391+/* NSR Descriptor (ECMA 167 3/9.1) */
11392+struct NSRDesc {
11393+ Uint8 structType;
11394+ Uint8 stdIdent[STD_ID_LEN];
11395+ Uint8 structVersion;
11396+ Uint8 reserved;
11397+ Uint8 structData[2040];
11398+};
11399+
11400+/* Primary Volume Descriptor (ECMA 167 3/10.1) */
11401+struct PrimaryVolDesc {
11402+ tag descTag;
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;
11422+ Uint16 flags;
11423+ Uint8 reserved[22];
11424+};
11425+
11426+/* Primary volume descriptor flags (ECMA 167 3/10.1.21) */
11427+#define VOL_SET_IDENT 1
11428+
11429+/* Anchor Volume Descriptor Pointer (ECMA 167 3/10.2) */
11430+struct AnchorVolDescPtr {
11431+ tag descTag;
11432+ extent_ad mainVolDescSeqExt;
11433+ extent_ad reserveVolDescSeqExt;
11434+ Uint8 reserved[480];
11435+};
11436+
11437+/* Volume Descriptor Pointer (ECMA 167 3/10.3) */
11438+struct VolDescPtr {
11439+ tag descTag;
11440+ Uint32 volDescSeqNum;
11441+ extent_ad nextVolDescSeqExt;
11442+ Uint8 reserved[484];
11443+};
11444+
11445+/* Implementation Use Volume Descriptor (ECMA 167 3/10.4) */
11446+struct ImpUseVolDesc {
11447+ tag descTag;
11448+ Uint32 volDescSeqNum;
11449+ EntityID impIdent;
11450+ Uint8 impUse[460];
11451+};
11452+
11453+/* Partition Descriptor (ECMA 167 3/10.5) */
11454+struct PartitionDesc {
11455+ tag descTag;
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];
11467+};
11468+
11469+/* Partition Flags (ECMA 167 3/10.5.3) */
11470+#define PARTITION_FLAGS_ALLOC 1
11471+
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"
11478+
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
11485+
11486+/* Logical Volume Descriptor (ECMA 167 3/10.6) */
11487+struct LogicalVolDesc {
11488+ tag descTag;
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];
11501+};
11502+
11503+/* Generic Partition Map (ECMA 167 3/10.7.1) */
11504+struct GenericPartitionMap {
11505+ Uint8 partitionMapType;
11506+ Uint8 partitionMapLength;
11507+ Uint8 partitionMapping[0];
11508+};
11509+
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
11514+
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;
11521+};
11522+
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];
11528+};
11529+
11530+/* Unallocated Space Descriptor (ECMA 167 3/10.8) */
11531+struct UnallocatedSpaceDesc {
11532+ tag descTag;
11533+ Uint32 volDescSeqNum;
11534+ Uint32 numAllocDescs;
11535+ extent_ad allocDescs[0];
11536+};
11537+
11538+/* Terminating Descriptor (ECMA 3/10.9) */
11539+struct TerminatingDesc {
11540+ tag descTag;
11541+ Uint8 reserved[496];
11542+};
11543+
11544+struct GenericDesc
11545+{
11546+ tag descTag;
11547+ Uint32 volDescSeqNum;
11548+};
11549+
11550+/* Logical Volume Integrity Descriptor (ECMA 167 3/10.10) */
11551+struct LogicalVolIntegrityDesc {
11552+ tag descTag;
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];
11561+ Uint8 impUse[0];
11562+};
11563+
11564+/* Integrity Types (ECMA 167 3/10.10.3) */
11565+#define INTEGRITY_TYPE_OPEN 0
11566+#define INTEGRITY_TYPE_CLOSE 1
11567+
11568+/* Recorded Address (ECMA 167 4/7.1) */
11569+typedef struct {
11570+ Uint32 logicalBlockNum;
11571+ Uint16 partitionReferenceNum;
11572+} lb_addr;
11573+
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
11579+
11580+/* Long Allocation Descriptor (ECMA 167 4/14.14.2) */
11581+typedef struct {
11582+ Uint32 extLength;
11583+ lb_addr extLocation;
11584+ Uint8 impUse[6];
11585+} long_ad;
11586+ /* upper 2 bits of extLength indicate type */
11587+
11588+/* File Set Descriptor (ECMA 167 4/14.1) */
11589+struct FileSetDesc {
11590+ tag descTag;
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;
11606+ long_ad nextExt;
11607+ long_ad streamDirectoryICB;
11608+ Uint8 reserved[32];
11609+};
11610+
11611+/* Short Allocation Descriptor (ECMA 167 4/14.14.1) */
11612+typedef struct {
11613+ Uint32 extLength;
11614+ Uint32 extPosition;
11615+} short_ad;
11616+
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];
11625+};
11626+
11627+/* File Identifier Descriptor (ECMA 167 4/14.4) */
11628+struct FileIdentDesc
11629+{
11630+ tag descTag;
11631+ Uint16 fileVersionNum; /* 1 */
11632+ Uint8 fileCharacteristics;
11633+ Uint8 lengthFileIdent;
11634+ long_ad icb;
11635+ Uint16 lengthOfImpUse;
11636+ Uint8 impUse[0];
11637+ Uint8 fileIdent[0];
11638+ Uint8 padding[0];
11639+};
11640+
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 */
11647+
11648+/* Allocation Ext Descriptor (ECMA 167 4/14.5) */
11649+struct AllocExtDesc
11650+{
11651+ tag descTag;
11652+ Uint32 previousAllocExtLocation;
11653+ Uint32 lengthAllocDescs;
11654+};
11655+
11656+/* ICB Tag (ECMA 167 4/14.6) */
11657+typedef struct {
11658+ Uint32 priorRecordedNumDirectEntries;
11659+ Uint16 strategyType;
11660+ Uint16 strategyParameter;
11661+ Uint16 numEntries;
11662+ Uint8 reserved;
11663+ Uint8 fileType;
11664+ lb_addr parentICBLocation;
11665+ Uint16 flags;
11666+} icbtag;
11667+
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 */
11683+
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
11696+
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
11702+
11703+/* Indirect Entry (ECMA 167 4/14.7) */
11704+struct IndirectEntry {
11705+ tag descTag;
11706+ icbtag icbTag;
11707+ long_ad indirectICB;
11708+};
11709+
11710+/* Terminal Entry (ECMA 167 4/14.8) */
11711+struct TerminalEntry {
11712+ tag descTag;
11713+ icbtag icbTag;
11714+};
11715+
11716+/* File Entry (ECMA 167 4/14.9) */
11717+struct FileEntry {
11718+ tag descTag;
11719+ icbtag icbTag;
11720+ Uint32 uid;
11721+ Uint32 gid;
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];
11740+};
11741+
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
11758+
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
11772+
11773+/* Extended Attribute Header Descriptor (ECMA 167 4/14.10.1) */
11774+struct ExtendedAttrHeaderDesc {
11775+ tag descTag;
11776+ Uint32 impAttrLocation;
11777+ Uint32 appAttrLocation;
11778+};
11779+
11780+/* Generic Attribute Format (ECMA 4/14.10.2) */
11781+struct GenericAttrFormat {
11782+ Uint32 attrType;
11783+ Uint8 attrSubtype;
11784+ Uint8 reserved[3];
11785+ Uint32 attrLength;
11786+ Uint8 attrData[0];
11787+};
11788+
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];
11798+};
11799+
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;
11809+};
11810+
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;
11819+ Uint8 fileTimes;
11820+};
11821+
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
11827+
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];
11837+};
11838+
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;
11848+ Uint8 impUse[0];
11849+};
11850+
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;
11859+ Uint8 impUse[0];
11860+};
11861+
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;
11870+ Uint8 appUse[0];
11871+};
11872+
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
11880+
11881+
11882+/* Unallocated Space Entry (ECMA 167 4/14.11) */
11883+struct UnallocatedSpaceEntry {
11884+ tag descTag;
11885+ icbtag icbTag;
11886+ Uint32 lengthAllocDescs;
11887+ Uint8 allocDescs[0];
11888+};
11889+
11890+/* Space Bitmap Descriptor (ECMA 167 4/14.12) */
11891+struct SpaceBitmapDesc {
11892+ tag descTag;
11893+ Uint32 numOfBits;
11894+ Uint32 numOfBytes;
11895+ Uint8 bitmap[0];
11896+};
11897+
11898+/* Partition Integrity Entry (ECMA 167 4/14.13) */
11899+struct PartitionIntegrityEntry {
11900+ tag descTag;
11901+ icbtag icbTag;
11902+ timestamp recordingDateAndTime;
11903+ Uint8 integrityType;
11904+ Uint8 reserved[175];
11905+ EntityID impIdent;
11906+ Uint8 impUse[256];
11907+};
11908+
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;
11915+} ext_ad;
11916+
11917+/* Logical Volume Header Descriptor (ECMA 167 4/14.5) */
11918+struct LogicalVolHeaderDesc {
11919+ Uint64 uniqueID;
11920+ Uint8 reserved[24];
11921+};
11922+
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];
11929+};
11930+
11931+/* File Entry (ECMA 167 4/14.17) */
11932+struct ExtendedFileEntry {
11933+ tag descTag;
11934+ icbtag icbTag;
11935+ Uint32 uid;
11936+ Uint32 gid;
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;
11950+ Uint32 reserved;
11951+ long_ad extendedAttrICB;
11952+ long_ad streamDirectoryICB;
11953+ EntityID impIdent;
11954+ Uint64 uniqueID;
11955+ Uint32 lengthExtendedAttr;
11956+ Uint32 lengthAllocDescs;
11957+ Uint8 extendedAttr[0];
11958+ Uint8 allocDescs[0];
11959+};
11960+#pragma pack()
11961+
11962+#endif /* !defined(_LINUX_UDF_167_H) */
11963diff -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
11966@@ -0,0 +1,72 @@
11967+/*
11968+ * udf_fs.h
11969+ *
11970+ * PURPOSE
11971+ * Included by fs/filesystems.c
11972+ *
11973+ * DESCRIPTION
11974+ * OSTA-UDF(tm) = Optical Storage Technology Association
11975+ * Universal Disk Format.
11976+ *
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/
11981+ *
11982+ * CONTACTS
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
11986+ *
11987+ * COPYRIGHT
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.
11992+ *
11993+ * (C) 1999-2000 Ben Fennema
11994+ * (C) 1999-2000 Stelias Computing Inc
11995+ *
11996+ * HISTORY
11997+ *
11998+ */
11999+
12000+#if !defined(_LINUX_UDF_FS_H)
12001+#define _LINUX_UDF_FS_H
12002+
12003+
12004+#define UDF_PREALLOCATE
12005+#define UDF_DEFAULT_PREALLOC_BLOCKS 8
12006+
12007+#define UDFFS_DATE "2000/05/10"
12008+#define UDFFS_VERSION "0.9.2.1"
12009+
12010+#define UDFFS_DEBUG
12011+
12012+#ifdef UDFFS_DEBUG
12013+#define udf_debug(f, a...) \
12014+ { \
12015+ printk (KERN_DEBUG "UDF-fs DEBUG (%s, %d): %s: ", \
12016+ __FILE__, __LINE__, __FUNCTION__); \
12017+ printk (## f, ## a); \
12018+ }
12019+#else
12020+#define udf_debug(f, a...) /**/
12021+#endif
12022+
12023+#define udf_info(f, a...) \
12024+ printk (KERN_INFO "UDF-fs INFO " ## f, ## a);
12025+
12026+#ifdef __KERNEL__
12027+
12028+#ifndef LINUX_VERSION_CODE
12029+#include <linux/version.h>
12030+#endif
12031+
12032+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
12033+extern int init_udf_fs(void);
12034+#endif /* 2.2.XX */
12035+
12036+#endif /* __KERNEL__ */
12037+
12038+#endif /* !defined(_LINUX_UDF_FS_H) */
12039diff -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
12042@@ -0,0 +1,58 @@
12043+/*
12044+ * udf_fs_i.h
12045+ *
12046+ * This file is intended for the Linux kernel/module.
12047+ *
12048+ * CONTACTS
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
12052+ *
12053+ * COPYRIGHT
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.
12058+ */
12059+
12060+#if !defined(_LINUX_UDF_FS_I_H)
12061+#define _LINUX_UDF_FS_I_H
12062+
12063+#ifdef __KERNEL__
12064+
12065+#ifndef _LINUX_UDF_167_H
12066+typedef struct
12067+{
12068+ __u32 logicalBlockNum;
12069+ __u16 partitionReferenceNum;
12070+} lb_addr;
12071+#endif
12072+
12073+struct udf_inode_info
12074+{
12075+ long i_uatime;
12076+ long i_umtime;
12077+ long i_uctime;
12078+ /* Physical address of inode */
12079+ lb_addr i_location;
12080+ __u64 i_unique;
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;
12090+};
12091+
12092+#endif
12093+
12094+/* exported IOCTLs, we have 'l', 0x40-0x7f */
12095+
12096+#define UDF_GETEASIZE _IOR('l', 0x40, int)
12097+#define UDF_GETEABLOCK _IOR('l', 0x41, void *)
12098+#define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
12099+
12100+#endif /* !defined(_LINUX_UDF_FS_I_H) */
12101diff -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
12104@@ -0,0 +1,124 @@
12105+/*
12106+ * udf_fs_sb.h
12107+ *
12108+ * This include file is for the Linux kernel/module.
12109+ *
12110+ * CONTACTS
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
12114+ *
12115+ * COPYRIGHT
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.
12120+ */
12121+
12122+#if !defined(_LINUX_UDF_FS_SB_H)
12123+#define _LINUX_UDF_FS_SB_H
12124+
12125+#pragma pack(1)
12126+
12127+#define UDF_MAX_BLOCK_LOADED 8
12128+
12129+#define UDF_TYPE1_MAP15 0x1511U
12130+#define UDF_VIRTUAL_MAP15 0x1512U
12131+#define UDF_VIRTUAL_MAP20 0x2012U
12132+#define UDF_SPARABLE_MAP15 0x1522U
12133+
12134+struct udf_sparing_data
12135+{
12136+ __u32 s_spar_loc[4];
12137+ __u8 s_spar_pshift;
12138+ __u8 s_spar_indexsize;
12139+ __u32 *s_spar_map;
12140+ union
12141+ {
12142+ __u8 *s_spar_remap8;
12143+ __u16 *s_spar_remap16;
12144+ __u32 *s_spar_remap32;
12145+ } s_spar_remap;
12146+};
12147+
12148+struct udf_virtual_data
12149+{
12150+ __u32 s_num_entries;
12151+ __u16 s_start_offset;
12152+};
12153+
12154+struct udf_bitmap
12155+{
12156+ __u32 s_extLength;
12157+ __u32 s_extPosition;
12158+ __u16 s_nr_groups;
12159+ struct buffer_head **s_block_bitmap;
12160+};
12161+
12162+struct udf_part_map
12163+{
12164+ union
12165+ {
12166+ struct udf_bitmap *s_bitmap;
12167+ struct inode *s_table;
12168+ } s_uspace;
12169+ union
12170+ {
12171+ struct udf_bitmap *s_bitmap;
12172+ struct inode *s_table;
12173+ } s_fspace;
12174+ __u32 s_partition_root;
12175+ __u32 s_partition_len;
12176+ __u16 s_partition_type;
12177+ __u16 s_partition_num;
12178+ union
12179+ {
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;
12186+};
12187+
12188+#pragma pack()
12189+
12190+struct udf_sb_info
12191+{
12192+ struct udf_part_map *s_partmaps;
12193+ __u8 s_volident[32];
12194+
12195+ /* Overall info */
12196+ __u16 s_partitions;
12197+ __u16 s_partition;
12198+
12199+ /* Sector headers */
12200+ __u32 s_session;
12201+ __u32 s_anchor[4];
12202+ __u32 s_lastblock;
12203+
12204+ struct buffer_head *s_lvidbh;
12205+
12206+ /* Default permissions */
12207+ mode_t s_umask;
12208+ gid_t s_gid;
12209+ uid_t s_uid;
12210+
12211+ /* Root Info */
12212+ time_t s_recordtime;
12213+
12214+ /* Fileset Info */
12215+ __u16 s_serialnum;
12216+
12217+ /* highest UDF revision we have recorded to this media */
12218+ __u16 s_udfrev;
12219+
12220+ /* Miscellaneous flags */
12221+ __u32 s_flags;
12222+
12223+ /* VAT inode */
12224+ struct inode *s_vat;
12225+
12226+};
12227+
12228+#endif /* !defined(_LINUX_UDF_FS_SB_H) */
12229diff -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
12232@@ -0,0 +1,227 @@
12233+#if !defined(_LINUX_UDF_UDF_H)
12234+#define _LINUX_UDF_UDF_H
12235+/*
12236+ * udf_udf.h
12237+ *
12238+ * PURPOSE
12239+ * OSTA-UDF(tm) format specification [based on ECMA 167 standard].
12240+ * http://www.osta.org/
12241+ *
12242+ * CONTACTS
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
12246+ *
12247+ * COPYRIGHT
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.
12252+ *
12253+ * HISTORY
12254+ * July 1, 1997 - Andrew E. Mileski
12255+ * Written, tested, and released.
12256+ *
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
12260+ */
12261+
12262+/* based on ECMA 167 structure definitions */
12263+#include <linux/udf_167.h>
12264+
12265+#pragma pack(1)
12266+
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"
12271+
12272+#define UDF_ID_DEVELOPER "*Linux UDFFS"
12273+
12274+/* UDF 1.02 2.2.6.4 */
12275+struct LogicalVolIntegrityDescImpUse
12276+{
12277+ EntityID impIdent;
12278+ Uint32 numFiles;
12279+ Uint32 numDirs;
12280+ Uint16 minUDFReadRev;
12281+ Uint16 minUDFWriteRev;
12282+ Uint16 maxUDFWriteRev;
12283+};
12284+
12285+/* UDF 1.02 2.2.7.2 */
12286+/* LVInformation may be present in ImpUseVolDesc.impUse */
12287+struct ImpUseVolDescImpUse
12288+{
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];
12296+};
12297+
12298+struct UdfPartitionMap2
12299+{
12300+ Uint8 partitionMapType;
12301+ Uint8 partitionMapLength;
12302+ Uint8 reserved1[2];
12303+ EntityID partIdent;
12304+ Uint16 volSeqNum;
12305+ Uint16 partitionNum;
12306+ Uint8 reserved2[24];
12307+};
12308+
12309+/* UDF 1.5 2.2.8 */
12310+struct VirtualPartitionMap
12311+{
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 */
12319+};
12320+
12321+/* UDF 1.5 2.2.9 */
12322+struct SparablePartitionMap
12323+{
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];
12337+};
12338+
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;
12343+ Uint8 CGMSInfo;
12344+ Uint8 dataType;
12345+ Uint8 protectionSystemInfo[4];
12346+};
12347+
12348+/* the impUse of long_ad used in AllocDescs - UDF 1.02 2.3.10.1 */
12349+struct ADImpUse
12350+{
12351+ Uint16 flags;
12352+ Uint8 impUse[4];
12353+};
12354+
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
12359+
12360+/*
12361+ * Important! VirtualAllocationTables are
12362+ * very different between 1.5 and 2.0!
12363+ */
12364+
12365+/* ----------- 1.5 ------------- */
12366+/* UDF 1.5 2.2.10 */
12367+#define FILE_TYPE_VAT15 0x0U
12368+
12369+/* UDF 1.5 2.2.10 - VAT layout: */
12370+struct VirutalAllocationTable15 {
12371+ Uint32 VirtualSector[0];
12372+ EntityID ident;
12373+ Uint32 previousVATICB;
12374+ };
12375+/* where number of VirtualSector's is (VATSize-36)/4 */
12376+
12377+/* ----------- 2.0 ------------- */
12378+/* UDF 2.0 2.2.10 */
12379+#define FILE_TYPE_VAT20 0xf8U
12380+
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;
12392+ Uint16 reserved;
12393+ Uint8 impUse[0];
12394+ Uint32 vatEntry[0];
12395+};
12396+
12397+/* Sparing maps, see UDF 1.5 2.2.11 */
12398+typedef struct {
12399+ Uint32 origLocation;
12400+ Uint32 mappedLocation;
12401+} SparingEntry;
12402+
12403+/* sparing maps, see UDF 2.0 2.2.11 */
12404+struct SparingTable {
12405+ tag descTag;
12406+ EntityID sparingIdent; /* *UDF Sparing Table */
12407+ Uint16 reallocationTableLen;
12408+ Uint16 reserved; /* #00 */
12409+ Uint32 sequenceNum;
12410+ SparingEntry mapEntry[0];
12411+};
12412+
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"
12429+
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
12452+
12453+#define UDF_NAME_PAD 4
12454+#define UDF_NAME_LEN 255
12455+#define UDF_PATH_LEN 1023
12456+
12457+#pragma pack()
12458+
12459+#endif /* !defined(_LINUX_UDF_FMT_H) */
This page took 1.4907 seconds and 4 git commands to generate.