diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/udf | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/balloc.c | 50 | ||||
-rw-r--r-- | fs/udf/dir.c | 11 | ||||
-rw-r--r-- | fs/udf/directory.c | 3 | ||||
-rw-r--r-- | fs/udf/file.c | 24 | ||||
-rw-r--r-- | fs/udf/inode.c | 39 | ||||
-rw-r--r-- | fs/udf/lowlevel.c | 2 | ||||
-rw-r--r-- | fs/udf/namei.c | 50 | ||||
-rw-r--r-- | fs/udf/super.c | 16 | ||||
-rw-r--r-- | fs/udf/symlink.c | 184 | ||||
-rw-r--r-- | fs/udf/truncate.c | 3 | ||||
-rw-r--r-- | fs/udf/udf_sb.h | 3 | ||||
-rw-r--r-- | fs/udf/udfdecl.h | 233 | ||||
-rw-r--r-- | fs/udf/udfend.h | 5 |
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__ */ |