diff options
Diffstat (limited to 'fs/isofs')
-rw-r--r-- | fs/isofs/Makefile | 5 | ||||
-rw-r--r-- | fs/isofs/dir.c | 87 | ||||
-rw-r--r-- | fs/isofs/inode.c | 199 | ||||
-rw-r--r-- | fs/isofs/joliet.c | 110 | ||||
-rw-r--r-- | fs/isofs/namei.c | 88 | ||||
-rw-r--r-- | fs/isofs/rock.c | 26 | ||||
-rw-r--r-- | fs/isofs/symlink.c | 2 | ||||
-rw-r--r-- | fs/isofs/util.c | 8 |
8 files changed, 382 insertions, 143 deletions
diff --git a/fs/isofs/Makefile b/fs/isofs/Makefile index 8dd4cc9ec..10a4404f8 100644 --- a/fs/isofs/Makefile +++ b/fs/isofs/Makefile @@ -9,6 +9,11 @@ O_TARGET := isofs.o O_OBJS := namei.o inode.o file.o dir.o util.o rock.o symlink.o + +ifdef CONFIG_JOLIET +O_OBJS += joliet.o +endif + M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index a198141d8..67ff77bd9 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -20,6 +20,7 @@ #include <linux/malloc.h> #include <linux/sched.h> #include <linux/locks.h> +#include <linux/config.h> #include <asm/uaccess.h> @@ -102,15 +103,14 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, unsigned int block, offset; int inode_number; struct buffer_head *bh; - int len, rrflag; + int len; + int map; int high_sierra = 0; - char *name; + char *p = NULL; /* Quiet GCC */ struct iso_directory_record *de; - if( filp->f_pos >= inode->i_size ) { - return 0; - - } + if (filp->f_pos >= inode->i_size) + return 0; offset = filp->f_pos & (bufsize - 1); block = isofs_bmap(inode, filp->f_pos >> bufbits); @@ -141,15 +141,19 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, CDROM sector. If we are at the end of the directory, we kick out of the while loop. */ - if ((de_len == 0) || (offset == bufsize) ) { + if ((de_len == 0) || (offset >= bufsize) ) { brelse(bh); - filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); - offset = 0; - if( filp->f_pos >= inode->i_size ) - { - return 0; - } + if (de_len == 0) { + filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1)) + + ISOFS_BLOCK_SIZE); + offset = 0; + } else { + offset -= bufsize; + filp->f_pos += offset; + } + + if (filp->f_pos >= inode->i_size) + return 0; block = isofs_bmap(inode, (filp->f_pos) >> bufbits); if (!block) @@ -181,6 +185,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, continue; } + len = 0; + /* Handle the case of the '..' directory */ if (de->name_len[0] == 1 && de->name[0] == 1) { inode_number = filp->f_dentry->d_parent->d_inode->i_ino; @@ -192,7 +198,6 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, /* Handle everything else. Do name translation if there is no Rock Ridge NM field. */ - if (inode->i_sb->u.isofs_sb.s_unhide == 'n') { /* Do not report hidden or associated files */ high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; @@ -202,34 +207,38 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, } } - /* Check Rock Ridge name translation.. */ - len = de->name_len[0]; - name = de->name; - rrflag = get_rock_ridge_filename(de, &name, &len, inode); - if (rrflag) { - /* rrflag == 1 means that we have a new name (kmalloced) */ - if (rrflag == 1) { - rrflag = filldir(dirent, name, len, filp->f_pos, inode_number); - kfree(name); /* this was allocated in get_r_r_filename.. */ - if (rrflag < 0) - break; +#ifdef CONFIG_JOLIET + if (inode->i_sb->u.isofs_sb.s_joliet_level) { + len = get_joliet_filename(de, inode, tmpname); + p = tmpname; + } else +#endif + /* if not joliet */ { + map = 1; + if (inode->i_sb->u.isofs_sb.s_rock) { + len = get_rock_ridge_filename(de, tmpname, inode); + if (len != 0) { + p = tmpname; + map = 0; + } + } + if (map) { + if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { + len = isofs_name_translate(de->name, de->name_len[0], + tmpname); + p = tmpname; + } else { + p = de->name; + len = de->name_len[0]; + } } - filp->f_pos += de_len; - continue; } - - if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { - len = isofs_name_translate(name, len, tmpname); - if (filldir(dirent, tmpname, len, filp->f_pos, inode_number) < 0) + if (len > 0) { + if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0) break; - filp->f_pos += de_len; - continue; } - - if (filldir(dirent, name, len, filp->f_pos, inode_number) < 0) - break; - filp->f_pos += de_len; + continue; } brelse(bh); @@ -255,7 +264,7 @@ static int isofs_readdir(struct file *filp, tmpname = (char *) __get_free_page(GFP_KERNEL); if (!tmpname) return -ENOMEM; - tmpde = (struct iso_directory_record *) (tmpname+256); + tmpde = (struct iso_directory_record *) (tmpname+1024); result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde); diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index a925159bf..b77e9facd 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -23,6 +23,7 @@ #include <linux/errno.h> #include <linux/cdrom.h> #include <linux/init.h> +#include <linux/nls.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -40,6 +41,12 @@ static int check_bread = 0; void isofs_put_super(struct super_block *sb) { +#ifdef CONFIG_JOLIET + if (sb->u.isofs_sb.s_nls_iocharset) { + unload_nls(sb->u.isofs_sb.s_nls_iocharset); + sb->u.isofs_sb.s_nls_iocharset = NULL; + } +#endif lock_super(sb); #ifdef LEAK_CHECK @@ -67,6 +74,7 @@ static struct super_operations isofs_sops = { struct iso9660_options{ char map; char rock; + char joliet; char cruft; char unhide; unsigned char check; @@ -75,6 +83,8 @@ struct iso9660_options{ mode_t mode; gid_t gid; uid_t uid; + char *iocharset; + unsigned char utf8; }; static int parse_options(char *options, struct iso9660_options * popt) @@ -83,6 +93,7 @@ static int parse_options(char *options, struct iso9660_options * popt) popt->map = 'n'; popt->rock = 'y'; + popt->joliet = 'y'; popt->cruft = 'n'; popt->unhide = 'n'; popt->check = 's'; /* default: strict */ @@ -94,12 +105,18 @@ static int parse_options(char *options, struct iso9660_options * popt) a valid executable. */ popt->gid = 0; popt->uid = 0; + popt->iocharset = NULL; + popt->utf8 = 0; if (!options) return 1; for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { if (strncmp(this_char,"norock",6) == 0) { popt->rock = 'n'; continue; } + if (strncmp(this_char,"nojoliet",8) == 0) { + popt->joliet = 'n'; + continue; + } if (strncmp(this_char,"unhide",6) == 0) { popt->unhide = 'y'; continue; @@ -108,8 +125,31 @@ static int parse_options(char *options, struct iso9660_options * popt) popt->cruft = 'y'; continue; } + if (strncmp(this_char,"utf8",4) == 0) { + popt->utf8 = 1; + continue; + } if ((value = strchr(this_char,'=')) != NULL) *value++ = 0; + +#ifdef CONFIG_JOLIET + if (!strcmp(this_char,"iocharset")) { + char *p; + int len; + + p = value; + while (*value && *value != ',') value++; + len = value - p; + if (len) { + popt->iocharset = kmalloc(len+1, GFP_KERNEL); + memcpy(popt->iocharset, p, len); + popt->iocharset[len] = 0; + } else { + popt->iocharset = NULL; + return 0; + } + } else +#endif if (!strcmp(this_char,"map") && value) { if (value[0] && !value[1] && strchr("on",*value)) popt->map = *value; @@ -234,10 +274,12 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, struct hs_primary_descriptor * h_pri = NULL; int high_sierra; int iso_blknum; + int joliet_level = 0; struct iso9660_options opt; int orig_zonesize; struct iso_primary_descriptor * pri = NULL; struct iso_directory_record * rootp; + struct iso_supplementary_descriptor *sec = NULL; struct iso_volume_descriptor * vdp; unsigned int vol_desc_start; @@ -254,6 +296,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, #if 0 printk("map = %c\n", opt.map); printk("rock = %c\n", opt.rock); + printk("joliet = %c\n", opt.joliet); printk("check = %c\n", opt.check); printk("cruft = %c\n", opt.cruft); printk("unhide = %c\n", opt.unhide); @@ -297,57 +340,93 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, vol_desc_start = isofs_get_last_session(dev); - for (iso_blknum = vol_desc_start+16; - iso_blknum < vol_desc_start+100; iso_blknum++) { - int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits); - - if (!(bh = bread(dev,b,opt.blocksize))) { - s->s_dev = 0; - printk("isofs_read_super: bread failed, dev " - "%s iso_blknum %d block %d\n", - kdevname(dev), iso_blknum, b); - unlock_super(s); - MOD_DEC_USE_COUNT; - return NULL; - } - - vdp = (struct iso_volume_descriptor *)bh->b_data; - hdp = (struct hs_volume_descriptor *)bh->b_data; + for (iso_blknum = vol_desc_start+16; + iso_blknum < vol_desc_start+100; iso_blknum++) + { + int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits); + if (!(bh = bread(dev,b,opt.blocksize))) { + s->s_dev = 0; + printk("isofs_read_super: bread failed, dev " + "%s iso_blknum %d block %d\n", + kdevname(dev), iso_blknum, b); + unlock_super(s); + MOD_DEC_USE_COUNT; + return NULL; + } - if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) { - if (isonum_711 (hdp->type) != ISO_VD_PRIMARY) - goto out; - if (isonum_711 (hdp->type) == ISO_VD_END) - goto out; + vdp = (struct iso_volume_descriptor *)bh->b_data; + hdp = (struct hs_volume_descriptor *)bh->b_data; + + if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) { + if (isonum_711 (hdp->type) != ISO_VD_PRIMARY) + goto out; + if (isonum_711 (hdp->type) == ISO_VD_END) + goto out; + + s->u.isofs_sb.s_high_sierra = 1; + high_sierra = 1; + opt.rock = 'n'; + h_pri = (struct hs_primary_descriptor *)vdp; + break; + } - s->u.isofs_sb.s_high_sierra = 1; - high_sierra = 1; - opt.rock = 'n'; - h_pri = (struct hs_primary_descriptor *)vdp; + if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) { + if (isonum_711 (vdp->type) == ISO_VD_END) + break; + if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) { + if (pri == NULL) { + pri = (struct iso_primary_descriptor *)vdp; + } +#ifdef CONFIG_JOLIET + } else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) { + sec = (struct iso_supplementary_descriptor *)vdp; + if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) { + if (opt.joliet == 'y') { + opt.rock = 'n'; + if (sec->escape[2] == 0x40) { + joliet_level = 1; + } else if (sec->escape[2] == 0x43) { + joliet_level = 2; + } else if (sec->escape[2] == 0x45) { + joliet_level = 3; + } + printk("ISO9660 Extensions: Microsoft Joliet Level %d\n", + joliet_level); + } break; + } else { + /* Unknown supplementary volume descriptor */ + sec = NULL; + } +#endif } + /* Just skip any volume descriptors we don't recognize */ + } - if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) { - if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) - goto out; - if (isonum_711 (vdp->type) == ISO_VD_END) - goto out; + brelse(bh); + } + if ((pri == NULL) && (sec == NULL) && (h_pri == NULL)) { + if (!silent) + printk("Unable to identify CD-ROM format.\n"); + s->s_dev = 0; + unlock_super(s); + MOD_DEC_USE_COUNT; + return NULL; + } - pri = (struct iso_primary_descriptor *)vdp; - break; - } + s->u.isofs_sb.s_joliet_level = joliet_level; - brelse(bh); - } - if(iso_blknum == vol_desc_start + 100) { - if (!silent) - printk("Unable to identify CD-ROM format.\n"); - s->s_dev = 0; - unlock_super(s); - MOD_DEC_USE_COUNT; - return NULL; +#ifdef CONFIG_JOLIET + if (joliet_level) { + /* Note: In theory, it is possible to have Rock Ridge + * extensions mixed with Joliet. All character strings + * would just be saved as Unicode. Until someone sees such + * a disc, do not allow the two to be mixed + */ + pri = (struct iso_primary_descriptor *) sec; } +#endif if(high_sierra){ rootp = (struct iso_directory_record *) h_pri->root_directory_record; @@ -465,6 +544,28 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize); } +#ifdef CONFIG_JOLIET + s->u.isofs_sb.s_nls_iocharset = NULL; + if (joliet_level == 0) { + if (opt.iocharset) { + kfree(opt.iocharset); + opt.iocharset = NULL; + } + } else if (opt.utf8 == 0) { + char * p; + p = opt.iocharset ? opt.iocharset : "iso8859-1"; + s->u.isofs_sb.s_nls_iocharset = load_nls(p); + if (! s->u.isofs_sb.s_nls_iocharset) { + /* Fail only if explicit charset specified */ + if (opt.iocharset) { + kfree(opt.iocharset); + goto out; + } else { + s->u.isofs_sb.s_nls_iocharset = load_nls_default(); + } + } + } +#endif s->s_dev = dev; s->s_op = &isofs_sops; s->u.isofs_sb.s_mapping = opt.map; @@ -475,6 +576,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, s->u.isofs_sb.s_unhide = opt.unhide; s->u.isofs_sb.s_uid = opt.uid; s->u.isofs_sb.s_gid = opt.gid; + s->u.isofs_sb.s_utf8 = opt.utf8; /* * It would be incredibly stupid to allow people to mark every file on the disk * as suid, so we merely allow them to set the default permissions. @@ -490,13 +592,24 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, if (!(s->s_root)) { s->s_dev = 0; printk("get root inode failed\n"); +#ifdef CONFIG_JOLIET + if (s->u.isofs_sb.s_nls_iocharset) + unload_nls(s->u.isofs_sb.s_nls_iocharset); + if (opt.iocharset) kfree(opt.iocharset); +#endif MOD_DEC_USE_COUNT; return NULL; } if(!check_disk_change(s->s_dev)) { - return s; + return s; } +#ifdef CONFIG_JOLIET + if (s->u.isofs_sb.s_nls_iocharset) + unload_nls(s->u.isofs_sb.s_nls_iocharset); +#endif + if (opt.iocharset) kfree(opt.iocharset); + out: /* Kick out for various error conditions */ brelse(bh); s->s_dev = 0; diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c new file mode 100644 index 000000000..c34bfef76 --- /dev/null +++ b/fs/isofs/joliet.c @@ -0,0 +1,110 @@ +/* + * linux/fs/isofs/joliet.c + * + * (C) 1996 Gordon Chaffee + * + * Joliet: Microsoft's Unicode extensions to iso9660 + */ + +#include <linux/string.h> +#include <linux/nls.h> +#include <linux/malloc.h> +#include <linux/iso_fs.h> + +/* + * Convert Unicode 16 to UTF8 or ascii. + */ +static int +uni16_to_x8(unsigned char *ascii, unsigned char *uni, int len, + struct nls_table *nls) +{ + unsigned char *ip, *op; + unsigned char ch, cl; + unsigned char *uni_page; + + ip = uni; + op = ascii; + + while ((*ip || ip[1]) && len) { + ch = *ip++; + cl = *ip++; + + uni_page = nls->page_uni2charset[ch]; + if (uni_page && uni_page[cl]) { + *op++ = uni_page[cl]; + } else { + *op++ = '?'; + } + len--; + } + *op = 0; + return (op - ascii); +} + +/* Convert big endian wide character string to utf8 */ +static int +wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) +{ + const __u8 *ip; + __u8 *op; + int size; + __u16 c; + + op = s; + ip = pwcs; + while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) { + c = (*ip << 8) | ip[1]; + if (c > 0x7f) { + size = utf8_wctomb(op, c, maxlen); + if (size == -1) { + /* Ignore character and move on */ + maxlen--; + } else { + op += size; + maxlen -= size; + } + } else { + *op++ = (__u8) c; + } + ip += 2; + inlen--; + } + return (op - s); +} + +int +get_joliet_filename(struct iso_directory_record * de, struct inode * inode, + unsigned char *outname) +{ + unsigned char utf8; + struct nls_table *nls; + unsigned char len = 0; + int i; + char c; + + utf8 = inode->i_sb->u.isofs_sb.s_utf8; + nls = inode->i_sb->u.isofs_sb.s_nls_iocharset; + + if (utf8) { + len = wcsntombs_be(outname, de->name, + de->name_len[0] >> 1, PAGE_SIZE); + } else { + len = uni16_to_x8(outname, de->name, + de->name_len[0] >> 1, nls); + } + if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) { + len -= 2; + } + + if (inode->i_sb->u.isofs_sb.s_name_check == 'r') { + for (i = 0; i < len; i++) { + c = outname[i]; + /* lower case */ + if (c >= 'A' && c <= 'Z') c |= 0x20; + if (c == ';') c = '.'; + outname[i] = c; + } + } + + return len; +} diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 99555835b..1bedcf9be 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -12,10 +12,11 @@ #include <linux/string.h> #include <linux/stat.h> #include <linux/fcntl.h> -#include <asm/uaccess.h> #include <linux/malloc.h> - #include <linux/errno.h> +#include <linux/config.h> /* Joliet? */ + +#include <asm/uaccess.h> /* * ok, we cannot use strncmp, as the name is not in our data space. @@ -67,8 +68,9 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, inode_number = 0; /* shut gcc up */ struct buffer_head * bh; unsigned int old_offset; - int dlen, rrflag, match; + int dlen, match; char * dpnt; + unsigned char *page = NULL; struct iso_directory_record * de = NULL; /* shut gcc up */ char de_not_in_buf = 0; /* true if de is in kmalloc'd memory */ char c; @@ -92,9 +94,8 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, if(!de_not_in_buf) { de = (struct iso_directory_record *) (bh->b_data + offset); - inode_number = (block << bufbits) - + (offset & (bufsize - 1)); } + inode_number = (block << bufbits) + (offset & (bufsize - 1)); /* If byte is zero, or we had to fetch this de past the end of the buffer, this is the end of file, or @@ -109,22 +110,22 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, one */ de_not_in_buf = 0; kfree(de); - offset -= bufsize; + f_pos += offset; } - else + else { offset = 0; + f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1)) + + ISOFS_BLOCK_SIZE); + } brelse(bh); - f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE) + offset; - if( f_pos >= dir->i_size ) - { - return 0; - } + if (f_pos >= dir->i_size) + return 0; block = isofs_bmap(dir,f_pos>>bufbits); if (!block || !(bh = bread(dir->i_dev,block,bufsize))) - return 0; + return NULL; + continue; /* Will kick out if past end of directory */ } @@ -154,31 +155,44 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, bh_next->b_data, offset - bufsize); brelse(bh_next); de_not_in_buf = 1; + offset -= bufsize; } - dlen = de->name_len[0]; dpnt = de->name; - /* Now convert the filename in the buffer to lower case */ - rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, dir); - if (rrflag) { - if (rrflag == -1) goto out; /* Relocated deep directory */ - } else { - if(dir->i_sb->u.isofs_sb.s_mapping == 'n') { - for (i = 0; i < dlen; i++) { - c = dpnt[i]; - if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */ - if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') { - dlen -= 2; - break; - } - if (c == ';') c = '.'; - de->name[i] = c; - } - /* This allows us to match with and without a trailing - period. */ - if(dpnt[dlen-1] == '.' && namelen == dlen-1) - dlen--; - } + + if (dir->i_sb->u.isofs_sb.s_rock || + dir->i_sb->u.isofs_sb.s_joliet_level) { + page = (unsigned char *) + __get_free_page(GFP_KERNEL); + if (!page) return NULL; + } + if (dir->i_sb->u.isofs_sb.s_rock && + ((i = get_rock_ridge_filename(de, page, dir)))) { + if (i == -1) + goto out;/* Relocated deep directory */ + dlen = i; + dpnt = page; +#ifdef CONFIG_JOLIET + } else if (dir->i_sb->u.isofs_sb.s_joliet_level) { + dlen = get_joliet_filename(de, dir, page); + dpnt = page; +#endif + } else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') { + for (i = 0; i < dlen; i++) { + c = dpnt[i]; + /* lower case */ + if (c >= 'A' && c <= 'Z') c |= 0x20; + if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') { + dlen -= 2; + break; + } + if (c == ';') c = '.'; + dpnt[i] = c; + } + /* This allows us to match with and without + * a trailing period. */ + if(dpnt[dlen-1] == '.' && namelen == dlen-1) + dlen--; } /* * Skip hidden or associated files unless unhide is set @@ -190,7 +204,7 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, match = isofs_match(namelen,name,dpnt,dlen); } - if(rrflag) kfree(dpnt); + if (page) free_page((unsigned long) page); if (match) { if(inode_number == -1) { /* Should only happen for the '..' entry */ diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index a9bb95f52..e006ac3ee 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -153,15 +153,16 @@ int find_rock_ridge_relocation(struct iso_directory_record * de, } int get_rock_ridge_filename(struct iso_directory_record * de, - char ** name, int * namlen, struct inode * inode) + char * retname, struct inode * inode) { int len; unsigned char * chr; CONTINUE_DECLS; - char * retname = NULL; int retnamlen = 0, truncate=0; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; + *retname = 0; + retnamlen = 0; SETUP_ROCK_RIDGE(de, chr, len); repeat: @@ -203,18 +204,6 @@ int get_rock_ridge_filename(struct iso_directory_record * de, printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags); break; }; - if (!retname){ - retname = (char *) kmalloc (255,GFP_KERNEL); - /* This may be a waste, but we only - need this for a moment. The layers - that call this function should - deallocate the mem fairly soon - after control is returned */ - - if (!retname) goto out; - *retname = 0; /* Zero length string */ - retnamlen = 0; - }; if((strlen(retname) + rr->len - 5) >= 254) { truncate = 1; break; @@ -227,7 +216,6 @@ int get_rock_ridge_filename(struct iso_directory_record * de, printk("RR: RE (%x)\n", inode->i_ino); #endif if (buffer) kfree(buffer); - if (retname) kfree(retname); return -1; default: break; @@ -235,15 +223,9 @@ int get_rock_ridge_filename(struct iso_directory_record * de, }; } MAYBE_CONTINUE(repeat,inode); - if(retname){ - *name = retname; - *namlen = retnamlen; - return 1; - }; - return 0; /* This file did not have a NM field */ + return retnamlen; /* If 0, this file did not have a NM field */ out: if(buffer) kfree(buffer); - if (retname) kfree(retname); return 0; } diff --git a/fs/isofs/symlink.c b/fs/isofs/symlink.c index c88c56760..5321e011a 100644 --- a/fs/isofs/symlink.c +++ b/fs/isofs/symlink.c @@ -56,7 +56,7 @@ static int isofs_readlink(struct inode * inode, char * buffer, int buflen) if (!pnt) return 0; - i = strlen(pnt)+1; + i = strlen(pnt); if (i > buflen) i = buflen; if (copy_to_user(buffer, pnt, i)) diff --git a/fs/isofs/util.c b/fs/isofs/util.c index 75183cc8f..2d578fb8b 100644 --- a/fs/isofs/util.c +++ b/fs/isofs/util.c @@ -9,6 +9,8 @@ * the 386bsd iso9660 filesystem, by Pace Willisson <pace@blitz.com>. */ +#include <linux/time.h> + int isonum_711 (char * p) { @@ -112,6 +114,8 @@ int iso_date(char * p, int flag) crtime = 0; } else { int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + extern struct timezone sys_tz; + days = year * 365; if (year > 2) days += (year+1) / 4; @@ -122,7 +126,9 @@ int iso_date(char * p, int flag) days += day - 1; crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; - + if (sys_tz.tz_dsttime) + crtime -= 3600; + /* sign extend */ if (tz & 0x80) tz |= (-1 << 8); |