aboutsummaryrefslogtreecommitdiffstats
path: root/fs/isofs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/isofs
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/isofs')
-rw-r--r--fs/isofs/Makefile10
-rw-r--r--fs/isofs/compress.c359
-rw-r--r--fs/isofs/dir.c280
-rw-r--r--fs/isofs/export.c228
-rw-r--r--fs/isofs/inode.c1503
-rw-r--r--fs/isofs/joliet.c103
-rw-r--r--fs/isofs/namei.c201
-rw-r--r--fs/isofs/rock.c565
-rw-r--r--fs/isofs/rock.h119
-rw-r--r--fs/isofs/util.c83
-rw-r--r--fs/isofs/zisofs.h21
11 files changed, 3472 insertions, 0 deletions
diff --git a/fs/isofs/Makefile b/fs/isofs/Makefile
new file mode 100644
index 000000000000..bf162f0942d5
--- /dev/null
+++ b/fs/isofs/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for the Linux isofs filesystem routines.
3#
4
5obj-$(CONFIG_ISO9660_FS) += isofs.o
6
7isofs-objs-y := namei.o inode.o dir.o util.o rock.o export.o
8isofs-objs-$(CONFIG_JOLIET) += joliet.o
9isofs-objs-$(CONFIG_ZISOFS) += compress.o
10isofs-objs := $(isofs-objs-y)
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
new file mode 100644
index 000000000000..fb42c3f3bf0d
--- /dev/null
+++ b/fs/isofs/compress.c
@@ -0,0 +1,359 @@
1/* -*- linux-c -*- ------------------------------------------------------- *
2 *
3 * Copyright 2001 H. Peter Anvin - All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
8 * USA; either version 2 of the License, or (at your option) any later
9 * version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13/*
14 * linux/fs/isofs/compress.c
15 *
16 * Transparent decompression of files on an iso9660 filesystem
17 */
18
19#include <linux/config.h>
20#include <linux/module.h>
21
22#include <linux/stat.h>
23#include <linux/time.h>
24#include <linux/iso_fs.h>
25#include <linux/kernel.h>
26#include <linux/major.h>
27#include <linux/mm.h>
28#include <linux/string.h>
29#include <linux/slab.h>
30#include <linux/errno.h>
31#include <linux/init.h>
32#include <linux/nls.h>
33#include <linux/ctype.h>
34#include <linux/smp_lock.h>
35#include <linux/blkdev.h>
36#include <linux/vmalloc.h>
37#include <linux/zlib.h>
38#include <linux/buffer_head.h>
39
40#include <asm/system.h>
41#include <asm/uaccess.h>
42#include <asm/semaphore.h>
43
44#include "zisofs.h"
45
46/* This should probably be global. */
47static char zisofs_sink_page[PAGE_CACHE_SIZE];
48
49/*
50 * This contains the zlib memory allocation and the mutex for the
51 * allocation; this avoids failures at block-decompression time.
52 */
53static void *zisofs_zlib_workspace;
54static struct semaphore zisofs_zlib_semaphore;
55
56/*
57 * When decompressing, we typically obtain more than one page
58 * per reference. We inject the additional pages into the page
59 * cache as a form of readahead.
60 */
61static int zisofs_readpage(struct file *file, struct page *page)
62{
63 struct inode *inode = file->f_dentry->d_inode;
64 struct address_space *mapping = inode->i_mapping;
65 unsigned int maxpage, xpage, fpage, blockindex;
66 unsigned long offset;
67 unsigned long blockptr, blockendptr, cstart, cend, csize;
68 struct buffer_head *bh, *ptrbh[2];
69 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
70 unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
71 unsigned long bufmask = bufsize - 1;
72 int err = -EIO;
73 int i;
74 unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
75 unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
76 /* unsigned long zisofs_block_size = 1UL << zisofs_block_shift; */
77 unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT;
78 unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift;
79 unsigned long zisofs_block_page_mask = zisofs_block_pages-1;
80 struct page *pages[zisofs_block_pages];
81 unsigned long index = page->index;
82 int indexblocks;
83
84 /* We have already been given one page, this is the one
85 we must do. */
86 xpage = index & zisofs_block_page_mask;
87 pages[xpage] = page;
88
89 /* The remaining pages need to be allocated and inserted */
90 offset = index & ~zisofs_block_page_mask;
91 blockindex = offset >> zisofs_block_page_shift;
92 maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
93 maxpage = min(zisofs_block_pages, maxpage-offset);
94
95 for ( i = 0 ; i < maxpage ; i++, offset++ ) {
96 if ( i != xpage ) {
97 pages[i] = grab_cache_page_nowait(mapping, offset);
98 }
99 page = pages[i];
100 if ( page ) {
101 ClearPageError(page);
102 kmap(page);
103 }
104 }
105
106 /* This is the last page filled, plus one; used in case of abort. */
107 fpage = 0;
108
109 /* Find the pointer to this specific chunk */
110 /* Note: we're not using isonum_731() here because the data is known aligned */
111 /* Note: header_size is in 32-bit words (4 bytes) */
112 blockptr = (header_size + blockindex) << 2;
113 blockendptr = blockptr + 4;
114
115 indexblocks = ((blockptr^blockendptr) >> bufshift) ? 2 : 1;
116 ptrbh[0] = ptrbh[1] = NULL;
117
118 if ( isofs_get_blocks(inode, blockptr >> bufshift, ptrbh, indexblocks) != indexblocks ) {
119 if ( ptrbh[0] ) brelse(ptrbh[0]);
120 printk(KERN_DEBUG "zisofs: Null buffer on reading block table, inode = %lu, block = %lu\n",
121 inode->i_ino, blockptr >> bufshift);
122 goto eio;
123 }
124 ll_rw_block(READ, indexblocks, ptrbh);
125
126 bh = ptrbh[0];
127 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
128 printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
129 inode->i_ino, blockptr >> bufshift);
130 if ( ptrbh[1] )
131 brelse(ptrbh[1]);
132 goto eio;
133 }
134 cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask)));
135
136 if ( indexblocks == 2 ) {
137 /* We just crossed a block boundary. Switch to the next block */
138 brelse(bh);
139 bh = ptrbh[1];
140 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
141 printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
142 inode->i_ino, blockendptr >> bufshift);
143 goto eio;
144 }
145 }
146 cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
147 brelse(bh);
148
149 csize = cend-cstart;
150
151 /* Now page[] contains an array of pages, any of which can be NULL,
152 and the locks on which we hold. We should now read the data and
153 release the pages. If the pages are NULL the decompressed data
154 for that particular page should be discarded. */
155
156 if ( csize == 0 ) {
157 /* This data block is empty. */
158
159 for ( fpage = 0 ; fpage < maxpage ; fpage++ ) {
160 if ( (page = pages[fpage]) != NULL ) {
161 memset(page_address(page), 0, PAGE_CACHE_SIZE);
162
163 flush_dcache_page(page);
164 SetPageUptodate(page);
165 kunmap(page);
166 unlock_page(page);
167 if ( fpage == xpage )
168 err = 0; /* The critical page */
169 else
170 page_cache_release(page);
171 }
172 }
173 } else {
174 /* This data block is compressed. */
175 z_stream stream;
176 int bail = 0, left_out = -1;
177 int zerr;
178 int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift;
179 int haveblocks;
180 struct buffer_head *bhs[needblocks+1];
181 struct buffer_head **bhptr;
182
183 /* Because zlib is not thread-safe, do all the I/O at the top. */
184
185 blockptr = cstart >> bufshift;
186 memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *));
187 haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks);
188 ll_rw_block(READ, haveblocks, bhs);
189
190 bhptr = &bhs[0];
191 bh = *bhptr++;
192
193 /* First block is special since it may be fractional.
194 We also wait for it before grabbing the zlib
195 semaphore; odds are that the subsequent blocks are
196 going to come in in short order so we don't hold
197 the zlib semaphore longer than necessary. */
198
199 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
200 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
201 fpage, xpage, csize);
202 goto b_eio;
203 }
204 stream.next_in = bh->b_data + (cstart & bufmask);
205 stream.avail_in = min(bufsize-(cstart & bufmask), csize);
206 csize -= stream.avail_in;
207
208 stream.workspace = zisofs_zlib_workspace;
209 down(&zisofs_zlib_semaphore);
210
211 zerr = zlib_inflateInit(&stream);
212 if ( zerr != Z_OK ) {
213 if ( err && zerr == Z_MEM_ERROR )
214 err = -ENOMEM;
215 printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
216 zerr);
217 goto z_eio;
218 }
219
220 while ( !bail && fpage < maxpage ) {
221 page = pages[fpage];
222 if ( page )
223 stream.next_out = page_address(page);
224 else
225 stream.next_out = (void *)&zisofs_sink_page;
226 stream.avail_out = PAGE_CACHE_SIZE;
227
228 while ( stream.avail_out ) {
229 int ao, ai;
230 if ( stream.avail_in == 0 && left_out ) {
231 if ( !csize ) {
232 printk(KERN_WARNING "zisofs: ZF read beyond end of input\n");
233 bail = 1;
234 break;
235 } else {
236 bh = *bhptr++;
237 if ( !bh ||
238 (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
239 /* Reached an EIO */
240 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
241 fpage, xpage, csize);
242
243 bail = 1;
244 break;
245 }
246 stream.next_in = bh->b_data;
247 stream.avail_in = min(csize,bufsize);
248 csize -= stream.avail_in;
249 }
250 }
251 ao = stream.avail_out; ai = stream.avail_in;
252 zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
253 left_out = stream.avail_out;
254 if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 )
255 continue;
256 if ( zerr != Z_OK ) {
257 /* EOF, error, or trying to read beyond end of input */
258 if ( err && zerr == Z_MEM_ERROR )
259 err = -ENOMEM;
260 if ( zerr != Z_STREAM_END )
261 printk(KERN_DEBUG "zisofs: zisofs_inflate returned %d, inode = %lu, index = %lu, fpage = %d, xpage = %d, avail_in = %d, avail_out = %d, ai = %d, ao = %d\n",
262 zerr, inode->i_ino, index,
263 fpage, xpage,
264 stream.avail_in, stream.avail_out,
265 ai, ao);
266 bail = 1;
267 break;
268 }
269 }
270
271 if ( stream.avail_out && zerr == Z_STREAM_END ) {
272 /* Fractional page written before EOF. This may
273 be the last page in the file. */
274 memset(stream.next_out, 0, stream.avail_out);
275 stream.avail_out = 0;
276 }
277
278 if ( !stream.avail_out ) {
279 /* This page completed */
280 if ( page ) {
281 flush_dcache_page(page);
282 SetPageUptodate(page);
283 kunmap(page);
284 unlock_page(page);
285 if ( fpage == xpage )
286 err = 0; /* The critical page */
287 else
288 page_cache_release(page);
289 }
290 fpage++;
291 }
292 }
293 zlib_inflateEnd(&stream);
294
295 z_eio:
296 up(&zisofs_zlib_semaphore);
297
298 b_eio:
299 for ( i = 0 ; i < haveblocks ; i++ ) {
300 if ( bhs[i] )
301 brelse(bhs[i]);
302 }
303 }
304
305eio:
306
307 /* Release any residual pages, do not SetPageUptodate */
308 while ( fpage < maxpage ) {
309 page = pages[fpage];
310 if ( page ) {
311 flush_dcache_page(page);
312 if ( fpage == xpage )
313 SetPageError(page);
314 kunmap(page);
315 unlock_page(page);
316 if ( fpage != xpage )
317 page_cache_release(page);
318 }
319 fpage++;
320 }
321
322 /* At this point, err contains 0 or -EIO depending on the "critical" page */
323 return err;
324}
325
326struct address_space_operations zisofs_aops = {
327 .readpage = zisofs_readpage,
328 /* No sync_page operation supported? */
329 /* No bmap operation supported */
330};
331
332static int initialized;
333
334int __init zisofs_init(void)
335{
336 if ( initialized ) {
337 printk("zisofs_init: called more than once\n");
338 return 0;
339 }
340
341 zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
342 if ( !zisofs_zlib_workspace )
343 return -ENOMEM;
344 init_MUTEX(&zisofs_zlib_semaphore);
345
346 initialized = 1;
347 return 0;
348}
349
350void zisofs_cleanup(void)
351{
352 if ( !initialized ) {
353 printk("zisofs_cleanup: called without initialization\n");
354 return;
355 }
356
357 vfree(zisofs_zlib_workspace);
358 initialized = 0;
359}
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
new file mode 100644
index 000000000000..14d86de6637d
--- /dev/null
+++ b/fs/isofs/dir.c
@@ -0,0 +1,280 @@
1/*
2 * linux/fs/isofs/dir.c
3 *
4 * (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem.
5 *
6 * (C) 1991 Linus Torvalds - minix filesystem
7 *
8 * Steve Beynon : Missing last directory entries fixed
9 * (stephen@askone.demon.co.uk) : 21st June 1996
10 *
11 * isofs directory handling functions
12 */
13#include <linux/errno.h>
14#include <linux/fs.h>
15#include <linux/iso_fs.h>
16#include <linux/kernel.h>
17#include <linux/stat.h>
18#include <linux/string.h>
19#include <linux/mm.h>
20#include <linux/slab.h>
21#include <linux/time.h>
22#include <linux/config.h>
23#include <linux/smp_lock.h>
24#include <linux/buffer_head.h>
25
26#include <asm/uaccess.h>
27
28static int isofs_readdir(struct file *, void *, filldir_t);
29
30struct file_operations isofs_dir_operations =
31{
32 .read = generic_read_dir,
33 .readdir = isofs_readdir,
34};
35
36/*
37 * directories can handle most operations...
38 */
39struct inode_operations isofs_dir_inode_operations =
40{
41 .lookup = isofs_lookup,
42};
43
44int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
45{
46 char * old = de->name;
47 int len = de->name_len[0];
48 int i;
49
50 for (i = 0; i < len; i++) {
51 unsigned char c = old[i];
52 if (!c)
53 break;
54
55 if (c >= 'A' && c <= 'Z')
56 c |= 0x20; /* lower case */
57
58 /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
59 if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
60 break;
61
62 /* Drop trailing ';1' */
63 if (c == ';' && i == len - 2 && old[i + 1] == '1')
64 break;
65
66 /* Convert remaining ';' to '.' */
67 /* Also '/' to '.' (broken Acorn-generated ISO9660 images) */
68 if (c == ';' || c == '/')
69 c = '.';
70
71 new[i] = c;
72 }
73 return i;
74}
75
76/* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */
77int get_acorn_filename(struct iso_directory_record * de,
78 char * retname, struct inode * inode)
79{
80 int std;
81 unsigned char * chr;
82 int retnamlen = isofs_name_translate(de, retname, inode);
83 if (retnamlen == 0) return 0;
84 std = sizeof(struct iso_directory_record) + de->name_len[0];
85 if (std & 1) std++;
86 if ((*((unsigned char *) de) - std) != 32) return retnamlen;
87 chr = ((unsigned char *) de) + std;
88 if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen;
89 if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!';
90 if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
91 && ((chr[12] & 0xf0) == 0xf0))
92 {
93 retname[retnamlen] = ',';
94 sprintf(retname+retnamlen+1, "%3.3x",
95 ((chr[12] & 0xf) << 8) | chr[11]);
96 retnamlen += 4;
97 }
98 return retnamlen;
99}
100
101/*
102 * This should _really_ be cleaned up some day..
103 */
104static int do_isofs_readdir(struct inode *inode, struct file *filp,
105 void *dirent, filldir_t filldir,
106 char * tmpname, struct iso_directory_record * tmpde)
107{
108 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
109 unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
110 unsigned long block, offset, block_saved, offset_saved;
111 unsigned long inode_number = 0; /* Quiet GCC */
112 struct buffer_head *bh = NULL;
113 int len;
114 int map;
115 int first_de = 1;
116 char *p = NULL; /* Quiet GCC */
117 struct iso_directory_record *de;
118 struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
119
120 offset = filp->f_pos & (bufsize - 1);
121 block = filp->f_pos >> bufbits;
122
123 while (filp->f_pos < inode->i_size) {
124 int de_len;
125
126 if (!bh) {
127 bh = isofs_bread(inode, block);
128 if (!bh)
129 return 0;
130 }
131
132 de = (struct iso_directory_record *) (bh->b_data + offset);
133
134 de_len = *(unsigned char *) de;
135
136 /* If the length byte is zero, we should move on to the next
137 CDROM sector. If we are at the end of the directory, we
138 kick out of the while loop. */
139
140 if (de_len == 0) {
141 brelse(bh);
142 bh = NULL;
143 filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
144 block = filp->f_pos >> bufbits;
145 offset = 0;
146 continue;
147 }
148
149 block_saved = block;
150 offset_saved = offset;
151 offset += de_len;
152
153 /* Make sure we have a full directory entry */
154 if (offset >= bufsize) {
155 int slop = bufsize - offset + de_len;
156 memcpy(tmpde, de, slop);
157 offset &= bufsize - 1;
158 block++;
159 brelse(bh);
160 bh = NULL;
161 if (offset) {
162 bh = isofs_bread(inode, block);
163 if (!bh)
164 return 0;
165 memcpy((void *) tmpde + slop, bh->b_data, offset);
166 }
167 de = tmpde;
168 }
169
170 if (first_de) {
171 isofs_normalize_block_and_offset(de,
172 &block_saved,
173 &offset_saved);
174 inode_number = isofs_get_ino(block_saved,
175 offset_saved,
176 bufbits);
177 }
178
179 if (de->flags[-sbi->s_high_sierra] & 0x80) {
180 first_de = 0;
181 filp->f_pos += de_len;
182 continue;
183 }
184 first_de = 1;
185
186 /* Handle the case of the '.' directory */
187 if (de->name_len[0] == 1 && de->name[0] == 0) {
188 if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0)
189 break;
190 filp->f_pos += de_len;
191 continue;
192 }
193
194 len = 0;
195
196 /* Handle the case of the '..' directory */
197 if (de->name_len[0] == 1 && de->name[0] == 1) {
198 inode_number = parent_ino(filp->f_dentry);
199 if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
200 break;
201 filp->f_pos += de_len;
202 continue;
203 }
204
205 /* Handle everything else. Do name translation if there
206 is no Rock Ridge NM field. */
207 if (sbi->s_unhide == 'n') {
208 /* Do not report hidden or associated files */
209 if (de->flags[-sbi->s_high_sierra] & 5) {
210 filp->f_pos += de_len;
211 continue;
212 }
213 }
214
215 map = 1;
216 if (sbi->s_rock) {
217 len = get_rock_ridge_filename(de, tmpname, inode);
218 if (len != 0) { /* may be -1 */
219 p = tmpname;
220 map = 0;
221 }
222 }
223 if (map) {
224#ifdef CONFIG_JOLIET
225 if (sbi->s_joliet_level) {
226 len = get_joliet_filename(de, tmpname, inode);
227 p = tmpname;
228 } else
229#endif
230 if (sbi->s_mapping == 'a') {
231 len = get_acorn_filename(de, tmpname, inode);
232 p = tmpname;
233 } else
234 if (sbi->s_mapping == 'n') {
235 len = isofs_name_translate(de, tmpname, inode);
236 p = tmpname;
237 } else {
238 p = de->name;
239 len = de->name_len[0];
240 }
241 }
242 if (len > 0) {
243 if (filldir(dirent, p, len, filp->f_pos, inode_number, DT_UNKNOWN) < 0)
244 break;
245 }
246 filp->f_pos += de_len;
247
248 continue;
249 }
250 if (bh) brelse(bh);
251 return 0;
252}
253
254/*
255 * Handle allocation of temporary space for name translation and
256 * handling split directory entries.. The real work is done by
257 * "do_isofs_readdir()".
258 */
259static int isofs_readdir(struct file *filp,
260 void *dirent, filldir_t filldir)
261{
262 int result;
263 char * tmpname;
264 struct iso_directory_record * tmpde;
265 struct inode *inode = filp->f_dentry->d_inode;
266
267
268 tmpname = (char *)__get_free_page(GFP_KERNEL);
269 if (tmpname == NULL)
270 return -ENOMEM;
271
272 lock_kernel();
273 tmpde = (struct iso_directory_record *) (tmpname+1024);
274
275 result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
276
277 free_page((unsigned long) tmpname);
278 unlock_kernel();
279 return result;
280}
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
new file mode 100644
index 000000000000..e4252c960871
--- /dev/null
+++ b/fs/isofs/export.c
@@ -0,0 +1,228 @@
1/*
2 * fs/isofs/export.c
3 *
4 * (C) 2004 Paul Serice - The new inode scheme requires switching
5 * from iget() to iget5_locked() which means
6 * the NFS export operations have to be hand
7 * coded because the default routines rely on
8 * iget().
9 *
10 * The following files are helpful:
11 *
12 * Documentation/filesystems/Exporting
13 * fs/exportfs/expfs.c.
14 */
15
16#include <linux/buffer_head.h>
17#include <linux/errno.h>
18#include <linux/fs.h>
19#include <linux/iso_fs.h>
20#include <linux/kernel.h>
21
22static struct dentry *
23isofs_export_iget(struct super_block *sb,
24 unsigned long block,
25 unsigned long offset,
26 __u32 generation)
27{
28 struct inode *inode;
29 struct dentry *result;
30 if (block == 0)
31 return ERR_PTR(-ESTALE);
32 inode = isofs_iget(sb, block, offset);
33 if (inode == NULL)
34 return ERR_PTR(-ENOMEM);
35 if (is_bad_inode(inode)
36 || (generation && inode->i_generation != generation))
37 {
38 iput(inode);
39 return ERR_PTR(-ESTALE);
40 }
41 result = d_alloc_anon(inode);
42 if (!result) {
43 iput(inode);
44 return ERR_PTR(-ENOMEM);
45 }
46 return result;
47}
48
49static struct dentry *
50isofs_export_get_dentry(struct super_block *sb, void *vobjp)
51{
52 __u32 *objp = vobjp;
53 unsigned long block = objp[0];
54 unsigned long offset = objp[1];
55 __u32 generation = objp[2];
56 return isofs_export_iget(sb, block, offset, generation);
57}
58
59/* This function is surprisingly simple. The trick is understanding
60 * that "child" is always a directory. So, to find its parent, you
61 * simply need to find its ".." entry, normalize its block and offset,
62 * and return the underlying inode. See the comments for
63 * isofs_normalize_block_and_offset(). */
64static struct dentry *isofs_export_get_parent(struct dentry *child)
65{
66 unsigned long parent_block = 0;
67 unsigned long parent_offset = 0;
68 struct inode *child_inode = child->d_inode;
69 struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
70 struct inode *parent_inode = NULL;
71 struct iso_directory_record *de = NULL;
72 struct buffer_head * bh = NULL;
73 struct dentry *rv = NULL;
74
75 /* "child" must always be a directory. */
76 if (!S_ISDIR(child_inode->i_mode)) {
77 printk(KERN_ERR "isofs: isofs_export_get_parent(): "
78 "child is not a directory!\n");
79 rv = ERR_PTR(-EACCES);
80 goto out;
81 }
82
83 /* It is an invariant that the directory offset is zero. If
84 * it is not zero, it means the directory failed to be
85 * normalized for some reason. */
86 if (e_child_inode->i_iget5_offset != 0) {
87 printk(KERN_ERR "isofs: isofs_export_get_parent(): "
88 "child directory not normalized!\n");
89 rv = ERR_PTR(-EACCES);
90 goto out;
91 }
92
93 /* The child inode has been normalized such that its
94 * i_iget5_block value points to the "." entry. Fortunately,
95 * the ".." entry is located in the same block. */
96 parent_block = e_child_inode->i_iget5_block;
97
98 /* Get the block in question. */
99 bh = sb_bread(child_inode->i_sb, parent_block);
100 if (bh == NULL) {
101 rv = ERR_PTR(-EACCES);
102 goto out;
103 }
104
105 /* This is the "." entry. */
106 de = (struct iso_directory_record*)bh->b_data;
107
108 /* The ".." entry is always the second entry. */
109 parent_offset = (unsigned long)isonum_711(de->length);
110 de = (struct iso_directory_record*)(bh->b_data + parent_offset);
111
112 /* Verify it is in fact the ".." entry. */
113 if ((isonum_711(de->name_len) != 1) || (de->name[0] != 1)) {
114 printk(KERN_ERR "isofs: Unable to find the \"..\" "
115 "directory for NFS.\n");
116 rv = ERR_PTR(-EACCES);
117 goto out;
118 }
119
120 /* Normalize */
121 isofs_normalize_block_and_offset(de, &parent_block, &parent_offset);
122
123 /* Get the inode. */
124 parent_inode = isofs_iget(child_inode->i_sb,
125 parent_block,
126 parent_offset);
127 if (parent_inode == NULL) {
128 rv = ERR_PTR(-EACCES);
129 goto out;
130 }
131
132 /* Allocate the dentry. */
133 rv = d_alloc_anon(parent_inode);
134 if (rv == NULL) {
135 rv = ERR_PTR(-ENOMEM);
136 goto out;
137 }
138
139 out:
140 if (bh) {
141 brelse(bh);
142 }
143 return rv;
144}
145
146static int
147isofs_export_encode_fh(struct dentry *dentry,
148 __u32 *fh32,
149 int *max_len,
150 int connectable)
151{
152 struct inode * inode = dentry->d_inode;
153 struct iso_inode_info * ei = ISOFS_I(inode);
154 int len = *max_len;
155 int type = 1;
156 __u16 *fh16 = (__u16*)fh32;
157
158 /*
159 * WARNING: max_len is 5 for NFSv2. Because of this
160 * limitation, we use the lower 16 bits of fh32[1] to hold the
161 * offset of the inode and the upper 16 bits of fh32[1] to
162 * hold the offset of the parent.
163 */
164
165 if (len < 3 || (connectable && len < 5))
166 return 255;
167
168 len = 3;
169 fh32[0] = ei->i_iget5_block;
170 fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */
171 fh32[2] = inode->i_generation;
172 if (connectable && !S_ISDIR(inode->i_mode)) {
173 struct inode *parent;
174 struct iso_inode_info *eparent;
175 spin_lock(&dentry->d_lock);
176 parent = dentry->d_parent->d_inode;
177 eparent = ISOFS_I(parent);
178 fh32[3] = eparent->i_iget5_block;
179 fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */
180 fh32[4] = parent->i_generation;
181 spin_unlock(&dentry->d_lock);
182 len = 5;
183 type = 2;
184 }
185 *max_len = len;
186 return type;
187}
188
189
190static struct dentry *
191isofs_export_decode_fh(struct super_block *sb,
192 __u32 *fh32,
193 int fh_len,
194 int fileid_type,
195 int (*acceptable)(void *context, struct dentry *de),
196 void *context)
197{
198 __u16 *fh16 = (__u16*)fh32;
199 __u32 child[3]; /* The child is what triggered all this. */
200 __u32 parent[3]; /* The parent is just along for the ride. */
201
202 if (fh_len < 3 || fileid_type > 2)
203 return NULL;
204
205 child[0] = fh32[0];
206 child[1] = fh16[2]; /* fh16 [sic] */
207 child[2] = fh32[2];
208
209 parent[0] = 0;
210 parent[1] = 0;
211 parent[2] = 0;
212 if (fileid_type == 2) {
213 if (fh_len > 2) parent[0] = fh32[3];
214 parent[1] = fh16[3]; /* fh16 [sic] */
215 if (fh_len > 4) parent[2] = fh32[4];
216 }
217
218 return sb->s_export_op->find_exported_dentry(sb, child, parent,
219 acceptable, context);
220}
221
222
223struct export_operations isofs_export_ops = {
224 .decode_fh = isofs_export_decode_fh,
225 .encode_fh = isofs_export_encode_fh,
226 .get_dentry = isofs_export_get_dentry,
227 .get_parent = isofs_export_get_parent,
228};
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
new file mode 100644
index 000000000000..b9256e65e144
--- /dev/null
+++ b/fs/isofs/inode.c
@@ -0,0 +1,1503 @@
1/*
2 * linux/fs/isofs/inode.c
3 *
4 * (C) 1991 Linus Torvalds - minix filesystem
5 * 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem.
6 * 1994 Eberhard Moenkeberg - multi session handling.
7 * 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
8 * 1997 Gordon Chaffee - Joliet CDs
9 * 1998 Eric Lammerts - ISO 9660 Level 3
10 * 2004 Paul Serice - Inode Support pushed out from 4GB to 128GB
11 * 2004 Paul Serice - NFS Export Operations
12 */
13
14#include <linux/config.h>
15#include <linux/module.h>
16
17#include <linux/stat.h>
18#include <linux/time.h>
19#include <linux/iso_fs.h>
20#include <linux/kernel.h>
21#include <linux/major.h>
22#include <linux/mm.h>
23#include <linux/string.h>
24#include <linux/slab.h>
25#include <linux/errno.h>
26#include <linux/cdrom.h>
27#include <linux/init.h>
28#include <linux/nls.h>
29#include <linux/ctype.h>
30#include <linux/smp_lock.h>
31#include <linux/blkdev.h>
32#include <linux/buffer_head.h>
33#include <linux/vfs.h>
34#include <linux/parser.h>
35#include <asm/system.h>
36#include <asm/uaccess.h>
37
38#include "zisofs.h"
39
40#define BEQUIET
41
42#ifdef LEAK_CHECK
43static int check_malloc;
44static int check_bread;
45#endif
46
47static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
48static int isofs_hash(struct dentry *parent, struct qstr *qstr);
49static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
50static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
51
52#ifdef CONFIG_JOLIET
53static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
54static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
55static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
56static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
57#endif
58
59static void isofs_put_super(struct super_block *sb)
60{
61 struct isofs_sb_info *sbi = ISOFS_SB(sb);
62#ifdef CONFIG_JOLIET
63 if (sbi->s_nls_iocharset) {
64 unload_nls(sbi->s_nls_iocharset);
65 sbi->s_nls_iocharset = NULL;
66 }
67#endif
68
69#ifdef LEAK_CHECK
70 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
71 check_malloc, check_bread);
72#endif
73
74 kfree(sbi);
75 sb->s_fs_info = NULL;
76 return;
77}
78
79static void isofs_read_inode(struct inode *);
80static int isofs_statfs (struct super_block *, struct kstatfs *);
81
82static kmem_cache_t *isofs_inode_cachep;
83
84static struct inode *isofs_alloc_inode(struct super_block *sb)
85{
86 struct iso_inode_info *ei;
87 ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
88 if (!ei)
89 return NULL;
90 return &ei->vfs_inode;
91}
92
93static void isofs_destroy_inode(struct inode *inode)
94{
95 kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
96}
97
98static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
99{
100 struct iso_inode_info *ei = (struct iso_inode_info *) foo;
101
102 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
103 SLAB_CTOR_CONSTRUCTOR)
104 inode_init_once(&ei->vfs_inode);
105}
106
107static int init_inodecache(void)
108{
109 isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
110 sizeof(struct iso_inode_info),
111 0, SLAB_RECLAIM_ACCOUNT,
112 init_once, NULL);
113 if (isofs_inode_cachep == NULL)
114 return -ENOMEM;
115 return 0;
116}
117
118static void destroy_inodecache(void)
119{
120 if (kmem_cache_destroy(isofs_inode_cachep))
121 printk(KERN_INFO "iso_inode_cache: not all structures were freed\n");
122}
123
124static int isofs_remount(struct super_block *sb, int *flags, char *data)
125{
126 /* we probably want a lot more here */
127 *flags |= MS_RDONLY;
128 return 0;
129}
130
131static struct super_operations isofs_sops = {
132 .alloc_inode = isofs_alloc_inode,
133 .destroy_inode = isofs_destroy_inode,
134 .read_inode = isofs_read_inode,
135 .put_super = isofs_put_super,
136 .statfs = isofs_statfs,
137 .remount_fs = isofs_remount,
138};
139
140
141static struct dentry_operations isofs_dentry_ops[] = {
142 {
143 .d_hash = isofs_hash,
144 .d_compare = isofs_dentry_cmp,
145 },
146 {
147 .d_hash = isofs_hashi,
148 .d_compare = isofs_dentry_cmpi,
149 },
150#ifdef CONFIG_JOLIET
151 {
152 .d_hash = isofs_hash_ms,
153 .d_compare = isofs_dentry_cmp_ms,
154 },
155 {
156 .d_hash = isofs_hashi_ms,
157 .d_compare = isofs_dentry_cmpi_ms,
158 }
159#endif
160};
161
162struct iso9660_options{
163 char map;
164 char rock;
165 char joliet;
166 char cruft;
167 char unhide;
168 char nocompress;
169 unsigned char check;
170 unsigned int blocksize;
171 mode_t mode;
172 gid_t gid;
173 uid_t uid;
174 char *iocharset;
175 unsigned char utf8;
176 /* LVE */
177 s32 session;
178 s32 sbsector;
179};
180
181/*
182 * Compute the hash for the isofs name corresponding to the dentry.
183 */
184static int
185isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
186{
187 const char *name;
188 int len;
189
190 len = qstr->len;
191 name = qstr->name;
192 if (ms) {
193 while (len && name[len-1] == '.')
194 len--;
195 }
196
197 qstr->hash = full_name_hash(name, len);
198
199 return 0;
200}
201
202/*
203 * Compute the hash for the isofs name corresponding to the dentry.
204 */
205static int
206isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
207{
208 const char *name;
209 int len;
210 char c;
211 unsigned long hash;
212
213 len = qstr->len;
214 name = qstr->name;
215 if (ms) {
216 while (len && name[len-1] == '.')
217 len--;
218 }
219
220 hash = init_name_hash();
221 while (len--) {
222 c = tolower(*name++);
223 hash = partial_name_hash(tolower(c), hash);
224 }
225 qstr->hash = end_name_hash(hash);
226
227 return 0;
228}
229
230/*
231 * Case insensitive compare of two isofs names.
232 */
233static int
234isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
235{
236 int alen, blen;
237
238 /* A filename cannot end in '.' or we treat it like it has none */
239 alen = a->len;
240 blen = b->len;
241 if (ms) {
242 while (alen && a->name[alen-1] == '.')
243 alen--;
244 while (blen && b->name[blen-1] == '.')
245 blen--;
246 }
247 if (alen == blen) {
248 if (strnicmp(a->name, b->name, alen) == 0)
249 return 0;
250 }
251 return 1;
252}
253
254/*
255 * Case sensitive compare of two isofs names.
256 */
257static int
258isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
259{
260 int alen, blen;
261
262 /* A filename cannot end in '.' or we treat it like it has none */
263 alen = a->len;
264 blen = b->len;
265 if (ms) {
266 while (alen && a->name[alen-1] == '.')
267 alen--;
268 while (blen && b->name[blen-1] == '.')
269 blen--;
270 }
271 if (alen == blen) {
272 if (strncmp(a->name, b->name, alen) == 0)
273 return 0;
274 }
275 return 1;
276}
277
278static int
279isofs_hash(struct dentry *dentry, struct qstr *qstr)
280{
281 return isofs_hash_common(dentry, qstr, 0);
282}
283
284static int
285isofs_hashi(struct dentry *dentry, struct qstr *qstr)
286{
287 return isofs_hashi_common(dentry, qstr, 0);
288}
289
290static int
291isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
292{
293 return isofs_dentry_cmp_common(dentry, a, b, 0);
294}
295
296static int
297isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
298{
299 return isofs_dentry_cmpi_common(dentry, a, b, 0);
300}
301
302#ifdef CONFIG_JOLIET
303static int
304isofs_hash_ms(struct dentry *dentry, struct qstr *qstr)
305{
306 return isofs_hash_common(dentry, qstr, 1);
307}
308
309static int
310isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
311{
312 return isofs_hashi_common(dentry, qstr, 1);
313}
314
315static int
316isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
317{
318 return isofs_dentry_cmp_common(dentry, a, b, 1);
319}
320
321static int
322isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
323{
324 return isofs_dentry_cmpi_common(dentry, a, b, 1);
325}
326#endif
327
328enum {
329 Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
330 Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
331 Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
332 Opt_nocompress,
333};
334
335static match_table_t tokens = {
336 {Opt_norock, "norock"},
337 {Opt_nojoliet, "nojoliet"},
338 {Opt_unhide, "unhide"},
339 {Opt_cruft, "cruft"},
340 {Opt_utf8, "utf8"},
341 {Opt_iocharset, "iocharset=%s"},
342 {Opt_map_a, "map=acorn"},
343 {Opt_map_a, "map=a"},
344 {Opt_map_n, "map=normal"},
345 {Opt_map_n, "map=n"},
346 {Opt_map_o, "map=off"},
347 {Opt_map_o, "map=o"},
348 {Opt_session, "session=%u"},
349 {Opt_sb, "sbsector=%u"},
350 {Opt_check_r, "check=relaxed"},
351 {Opt_check_r, "check=r"},
352 {Opt_check_s, "check=strict"},
353 {Opt_check_s, "check=s"},
354 {Opt_uid, "uid=%u"},
355 {Opt_gid, "gid=%u"},
356 {Opt_mode, "mode=%u"},
357 {Opt_block, "block=%u"},
358 {Opt_ignore, "conv=binary"},
359 {Opt_ignore, "conv=b"},
360 {Opt_ignore, "conv=text"},
361 {Opt_ignore, "conv=t"},
362 {Opt_ignore, "conv=mtext"},
363 {Opt_ignore, "conv=m"},
364 {Opt_ignore, "conv=auto"},
365 {Opt_ignore, "conv=a"},
366 {Opt_nocompress, "nocompress"},
367 {Opt_err, NULL}
368};
369
370static int parse_options(char *options, struct iso9660_options * popt)
371{
372 char *p;
373 int option;
374
375 popt->map = 'n';
376 popt->rock = 'y';
377 popt->joliet = 'y';
378 popt->cruft = 'n';
379 popt->unhide = 'n';
380 popt->check = 'u'; /* unset */
381 popt->nocompress = 0;
382 popt->blocksize = 1024;
383 popt->mode = S_IRUGO | S_IXUGO; /* r-x for all. The disc could
384 be shared with DOS machines so
385 virtually anything could be
386 a valid executable. */
387 popt->gid = 0;
388 popt->uid = 0;
389 popt->iocharset = NULL;
390 popt->utf8 = 0;
391 popt->session=-1;
392 popt->sbsector=-1;
393 if (!options)
394 return 1;
395
396 while ((p = strsep(&options, ",")) != NULL) {
397 int token;
398 substring_t args[MAX_OPT_ARGS];
399 unsigned n;
400
401 if (!*p)
402 continue;
403
404 token = match_token(p, tokens, args);
405 switch (token) {
406 case Opt_norock:
407 popt->rock = 'n';
408 break;
409 case Opt_nojoliet:
410 popt->joliet = 'n';
411 break;
412 case Opt_unhide:
413 popt->unhide = 'y';
414 break;
415 case Opt_cruft:
416 popt->cruft = 'y';
417 break;
418 case Opt_utf8:
419 popt->utf8 = 1;
420 break;
421#ifdef CONFIG_JOLIET
422 case Opt_iocharset:
423 popt->iocharset = match_strdup(&args[0]);
424 break;
425#endif
426 case Opt_map_a:
427 popt->map = 'a';
428 break;
429 case Opt_map_o:
430 popt->map = 'o';
431 break;
432 case Opt_map_n:
433 popt->map = 'n';
434 break;
435 case Opt_session:
436 if (match_int(&args[0], &option))
437 return 0;
438 n = option;
439 if (n > 99)
440 return 0;
441 popt->session = n + 1;
442 break;
443 case Opt_sb:
444 if (match_int(&args[0], &option))
445 return 0;
446 popt->sbsector = option;
447 break;
448 case Opt_check_r:
449 popt->check = 'r';
450 break;
451 case Opt_check_s:
452 popt->check = 's';
453 break;
454 case Opt_ignore:
455 break;
456 case Opt_uid:
457 if (match_int(&args[0], &option))
458 return 0;
459 popt->uid = option;
460 break;
461 case Opt_gid:
462 if (match_int(&args[0], &option))
463 return 0;
464 popt->gid = option;
465 break;
466 case Opt_mode:
467 if (match_int(&args[0], &option))
468 return 0;
469 popt->mode = option;
470 break;
471 case Opt_block:
472 if (match_int(&args[0], &option))
473 return 0;
474 n = option;
475 if (n != 512 && n != 1024 && n != 2048)
476 return 0;
477 popt->blocksize = n;
478 break;
479 case Opt_nocompress:
480 popt->nocompress = 1;
481 break;
482 default:
483 return 0;
484 }
485 }
486 return 1;
487}
488
489/*
490 * look if the driver can tell the multi session redirection value
491 *
492 * don't change this if you don't know what you do, please!
493 * Multisession is legal only with XA disks.
494 * A non-XA disk with more than one volume descriptor may do it right, but
495 * usually is written in a nowhere standardized "multi-partition" manner.
496 * Multisession uses absolute addressing (solely the first frame of the whole
497 * track is #0), multi-partition uses relative addressing (each first frame of
498 * each track is #0), and a track is not a session.
499 *
500 * A broken CDwriter software or drive firmware does not set new standards,
501 * at least not if conflicting with the existing ones.
502 *
503 * emoenke@gwdg.de
504 */
505#define WE_OBEY_THE_WRITTEN_STANDARDS 1
506
507static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
508{
509 struct cdrom_multisession ms_info;
510 unsigned int vol_desc_start;
511 struct block_device *bdev = sb->s_bdev;
512 int i;
513
514 vol_desc_start=0;
515 ms_info.addr_format=CDROM_LBA;
516 if(session >= 0 && session <= 99) {
517 struct cdrom_tocentry Te;
518 Te.cdte_track=session;
519 Te.cdte_format=CDROM_LBA;
520 i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
521 if (!i) {
522 printk(KERN_DEBUG "Session %d start %d type %d\n",
523 session, Te.cdte_addr.lba,
524 Te.cdte_ctrl&CDROM_DATA_TRACK);
525 if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
526 return Te.cdte_addr.lba;
527 }
528
529 printk(KERN_ERR "Invalid session number or type of track\n");
530 }
531 i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
532 if(session > 0) printk(KERN_ERR "Invalid session number\n");
533#if 0
534 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
535 if (i==0) {
536 printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
537 printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
538 }
539#endif
540 if (i==0)
541#if WE_OBEY_THE_WRITTEN_STANDARDS
542 if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
543#endif
544 vol_desc_start=ms_info.addr.lba;
545 return vol_desc_start;
546}
547
548/*
549 * Initialize the superblock and read the root inode.
550 *
551 * Note: a check_disk_change() has been done immediately prior
552 * to this call, so we don't need to check again.
553 */
554static int isofs_fill_super(struct super_block *s, void *data, int silent)
555{
556 struct buffer_head * bh = NULL, *pri_bh = NULL;
557 struct hs_primary_descriptor * h_pri = NULL;
558 struct iso_primary_descriptor * pri = NULL;
559 struct iso_supplementary_descriptor *sec = NULL;
560 struct iso_directory_record * rootp;
561 int joliet_level = 0;
562 int iso_blknum, block;
563 int orig_zonesize;
564 int table;
565 unsigned int vol_desc_start;
566 unsigned long first_data_zone;
567 struct inode * inode;
568 struct iso9660_options opt;
569 struct isofs_sb_info * sbi;
570
571 sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL);
572 if (!sbi)
573 return -ENOMEM;
574 s->s_fs_info = sbi;
575 memset(sbi, 0, sizeof(struct isofs_sb_info));
576
577 if (!parse_options((char *) data, &opt))
578 goto out_freesbi;
579
580 /*
581 * First of all, get the hardware blocksize for this device.
582 * If we don't know what it is, or the hardware blocksize is
583 * larger than the blocksize the user specified, then use
584 * that value.
585 */
586 /*
587 * What if bugger tells us to go beyond page size?
588 */
589 opt.blocksize = sb_min_blocksize(s, opt.blocksize);
590
591 sbi->s_high_sierra = 0; /* default is iso9660 */
592
593 vol_desc_start = (opt.sbsector != -1) ?
594 opt.sbsector : isofs_get_last_session(s,opt.session);
595
596 for (iso_blknum = vol_desc_start+16;
597 iso_blknum < vol_desc_start+100; iso_blknum++)
598 {
599 struct hs_volume_descriptor * hdp;
600 struct iso_volume_descriptor * vdp;
601
602 block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
603 if (!(bh = sb_bread(s, block)))
604 goto out_no_read;
605
606 vdp = (struct iso_volume_descriptor *)bh->b_data;
607 hdp = (struct hs_volume_descriptor *)bh->b_data;
608
609 /* Due to the overlapping physical location of the descriptors,
610 * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
611 * proper identification in this case, we first check for ISO.
612 */
613 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
614 if (isonum_711 (vdp->type) == ISO_VD_END)
615 break;
616 if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
617 if (pri == NULL) {
618 pri = (struct iso_primary_descriptor *)vdp;
619 /* Save the buffer in case we need it ... */
620 pri_bh = bh;
621 bh = NULL;
622 }
623 }
624#ifdef CONFIG_JOLIET
625 else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
626 sec = (struct iso_supplementary_descriptor *)vdp;
627 if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
628 if (opt.joliet == 'y') {
629 if (sec->escape[2] == 0x40) {
630 joliet_level = 1;
631 } else if (sec->escape[2] == 0x43) {
632 joliet_level = 2;
633 } else if (sec->escape[2] == 0x45) {
634 joliet_level = 3;
635 }
636 printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n",
637 joliet_level);
638 }
639 goto root_found;
640 } else {
641 /* Unknown supplementary volume descriptor */
642 sec = NULL;
643 }
644 }
645#endif
646 } else {
647 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
648 if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
649 goto out_freebh;
650
651 sbi->s_high_sierra = 1;
652 opt.rock = 'n';
653 h_pri = (struct hs_primary_descriptor *)vdp;
654 goto root_found;
655 }
656 }
657
658 /* Just skip any volume descriptors we don't recognize */
659
660 brelse(bh);
661 bh = NULL;
662 }
663 /*
664 * If we fall through, either no volume descriptor was found,
665 * or else we passed a primary descriptor looking for others.
666 */
667 if (!pri)
668 goto out_unknown_format;
669 brelse(bh);
670 bh = pri_bh;
671 pri_bh = NULL;
672
673root_found:
674
675 if (joliet_level && (pri == NULL || opt.rock == 'n')) {
676 /* This is the case of Joliet with the norock mount flag.
677 * A disc with both Joliet and Rock Ridge is handled later
678 */
679 pri = (struct iso_primary_descriptor *) sec;
680 }
681
682 if(sbi->s_high_sierra){
683 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
684 sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
685 sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
686 sbi->s_max_size = isonum_733(h_pri->volume_space_size);
687 } else {
688 if (!pri)
689 goto out_freebh;
690 rootp = (struct iso_directory_record *) pri->root_directory_record;
691 sbi->s_nzones = isonum_733 (pri->volume_space_size);
692 sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
693 sbi->s_max_size = isonum_733(pri->volume_space_size);
694 }
695
696 sbi->s_ninodes = 0; /* No way to figure this out easily */
697
698 orig_zonesize = sbi->s_log_zone_size;
699 /*
700 * If the zone size is smaller than the hardware sector size,
701 * this is a fatal error. This would occur if the disc drive
702 * had sectors that were 2048 bytes, but the filesystem had
703 * blocks that were 512 bytes (which should only very rarely
704 * happen.)
705 */
706 if(orig_zonesize < opt.blocksize)
707 goto out_bad_size;
708
709 /* RDE: convert log zone size to bit shift */
710 switch (sbi->s_log_zone_size)
711 { case 512: sbi->s_log_zone_size = 9; break;
712 case 1024: sbi->s_log_zone_size = 10; break;
713 case 2048: sbi->s_log_zone_size = 11; break;
714
715 default:
716 goto out_bad_zone_size;
717 }
718
719 s->s_magic = ISOFS_SUPER_MAGIC;
720 s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */
721
722 /* The CDROM is read-only, has no nodes (devices) on it, and since
723 all of the files appear to be owned by root, we really do not want
724 to allow suid. (suid or devices will not show up unless we have
725 Rock Ridge extensions) */
726
727 s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
728
729 /* Set this for reference. Its not currently used except on write
730 which we don't have .. */
731
732 first_data_zone = isonum_733 (rootp->extent) +
733 isonum_711 (rootp->ext_attr_length);
734 sbi->s_firstdatazone = first_data_zone;
735#ifndef BEQUIET
736 printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
737 sbi->s_max_size,
738 1UL << sbi->s_log_zone_size);
739 printk(KERN_DEBUG "First datazone:%ld\n", sbi->s_firstdatazone);
740 if(sbi->s_high_sierra)
741 printk(KERN_DEBUG "Disc in High Sierra format.\n");
742#endif
743
744 /*
745 * If the Joliet level is set, we _may_ decide to use the
746 * secondary descriptor, but can't be sure until after we
747 * read the root inode. But before reading the root inode
748 * we may need to change the device blocksize, and would
749 * rather release the old buffer first. So, we cache the
750 * first_data_zone value from the secondary descriptor.
751 */
752 if (joliet_level) {
753 pri = (struct iso_primary_descriptor *) sec;
754 rootp = (struct iso_directory_record *)
755 pri->root_directory_record;
756 first_data_zone = isonum_733 (rootp->extent) +
757 isonum_711 (rootp->ext_attr_length);
758 }
759
760 /*
761 * We're all done using the volume descriptor, and may need
762 * to change the device blocksize, so release the buffer now.
763 */
764 brelse(pri_bh);
765 brelse(bh);
766
767 /*
768 * Force the blocksize to 512 for 512 byte sectors. The file
769 * read primitives really get it wrong in a bad way if we don't
770 * do this.
771 *
772 * Note - we should never be setting the blocksize to something
773 * less than the hardware sector size for the device. If we
774 * do, we would end up having to read larger buffers and split
775 * out portions to satisfy requests.
776 *
777 * Note2- the idea here is that we want to deal with the optimal
778 * zonesize in the filesystem. If we have it set to something less,
779 * then we have horrible problems with trying to piece together
780 * bits of adjacent blocks in order to properly read directory
781 * entries. By forcing the blocksize in this way, we ensure
782 * that we will never be required to do this.
783 */
784 sb_set_blocksize(s, orig_zonesize);
785
786 sbi->s_nls_iocharset = NULL;
787
788#ifdef CONFIG_JOLIET
789 if (joliet_level && opt.utf8 == 0) {
790 char * p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
791 sbi->s_nls_iocharset = load_nls(p);
792 if (! sbi->s_nls_iocharset) {
793 /* Fail only if explicit charset specified */
794 if (opt.iocharset)
795 goto out_freesbi;
796 sbi->s_nls_iocharset = load_nls_default();
797 }
798 }
799#endif
800 s->s_op = &isofs_sops;
801 s->s_export_op = &isofs_export_ops;
802 sbi->s_mapping = opt.map;
803 sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
804 sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
805 sbi->s_cruft = opt.cruft;
806 sbi->s_unhide = opt.unhide;
807 sbi->s_uid = opt.uid;
808 sbi->s_gid = opt.gid;
809 sbi->s_utf8 = opt.utf8;
810 sbi->s_nocompress = opt.nocompress;
811 /*
812 * It would be incredibly stupid to allow people to mark every file
813 * on the disk as suid, so we merely allow them to set the default
814 * permissions.
815 */
816 sbi->s_mode = opt.mode & 0777;
817
818 /*
819 * Read the root inode, which _may_ result in changing
820 * the s_rock flag. Once we have the final s_rock value,
821 * we then decide whether to use the Joliet descriptor.
822 */
823 inode = isofs_iget(s, sbi->s_firstdatazone, 0);
824
825 /*
826 * If this disk has both Rock Ridge and Joliet on it, then we
827 * want to use Rock Ridge by default. This can be overridden
828 * by using the norock mount option. There is still one other
829 * possibility that is not taken into account: a Rock Ridge
830 * CD with Unicode names. Until someone sees such a beast, it
831 * will not be supported.
832 */
833 if (sbi->s_rock == 1) {
834 joliet_level = 0;
835 } else if (joliet_level) {
836 sbi->s_rock = 0;
837 if (sbi->s_firstdatazone != first_data_zone) {
838 sbi->s_firstdatazone = first_data_zone;
839 printk(KERN_DEBUG
840 "ISOFS: changing to secondary root\n");
841 iput(inode);
842 inode = isofs_iget(s, sbi->s_firstdatazone, 0);
843 }
844 }
845
846 if (opt.check == 'u') {
847 /* Only Joliet is case insensitive by default */
848 if (joliet_level) opt.check = 'r';
849 else opt.check = 's';
850 }
851 sbi->s_joliet_level = joliet_level;
852
853 /* check the root inode */
854 if (!inode)
855 goto out_no_root;
856 if (!inode->i_op)
857 goto out_bad_root;
858 /* get the root dentry */
859 s->s_root = d_alloc_root(inode);
860 if (!(s->s_root))
861 goto out_no_root;
862
863 table = 0;
864 if (joliet_level) table += 2;
865 if (opt.check == 'r') table++;
866 s->s_root->d_op = &isofs_dentry_ops[table];
867
868 if (opt.iocharset)
869 kfree(opt.iocharset);
870
871 return 0;
872
873 /*
874 * Display error messages and free resources.
875 */
876out_bad_root:
877 printk(KERN_WARNING "isofs_fill_super: root inode not initialized\n");
878 goto out_iput;
879out_no_root:
880 printk(KERN_WARNING "isofs_fill_super: get root inode failed\n");
881out_iput:
882 iput(inode);
883#ifdef CONFIG_JOLIET
884 if (sbi->s_nls_iocharset)
885 unload_nls(sbi->s_nls_iocharset);
886#endif
887 goto out_freesbi;
888out_no_read:
889 printk(KERN_WARNING "isofs_fill_super: "
890 "bread failed, dev=%s, iso_blknum=%d, block=%d\n",
891 s->s_id, iso_blknum, block);
892 goto out_freesbi;
893out_bad_zone_size:
894 printk(KERN_WARNING "Bad logical zone size %ld\n",
895 sbi->s_log_zone_size);
896 goto out_freebh;
897out_bad_size:
898 printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
899 orig_zonesize, opt.blocksize);
900 goto out_freebh;
901out_unknown_format:
902 if (!silent)
903 printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
904
905out_freebh:
906 brelse(bh);
907out_freesbi:
908 if (opt.iocharset)
909 kfree(opt.iocharset);
910 kfree(sbi);
911 s->s_fs_info = NULL;
912 return -EINVAL;
913}
914
915static int isofs_statfs (struct super_block *sb, struct kstatfs *buf)
916{
917 buf->f_type = ISOFS_SUPER_MAGIC;
918 buf->f_bsize = sb->s_blocksize;
919 buf->f_blocks = (ISOFS_SB(sb)->s_nzones
920 << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
921 buf->f_bfree = 0;
922 buf->f_bavail = 0;
923 buf->f_files = ISOFS_SB(sb)->s_ninodes;
924 buf->f_ffree = 0;
925 buf->f_namelen = NAME_MAX;
926 return 0;
927}
928
929/*
930 * Get a set of blocks; filling in buffer_heads if already allocated
931 * or getblk() if they are not. Returns the number of blocks inserted
932 * (0 == error.)
933 */
934int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
935 struct buffer_head **bh, unsigned long nblocks)
936{
937 unsigned long b_off;
938 unsigned offset, sect_size;
939 unsigned int firstext;
940 unsigned long nextblk, nextoff;
941 long iblock = (long)iblock_s;
942 int section, rv;
943 struct iso_inode_info *ei = ISOFS_I(inode);
944
945 lock_kernel();
946
947 rv = 0;
948 if (iblock < 0 || iblock != iblock_s) {
949 printk("isofs_get_blocks: block number too large\n");
950 goto abort;
951 }
952
953 b_off = iblock;
954
955 offset = 0;
956 firstext = ei->i_first_extent;
957 sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
958 nextblk = ei->i_next_section_block;
959 nextoff = ei->i_next_section_offset;
960 section = 0;
961
962 while ( nblocks ) {
963 /* If we are *way* beyond the end of the file, print a message.
964 * Access beyond the end of the file up to the next page boundary
965 * is normal, however because of the way the page cache works.
966 * In this case, we just return 0 so that we can properly fill
967 * the page with useless information without generating any
968 * I/O errors.
969 */
970 if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) {
971 printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n",
972 iblock, (unsigned long) inode->i_size);
973 goto abort;
974 }
975
976 if (nextblk) {
977 while (b_off >= (offset + sect_size)) {
978 struct inode *ninode;
979
980 offset += sect_size;
981 if (nextblk == 0)
982 goto abort;
983 ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
984 if (!ninode)
985 goto abort;
986 firstext = ISOFS_I(ninode)->i_first_extent;
987 sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
988 nextblk = ISOFS_I(ninode)->i_next_section_block;
989 nextoff = ISOFS_I(ninode)->i_next_section_offset;
990 iput(ninode);
991
992 if (++section > 100) {
993 printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
994 printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
995 "nextblk=%lu nextoff=%lu\n",
996 iblock, firstext, (unsigned) sect_size,
997 nextblk, nextoff);
998 goto abort;
999 }
1000 }
1001 }
1002
1003 if ( *bh ) {
1004 map_bh(*bh, inode->i_sb, firstext + b_off - offset);
1005 } else {
1006 *bh = sb_getblk(inode->i_sb, firstext+b_off-offset);
1007 if ( !*bh )
1008 goto abort;
1009 }
1010 bh++; /* Next buffer head */
1011 b_off++; /* Next buffer offset */
1012 nblocks--;
1013 rv++;
1014 }
1015
1016
1017abort:
1018 unlock_kernel();
1019 return rv;
1020}
1021
1022/*
1023 * Used by the standard interfaces.
1024 */
1025static int isofs_get_block(struct inode *inode, sector_t iblock,
1026 struct buffer_head *bh_result, int create)
1027{
1028 if ( create ) {
1029 printk("isofs_get_block: Kernel tries to allocate a block\n");
1030 return -EROFS;
1031 }
1032
1033 return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;
1034}
1035
1036static int isofs_bmap(struct inode *inode, sector_t block)
1037{
1038 struct buffer_head dummy;
1039 int error;
1040
1041 dummy.b_state = 0;
1042 dummy.b_blocknr = -1000;
1043 error = isofs_get_block(inode, block, &dummy, 0);
1044 if (!error)
1045 return dummy.b_blocknr;
1046 return 0;
1047}
1048
1049struct buffer_head *isofs_bread(struct inode *inode, sector_t block)
1050{
1051 sector_t blknr = isofs_bmap(inode, block);
1052 if (!blknr)
1053 return NULL;
1054 return sb_bread(inode->i_sb, blknr);
1055}
1056
1057static int isofs_readpage(struct file *file, struct page *page)
1058{
1059 return block_read_full_page(page,isofs_get_block);
1060}
1061
1062static sector_t _isofs_bmap(struct address_space *mapping, sector_t block)
1063{
1064 return generic_block_bmap(mapping,block,isofs_get_block);
1065}
1066
1067static struct address_space_operations isofs_aops = {
1068 .readpage = isofs_readpage,
1069 .sync_page = block_sync_page,
1070 .bmap = _isofs_bmap
1071};
1072
1073static inline void test_and_set_uid(uid_t *p, uid_t value)
1074{
1075 if(value) {
1076 *p = value;
1077 }
1078}
1079
1080static inline void test_and_set_gid(gid_t *p, gid_t value)
1081{
1082 if(value) {
1083 *p = value;
1084 }
1085}
1086
1087static int isofs_read_level3_size(struct inode * inode)
1088{
1089 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1090 int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
1091 struct buffer_head * bh = NULL;
1092 unsigned long block, offset, block_saved, offset_saved;
1093 int i = 0;
1094 int more_entries = 0;
1095 struct iso_directory_record * tmpde = NULL;
1096 struct iso_inode_info *ei = ISOFS_I(inode);
1097
1098 inode->i_size = 0;
1099
1100 /* The first 16 blocks are reserved as the System Area. Thus,
1101 * no inodes can appear in block 0. We use this to flag that
1102 * this is the last section. */
1103 ei->i_next_section_block = 0;
1104 ei->i_next_section_offset = 0;
1105
1106 block = ei->i_iget5_block;
1107 offset = ei->i_iget5_offset;
1108
1109 do {
1110 struct iso_directory_record * de;
1111 unsigned int de_len;
1112
1113 if (!bh) {
1114 bh = sb_bread(inode->i_sb, block);
1115 if (!bh)
1116 goto out_noread;
1117 }
1118 de = (struct iso_directory_record *) (bh->b_data + offset);
1119 de_len = *(unsigned char *) de;
1120
1121 if (de_len == 0) {
1122 brelse(bh);
1123 bh = NULL;
1124 ++block;
1125 offset = 0;
1126 continue;
1127 }
1128
1129 block_saved = block;
1130 offset_saved = offset;
1131 offset += de_len;
1132
1133 /* Make sure we have a full directory entry */
1134 if (offset >= bufsize) {
1135 int slop = bufsize - offset + de_len;
1136 if (!tmpde) {
1137 tmpde = kmalloc(256, GFP_KERNEL);
1138 if (!tmpde)
1139 goto out_nomem;
1140 }
1141 memcpy(tmpde, de, slop);
1142 offset &= bufsize - 1;
1143 block++;
1144 brelse(bh);
1145 bh = NULL;
1146 if (offset) {
1147 bh = sb_bread(inode->i_sb, block);
1148 if (!bh)
1149 goto out_noread;
1150 memcpy((void *) tmpde + slop, bh->b_data, offset);
1151 }
1152 de = tmpde;
1153 }
1154
1155 inode->i_size += isonum_733(de->size);
1156 if (i == 1) {
1157 ei->i_next_section_block = block_saved;
1158 ei->i_next_section_offset = offset_saved;
1159 }
1160
1161 more_entries = de->flags[-high_sierra] & 0x80;
1162
1163 i++;
1164 if(i > 100)
1165 goto out_toomany;
1166 } while(more_entries);
1167out:
1168 if (tmpde)
1169 kfree(tmpde);
1170 if (bh)
1171 brelse(bh);
1172 return 0;
1173
1174out_nomem:
1175 if (bh)
1176 brelse(bh);
1177 return -ENOMEM;
1178
1179out_noread:
1180 printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);
1181 if (tmpde)
1182 kfree(tmpde);
1183 return -EIO;
1184
1185out_toomany:
1186 printk(KERN_INFO "isofs_read_level3_size: "
1187 "More than 100 file sections ?!?, aborting...\n"
1188 "isofs_read_level3_size: inode=%lu\n",
1189 inode->i_ino);
1190 goto out;
1191}
1192
1193static void isofs_read_inode(struct inode * inode)
1194{
1195 struct super_block *sb = inode->i_sb;
1196 struct isofs_sb_info *sbi = ISOFS_SB(sb);
1197 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1198 unsigned long block;
1199 int high_sierra = sbi->s_high_sierra;
1200 struct buffer_head * bh = NULL;
1201 struct iso_directory_record * de;
1202 struct iso_directory_record * tmpde = NULL;
1203 unsigned int de_len;
1204 unsigned long offset;
1205 struct iso_inode_info *ei = ISOFS_I(inode);
1206
1207 block = ei->i_iget5_block;
1208 bh = sb_bread(inode->i_sb, block);
1209 if (!bh)
1210 goto out_badread;
1211
1212 offset = ei->i_iget5_offset;
1213
1214 de = (struct iso_directory_record *) (bh->b_data + offset);
1215 de_len = *(unsigned char *) de;
1216
1217 if (offset + de_len > bufsize) {
1218 int frag1 = bufsize - offset;
1219
1220 tmpde = kmalloc(de_len, GFP_KERNEL);
1221 if (tmpde == NULL) {
1222 printk(KERN_INFO "isofs_read_inode: out of memory\n");
1223 goto fail;
1224 }
1225 memcpy(tmpde, bh->b_data + offset, frag1);
1226 brelse(bh);
1227 bh = sb_bread(inode->i_sb, ++block);
1228 if (!bh)
1229 goto out_badread;
1230 memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);
1231 de = tmpde;
1232 }
1233
1234 inode->i_ino = isofs_get_ino(ei->i_iget5_block,
1235 ei->i_iget5_offset,
1236 ISOFS_BUFFER_BITS(inode));
1237
1238 /* Assume it is a normal-format file unless told otherwise */
1239 ei->i_file_format = isofs_file_normal;
1240
1241 if (de->flags[-high_sierra] & 2) {
1242 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
1243 inode->i_nlink = 1; /* Set to 1. We know there are 2, but
1244 the find utility tries to optimize
1245 if it is 2, and it screws up. It is
1246 easier to give 1 which tells find to
1247 do it the hard way. */
1248 } else {
1249 /* Everybody gets to read the file. */
1250 inode->i_mode = sbi->s_mode;
1251 inode->i_nlink = 1;
1252 inode->i_mode |= S_IFREG;
1253 }
1254 inode->i_uid = sbi->s_uid;
1255 inode->i_gid = sbi->s_gid;
1256 inode->i_blocks = inode->i_blksize = 0;
1257
1258 ei->i_format_parm[0] = 0;
1259 ei->i_format_parm[1] = 0;
1260 ei->i_format_parm[2] = 0;
1261
1262 ei->i_section_size = isonum_733 (de->size);
1263 if(de->flags[-high_sierra] & 0x80) {
1264 if(isofs_read_level3_size(inode)) goto fail;
1265 } else {
1266 ei->i_next_section_block = 0;
1267 ei->i_next_section_offset = 0;
1268 inode->i_size = isonum_733 (de->size);
1269 }
1270
1271 /*
1272 * Some dipshit decided to store some other bit of information
1273 * in the high byte of the file length. Truncate size in case
1274 * this CDROM was mounted with the cruft option.
1275 */
1276
1277 if (sbi->s_cruft == 'y')
1278 inode->i_size &= 0x00ffffff;
1279
1280 if (de->interleave[0]) {
1281 printk("Interleaved files not (yet) supported.\n");
1282 inode->i_size = 0;
1283 }
1284
1285 /* I have no idea what file_unit_size is used for, so
1286 we will flag it for now */
1287 if (de->file_unit_size[0] != 0) {
1288 printk("File unit size != 0 for ISO file (%ld).\n",
1289 inode->i_ino);
1290 }
1291
1292 /* I have no idea what other flag bits are used for, so
1293 we will flag it for now */
1294#ifdef DEBUG
1295 if((de->flags[-high_sierra] & ~2)!= 0){
1296 printk("Unusual flag settings for ISO file (%ld %x).\n",
1297 inode->i_ino, de->flags[-high_sierra]);
1298 }
1299#endif
1300
1301 inode->i_mtime.tv_sec =
1302 inode->i_atime.tv_sec =
1303 inode->i_ctime.tv_sec = iso_date(de->date, high_sierra);
1304 inode->i_mtime.tv_nsec =
1305 inode->i_atime.tv_nsec =
1306 inode->i_ctime.tv_nsec = 0;
1307
1308 ei->i_first_extent = (isonum_733 (de->extent) +
1309 isonum_711 (de->ext_attr_length));
1310
1311 /* Set the number of blocks for stat() - should be done before RR */
1312 inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */
1313 inode->i_blocks = (inode->i_size + 511) >> 9;
1314
1315 /*
1316 * Now test for possible Rock Ridge extensions which will override
1317 * some of these numbers in the inode structure.
1318 */
1319
1320 if (!high_sierra) {
1321 parse_rock_ridge_inode(de, inode);
1322 /* if we want uid/gid set, override the rock ridge setting */
1323 test_and_set_uid(&inode->i_uid, sbi->s_uid);
1324 test_and_set_gid(&inode->i_gid, sbi->s_gid);
1325 }
1326
1327 /* Install the inode operations vector */
1328 if (S_ISREG(inode->i_mode)) {
1329 inode->i_fop = &generic_ro_fops;
1330 switch ( ei->i_file_format ) {
1331#ifdef CONFIG_ZISOFS
1332 case isofs_file_compressed:
1333 inode->i_data.a_ops = &zisofs_aops;
1334 break;
1335#endif
1336 default:
1337 inode->i_data.a_ops = &isofs_aops;
1338 break;
1339 }
1340 } else if (S_ISDIR(inode->i_mode)) {
1341 inode->i_op = &isofs_dir_inode_operations;
1342 inode->i_fop = &isofs_dir_operations;
1343 } else if (S_ISLNK(inode->i_mode)) {
1344 inode->i_op = &page_symlink_inode_operations;
1345 inode->i_data.a_ops = &isofs_symlink_aops;
1346 } else
1347 /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
1348 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1349
1350 out:
1351 if (tmpde)
1352 kfree(tmpde);
1353 if (bh)
1354 brelse(bh);
1355 return;
1356
1357 out_badread:
1358 printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
1359 fail:
1360 make_bad_inode(inode);
1361 goto out;
1362}
1363
1364struct isofs_iget5_callback_data {
1365 unsigned long block;
1366 unsigned long offset;
1367};
1368
1369static int isofs_iget5_test(struct inode *ino, void *data)
1370{
1371 struct iso_inode_info *i = ISOFS_I(ino);
1372 struct isofs_iget5_callback_data *d =
1373 (struct isofs_iget5_callback_data*)data;
1374 return (i->i_iget5_block == d->block)
1375 && (i->i_iget5_offset == d->offset);
1376}
1377
1378static int isofs_iget5_set(struct inode *ino, void *data)
1379{
1380 struct iso_inode_info *i = ISOFS_I(ino);
1381 struct isofs_iget5_callback_data *d =
1382 (struct isofs_iget5_callback_data*)data;
1383 i->i_iget5_block = d->block;
1384 i->i_iget5_offset = d->offset;
1385 return 0;
1386}
1387
1388/* Store, in the inode's containing structure, the block and block
1389 * offset that point to the underlying meta-data for the inode. The
1390 * code below is otherwise similar to the iget() code in
1391 * include/linux/fs.h */
1392struct inode *isofs_iget(struct super_block *sb,
1393 unsigned long block,
1394 unsigned long offset)
1395{
1396 unsigned long hashval;
1397 struct inode *inode;
1398 struct isofs_iget5_callback_data data;
1399
1400 if (offset >= 1ul << sb->s_blocksize_bits)
1401 return NULL;
1402
1403 data.block = block;
1404 data.offset = offset;
1405
1406 hashval = (block << sb->s_blocksize_bits) | offset;
1407
1408 inode = iget5_locked(sb,
1409 hashval,
1410 &isofs_iget5_test,
1411 &isofs_iget5_set,
1412 &data);
1413
1414 if (inode && (inode->i_state & I_NEW)) {
1415 sb->s_op->read_inode(inode);
1416 unlock_new_inode(inode);
1417 }
1418
1419 return inode;
1420}
1421
1422#ifdef LEAK_CHECK
1423#undef malloc
1424#undef free_s
1425#undef sb_bread
1426#undef brelse
1427
1428void * leak_check_malloc(unsigned int size){
1429 void * tmp;
1430 check_malloc++;
1431 tmp = kmalloc(size, GFP_KERNEL);
1432 return tmp;
1433}
1434
1435void leak_check_free_s(void * obj, int size){
1436 check_malloc--;
1437 return kfree(obj);
1438}
1439
1440struct buffer_head * leak_check_bread(struct super_block *sb, int block){
1441 check_bread++;
1442 return sb_bread(sb, block);
1443}
1444
1445void leak_check_brelse(struct buffer_head * bh){
1446 check_bread--;
1447 return brelse(bh);
1448}
1449
1450#endif
1451
1452static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
1453 int flags, const char *dev_name, void *data)
1454{
1455 return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
1456}
1457
1458static struct file_system_type iso9660_fs_type = {
1459 .owner = THIS_MODULE,
1460 .name = "iso9660",
1461 .get_sb = isofs_get_sb,
1462 .kill_sb = kill_block_super,
1463 .fs_flags = FS_REQUIRES_DEV,
1464};
1465
1466static int __init init_iso9660_fs(void)
1467{
1468 int err = init_inodecache();
1469 if (err)
1470 goto out;
1471#ifdef CONFIG_ZISOFS
1472 err = zisofs_init();
1473 if (err)
1474 goto out1;
1475#endif
1476 err = register_filesystem(&iso9660_fs_type);
1477 if (err)
1478 goto out2;
1479 return 0;
1480out2:
1481#ifdef CONFIG_ZISOFS
1482 zisofs_cleanup();
1483out1:
1484#endif
1485 destroy_inodecache();
1486out:
1487 return err;
1488}
1489
1490static void __exit exit_iso9660_fs(void)
1491{
1492 unregister_filesystem(&iso9660_fs_type);
1493#ifdef CONFIG_ZISOFS
1494 zisofs_cleanup();
1495#endif
1496 destroy_inodecache();
1497}
1498
1499module_init(init_iso9660_fs)
1500module_exit(exit_iso9660_fs)
1501MODULE_LICENSE("GPL");
1502/* Actual filesystem name is iso9660, as requested in filesystems.c */
1503MODULE_ALIAS("iso9660");
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
new file mode 100644
index 000000000000..86c50e22fc87
--- /dev/null
+++ b/fs/isofs/joliet.c
@@ -0,0 +1,103 @@
1/*
2 * linux/fs/isofs/joliet.c
3 *
4 * (C) 1996 Gordon Chaffee
5 *
6 * Joliet: Microsoft's Unicode extensions to iso9660
7 */
8
9#include <linux/string.h>
10#include <linux/nls.h>
11#include <linux/mm.h>
12#include <linux/iso_fs.h>
13#include <asm/unaligned.h>
14
15/*
16 * Convert Unicode 16 to UTF8 or ASCII.
17 */
18static int
19uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls)
20{
21 wchar_t *ip, ch;
22 unsigned char *op;
23
24 ip = uni;
25 op = ascii;
26
27 while ((ch = get_unaligned(ip)) && len) {
28 int llen;
29 ch = be16_to_cpu(ch);
30 if ((llen = nls->uni2char(ch, op, NLS_MAX_CHARSET_SIZE)) > 0)
31 op += llen;
32 else
33 *op++ = '?';
34 ip++;
35
36 len--;
37 }
38 *op = 0;
39 return (op - ascii);
40}
41
42/* Convert big endian wide character string to utf8 */
43static int
44wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen)
45{
46 const __u8 *ip;
47 __u8 *op;
48 int size;
49 __u16 c;
50
51 op = s;
52 ip = pwcs;
53 while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) {
54 c = (*ip << 8) | ip[1];
55 if (c > 0x7f) {
56 size = utf8_wctomb(op, c, maxlen);
57 if (size == -1) {
58 /* Ignore character and move on */
59 maxlen--;
60 } else {
61 op += size;
62 maxlen -= size;
63 }
64 } else {
65 *op++ = (__u8) c;
66 }
67 ip += 2;
68 inlen--;
69 }
70 return (op - s);
71}
72
73int
74get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode)
75{
76 unsigned char utf8;
77 struct nls_table *nls;
78 unsigned char len = 0;
79
80 utf8 = ISOFS_SB(inode->i_sb)->s_utf8;
81 nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
82
83 if (utf8) {
84 len = wcsntombs_be(outname, de->name,
85 de->name_len[0] >> 1, PAGE_SIZE);
86 } else {
87 len = uni16_to_x8(outname, (u16 *) de->name,
88 de->name_len[0] >> 1, nls);
89 }
90 if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) {
91 len -= 2;
92 }
93
94 /*
95 * Windows doesn't like periods at the end of a name,
96 * so neither do we
97 */
98 while (len >= 2 && (outname[len-1] == '.')) {
99 len--;
100 }
101
102 return len;
103}
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
new file mode 100644
index 000000000000..9569fc44102d
--- /dev/null
+++ b/fs/isofs/namei.c
@@ -0,0 +1,201 @@
1/*
2 * linux/fs/isofs/namei.c
3 *
4 * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
5 *
6 * (C) 1991 Linus Torvalds - minix filesystem
7 */
8
9#include <linux/time.h>
10#include <linux/iso_fs.h>
11#include <linux/kernel.h>
12#include <linux/string.h>
13#include <linux/stat.h>
14#include <linux/fcntl.h>
15#include <linux/mm.h>
16#include <linux/errno.h>
17#include <linux/config.h> /* Joliet? */
18#include <linux/smp_lock.h>
19#include <linux/buffer_head.h>
20#include <linux/dcache.h>
21
22#include <asm/uaccess.h>
23
24/*
25 * ok, we cannot use strncmp, as the name is not in our data space.
26 * Thus we'll have to use isofs_match. No big problem. Match also makes
27 * some sanity tests.
28 */
29static int
30isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
31{
32 struct qstr qstr;
33
34 if (!compare)
35 return 1;
36
37 /* check special "." and ".." files */
38 if (dlen == 1) {
39 /* "." */
40 if (compare[0] == 0) {
41 if (!dentry->d_name.len)
42 return 0;
43 compare = ".";
44 } else if (compare[0] == 1) {
45 compare = "..";
46 dlen = 2;
47 }
48 }
49
50 qstr.name = compare;
51 qstr.len = dlen;
52 return dentry->d_op->d_compare(dentry, &dentry->d_name, &qstr);
53}
54
55/*
56 * isofs_find_entry()
57 *
58 * finds an entry in the specified directory with the wanted name. It
59 * returns the inode number of the found entry, or 0 on error.
60 */
61static unsigned long
62isofs_find_entry(struct inode *dir, struct dentry *dentry,
63 unsigned long *block_rv, unsigned long* offset_rv,
64 char * tmpname, struct iso_directory_record * tmpde)
65{
66 unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
67 unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
68 unsigned long block, f_pos, offset, block_saved, offset_saved;
69 struct buffer_head * bh = NULL;
70 struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
71
72 if (!ISOFS_I(dir)->i_first_extent)
73 return 0;
74
75 f_pos = 0;
76 offset = 0;
77 block = 0;
78
79 while (f_pos < dir->i_size) {
80 struct iso_directory_record * de;
81 int de_len, match, i, dlen;
82 char *dpnt;
83
84 if (!bh) {
85 bh = isofs_bread(dir, block);
86 if (!bh)
87 return 0;
88 }
89
90 de = (struct iso_directory_record *) (bh->b_data + offset);
91
92 de_len = *(unsigned char *) de;
93 if (!de_len) {
94 brelse(bh);
95 bh = NULL;
96 f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
97 block = f_pos >> bufbits;
98 offset = 0;
99 continue;
100 }
101
102 block_saved = bh->b_blocknr;
103 offset_saved = offset;
104 offset += de_len;
105 f_pos += de_len;
106
107 /* Make sure we have a full directory entry */
108 if (offset >= bufsize) {
109 int slop = bufsize - offset + de_len;
110 memcpy(tmpde, de, slop);
111 offset &= bufsize - 1;
112 block++;
113 brelse(bh);
114 bh = NULL;
115 if (offset) {
116 bh = isofs_bread(dir, block);
117 if (!bh)
118 return 0;
119 memcpy((void *) tmpde + slop, bh->b_data, offset);
120 }
121 de = tmpde;
122 }
123
124 dlen = de->name_len[0];
125 dpnt = de->name;
126
127 if (sbi->s_rock &&
128 ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
129 dlen = i; /* possibly -1 */
130 dpnt = tmpname;
131#ifdef CONFIG_JOLIET
132 } else if (sbi->s_joliet_level) {
133 dlen = get_joliet_filename(de, tmpname, dir);
134 dpnt = tmpname;
135#endif
136 } else if (sbi->s_mapping == 'a') {
137 dlen = get_acorn_filename(de, tmpname, dir);
138 dpnt = tmpname;
139 } else if (sbi->s_mapping == 'n') {
140 dlen = isofs_name_translate(de, tmpname, dir);
141 dpnt = tmpname;
142 }
143
144 /*
145 * Skip hidden or associated files unless unhide is set
146 */
147 match = 0;
148 if (dlen > 0 &&
149 (!(de->flags[-sbi->s_high_sierra] & 5)
150 || sbi->s_unhide == 'y'))
151 {
152 match = (isofs_cmp(dentry,dpnt,dlen) == 0);
153 }
154 if (match) {
155 isofs_normalize_block_and_offset(de,
156 &block_saved,
157 &offset_saved);
158 *block_rv = block_saved;
159 *offset_rv = offset_saved;
160 if (bh) brelse(bh);
161 return 1;
162 }
163 }
164 if (bh) brelse(bh);
165 return 0;
166}
167
168struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
169{
170 int found;
171 unsigned long block, offset;
172 struct inode *inode;
173 struct page *page;
174
175 dentry->d_op = dir->i_sb->s_root->d_op;
176
177 page = alloc_page(GFP_USER);
178 if (!page)
179 return ERR_PTR(-ENOMEM);
180
181 lock_kernel();
182 found = isofs_find_entry(dir, dentry,
183 &block, &offset,
184 page_address(page),
185 1024 + page_address(page));
186 __free_page(page);
187
188 inode = NULL;
189 if (found) {
190 inode = isofs_iget(dir->i_sb, block, offset);
191 if (!inode) {
192 unlock_kernel();
193 return ERR_PTR(-EACCES);
194 }
195 }
196 unlock_kernel();
197 if (inode)
198 return d_splice_alias(inode, dentry);
199 d_add(dentry, inode);
200 return NULL;
201}
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
new file mode 100644
index 000000000000..8bdd3e409543
--- /dev/null
+++ b/fs/isofs/rock.c
@@ -0,0 +1,565 @@
1/*
2 * linux/fs/isofs/rock.c
3 *
4 * (C) 1992, 1993 Eric Youngdale
5 *
6 * Rock Ridge Extensions to iso9660
7 */
8
9#include <linux/stat.h>
10#include <linux/time.h>
11#include <linux/iso_fs.h>
12#include <linux/string.h>
13#include <linux/mm.h>
14#include <linux/slab.h>
15#include <linux/pagemap.h>
16#include <linux/smp_lock.h>
17#include <linux/buffer_head.h>
18#include <asm/page.h>
19
20#include "rock.h"
21
22/* These functions are designed to read the system areas of a directory record
23 * and extract relevant information. There are different functions provided
24 * depending upon what information we need at the time. One function fills
25 * out an inode structure, a second one extracts a filename, a third one
26 * returns a symbolic link name, and a fourth one returns the extent number
27 * for the file. */
28
29#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
30
31
32/* This is a way of ensuring that we have something in the system
33 use fields that is compatible with Rock Ridge */
34#define CHECK_SP(FAIL) \
35 if(rr->u.SP.magic[0] != 0xbe) FAIL; \
36 if(rr->u.SP.magic[1] != 0xef) FAIL; \
37 ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip;
38/* We define a series of macros because each function must do exactly the
39 same thing in certain places. We use the macros to ensure that everything
40 is done correctly */
41
42#define CONTINUE_DECLS \
43 int cont_extent = 0, cont_offset = 0, cont_size = 0; \
44 void *buffer = NULL
45
46#define CHECK_CE \
47 {cont_extent = isonum_733(rr->u.CE.extent); \
48 cont_offset = isonum_733(rr->u.CE.offset); \
49 cont_size = isonum_733(rr->u.CE.size);}
50
51#define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
52 {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
53 if(LEN & 1) LEN++; \
54 CHR = ((unsigned char *) DE) + LEN; \
55 LEN = *((unsigned char *) DE) - LEN; \
56 if (LEN<0) LEN=0; \
57 if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
58 { \
59 LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
60 CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset; \
61 if (LEN<0) LEN=0; \
62 } \
63}
64
65#define MAYBE_CONTINUE(LABEL,DEV) \
66 {if (buffer) { kfree(buffer); buffer = NULL; } \
67 if (cont_extent){ \
68 int block, offset, offset1; \
69 struct buffer_head * pbh; \
70 buffer = kmalloc(cont_size,GFP_KERNEL); \
71 if (!buffer) goto out; \
72 block = cont_extent; \
73 offset = cont_offset; \
74 offset1 = 0; \
75 pbh = sb_bread(DEV->i_sb, block); \
76 if(pbh){ \
77 if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \
78 brelse(pbh); \
79 goto out; \
80 } \
81 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
82 brelse(pbh); \
83 chr = (unsigned char *) buffer; \
84 len = cont_size; \
85 cont_extent = 0; \
86 cont_size = 0; \
87 cont_offset = 0; \
88 goto LABEL; \
89 } \
90 printk("Unable to read rock-ridge attributes\n"); \
91 }}
92
93/* return length of name field; 0: not found, -1: to be ignored */
94int get_rock_ridge_filename(struct iso_directory_record * de,
95 char * retname, struct inode * inode)
96{
97 int len;
98 unsigned char * chr;
99 CONTINUE_DECLS;
100 int retnamlen = 0, truncate=0;
101
102 if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
103 *retname = 0;
104
105 SETUP_ROCK_RIDGE(de, chr, len);
106 repeat:
107 {
108 struct rock_ridge * rr;
109 int sig;
110
111 while (len > 2){ /* There may be one byte for padding somewhere */
112 rr = (struct rock_ridge *) chr;
113 if (rr->len < 3) goto out; /* Something got screwed up here */
114 sig = isonum_721(chr);
115 chr += rr->len;
116 len -= rr->len;
117 if (len < 0) goto out; /* corrupted isofs */
118
119 switch(sig){
120 case SIG('R','R'):
121 if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
122 break;
123 case SIG('S','P'):
124 CHECK_SP(goto out);
125 break;
126 case SIG('C','E'):
127 CHECK_CE;
128 break;
129 case SIG('N','M'):
130 if (truncate) break;
131 if (rr->len < 5) break;
132 /*
133 * If the flags are 2 or 4, this indicates '.' or '..'.
134 * We don't want to do anything with this, because it
135 * screws up the code that calls us. We don't really
136 * care anyways, since we can just use the non-RR
137 * name.
138 */
139 if (rr->u.NM.flags & 6) {
140 break;
141 }
142
143 if (rr->u.NM.flags & ~1) {
144 printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
145 break;
146 }
147 if((strlen(retname) + rr->len - 5) >= 254) {
148 truncate = 1;
149 break;
150 }
151 strncat(retname, rr->u.NM.name, rr->len - 5);
152 retnamlen += rr->len - 5;
153 break;
154 case SIG('R','E'):
155 if (buffer) kfree(buffer);
156 return -1;
157 default:
158 break;
159 }
160 }
161 }
162 MAYBE_CONTINUE(repeat,inode);
163 if (buffer) kfree(buffer);
164 return retnamlen; /* If 0, this file did not have a NM field */
165 out:
166 if(buffer) kfree(buffer);
167 return 0;
168}
169
170static int
171parse_rock_ridge_inode_internal(struct iso_directory_record *de,
172 struct inode *inode, int regard_xa)
173{
174 int len;
175 unsigned char * chr;
176 int symlink_len = 0;
177 CONTINUE_DECLS;
178
179 if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
180
181 SETUP_ROCK_RIDGE(de, chr, len);
182 if (regard_xa)
183 {
184 chr+=14;
185 len-=14;
186 if (len<0) len=0;
187 }
188
189 repeat:
190 {
191 int cnt, sig;
192 struct inode * reloc;
193 struct rock_ridge * rr;
194 int rootflag;
195
196 while (len > 2){ /* There may be one byte for padding somewhere */
197 rr = (struct rock_ridge *) chr;
198 if (rr->len < 3) goto out; /* Something got screwed up here */
199 sig = isonum_721(chr);
200 chr += rr->len;
201 len -= rr->len;
202 if (len < 0) goto out; /* corrupted isofs */
203
204 switch(sig){
205#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
206 case SIG('R','R'):
207 if((rr->u.RR.flags[0] &
208 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
209 break;
210#endif
211 case SIG('S','P'):
212 CHECK_SP(goto out);
213 break;
214 case SIG('C','E'):
215 CHECK_CE;
216 break;
217 case SIG('E','R'):
218 ISOFS_SB(inode->i_sb)->s_rock = 1;
219 printk(KERN_DEBUG "ISO 9660 Extensions: ");
220 { int p;
221 for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
222 }
223 printk("\n");
224 break;
225 case SIG('P','X'):
226 inode->i_mode = isonum_733(rr->u.PX.mode);
227 inode->i_nlink = isonum_733(rr->u.PX.n_links);
228 inode->i_uid = isonum_733(rr->u.PX.uid);
229 inode->i_gid = isonum_733(rr->u.PX.gid);
230 break;
231 case SIG('P','N'):
232 { int high, low;
233 high = isonum_733(rr->u.PN.dev_high);
234 low = isonum_733(rr->u.PN.dev_low);
235 /*
236 * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
237 * then the high field is unused, and the device number is completely
238 * stored in the low field. Some writers may ignore this subtlety,
239 * and as a result we test to see if the entire device number is
240 * stored in the low field, and use that.
241 */
242 if((low & ~0xff) && high == 0) {
243 inode->i_rdev = MKDEV(low >> 8, low & 0xff);
244 } else {
245 inode->i_rdev = MKDEV(high, low);
246 }
247 }
248 break;
249 case SIG('T','F'):
250 /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
251 Try to handle this correctly for either case. */
252 cnt = 0; /* Rock ridge never appears on a High Sierra disk */
253 if(rr->u.TF.flags & TF_CREATE) {
254 inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
255 inode->i_ctime.tv_nsec = 0;
256 }
257 if(rr->u.TF.flags & TF_MODIFY) {
258 inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
259 inode->i_mtime.tv_nsec = 0;
260 }
261 if(rr->u.TF.flags & TF_ACCESS) {
262 inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
263 inode->i_atime.tv_nsec = 0;
264 }
265 if(rr->u.TF.flags & TF_ATTRIBUTES) {
266 inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
267 inode->i_ctime.tv_nsec = 0;
268 }
269 break;
270 case SIG('S','L'):
271 {int slen;
272 struct SL_component * slp;
273 struct SL_component * oldslp;
274 slen = rr->len - 5;
275 slp = &rr->u.SL.link;
276 inode->i_size = symlink_len;
277 while (slen > 1){
278 rootflag = 0;
279 switch(slp->flags &~1){
280 case 0:
281 inode->i_size += slp->len;
282 break;
283 case 2:
284 inode->i_size += 1;
285 break;
286 case 4:
287 inode->i_size += 2;
288 break;
289 case 8:
290 rootflag = 1;
291 inode->i_size += 1;
292 break;
293 default:
294 printk("Symlink component flag not implemented\n");
295 }
296 slen -= slp->len + 2;
297 oldslp = slp;
298 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
299
300 if(slen < 2) {
301 if( ((rr->u.SL.flags & 1) != 0)
302 && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
303 break;
304 }
305
306 /*
307 * If this component record isn't continued, then append a '/'.
308 */
309 if (!rootflag && (oldslp->flags & 1) == 0)
310 inode->i_size += 1;
311 }
312 }
313 symlink_len = inode->i_size;
314 break;
315 case SIG('R','E'):
316 printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
317 goto out;
318 case SIG('C','L'):
319 ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
320 reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0);
321 if (!reloc)
322 goto out;
323 inode->i_mode = reloc->i_mode;
324 inode->i_nlink = reloc->i_nlink;
325 inode->i_uid = reloc->i_uid;
326 inode->i_gid = reloc->i_gid;
327 inode->i_rdev = reloc->i_rdev;
328 inode->i_size = reloc->i_size;
329 inode->i_blocks = reloc->i_blocks;
330 inode->i_atime = reloc->i_atime;
331 inode->i_ctime = reloc->i_ctime;
332 inode->i_mtime = reloc->i_mtime;
333 iput(reloc);
334 break;
335#ifdef CONFIG_ZISOFS
336 case SIG('Z','F'):
337 if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) {
338 int algo;
339 algo = isonum_721(rr->u.ZF.algorithm);
340 if ( algo == SIG('p','z') ) {
341 int block_shift = isonum_711(&rr->u.ZF.parms[1]);
342 if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) {
343 printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
344 } else {
345 /* Note: we don't change i_blocks here */
346 ISOFS_I(inode)->i_file_format = isofs_file_compressed;
347 /* Parameters to compression algorithm (header size, block size) */
348 ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
349 ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
350 inode->i_size = isonum_733(rr->u.ZF.real_size);
351 }
352 } else {
353 printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n",
354 rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]);
355 }
356 }
357 break;
358#endif
359 default:
360 break;
361 }
362 }
363 }
364 MAYBE_CONTINUE(repeat,inode);
365 out:
366 if(buffer) kfree(buffer);
367 return 0;
368}
369
370static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
371{
372 int slen;
373 int rootflag;
374 struct SL_component *oldslp;
375 struct SL_component *slp;
376 slen = rr->len - 5;
377 slp = &rr->u.SL.link;
378 while (slen > 1) {
379 rootflag = 0;
380 switch (slp->flags & ~1) {
381 case 0:
382 if (slp->len > plimit - rpnt)
383 return NULL;
384 memcpy(rpnt, slp->text, slp->len);
385 rpnt+=slp->len;
386 break;
387 case 2:
388 if (rpnt >= plimit)
389 return NULL;
390 *rpnt++='.';
391 break;
392 case 4:
393 if (2 > plimit - rpnt)
394 return NULL;
395 *rpnt++='.';
396 *rpnt++='.';
397 break;
398 case 8:
399 if (rpnt >= plimit)
400 return NULL;
401 rootflag = 1;
402 *rpnt++='/';
403 break;
404 default:
405 printk("Symlink component flag not implemented (%d)\n",
406 slp->flags);
407 }
408 slen -= slp->len + 2;
409 oldslp = slp;
410 slp = (struct SL_component *) ((char *) slp + slp->len + 2);
411
412 if (slen < 2) {
413 /*
414 * If there is another SL record, and this component
415 * record isn't continued, then add a slash.
416 */
417 if ((!rootflag) && (rr->u.SL.flags & 1) &&
418 !(oldslp->flags & 1)) {
419 if (rpnt >= plimit)
420 return NULL;
421 *rpnt++='/';
422 }
423 break;
424 }
425
426 /*
427 * If this component record isn't continued, then append a '/'.
428 */
429 if (!rootflag && !(oldslp->flags & 1)) {
430 if (rpnt >= plimit)
431 return NULL;
432 *rpnt++='/';
433 }
434 }
435 return rpnt;
436}
437
438int parse_rock_ridge_inode(struct iso_directory_record * de,
439 struct inode * inode)
440{
441 int result=parse_rock_ridge_inode_internal(de,inode,0);
442 /* if rockridge flag was reset and we didn't look for attributes
443 * behind eventual XA attributes, have a look there */
444 if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
445 &&(ISOFS_SB(inode->i_sb)->s_rock==2))
446 {
447 result=parse_rock_ridge_inode_internal(de,inode,14);
448 }
449 return result;
450}
451
452/* readpage() for symlinks: reads symlink contents into the page and either
453 makes it uptodate and returns 0 or returns error (-EIO) */
454
455static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
456{
457 struct inode *inode = page->mapping->host;
458 struct iso_inode_info *ei = ISOFS_I(inode);
459 char *link = kmap(page);
460 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
461 struct buffer_head *bh;
462 char *rpnt = link;
463 unsigned char *pnt;
464 struct iso_directory_record *raw_inode;
465 CONTINUE_DECLS;
466 unsigned long block, offset;
467 int sig;
468 int len;
469 unsigned char *chr;
470 struct rock_ridge *rr;
471
472 if (!ISOFS_SB(inode->i_sb)->s_rock)
473 goto error;
474
475 block = ei->i_iget5_block;
476 lock_kernel();
477 bh = sb_bread(inode->i_sb, block);
478 if (!bh)
479 goto out_noread;
480
481 offset = ei->i_iget5_offset;
482 pnt = (unsigned char *) bh->b_data + offset;
483
484 raw_inode = (struct iso_directory_record *) pnt;
485
486 /*
487 * If we go past the end of the buffer, there is some sort of error.
488 */
489 if (offset + *pnt > bufsize)
490 goto out_bad_span;
491
492 /* Now test for possible Rock Ridge extensions which will override
493 some of these numbers in the inode structure. */
494
495 SETUP_ROCK_RIDGE(raw_inode, chr, len);
496
497 repeat:
498 while (len > 2) { /* There may be one byte for padding somewhere */
499 rr = (struct rock_ridge *) chr;
500 if (rr->len < 3)
501 goto out; /* Something got screwed up here */
502 sig = isonum_721(chr);
503 chr += rr->len;
504 len -= rr->len;
505 if (len < 0)
506 goto out; /* corrupted isofs */
507
508 switch (sig) {
509 case SIG('R', 'R'):
510 if ((rr->u.RR.flags[0] & RR_SL) == 0)
511 goto out;
512 break;
513 case SIG('S', 'P'):
514 CHECK_SP(goto out);
515 break;
516 case SIG('S', 'L'):
517 rpnt = get_symlink_chunk(rpnt, rr,
518 link + (PAGE_SIZE - 1));
519 if (rpnt == NULL)
520 goto out;
521 break;
522 case SIG('C', 'E'):
523 /* This tells is if there is a continuation record */
524 CHECK_CE;
525 default:
526 break;
527 }
528 }
529 MAYBE_CONTINUE(repeat, inode);
530 if (buffer)
531 kfree(buffer);
532
533 if (rpnt == link)
534 goto fail;
535 brelse(bh);
536 *rpnt = '\0';
537 unlock_kernel();
538 SetPageUptodate(page);
539 kunmap(page);
540 unlock_page(page);
541 return 0;
542
543 /* error exit from macro */
544 out:
545 if (buffer)
546 kfree(buffer);
547 goto fail;
548 out_noread:
549 printk("unable to read i-node block");
550 goto fail;
551 out_bad_span:
552 printk("symlink spans iso9660 blocks\n");
553 fail:
554 brelse(bh);
555 unlock_kernel();
556 error:
557 SetPageError(page);
558 kunmap(page);
559 unlock_page(page);
560 return -EIO;
561}
562
563struct address_space_operations isofs_symlink_aops = {
564 .readpage = rock_ridge_symlink_readpage
565};
diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h
new file mode 100644
index 000000000000..deaf5c8e8b4a
--- /dev/null
+++ b/fs/isofs/rock.h
@@ -0,0 +1,119 @@
1/* These structs are used by the system-use-sharing protocol, in which the
2 Rock Ridge extensions are embedded. It is quite possible that other
3 extensions are present on the disk, and this is fine as long as they
4 all use SUSP */
5
6struct SU_SP{
7 unsigned char magic[2];
8 unsigned char skip;
9} __attribute__((packed));
10
11struct SU_CE{
12 char extent[8];
13 char offset[8];
14 char size[8];
15};
16
17struct SU_ER{
18 unsigned char len_id;
19 unsigned char len_des;
20 unsigned char len_src;
21 unsigned char ext_ver;
22 char data[0];
23} __attribute__((packed));
24
25struct RR_RR{
26 char flags[1];
27} __attribute__((packed));
28
29struct RR_PX{
30 char mode[8];
31 char n_links[8];
32 char uid[8];
33 char gid[8];
34};
35
36struct RR_PN{
37 char dev_high[8];
38 char dev_low[8];
39};
40
41
42struct SL_component{
43 unsigned char flags;
44 unsigned char len;
45 char text[0];
46} __attribute__((packed));
47
48struct RR_SL{
49 unsigned char flags;
50 struct SL_component link;
51} __attribute__((packed));
52
53struct RR_NM{
54 unsigned char flags;
55 char name[0];
56} __attribute__((packed));
57
58struct RR_CL{
59 char location[8];
60};
61
62struct RR_PL{
63 char location[8];
64};
65
66struct stamp{
67 char time[7];
68} __attribute__((packed));
69
70struct RR_TF{
71 char flags;
72 struct stamp times[0]; /* Variable number of these beasts */
73} __attribute__((packed));
74
75/* Linux-specific extension for transparent decompression */
76struct RR_ZF{
77 char algorithm[2];
78 char parms[2];
79 char real_size[8];
80};
81
82/* These are the bits and their meanings for flags in the TF structure. */
83#define TF_CREATE 1
84#define TF_MODIFY 2
85#define TF_ACCESS 4
86#define TF_ATTRIBUTES 8
87#define TF_BACKUP 16
88#define TF_EXPIRATION 32
89#define TF_EFFECTIVE 64
90#define TF_LONG_FORM 128
91
92struct rock_ridge{
93 char signature[2];
94 unsigned char len;
95 unsigned char version;
96 union{
97 struct SU_SP SP;
98 struct SU_CE CE;
99 struct SU_ER ER;
100 struct RR_RR RR;
101 struct RR_PX PX;
102 struct RR_PN PN;
103 struct RR_SL SL;
104 struct RR_NM NM;
105 struct RR_CL CL;
106 struct RR_PL PL;
107 struct RR_TF TF;
108 struct RR_ZF ZF;
109 } u;
110};
111
112#define RR_PX 1 /* POSIX attributes */
113#define RR_PN 2 /* POSIX devices */
114#define RR_SL 4 /* Symbolic link */
115#define RR_NM 8 /* Alternate Name */
116#define RR_CL 16 /* Child link */
117#define RR_PL 32 /* Parent link */
118#define RR_RE 64 /* Relocation directory */
119#define RR_TF 128 /* Timestamps */
diff --git a/fs/isofs/util.c b/fs/isofs/util.c
new file mode 100644
index 000000000000..3f6d9c1ac95a
--- /dev/null
+++ b/fs/isofs/util.c
@@ -0,0 +1,83 @@
1/*
2 * linux/fs/isofs/util.c
3 */
4
5#include <linux/time.h>
6#include <linux/fs.h>
7#include <linux/iso_fs.h>
8
9/*
10 * We have to convert from a MM/DD/YY format to the Unix ctime format.
11 * We have to take into account leap years and all of that good stuff.
12 * Unfortunately, the kernel does not have the information on hand to
13 * take into account daylight savings time, but it shouldn't matter.
14 * The time stored should be localtime (with or without DST in effect),
15 * and the timezone offset should hold the offset required to get back
16 * to GMT. Thus we should always be correct.
17 */
18
19int iso_date(char * p, int flag)
20{
21 int year, month, day, hour, minute, second, tz;
22 int crtime, days, i;
23
24 year = p[0] - 70;
25 month = p[1];
26 day = p[2];
27 hour = p[3];
28 minute = p[4];
29 second = p[5];
30 if (flag == 0) tz = p[6]; /* High sierra has no time zone */
31 else tz = 0;
32
33 if (year < 0) {
34 crtime = 0;
35 } else {
36 int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
37
38 days = year * 365;
39 if (year > 2)
40 days += (year+1) / 4;
41 for (i = 1; i < month; i++)
42 days += monlen[i-1];
43 if (((year+2) % 4) == 0 && month > 2)
44 days++;
45 days += day - 1;
46 crtime = ((((days * 24) + hour) * 60 + minute) * 60)
47 + second;
48
49 /* sign extend */
50 if (tz & 0x80)
51 tz |= (-1 << 8);
52
53 /*
54 * The timezone offset is unreliable on some disks,
55 * so we make a sanity check. In no case is it ever
56 * more than 13 hours from GMT, which is 52*15min.
57 * The time is always stored in localtime with the
58 * timezone offset being what get added to GMT to
59 * get to localtime. Thus we need to subtract the offset
60 * to get to true GMT, which is what we store the time
61 * as internally. On the local system, the user may set
62 * their timezone any way they wish, of course, so GMT
63 * gets converted back to localtime on the receiving
64 * system.
65 *
66 * NOTE: mkisofs in versions prior to mkisofs-1.10 had
67 * the sign wrong on the timezone offset. This has now
68 * been corrected there too, but if you are getting screwy
69 * results this may be the explanation. If enough people
70 * complain, a user configuration option could be added
71 * to add the timezone offset in with the wrong sign
72 * for 'compatibility' with older discs, but I cannot see how
73 * it will matter that much.
74 *
75 * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
76 * for pointing out the sign error.
77 */
78 if (-52 <= tz && tz <= 52)
79 crtime -= tz * 15 * 60;
80 }
81 return crtime;
82}
83
diff --git a/fs/isofs/zisofs.h b/fs/isofs/zisofs.h
new file mode 100644
index 000000000000..d78485d101c2
--- /dev/null
+++ b/fs/isofs/zisofs.h
@@ -0,0 +1,21 @@
1/* ----------------------------------------------------------------------- *
2 *
3 * Copyright 2001 H. Peter Anvin - All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
8 * USA; either version 2 of the License, or (at your option) any later
9 * version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13/*
14 * Prototypes for functions exported from the compressed isofs subsystem
15 */
16
17#ifdef CONFIG_ZISOFS
18extern struct address_space_operations zisofs_aops;
19extern int __init zisofs_init(void);
20extern void zisofs_cleanup(void);
21#endif