]>
Commit | Line | Data |
---|---|---|
7416c8cd | 1 | diff -Nru linux/Documentation/Configure.help linux.new/Documentation/Configure.help |
2 | --- linux/Documentation/Configure.help Fri Sep 7 11:18:50 2001 | |
3 | +++ linux.new/Documentation/Configure.help Fri Sep 7 11:32:15 2001 | |
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, | |
31 | diff -Nru linux/Documentation/filesystems/00-INDEX linux.new/Documentation/filesystems/00-INDEX | |
32 | --- linux/Documentation/filesystems/00-INDEX Sun Mar 25 18:31:56 2001 | |
33 | +++ linux.new/Documentation/filesystems/00-INDEX Fri Sep 7 11:32:15 2001 | |
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 | |
43 | diff -Nru linux/Documentation/filesystems/udf.txt linux.new/Documentation/filesystems/udf.txt | |
44 | --- linux/Documentation/filesystems/udf.txt Thu Jan 1 01:00:00 1970 | |
45 | +++ linux.new/Documentation/filesystems/udf.txt Fri Sep 7 11:32:15 2001 | |
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> | |
107 | diff -Nru linux/Documentation/ioctl-number.txt linux.new/Documentation/ioctl-number.txt | |
108 | --- linux/Documentation/ioctl-number.txt Sun Mar 25 18:37:29 2001 | |
109 | +++ linux.new/Documentation/ioctl-number.txt Fri Sep 7 11:32:15 2001 | |
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 | |
119 | diff -Nru linux/MAINTAINERS linux.new/MAINTAINERS | |
120 | --- linux/MAINTAINERS Fri Sep 7 11:18:22 2001 | |
121 | +++ linux.new/MAINTAINERS Fri Sep 7 11:32:15 2001 | |
122 | @@ -1042,6 +1042,15 @@ | |
123 | L: linux-scsi@vger.kernel.org | |
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 | |
138 | diff -Nru linux/fs/Config.in linux.new/fs/Config.in | |
139 | --- linux/fs/Config.in Fri Sep 7 11:18:14 2001 | |
140 | +++ linux.new/fs/Config.in Fri Sep 7 11:32:16 2001 | |
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 |
155 | diff -Nru linux.orig/fs/Makefile linux/fs/Makefile |
156 | --- linux.orig/fs/Makefile Wed Nov 21 21:18:15 2001 | |
157 | +++ linux/fs/Makefile Wed Nov 21 21:27:00 2001 | |
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 | |
182 | diff -Nru linux/fs/filesystems.c linux.new/fs/filesystems.c | |
183 | --- linux/fs/filesystems.c Fri Sep 7 11:17:42 2001 | |
184 | +++ linux.new/fs/filesystems.c Fri Sep 7 11:32:16 2001 | |
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 | |
203 | diff -Nru linux/fs/udf/Makefile linux.new/fs/udf/Makefile | |
204 | --- linux/fs/udf/Makefile Thu Jan 1 01:00:00 1970 | |
205 | +++ linux.new/fs/udf/Makefile Fri Sep 7 11:32:16 2001 | |
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 | |
223 | diff -Nru linux/fs/udf/balloc.c linux.new/fs/udf/balloc.c | |
224 | --- linux/fs/udf/balloc.c Thu Jan 1 01:00:00 1970 | |
225 | +++ linux.new/fs/udf/balloc.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
1235 | diff -Nru linux/fs/udf/crc.c linux.new/fs/udf/crc.c | |
1236 | --- linux/fs/udf/crc.c Thu Jan 1 01:00:00 1970 | |
1237 | +++ linux.new/fs/udf/crc.c Fri Sep 7 11:32:16 2001 | |
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) */ | |
1417 | diff -Nru linux/fs/udf/dir.c linux.new/fs/udf/dir.c | |
1418 | --- linux/fs/udf/dir.c Thu Jan 1 01:00:00 1970 | |
1419 | +++ linux.new/fs/udf/dir.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
1704 | diff -Nru linux/fs/udf/directory.c linux.new/fs/udf/directory.c | |
1705 | --- linux/fs/udf/directory.c Thu Jan 1 01:00:00 1970 | |
1706 | +++ linux.new/fs/udf/directory.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
2038 | diff -Nru linux/fs/udf/file.c linux.new/fs/udf/file.c | |
2039 | --- linux/fs/udf/file.c Thu Jan 1 01:00:00 1970 | |
2040 | +++ linux.new/fs/udf/file.c Fri Sep 7 11:32:16 2001 | |
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 | +}; | |
2591 | diff -Nru linux/fs/udf/fsync.c linux.new/fs/udf/fsync.c | |
2592 | --- linux/fs/udf/fsync.c Thu Jan 1 01:00:00 1970 | |
2593 | +++ linux.new/fs/udf/fsync.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
2710 | diff -Nru linux/fs/udf/ialloc.c linux.new/fs/udf/ialloc.c | |
2711 | --- linux/fs/udf/ialloc.c Thu Jan 1 01:00:00 1970 | |
2712 | +++ linux.new/fs/udf/ialloc.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
2909 | diff -Nru linux/fs/udf/inode.c linux.new/fs/udf/inode.c | |
2910 | --- linux/fs/udf/inode.c Thu Jan 1 01:00:00 1970 | |
2911 | +++ linux.new/fs/udf/inode.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
4935 | diff -Nru linux/fs/udf/lowlevel.c linux.new/fs/udf/lowlevel.c | |
4936 | --- linux/fs/udf/lowlevel.c Thu Jan 1 01:00:00 1970 | |
4937 | +++ linux.new/fs/udf/lowlevel.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
5329 | diff -Nru linux/fs/udf/misc.c linux.new/fs/udf/misc.c | |
5330 | --- linux/fs/udf/misc.c Thu Jan 1 01:00:00 1970 | |
5331 | +++ linux.new/fs/udf/misc.c Fri Sep 7 11:32:16 2001 | |
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 | |
5848 | diff -Nru linux/fs/udf/namei.c linux.new/fs/udf/namei.c | |
5849 | --- linux/fs/udf/namei.c Thu Jan 1 01:00:00 1970 | |
5850 | +++ linux.new/fs/udf/namei.c Fri Sep 7 11:32:16 2001 | |
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 | |
7461 | diff -Nru linux/fs/udf/partition.c linux.new/fs/udf/partition.c | |
7462 | --- linux/fs/udf/partition.c Thu Jan 1 01:00:00 1970 | |
7463 | +++ linux.new/fs/udf/partition.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
7698 | diff -Nru linux/fs/udf/super.c linux.new/fs/udf/super.c | |
7699 | --- linux/fs/udf/super.c Thu Jan 1 01:00:00 1970 | |
7700 | +++ linux.new/fs/udf/super.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
9467 | diff -Nru linux/fs/udf/symlink.c linux.new/fs/udf/symlink.c | |
9468 | --- linux/fs/udf/symlink.c Thu Jan 1 01:00:00 1970 | |
9469 | +++ linux.new/fs/udf/symlink.c Fri Sep 7 11:32:16 2001 | |
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 | +}; | |
9652 | diff -Nru linux/fs/udf/truncate.c linux.new/fs/udf/truncate.c | |
9653 | --- linux/fs/udf/truncate.c Thu Jan 1 01:00:00 1970 | |
9654 | +++ linux.new/fs/udf/truncate.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
9944 | diff -Nru linux/fs/udf/udf_i.h linux.new/fs/udf/udf_i.h | |
9945 | --- linux/fs/udf/udf_i.h Thu Jan 1 01:00:00 1970 | |
9946 | +++ linux.new/fs/udf/udf_i.h Fri Sep 7 11:32:16 2001 | |
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) */ | |
9977 | diff -Nru linux/fs/udf/udf_sb.h linux.new/fs/udf/udf_sb.h | |
9978 | --- linux/fs/udf/udf_sb.h Thu Jan 1 01:00:00 1970 | |
9979 | +++ linux.new/fs/udf/udf_sb.h Fri Sep 7 11:32:16 2001 | |
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 */ | |
10106 | diff -Nru linux/fs/udf/udfdecl.h linux.new/fs/udf/udfdecl.h | |
10107 | --- linux/fs/udf/udfdecl.h Thu Jan 1 01:00:00 1970 | |
10108 | +++ linux.new/fs/udf/udfdecl.h Fri Sep 7 11:32:16 2001 | |
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 */ | |
10354 | diff -Nru linux/fs/udf/udfend.h linux.new/fs/udf/udfend.h | |
10355 | --- linux/fs/udf/udfend.h Thu Jan 1 01:00:00 1970 | |
10356 | +++ linux.new/fs/udf/udfend.h Fri Sep 7 11:32:16 2001 | |
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 */ | |
10490 | diff -Nru linux/fs/udf/udftime.c linux.new/fs/udf/udftime.c | |
10491 | --- linux/fs/udf/udftime.c Thu Jan 1 01:00:00 1970 | |
10492 | +++ linux.new/fs/udf/udftime.c Fri Sep 7 11:32:16 2001 | |
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 */ | |
10680 | diff -Nru linux/fs/udf/unicode.c linux.new/fs/udf/unicode.c | |
10681 | --- linux/fs/udf/unicode.c Thu Jan 1 01:00:00 1970 | |
10682 | +++ linux.new/fs/udf/unicode.c Fri Sep 7 11:32:16 2001 | |
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 | +} | |
11136 | diff -Nru linux/include/linux/fs.h linux.new/include/linux/fs.h | |
11137 | --- linux/include/linux/fs.h Fri Sep 7 11:17:46 2001 | |
11138 | +++ linux.new/include/linux/fs.h Fri Sep 7 11:37:56 2001 | |
11139 | @@ -286,6 +286,7 @@ | |
11140 | #include <linux/hfs_fs_i.h> | |
11141 | #include <linux/adfs_fs_i.h> | |
11142 | #include <linux/qnx4_fs_i.h> | |
11143 | +#include <linux/udf_fs_i.h> | |
11144 | #include <linux/reiserfs_fs_i.h> | |
11145 | #include <linux/usbdev_fs_i.h> | |
11146 | #include <linux/beos_fs_i.h> | |
11147 | @@ -403,6 +404,7 @@ | |
11148 | struct hfs_inode_info hfs_i; | |
11149 | struct adfs_inode_info adfs_i; | |
11150 | struct qnx4_inode_info qnx4_i; | |
11151 | + struct udf_inode_info udf_i; | |
11152 | struct reiserfs_inode_info reiserfs_i; | |
11153 | struct usbdev_inode_info usbdev_i; | |
11154 | struct socket socket_i; | |
11155 | @@ -530,6 +532,7 @@ | |
11156 | #include <linux/hfs_fs_sb.h> | |
11157 | #include <linux/adfs_fs_sb.h> | |
11158 | #include <linux/qnx4_fs_sb.h> | |
11159 | +#include <linux/udf_fs_sb.h> | |
11160 | #include <linux/reiserfs_fs_sb.h> | |
11161 | #include <linux/usbdev_fs_sb.h> | |
11162 | #include <linux/beos_fs_sb.h> | |
11163 | @@ -576,7 +579,8 @@ | |
11164 | struct hfs_sb_info hfs_sb; | |
11165 | struct adfs_sb_info adfs_sb; | |
11166 | struct qnx4_sb_info qnx4_sb; | |
11167 | - struct reiserfs_sb_info reiserfs_sb; | |
11168 | + struct udf_sb_info udf_sb; | |
11169 | + struct reiserfs_sb_info reiserfs_sb; | |
11170 | struct usbdev_sb_info usbdevfs_sb; | |
11171 | struct beos_sb_info beos_sb; | |
11172 | void *generic_sbp; | |
11173 | diff -Nru linux/include/linux/udf_167.h linux.new/include/linux/udf_167.h | |
11174 | --- linux/include/linux/udf_167.h Thu Jan 1 01:00:00 1970 | |
11175 | +++ linux.new/include/linux/udf_167.h Fri Sep 7 11:32:16 2001 | |
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) */ | |
11963 | diff -Nru linux/include/linux/udf_fs.h linux.new/include/linux/udf_fs.h | |
11964 | --- linux/include/linux/udf_fs.h Thu Jan 1 01:00:00 1970 | |
11965 | +++ linux.new/include/linux/udf_fs.h Fri Sep 7 11:32:16 2001 | |
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) */ | |
12039 | diff -Nru linux/include/linux/udf_fs_i.h linux.new/include/linux/udf_fs_i.h | |
12040 | --- linux/include/linux/udf_fs_i.h Thu Jan 1 01:00:00 1970 | |
12041 | +++ linux.new/include/linux/udf_fs_i.h Fri Sep 7 11:32:16 2001 | |
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) */ | |
12101 | diff -Nru linux/include/linux/udf_fs_sb.h linux.new/include/linux/udf_fs_sb.h | |
12102 | --- linux/include/linux/udf_fs_sb.h Thu Jan 1 01:00:00 1970 | |
12103 | +++ linux.new/include/linux/udf_fs_sb.h Fri Sep 7 11:32:16 2001 | |
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) */ | |
12229 | diff -Nru linux/include/linux/udf_udf.h linux.new/include/linux/udf_udf.h | |
12230 | --- linux/include/linux/udf_udf.h Thu Jan 1 01:00:00 1970 | |
12231 | +++ linux.new/include/linux/udf_udf.h Fri Sep 7 11:32:16 2001 | |
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) */ |