patch-2.2.19 linux/fs/isofs/dir.c
Next file: linux/fs/isofs/inode.c
Previous file: linux/fs/inode.c
Back to the patch index
Back to the overall index
- Lines: 228
- Date:
Sun Mar 25 11:37:38 2001
- Orig file:
v2.2.18/fs/isofs/dir.c
- Orig date:
Sun Mar 25 11:12:31 2001
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/fs/isofs/dir.c linux/fs/isofs/dir.c
@@ -67,14 +67,18 @@
NULL /* permission */
};
-static int isofs_name_translate(char * old, int len, char * new)
+int isofs_name_translate(struct iso_directory_record *de, char *new,
+ struct inode *inode)
{
- int i, c;
+ char * old = de->name;
+ int len = de->name_len[0];
+ int i;
for (i = 0; i < len; i++) {
- c = old[i];
+ unsigned char c = old[i];
if (!c)
break;
+
if (c >= 'A' && c <= 'Z')
c |= 0x20; /* lower case */
@@ -101,8 +105,7 @@
{
int std;
unsigned char * chr;
- int retnamlen = isofs_name_translate(de->name,
- de->name_len[0], retname);
+ int retnamlen = isofs_name_translate(de, retname, inode);
if (retnamlen == 0) return 0;
std = sizeof(struct iso_directory_record) + de->name_len[0];
if (std & 1) std++;
@@ -122,7 +125,9 @@
}
/*
- * This should _really_ be cleaned up some day..
+ * Read directory and call the filldir() argument until either
+ * all entries were handled, or filldir() returns an error.
+ * Return 0.
*/
static int do_isofs_readdir(struct inode *inode, struct file *filp,
void *dirent, filldir_t filldir,
@@ -132,7 +137,7 @@
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
unsigned int block, offset;
int inode_number = 0; /* Quiet GCC */
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
int len;
int map;
int high_sierra;
@@ -140,78 +145,59 @@
char *p = NULL; /* Quiet GCC */
struct iso_directory_record *de;
- if (filp->f_pos >= inode->i_size)
- return 0;
-
offset = filp->f_pos & (bufsize - 1);
- block = isofs_bmap(inode, filp->f_pos >> bufbits);
+ block = filp->f_pos >> bufbits;
high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
- if (!block)
- return 0;
-
- if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
- return 0;
-
while (filp->f_pos < inode->i_size) {
int de_len;
-#ifdef DEBUG
- printk("Block, offset, f_pos: %x %x %x\n",
- block, offset, filp->f_pos);
- printk("inode->i_size = %x\n",inode->i_size);
-#endif
+
+ if (!bh) {
+ bh = isofs_bread(inode, bufsize, block);
+ if (!bh)
+ return 0;
+ }
+
de = (struct iso_directory_record *) (bh->b_data + offset);
- if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
+ if (first_de)
+ inode_number = (bh->b_blocknr << bufbits) + offset;
- /* Check boundaries and get length. by GO! */
- if (offset < bufsize) de_len = *(unsigned char *) de;
-#ifdef DEBUG
- if (offset < bufsize) printk("de_len = %ld\n", de_len);
- else printk("Move to next sector\n");
-#endif
-
+ de_len = *(unsigned char *) de;
/* If the length byte is zero, we should move on to the next
CDROM sector. If we are at the end of the directory, we
kick out of the while loop. */
- if ((offset >= bufsize) || (de_len == 0) ) {
+ if (de_len == 0) {
brelse(bh);
- if (offset >= bufsize) { /*Check first. by GO!*/
- offset -= bufsize;
- filp->f_pos += offset;
- } else {
- filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
- + ISOFS_BLOCK_SIZE);
- offset = 0;
- }
-
- if (filp->f_pos >= inode->i_size)
- return 0;
-
- block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
- if (!block)
- return 0;
- bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
- if (!bh)
- return 0;
+ bh = NULL;
+ filp->f_pos = (filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ + ISOFS_BLOCK_SIZE;
+ block = filp->f_pos >> bufbits;
+ offset = 0;
continue;
}
- offset += de_len;
- if (offset > bufsize) {
- /*
- * This would only normally happen if we had
- * a buggy cdrom image. All directory
- * entries should terminate with a null size
- * or end exactly at the end of the sector.
- */
- printk("next_offset (%x) > bufsize (%lx)\n",
- offset,bufsize);
- break;
+ offset += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= bufsize) {
+ int slop = bufsize - offset + de_len;
+ memcpy(tmpde, de, slop);
+ offset &= bufsize - 1;
+ block++;
+ brelse(bh);
+ bh = NULL;
+ if (offset) {
+ bh = isofs_bread(inode, bufsize, block);
+ if (!bh)
+ return 0;
+ memcpy((void *) tmpde + slop, bh->b_data, offset);
+ }
+ de = tmpde;
}
- if(de->flags[-high_sierra] & 0x80) {
+ if (de->flags[-high_sierra] & 0x80) {
first_de = 0;
filp->f_pos += de_len;
continue;
@@ -250,7 +236,7 @@
map = 1;
if (inode->i_sb->u.isofs_sb.s_rock) {
len = get_rock_ridge_filename(de, tmpname, inode);
- if (len != 0) {
+ if (len != 0) { /* may be -1 */
p = tmpname;
map = 0;
}
@@ -258,7 +244,7 @@
if (map) {
#ifdef CONFIG_JOLIET
if (inode->i_sb->u.isofs_sb.s_joliet_level) {
- len = get_joliet_filename(de, inode, tmpname);
+ len = get_joliet_filename(de, tmpname, inode);
p = tmpname;
} else
#endif
@@ -267,8 +253,7 @@
p = tmpname;
} else
if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
- len = isofs_name_translate(de->name,
- de->name_len[0], tmpname);
+ len = isofs_name_translate(de, tmpname, inode);
p = tmpname;
} else {
p = de->name;
@@ -283,7 +268,8 @@
continue;
}
- brelse(bh);
+ if (bh)
+ brelse(bh);
return 0;
}
@@ -296,17 +282,17 @@
void *dirent, filldir_t filldir)
{
int result;
- char * tmpname;
+ char * page;
struct iso_directory_record * tmpde;
struct inode *inode = filp->f_dentry->d_inode;
- tmpname = (char *) __get_free_page(GFP_KERNEL);
- if (!tmpname)
+ page = (char *) __get_free_page(GFP_KERNEL);
+ if (!page)
return -ENOMEM;
- tmpde = (struct iso_directory_record *) (tmpname+1024);
+ tmpde = (struct iso_directory_record *) (page+1024);
- result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
+ result = do_isofs_readdir(inode, filp, dirent, filldir, page, tmpde);
- free_page((unsigned long) tmpname);
+ free_page((unsigned long) page);
return result;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)