summaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/udf
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/balloc.c50
-rw-r--r--fs/udf/dir.c11
-rw-r--r--fs/udf/directory.c3
-rw-r--r--fs/udf/file.c24
-rw-r--r--fs/udf/inode.c39
-rw-r--r--fs/udf/lowlevel.c2
-rw-r--r--fs/udf/namei.c50
-rw-r--r--fs/udf/super.c16
-rw-r--r--fs/udf/symlink.c184
-rw-r--r--fs/udf/truncate.c3
-rw-r--r--fs/udf/udf_sb.h3
-rw-r--r--fs/udf/udfdecl.h233
-rw-r--r--fs/udf/udfend.h5
13 files changed, 293 insertions, 330 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index f5ab39437..03e66fe23 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -34,6 +34,56 @@
#include "udf_i.h"
#include "udf_sb.h"
+#define udf_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
+#define udf_set_bit(nr,addr) ext2_set_bit(nr,addr)
+#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
+#define udf_find_first_one_bit(addr, size) find_first_one_bit(addr, size)
+#define udf_find_next_one_bit(addr, size, offset) find_next_one_bit(addr, size, offset)
+
+#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
+#define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y)
+#define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
+
+extern inline int find_next_one_bit (void * addr, int size, int offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= (BITS_PER_LONG-1);
+ if (offset)
+ {
+ tmp = leBPL_to_cpup(p++);
+ tmp &= ~0UL << offset;
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1))
+ {
+ if ((tmp = leBPL_to_cpup(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = leBPL_to_cpup(p);
+found_first:
+ tmp &= ~0UL >> (BITS_PER_LONG-size);
+found_middle:
+ return result + ffz(~tmp);
+}
+
+#define find_first_one_bit(addr, size)\
+ find_next_one_bit((addr), (size), 0)
+
static int read_block_bitmap(struct super_block * sb, unsigned int block,
unsigned long bitmap_nr)
{
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 000ef6481..84218eb14 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -32,6 +32,7 @@
#include "udfdecl.h"
#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/config.h>
#include <linux/version.h>
#include "udf_i.h"
#include "udf_sb.h"
@@ -96,10 +97,8 @@ struct inode_operations udf_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -158,13 +157,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
struct FileIdentDesc *fi=NULL;
struct FileIdentDesc cfi;
int block, iblock;
- int nf_pos = filp->f_pos;
+ loff_t nf_pos = filp->f_pos;
int flen;
char fname[255];
char *nameptr;
Uint16 liu;
Uint8 lfi;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
struct buffer_head * bh = NULL;
lb_addr bloc, eloc;
Uint32 extoffset, elen, offset;
@@ -276,10 +275,6 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
return 1; /* halt enum */
}
}
- else
- {
- udf_debug("size=%d, nf_pos=%d, liu=%d, lfi=%d\n", size, nf_pos, liu, lfi);
- }
}
} /* end while */
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 7ea1ac38e..b8a94e8f5 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -17,7 +17,6 @@
*/
#include "udfdecl.h"
-#include "udf_sb.h"
#if defined(__linux__) && defined(__KERNEL__)
@@ -85,7 +84,7 @@ Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size,
}
struct FileIdentDesc *
-udf_fileident_read(struct inode *dir, int *nf_pos,
+udf_fileident_read(struct inode *dir, loff_t *nf_pos,
struct udf_fileident_bh *fibh,
struct FileIdentDesc *cfi,
lb_addr *bloc, Uint32 *extoffset,
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 0a9642b08..2e17d81d4 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -31,6 +31,7 @@
*/
#include "udfdecl.h"
+#include <linux/config.h>
#include <linux/fs.h>
#include <linux/udf_fs.h>
#include <asm/uaccess.h>
@@ -42,11 +43,7 @@
#include "udf_i.h"
#include "udf_sb.h"
-#define NBUF 32
-
-typedef void * poll_table;
-
-static long long udf_file_llseek(struct file *, long long, int);
+static loff_t udf_file_llseek(struct file *, loff_t, int);
static ssize_t udf_file_read_adinicb (struct file *, char *, size_t, loff_t *);
static ssize_t udf_file_write (struct file *, const char *, size_t, loff_t *);
#if BITS_PER_LONG < 64
@@ -92,14 +89,12 @@ struct inode_operations udf_file_inode_operations = {
udf_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
#ifdef CONFIG_UDF_RW
udf_truncate, /* truncate */
#else
NULL, /* truncate */
#endif
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -137,21 +132,19 @@ struct inode_operations udf_file_inode_operations_adinicb = {
udf_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
#ifdef CONFIG_UDF_RW
udf_truncate, /* truncate */
#else
NULL, /* truncate */
#endif
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
/*
* Make sure the offset never goes beyond the 32-bit mark..
*/
-static long long udf_file_llseek(struct file * file, long long offset, int origin)
+static loff_t udf_file_llseek(struct file * file, loff_t offset, int origin)
{
struct inode * inode = file->f_dentry->d_inode;
@@ -168,12 +161,6 @@ static long long udf_file_llseek(struct file * file, long long offset, int origi
break;
}
}
-#if BITS_PER_LONG < 64
- if (((unsigned long long) offset >> 32) != 0)
- {
- return -EINVAL;
- }
-#endif
if (offset != file->f_pos)
{
file->f_pos = offset;
@@ -271,7 +258,8 @@ static ssize_t udf_file_read_adinicb(struct file * filp, char * buf,
size_t bufsize, loff_t * loff)
{
struct inode *inode = filp->f_dentry->d_inode;
- Uint32 size, left, pos, block;
+ loff_t size, left, pos;
+ Uint32 block;
struct buffer_head *bh = NULL;
size = inode->i_size;
@@ -453,7 +441,7 @@ static int udf_release_file(struct inode * inode, struct file * filp)
*/
static int udf_open_file(struct inode * inode, struct file * filp)
{
- if (inode->i_size == (Uint32)-1 && (filp->f_mode & FMODE_WRITE))
+ if ((inode->i_size & 0xFFFFFFFF00000000UL) && !(filp->f_flags & O_LARGEFILE))
return -EFBIG;
return 0;
}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 71083a7bd..05e03def5 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -201,8 +201,8 @@ struct buffer_head * udf_expand_adinicb(struct inode *inode, int *block, int isd
if (isdir)
{
struct udf_fileident_bh sfibh, dfibh;
- int f_pos = UDF_I_EXT0OFFS(inode) >> 2;
- int size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2;
+ loff_t f_pos = UDF_I_EXT0OFFS(inode) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2;
struct FileIdentDesc cfi, *sfi, *dfi;
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
@@ -383,7 +383,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
pextoffset = cextoffset;
cextoffset = nextoffset;
-
+
if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1)
break;
@@ -701,14 +701,31 @@ static void udf_merge_extents(struct inode *inode,
(((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits)))
{
- laarr[i].extLength = laarr[i+1].extLength +
- (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
- inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
- if (*endnum > (i+2))
- memmove(&laarr[i+1], &laarr[i+2],
- sizeof(long_ad) * (*endnum - (i+2)));
- i --;
- (*endnum) --;
+ if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+ (laarr[i+1].extLength & UDF_EXTENT_LENGTH_MASK) +
+ inode->i_sb->s_blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK)
+ {
+ laarr[i+1].extLength = (laarr[i+1].extLength -
+ (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+ UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1);
+ laarr[i].extLength = (UDF_EXTENT_LENGTH_MASK + 1) -
+ inode->i_sb->s_blocksize;
+ laarr[i+1].extLocation.logicalBlockNum =
+ laarr[i].extLocation.logicalBlockNum +
+ ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >>
+ inode->i_sb->s_blocksize_bits);
+ }
+ else
+ {
+ laarr[i].extLength = laarr[i+1].extLength +
+ (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+ inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
+ if (*endnum > (i+2))
+ memmove(&laarr[i+1], &laarr[i+2],
+ sizeof(long_ad) * (*endnum - (i+2)));
+ i --;
+ (*endnum) --;
+ }
}
}
}
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index 635ab1b79..0f763b5d1 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -123,7 +123,7 @@ udf_get_last_block(kdev_t dev, int *flags)
BLKGETSIZE,
(unsigned long) &lblock);
- if (!ret) /* Hard Disk */
+ if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
{
if (mult)
lblock *= mult;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 712cf09fb..ea921eeb3 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -25,6 +25,8 @@
*
*/
+#include "udfdecl.h"
+
#if defined(__linux__) && defined(__KERNEL__)
#include <linux/version.h>
#include "udf_i.h"
@@ -36,8 +38,6 @@
#include <linux/udf_fs.h>
#endif
-#include "udfdecl.h"
-
static inline int udf_match(int len, const char * const name, struct qstr *qs)
{
if (len != qs->len)
@@ -147,13 +147,13 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
struct FileIdentDesc *cfi)
{
struct FileIdentDesc *fi=NULL;
- int f_pos, block;
- int flen;
+ loff_t f_pos;
+ int block, flen;
char fname[255];
char *nameptr;
Uint8 lfi;
Uint16 liu;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
lb_addr bloc, eloc;
Uint32 extoffset, elen, offset;
struct buffer_head *bh = NULL;
@@ -333,10 +333,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
struct ustr unifilename;
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
int namelen;
- int f_pos;
+ loff_t f_pos;
int flen;
char *nameptr;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
int nfidlen;
Uint8 lfi;
Uint16 liu;
@@ -492,7 +492,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
extoffset -= sizeof(long_ad);
}
- dir->i_size += nfidlen;
if (sb->s_blocksize - fibh->eoffset >= nfidlen)
{
fibh->soffset = fibh->eoffset;
@@ -550,8 +549,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
else
{
elen = ((elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
- block = eloc.logicalBlockNum + ((elen - 1) >>
- dir->i_sb->s_blocksize_bits);
+ block = eloc.logicalBlockNum +
+ ((elen - 1) >> dir->i_sb->s_blocksize_bits);
elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 0);
}
@@ -568,11 +567,30 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) ==
EXTENT_RECORDED_ALLOCATED)
{
- block = eloc.logicalBlockNum + ((elen - 1) >>
- dir->i_sb->s_blocksize_bits);
+ if (block == (eloc.logicalBlockNum +
+ ((elen - 1) >> dir->i_sb->s_blocksize_bits)))
+ {
+ if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) !=
+ EXTENT_RECORDED_ALLOCATED)
+ {
+ udf_release_data(bh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(fibh->ebh);
+ udf_debug("next extent not recorded and allocated\n");
+ return NULL;
+ }
+ }
}
else
- block ++;
+ {
+ udf_release_data(bh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(fibh->ebh);
+ udf_debug("next extent not recorded and allocated\n");
+ return NULL;
+ }
+ block = eloc.logicalBlockNum + ((elen - 1) >>
+ dir->i_sb->s_blocksize_bits);
}
fi = (struct FileIdentDesc *)(fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
@@ -586,6 +604,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (!udf_write_fi(cfi, fi, fibh, NULL, name))
{
udf_release_data(bh);
+ dir->i_size += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
UDF_I_LENALLOC(dir) += nfidlen;
dir->i_version = ++event;
@@ -595,7 +614,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
else
{
udf_release_data(bh);
- dir->i_size -= nfidlen;
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
@@ -807,8 +825,8 @@ static int empty_dir(struct inode *dir)
{
struct FileIdentDesc *fi, cfi;
struct udf_fileident_bh fibh;
- int f_pos;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t f_pos;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
int block;
lb_addr bloc, eloc;
Uint32 extoffset, elen, offset;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 97a0843bb..31fecbde2 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -42,12 +42,10 @@
* 12/20/98 find the free space bitmap (if it exists)
*/
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
#include "udfdecl.h"
+#include <linux/config.h>
+#include <linux/version.h>
#include <linux/blkdev.h>
#include <linux/malloc.h>
#include <linux/kernel.h>
@@ -65,6 +63,15 @@
#include <linux/init.h>
#include <asm/uaccess.h>
+#define VDS_POS_PRIMARY_VOL_DESC 0
+#define VDS_POS_UNALLOC_SPACE_DESC 1
+#define VDS_POS_LOGICAL_VOL_DESC 2
+#define VDS_POS_PARTITION_DESC 3
+#define VDS_POS_IMP_USE_VOL_DESC 4
+#define VDS_POS_VOL_DESC_PTR 5
+#define VDS_POS_TERMINATING_DESC 6
+#define VDS_POS_LENGTH 7
+
static char error_buf[1024];
/* These are the "meat" - everything else is stuffing */
@@ -1365,7 +1372,6 @@ udf_read_super(struct super_block *sb, void *options, int silent)
/* Fill in the rest of the superblock */
sb->s_op = &udf_sb_ops;
- sb->s_time = 0;
sb->dq_op = NULL;
sb->s_dirt = 0;
sb->s_magic = UDF_SUPER_MAGIC;
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 0e52198f5..63ebb5713 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -33,157 +33,93 @@
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
#include "udf_i.h"
-static int udf_readlink(struct dentry *, char *, int);
-static struct dentry * udf_follow_link(struct dentry * dentry,
- struct dentry * base, unsigned int follow);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations udf_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- udf_readlink, /* readlink */
- udf_follow_link,/* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-int udf_pc_to_char(char *from, int fromlen, char **to)
+static void udf_pc_to_char(char *from, int fromlen, char *to)
{
struct PathComponent *pc;
int elen = 0, len = 0;
+ char *p = to;
- *to = (char *)kmalloc(fromlen, GFP_KERNEL);
-
- if (!(*to))
- return -1;
-
- while (elen < fromlen)
- {
+ while (elen < fromlen) {
pc = (struct PathComponent *)(from + elen);
- if (pc->componentType == 1 && pc->lengthComponentIdent == 0)
- {
- (*to)[0] = '/';
- len = 1;
- }
- else if (pc->componentType == 3)
- {
- memcpy(&(*to)[len], "../", 3);
- len += 3;
- }
- else if (pc->componentType == 4)
- {
- memcpy(&(*to)[len], "./", 2);
- len += 2;
- }
- else if (pc->componentType == 5)
- {
- memcpy(&(*to)[len], pc->componentIdent, pc->lengthComponentIdent);
- len += pc->lengthComponentIdent + 1;
- (*to)[len-1] = '/';
+ switch (pc->componentType) {
+ case 1:
+ if (pc->lengthComponentIdent == 0) {
+ p = to;
+ *p++ = '/';
+ }
+ break;
+ case 3:
+ memcpy(p, "../", 3);
+ p += 3;
+ break;
+ case 4:
+ memcpy(p, "./", 2);
+ p += 2;
+ /* that would be . - just ignore */
+ break;
+ case 5:
+ memcpy(p+len, pc->componentIdent,
+ pc->lengthComponentIdent);
+ p += pc->lengthComponentIdent;
+ *p++ = '/';
}
elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
}
- if (len)
- {
- len --;
- (*to)[len] = '\0';
+ if (p>to+1) {
+ p[-1] = '\0';
}
- return len;
}
-static struct dentry * udf_follow_link(struct dentry * dentry,
- struct dentry * base, unsigned int follow)
+static int udf_symlink_filler(struct dentry * dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
- char *symlink, *tmpbuf;
- int len;
-
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- {
- bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
-
- if (!bh)
- return 0;
-
- symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
- }
- else
- {
- bh = bread(inode->i_dev, udf_block_map(inode, 0), inode->i_sb->s_blocksize);
-
- if (!bh)
- return 0;
-
- symlink = bh->b_data;
- }
-
- if ((len = udf_pc_to_char(symlink, inode->i_size, &tmpbuf)) >= 0)
- {
- base = lookup_dentry(tmpbuf, base, follow);
- kfree(tmpbuf);
- return base;
- }
- else
- return ERR_PTR(-ENOMEM);
-}
+ char *symlink;
+ int err;
-static int udf_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh = NULL;
- char *symlink, *tmpbuf;
- int len;
+ char *p = (char*)kmap(page);
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- {
- bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
+ err = -EIO;
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ bh = udf_tread(inode->i_sb, inode->i_ino,
+ inode->i_sb->s_blocksize);
if (!bh)
- return 0;
+ goto out;
symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
- }
- else
- {
- bh = bread(inode->i_dev, udf_block_map(inode, 0), inode->i_sb->s_blocksize);
+ } else {
+ bh = bread(inode->i_dev, udf_block_map(inode, 0),
+ inode->i_sb->s_blocksize);
if (!bh)
- return 0;
+ goto out;
symlink = bh->b_data;
}
- if ((len = udf_pc_to_char(symlink, inode->i_size, &tmpbuf)) >= 0)
- {
- if (copy_to_user(buffer, tmpbuf, len > buflen ? buflen : len))
- len = -EFAULT;
- kfree(tmpbuf);
- }
- else
- len = -ENOMEM;
-
- UPDATE_ATIME(inode);
- if (bh)
- udf_release_data(bh);
- return len;
+ udf_pc_to_char(symlink, inode->i_size, p);
+ udf_release_data(bh);
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+out:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return -EIO;
}
+
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations udf_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: udf_symlink_filler,
+};
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 676f8b3e6..1bf6e4cee 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -38,8 +38,7 @@ static void extent_trunc(struct inode * inode, lb_addr bloc, int *extoffset,
lb_addr neloc = { 0, 0 };
int nelen = 0;
int blocks = inode->i_sb->s_blocksize / 512;
- int last_block = (elen + inode->i_sb->s_blocksize - 1) / inode->i_sb->s_blocksize;
-
+ int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
if (offset)
{
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 407d6006d..310ba4aef 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -1,9 +1,6 @@
#ifndef __LINUX_UDF_SB_H
#define __LINUX_UDF_SB_H
-#include <linux/udf_167.h>
-#include <linux/udf_udf.h>
-
/* Since UDF 1.50 is ISO 13346 based... */
#define UDF_SUPER_MAGIC 0x15013346
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 543d15ea9..48dec10c5 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -1,9 +1,11 @@
#ifndef __UDF_DECL_H
#define __UDF_DECL_H
-#define UDF_VERSION_NOTICE "v0.8.9.3"
+#define UDF_VERSION_NOTICE "v0.8.9.4"
+#include <linux/udf_167.h>
#include <linux/udf_udf.h>
+#include "udfend.h"
#ifdef __KERNEL__
@@ -20,15 +22,33 @@
#endif
#include <linux/fs.h>
-/* if we're not defined, we must be compiling outside of the kernel tree */
+
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
-/* ... so override config */
#define CONFIG_UDF_FS_MODULE
-/* explicitly include udf_fs_sb.h and udf_fs_i.h */
#include <linux/udf_fs_sb.h>
#include <linux/udf_fs_i.h>
#endif
+#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
+#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
+
+#define CURRENT_UTIME (xtime.tv_usec)
+
+#define udf_file_entry_alloc_offset(inode)\
+ ((UDF_I_EXTENDED_FE(inode) ?\
+ sizeof(struct ExtendedFileEntry) :\
+ sizeof(struct FileEntry)) + UDF_I_LENEATTR(inode))
+
+#else
+
+#include <sys/types.h>
+
+#endif /* __KERNEL__ */
+
+
+
+#ifdef __KERNEL__
+
struct dentry;
struct inode;
struct task_struct;
@@ -48,8 +68,49 @@ struct udf_fileident_bh
int eoffset;
};
+#endif /* __KERNEL__ */
+
+struct udf_directory_record
+{
+ Uint32 d_parent;
+ Uint32 d_inode;
+ Uint32 d_name[255];
+};
+
+
+struct udf_vds_record
+{
+ Uint32 block;
+ Uint32 volDescSeqNum;
+};
+
+struct ktm
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_isdst;
+};
+
+struct ustr
+{
+ Uint8 u_cmpID;
+ Uint8 u_name[UDF_NAME_LEN-1];
+ Uint8 u_len;
+ Uint8 padding;
+ unsigned long u_hash;
+};
+
+#ifdef __KERNEL__
+
+/* super.c */
extern void udf_error(struct super_block *, const char *, const char *, ...);
extern void udf_warning(struct super_block *, const char *, const char *, ...);
+
+/* namei.c */
extern int udf_write_fi(struct FileIdentDesc *, struct FileIdentDesc *, struct udf_fileident_bh *, Uint8 *, Uint8 *);
extern struct dentry * udf_lookup(struct inode *, struct dentry *);
extern int udf_create(struct inode *, struct dentry *, int);
@@ -60,7 +121,11 @@ extern int udf_unlink(struct inode *, struct dentry *);
extern int udf_symlink(struct inode *, struct dentry *, const char *);
extern int udf_link(struct dentry *, struct inode *, struct dentry *);
extern int udf_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+
+/* file.c */
extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+/* inode.c */
extern struct inode *udf_iget(struct super_block *, lb_addr);
extern int udf_sync_inode(struct inode *);
extern struct buffer_head * udf_expand_adinicb(struct inode *, int *, int, int *);
@@ -80,9 +145,10 @@ extern int udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct
extern int udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
extern int udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
extern int udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
+extern void udf_discard_prealloc(struct inode *);
+/* misc.c */
extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
-
extern struct buffer_head *udf_tread(struct super_block *, int, int);
extern struct GenericAttrFormat *udf_add_extendedattr(struct inode *, Uint32, Uint32, Uint8, struct buffer_head **);
extern struct GenericAttrFormat *udf_get_extendedattr(struct inode *, Uint32, Uint8, struct buffer_head **);
@@ -91,186 +157,73 @@ extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, Uint3
extern struct buffer_head *udf_read_untagged(struct super_block *, Uint32, Uint32);
extern void udf_release_data(struct buffer_head *);
+/* lowlevel.c */
extern unsigned int udf_get_last_session(kdev_t);
extern unsigned int udf_get_last_block(kdev_t, int *);
+/* partition.c */
extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
extern Uint32 udf_get_lb_pblock(struct super_block *, lb_addr, Uint32);
+/* unicode.c */
extern int udf_get_filename(Uint8 *, Uint8 *, int);
+/* ialloc.c */
extern void udf_free_inode(struct inode *);
extern struct inode * udf_new_inode (const struct inode *, int, int *);
-extern void udf_discard_prealloc(struct inode *);
+
+/* truncate.c */
extern void udf_truncate(struct inode *);
extern void udf_truncate_adinicb(struct inode *);
+
+/* balloc.c */
extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32);
extern int udf_alloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
extern int udf_new_block(const struct inode *, Uint16, Uint32, int *);
extern int udf_sync_file(struct file *, struct dentry *);
-#else
-
-#include <sys/types.h>
+/* directory.c */
+extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *);
+extern struct FileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct FileIdentDesc *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
#endif /* __KERNEL__ */
-#include "udfend.h"
-
-/* structures */
-struct udf_directory_record
-{
- Uint32 d_parent;
- Uint32 d_inode;
- Uint32 d_name[255];
-};
-
-#define VDS_POS_PRIMARY_VOL_DESC 0
-#define VDS_POS_UNALLOC_SPACE_DESC 1
-#define VDS_POS_LOGICAL_VOL_DESC 2
-#define VDS_POS_PARTITION_DESC 3
-#define VDS_POS_IMP_USE_VOL_DESC 4
-#define VDS_POS_VOL_DESC_PTR 5
-#define VDS_POS_TERMINATING_DESC 6
-#define VDS_POS_LENGTH 7
-
-struct udf_vds_record
-{
- Uint32 block;
- Uint32 volDescSeqNum;
-};
-
-struct ktm
-{
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_isdst;
-};
-
-struct ustr
-{
- Uint8 u_cmpID;
- Uint8 u_name[UDF_NAME_LEN-1];
- Uint8 u_len;
- Uint8 padding;
- unsigned long u_hash;
-};
-
-
-#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
-#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
-
-#ifdef __KERNEL__
-
-#define CURRENT_UTIME (xtime.tv_usec)
-
-#define udf_file_entry_alloc_offset(inode)\
- ((UDF_I_EXTENDED_FE(inode) ?\
- sizeof(struct ExtendedFileEntry) :\
- sizeof(struct FileEntry)) + UDF_I_LENEATTR(inode))
-
-#define udf_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
-#define udf_set_bit(nr,addr) ext2_set_bit(nr,addr)
-#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
-#define udf_find_first_one_bit(addr, size) find_first_one_bit(addr, size)
-#define udf_find_next_one_bit(addr, size, offset) find_next_one_bit(addr, size, offset)
-
-#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
-#define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y)
-#define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
-
-extern inline int find_next_one_bit (void * addr, int size, int offset)
-{
- unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= (BITS_PER_LONG-1);
- if (offset)
- {
- tmp = leBPL_to_cpup(p++);
- tmp &= ~0UL << offset;
- if (size < BITS_PER_LONG)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG-1))
- {
- if ((tmp = leBPL_to_cpup(p++)))
- goto found_middle;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = leBPL_to_cpup(p);
-found_first:
- tmp &= ~0UL >> (BITS_PER_LONG-size);
-found_middle:
- return result + ffz(~tmp);
-}
-
-#define find_first_one_bit(addr, size)\
- find_next_one_bit((addr), (size), 0)
-
-#endif
-
/* Miscellaneous UDF Prototypes */
+/* unicode.c */
extern int udf_ustr_to_dchars(Uint8 *, const struct ustr *, int);
extern int udf_ustr_to_char(Uint8 *, const struct ustr *, int);
extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
extern int udf_dchars_to_ustr(struct ustr *, const Uint8 *, int);
extern int udf_char_to_ustr(struct ustr *, const Uint8 *, int);
extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
-
-extern Uint16 udf_crc(Uint8 *, Uint32, Uint16);
extern int udf_translate_to_linux(Uint8 *, Uint8 *, int, Uint8 *, int);
extern int udf_build_ustr(struct ustr *, dstring *, int);
extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
+/* crc.c */
+extern Uint16 udf_crc(Uint8 *, Uint32, Uint16);
+
+/* misc.c */
extern uid_t udf_convert_uid(int);
extern gid_t udf_convert_gid(int);
extern Uint32 udf64_low32(Uint64);
extern Uint32 udf64_high32(Uint64);
+extern void udf_update_tag(char *, int);
+extern void udf_new_tag(char *, Uint16, Uint16, Uint16, Uint32, int);
-
+/* udftime.c */
extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
extern time_t udf_converttime (struct ktm *);
-#ifdef __KERNEL__
-extern Uint8 *
-udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *,
- struct buffer_head **, int *);
-
-extern struct FileIdentDesc *
-udf_fileident_read(struct inode *, int *,
- struct udf_fileident_bh *,
- struct FileIdentDesc *,
- lb_addr *, Uint32 *,
- Uint32 *, struct buffer_head **);
-#endif
-extern struct FileIdentDesc *
-udf_get_fileident(void * buffer, int bufsize, int * offset);
+/* directory.c */
+extern struct FileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
extern Uint8 * udf_get_filead(struct FileEntry *, Uint8 *, int, int, int, int *);
-extern void udf_update_tag(char *, int);
-extern void udf_new_tag(char *, Uint16, Uint16, Uint16, Uint32, int);
-
-#endif
+#endif /* __UDF_DECL_H */
diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h
index 031f5b507..67161d7ae 100644
--- a/fs/udf/udfend.h
+++ b/fs/udf/udfend.h
@@ -3,6 +3,8 @@
#ifndef __KERNEL__
+#include <sys/types.h>
+
#if __BYTE_ORDER == 0
#error "__BYTE_ORDER must be defined"
@@ -44,8 +46,11 @@
#endif /* __BYTE_ORDER == 0 */
+#include <string.h>
+
#else /* __KERNEL__ */
+#include <asm/byteorder.h>
#include <linux/string.h>
#endif /* ! __KERNEL__ */