summaryrefslogtreecommitdiffstats
path: root/fs/isofs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-06 23:51:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-06 23:51:34 +0000
commit230e5ab6a084ed50470f101934782dbf54b0d06b (patch)
tree5dd821c8d33f450470588e7a543f74bf74306e9e /fs/isofs
parentc9b1c8a64c6444d189856f1e26bdcb8b4cd0113a (diff)
Merge with Linux 2.1.67.
Diffstat (limited to 'fs/isofs')
-rw-r--r--fs/isofs/Makefile5
-rw-r--r--fs/isofs/dir.c87
-rw-r--r--fs/isofs/inode.c199
-rw-r--r--fs/isofs/joliet.c110
-rw-r--r--fs/isofs/namei.c88
-rw-r--r--fs/isofs/rock.c26
-rw-r--r--fs/isofs/symlink.c2
-rw-r--r--fs/isofs/util.c8
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);