]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] UDF filesystem update
authorAndrew Morton <akpm@osdl.org>
Fri, 12 Mar 2004 00:14:43 +0000 (16:14 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 12 Mar 2004 00:14:43 +0000 (16:14 -0800)
From: Ben Fennema <bfennema@falcon.csc.calpoly.edu>

- added udf 2.5 #defines

- fixed prealloc discard race

- fixed several bugs in inode_getblk

- added S_IFSOCK support

- fix unicode encoding bug

- change partition allocation from kmalloc to vmalloc for large
  allocations

15 files changed:
CREDITS
Documentation/filesystems/udf.txt
MAINTAINERS
fs/udf/dir.c
fs/udf/file.c
fs/udf/inode.c
fs/udf/misc.c
fs/udf/namei.c
fs/udf/osta_udf.h
fs/udf/super.c
fs/udf/truncate.c
fs/udf/udf_sb.h
fs/udf/udfdecl.h
fs/udf/unicode.c
include/linux/udf_fs.h

diff --git a/CREDITS b/CREDITS
index 13eba329ee16847ebbfebec91716a08a000f29b1..04a6a8b91bdee3a62cf5f820be59e36b644ad2b7 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -975,8 +975,7 @@ N: Ben Fennema
 E: bfennema@falcon.csc.calpoly.edu
 W: http://www.csc.calpoly.edu/~bfennema
 D: UDF filesystem
-S: 21760 Irma Lyle Drive
-S: Los Gatos, CA 95033-8942
+S: (ask for current address)
 S: USA
 
 N: Jürgen Fischer
index 8c1e7f3b50a503231b8e9d16ef7d527dc565f3be..a0bb3b230bf89f7e061300ab5386233a43558649 100644 (file)
@@ -1,7 +1,7 @@
 *
 * ./Documentation/filesystems/udf.txt
 *
-UDF Filesystem version 0.9.5
+UDF Filesystem version 0.9.8.1
 
 If you encounter problems with reading UDF discs using this driver,
 please report them to linux_udf@hpesjro.fc.hp.com, which is the
@@ -16,7 +16,7 @@ The following mount options are supported:
        gid=            Set the default group.
        umask=          Set the default umask.
        uid=            Set the default user.
-       bs=                     Set the block size. 
+       bs=             Set the block size.
        unhide          Show otherwise hidden files.
        undelete        Show deleted files in lists.
        adinicb         Embed data in the inode (default)
@@ -47,15 +47,11 @@ The following expect a offset from the partition root.
 -------------------------------------------------------------------------------
 
 
-For more information see:
-       http://www.trylinux.com/projects/udf/index.html
-
 For the latest version and toolset see:
-       http://www.csc.calpoly.edu/~bfennema/udf.html
        http://linux-udf.sourceforge.net/
 
 Documentation on UDF and ECMA 167 is available FREE from:
-    http://www.osta.org/
-    http://www.ecma.ch/
+       http://www.osta.org/
+       http://www.ecma-international.org/
 
 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
index b6ce0c77a2bd48c99035d435074555b5fd772cd1..c7a2fd32eea4167141883e56685dfe4e3f3b8e8a 100644 (file)
@@ -2037,8 +2037,6 @@ S:        Maintained
 UDF FILESYSTEM
 P:     Ben Fennema
 M:     bfennema@falcon.csc.calpoly.edu
-P:     Dave Boynton
-M:     dave@trylinux.com
 L:     linux_udf@hpesjro.fc.hp.com
 W:     http://linux-udf.sourceforge.net
 S:     Maintained
index b2b977da15323cbebd8d84a76da2e308b3786d67..a67dceb36f65bcdfd4d7b35d0d8e69175648d167 100644 (file)
@@ -15,7 +15,7 @@
  *             ftp://prep.ai.mit.edu/pub/gnu/GPL
  *     Each contributing author retains all rights to their own work.
  *
- *  (C) 1998-2001 Ben Fennema
+ *  (C) 1998-2004 Ben Fennema
  *
  * HISTORY
  *
@@ -111,7 +111,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        int block, iblock;
        loff_t nf_pos = filp->f_pos - 1;
        int flen;
-       char fname[255];
+       char fname[UDF_NAME_LEN];
        char *nameptr;
        uint16_t liu;
        uint8_t lfi;
index b1cf9999e9026e85f6bc121a53cfd7c41995134c..3b955011ec1820b1d1b70f2f6b7b64e0b0809fb7 100644 (file)
@@ -16,7 +16,7 @@
  *  Each contributing author retains all rights to their own work.
  *
  *  (C) 1998-1999 Dave Boynton
- *  (C) 1998-2001 Ben Fennema
+ *  (C) 1998-2004 Ben Fennema
  *  (C) 1999-2000 Stelias Computing Inc
  *
  * HISTORY
@@ -247,9 +247,9 @@ static int udf_release_file(struct inode * inode, struct file * filp)
 {
        if (filp->f_mode & FMODE_WRITE)
        {
-               lock_kernel();
+               down(&inode->i_sem);
                udf_discard_prealloc(inode);
-               unlock_kernel();
+               up(&inode->i_sem);
        }
        return 0;
 }
index af81f88a1f802fc81c5d2a250df2ca2241743c20..c8e3b525ac61071eef4e24cd57f8cdd519b70167 100644 (file)
@@ -16,7 +16,7 @@
  *  Each contributing author retains all rights to their own work.
  *
  *  (C) 1998 Dave Boynton
- *  (C) 1998-2001 Ben Fennema
+ *  (C) 1998-2004 Ben Fennema
  *  (C) 1999-2000 Stelias Computing Inc
  *
  * HISTORY
@@ -84,9 +84,9 @@ void udf_put_inode(struct inode * inode)
 {
        if (!(inode->i_sb->s_flags & MS_RDONLY))
        {
-               lock_kernel();
+               down(&inode->i_sem);
                udf_discard_prealloc(inode);
-               unlock_kernel();
+               up(&inode->i_sem);
        }
 }
 
@@ -130,15 +130,6 @@ void udf_clear_inode(struct inode *inode)
        UDF_I_DATA(inode) = NULL;
 }
 
-void udf_discard_prealloc(struct inode * inode)
-{
-       if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
-               UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
-       {
-               udf_truncate_extents(inode);
-       }
-}
-
 static int udf_writepage(struct page *page, struct writeback_control *wbc)
 {
        return block_write_full_page(page, udf_get_block, wbc);
@@ -516,11 +507,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                else
                        lastblock = 1;
        }
+       udf_release_data(cbh);
        udf_release_data(nbh);
-       if (!pbh)
-               pbh = cbh;
-       else
-               udf_release_data(cbh);
 
        /* if the current extent is not recorded but allocated, get the
                block in the extent corresponding to the requested block */
@@ -595,7 +583,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
                int curr = *c;
                int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
                        inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
-               int type = laarr[curr].extLength & ~UDF_EXTENT_LENGTH_MASK;
+               int8_t etype = (laarr[curr].extLength >> 30);
 
                if (blen == 1)
                        ;
@@ -612,7 +600,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
 
                if (offset)
                {
-                       if ((type >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
+                       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
                        {
                                udf_free_blocks(inode->i_sb, inode, laarr[curr].extLocation, 0, offset);
                                laarr[curr].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
@@ -621,7 +609,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
                                laarr[curr].extLocation.partitionReferenceNum = 0;
                        }
                        else
-                               laarr[curr].extLength = type |
+                               laarr[curr].extLength = (etype << 30) |
                                        (offset << inode->i_sb->s_blocksize_bits);
                        curr ++;
                        (*c) ++;
@@ -629,7 +617,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
                }
                
                laarr[curr].extLocation.logicalBlockNum = newblocknum;
-               if ((type >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
+               if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
                        laarr[curr].extLocation.partitionReferenceNum =
                                UDF_I_LOCATION(inode).partitionReferenceNum;
                laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
@@ -638,9 +626,9 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
 
                if (blen != offset + 1)
                {
-                       if ((type >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
+                       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
                                laarr[curr].extLocation.logicalBlockNum += (offset + 1);
-                       laarr[curr].extLength = type |
+                       laarr[curr].extLength = (etype << 30) |
                                ((blen - (offset + 1)) << inode->i_sb->s_blocksize_bits);
                        curr ++;
                        (*endnum) ++;
@@ -761,8 +749,8 @@ static void udf_merge_extents(struct inode *inode,
                                        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].extLength = (laarr[i].extLength & UDF_EXTENT_FLAG_MASK) +
+                                               (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) >>
@@ -781,6 +769,47 @@ static void udf_merge_extents(struct inode *inode,
                                }
                        }
                }
+               else if (((laarr[i].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30)) &&
+                       ((laarr[i+1].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)))
+               {
+                       udf_free_blocks(inode->i_sb, inode, laarr[i].extLocation, 0,
+                               ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+                               inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
+                       laarr[i].extLocation.logicalBlockNum = 0;
+                       laarr[i].extLocation.partitionReferenceNum = 0;
+
+                       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 = (laarr[i].extLength & UDF_EXTENT_FLAG_MASK) +
+                                       (UDF_EXTENT_LENGTH_MASK + 1) - inode->i_sb->s_blocksize;
+                       }
+                       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) --;
+                       }
+               }
+               else if ((laarr[i].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
+               {
+                       udf_free_blocks(inode->i_sb, inode, laarr[i].extLocation, 0,
+                               ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+                              inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
+                       laarr[i].extLocation.logicalBlockNum = 0;
+                       laarr[i].extLocation.partitionReferenceNum = 0;
+                       laarr[i].extLength = (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) |
+                               EXT_NOT_RECORDED_NOT_ALLOCATED;
+               }
        }
 }
 
@@ -1014,7 +1043,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        struct extendedFileEntry *efe;
        time_t convtime;
        long convtime_usec;
-       int offset, alen;
+       int offset;
 
        fe = (struct fileEntry *)bh->b_data;
        efe = (struct extendedFileEntry *)bh->b_data;
@@ -1115,7 +1144,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
                UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);
                offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
-               alen = offset + UDF_I_LENALLOC(inode);
        }
        else
        {
@@ -1170,7 +1198,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
                UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);
                offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
-               alen = offset + UDF_I_LENALLOC(inode);
        }
 
        switch (fe->icbTag.fileType)
@@ -1211,6 +1238,11 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                        init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
                        break;
                }
+               case ICBTAG_FILE_TYPE_SOCKET:
+               {
+                       init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
+                       break;
+               }
                case ICBTAG_FILE_TYPE_SYMLINK:
                {
                        inode->i_data.a_ops = &udf_symlink_aops;
@@ -1228,19 +1260,16 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        }
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
        {
-               struct buffer_head *tbh = NULL;
                struct deviceSpec *dsea =
                        (struct deviceSpec *)
-                               udf_get_extendedattr(inode, 12, 1, &tbh);
+                               udf_get_extendedattr(inode, 12, 1);
 
                if (dsea)
                {
                        init_special_inode(inode, inode->i_mode, MKDEV(
                                le32_to_cpu(dsea->majorDeviceIdent),
-                               le32_to_cpu(dsea->minorDeviceIdent)
-                       ));
+                               le32_to_cpu(dsea->minorDeviceIdent)));
                        /* Developer ID ??? */
-                       udf_release_data(tbh);
                }
                else
                {
@@ -1372,17 +1401,16 @@ udf_update_inode(struct inode *inode, int do_sync)
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
        {
                regid *eid;
-               struct buffer_head *tbh = NULL;
                struct deviceSpec *dsea =
                        (struct deviceSpec *)
-                               udf_get_extendedattr(inode, 12, 1, &tbh);       
+                               udf_get_extendedattr(inode, 12, 1);
 
                if (!dsea)
                {
                        dsea = (struct deviceSpec *)
                                udf_add_extendedattr(inode,
                                        sizeof(struct deviceSpec) +
-                                       sizeof(regid), 12, 0x3, &tbh);
+                                       sizeof(regid), 12, 0x3);
                        dsea->attrType = 12;
                        dsea->attrSubtype = 1;
                        dsea->attrLength = sizeof(struct deviceSpec) +
@@ -1396,8 +1424,6 @@ udf_update_inode(struct inode *inode, int do_sync)
                eid->identSuffix[1] = UDF_OS_ID_LINUX;
                dsea->majorDeviceIdent = cpu_to_le32(imajor(inode));
                dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));
-               mark_buffer_dirty_inode(tbh, inode);
-               udf_release_data(tbh);
        }
 
        if (UDF_I_EFE(inode) == 0)
@@ -1493,6 +1519,8 @@ udf_update_inode(struct inode *inode, int do_sync)
                fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;
        else if (S_ISFIFO(inode->i_mode))
                fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO;
+       else if (S_ISSOCK(inode->i_mode))
+               fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET;
 
        icbflags =      UDF_I_ALLOCTYPE(inode) |
                        ((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) |
@@ -1625,7 +1653,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                int err, loffset;
                lb_addr obloc = *bloc;
 
-               if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, inode,
+               if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
                        obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
                {
                        return -1;
@@ -1833,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                if (!(*extoffset))
                        *extoffset = sizeof(struct allocExtDesc);
                ptr = (*bh)->b_data + *extoffset;
-               alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
+               alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
        }
 
        switch (UDF_I_ALLOCTYPE(inode))
index eef11b0f169d1ea15da887543bf4e7a0f85ec851..b6e1c25f6843c2199321f817643d6da681ab421a 100644 (file)
@@ -16,7 +16,7 @@
  *     Each contributing author retains all rights to their own work.
  *
  *  (C) 1998 Dave Boynton
- *  (C) 1998-2001 Ben Fennema
+ *  (C) 1998-2004 Ben Fennema
  *  (C) 1999-2000 Stelias Computing Inc
  *
  * HISTORY
 #include "udf_i.h"
 #include "udf_sb.h"
 
-uint32_t
-udf64_low32(uint64_t indat)
-{
-       return indat & 0x00000000FFFFFFFFULL;
-}
-
-uint32_t
-udf64_high32(uint64_t indat)
-{
-       return indat >> 32;
-}
-
 extern struct buffer_head *
 udf_tgetblk(struct super_block *sb, int block)
 {
@@ -66,42 +54,24 @@ udf_tread(struct super_block *sb, int block)
 
 extern struct genericFormat *
 udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
-       uint8_t loc, struct buffer_head **bh)
+       uint8_t loc)
 {
        uint8_t *ea = NULL, *ad = NULL;
-       long_ad eaicb;
        int offset;
+       uint16_t crclen;
+       int i;
 
-       *bh = udf_tread(inode->i_sb, inode->i_ino);
-
-       if (UDF_I_EFE(inode) == 0)
-       {
-               struct fileEntry *fe;
-
-               fe = (struct fileEntry *)(*bh)->b_data;
-               eaicb = lela_to_cpu(fe->extendedAttrICB);
-               offset = sizeof(struct fileEntry);
-       }
-       else
-       {
-               struct extendedFileEntry *efe;
-
-               efe = (struct extendedFileEntry *)(*bh)->b_data;
-               eaicb = lela_to_cpu(efe->extendedAttrICB);
-               offset = sizeof(struct extendedFileEntry);
-       }
-
-       ea = &(*bh)->b_data[offset];
+       ea = UDF_I_DATA(inode);
        if (UDF_I_LENEATTR(inode))
-               offset += UDF_I_LENEATTR(inode);
+               ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
        else
+       {
+               ad = ea;
                size += sizeof(struct extendedAttrHeaderDesc);
+       }
 
-       ad = &(*bh)->b_data[offset];
-       if (UDF_I_LENALLOC(inode))
-               offset += UDF_I_LENALLOC(inode);
-
-       offset = inode->i_sb->s_blocksize - offset;
+       offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
+               UDF_I_LENALLOC(inode);
 
        /* TODO - Check for FreeEASpace */
 
@@ -121,7 +91,6 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
                        if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
                                le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
                        {
-                               udf_release_data(*bh);
                                return NULL;
                        }
                }
@@ -130,8 +99,11 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
                        size -= sizeof(struct extendedAttrHeaderDesc);
                        UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
                        eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
-                       eahd->descTag.descVersion = cpu_to_le16(2);
-                       eahd->descTag.tagSerialNum = cpu_to_le16(1);
+                       if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
+                               eahd->descTag.descVersion = cpu_to_le16(3);
+                       else
+                               eahd->descTag.descVersion = cpu_to_le16(2);
+                       eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
                        eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
                        eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
                        eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
@@ -169,45 +141,30 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
                        }
                }
                /* rewrite CRC + checksum of eahd */
+               crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
+               eahd->descTag.descCRCLength = cpu_to_le16(crclen);
+               eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + sizeof(tag), crclen, 0));
+               eahd->descTag.tagChecksum = 0;
+               for (i=0; i<16; i++)
+                       if (i != 4)
+                               eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i];
                UDF_I_LENEATTR(inode) += size;
                return (struct genericFormat *)&ea[offset];
        }
        if (loc & 0x02)
        {
        }
-       udf_release_data(*bh);
        return NULL;
 }
 
 extern struct genericFormat *
-udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
-       struct buffer_head **bh)
+udf_get_extendedattr(struct inode *inode, uint32_t type, uint8_t subtype)
 {
        struct genericFormat *gaf;
        uint8_t *ea = NULL;
-       long_ad eaicb;
        uint32_t offset;
 
-       *bh = udf_tread(inode->i_sb, inode->i_ino);
-
-       if (UDF_I_EFE(inode) == 0)
-       {
-               struct fileEntry *fe;
-
-               fe = (struct fileEntry *)(*bh)->b_data;
-               eaicb = lela_to_cpu(fe->extendedAttrICB);
-               if (UDF_I_LENEATTR(inode))
-                       ea = fe->extendedAttr;
-       }
-       else
-       {
-               struct extendedFileEntry *efe;
-
-               efe = (struct extendedFileEntry *)(*bh)->b_data;
-               eaicb = lela_to_cpu(efe->extendedAttrICB);
-               if (UDF_I_LENEATTR(inode))
-                       ea = efe->extendedAttr;
-       }
+       ea = UDF_I_DATA(inode);
 
        if (UDF_I_LENEATTR(inode))
        {
@@ -218,7 +175,6 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
                if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
                        le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
                {
-                       udf_release_data(*bh);
                        return NULL;
                }
        
@@ -238,12 +194,6 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
                                offset += le32_to_cpu(gaf->attrLength);
                }
        }
-
-       udf_release_data(*bh);
-       if (eaicb.extLength)
-       {
-               /* TODO */
-       }
        return NULL;
 }
 
index a7350413f9b8fdd8b3bf4503cd34c2f981697f46..67882bf361ee17cea9df04e322a6e01daf4c8456 100644 (file)
@@ -15,7 +15,7 @@
  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
  *      Each contributing author retains all rights to their own work.
  *
- *  (C) 1998-2001 Ben Fennema
+ *  (C) 1998-2004 Ben Fennema
  *  (C) 1999-2000 Stelias Computing Inc
  *
  * HISTORY
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 
-static inline int udf_match(int len, const char * const name, struct qstr *qs)
+static inline int udf_match(int len1, const char *name1, int len2, const char *name2)
 {
-       if (len != qs->len)
+       if (len1 != len2)
                return 0;
-       return !memcmp(name, qs->name, len);
+       return !memcmp(name1, name2, len1);
 }
 
 int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
@@ -154,8 +154,8 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
 {
        struct fileIdentDesc *fi=NULL;
        loff_t f_pos;
-       int block, flen;
-       char fname[255];
+       int block, namelen;
+       char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
        char *nameptr;
        uint8_t lfi;
        uint16_t liu;
@@ -167,6 +167,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        if (!dir)
                return NULL;
 
+       if ( !(namelen = udf_put_filename(dir->i_sb, dentry->d_name.name, name, dentry->d_name.len)))
+               return NULL;
+
        f_pos = (udf_ext0_offset(dir) >> 2);
 
        fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
@@ -250,13 +253,10 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
                if (!lfi)
                        continue;
 
-               if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)))
+               if (udf_match(namelen, name, lfi, nameptr))
                {
-                       if (udf_match(flen, fname, &(dentry->d_name)))
-                       {
-                               udf_release_data(bh);
-                               return fi;
-                       }
+                       udf_release_data(bh);
+                       return fi;
                }
        }
        if (fibh->sbh != fibh->ebh)
@@ -306,7 +306,7 @@ udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        struct fileIdentDesc cfi, *fi;
        struct udf_fileident_bh fibh;
 
-       if (dentry->d_name.len > UDF_NAME_LEN)
+       if (dentry->d_name.len > UDF_NAME_LEN-2)
                return ERR_PTR(-ENAMETOOLONG);
 
        lock_kernel();
@@ -353,7 +353,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
        int namelen;
        loff_t f_pos;
-       int flen;
        char *nameptr;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        int nfidlen;
@@ -481,8 +480,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                if (!lfi || !dentry)
                        continue;
 
-               if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
-                       udf_match(flen, fname, &(dentry->d_name)))
+               if (udf_match(namelen, name, lfi, nameptr))
                {
                        if (fibh->sbh != fibh->ebh)
                                udf_release_data(fibh->ebh);
@@ -674,8 +672,8 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t
 {
        struct inode * inode;
        struct udf_fileident_bh fibh;
-       int err;
        struct fileIdentDesc cfi, *fi;
+       int err;
 
        if (!old_valid_dev(rdev))
                return -EINVAL;
@@ -721,8 +719,8 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
        struct inode * inode;
        struct udf_fileident_bh fibh;
-       int err;
        struct fileIdentDesc cfi, *fi;
+       int err;
 
        lock_kernel();
        err = -EMLINK;
@@ -1119,8 +1117,8 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
 {
        struct inode *inode = old_dentry->d_inode;
        struct udf_fileident_bh fibh;
-       int err;
        struct fileIdentDesc cfi, *fi;
+       int err;
 
        lock_kernel();
        if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
index efa6acc026666f1a98b547811167e3ba3c8f6e0a..037d0b7e36ad7bced37f58b58451d71ed4acf8c3 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * osta_udf.h
  *
- * This file is based on OSTA UDF(tm) 2.01 (March 15, 2000)
+ * This file is based on OSTA UDF(tm) 2.50 (April 30, 2003)
  * http://www.osta.org
  *
- * Copyright (c) 2001-2002  Ben Fennema <bfennema@falcon.csc.calpoly.edu>
+ * Copyright (c) 2001-2004  Ben Fennema <bfennema@falcon.csc.calpoly.edu>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef _OSTA_UDF_H
 #define _OSTA_UDF_H 1
 
-/* OSTA CS0 Charspec (UDF 2.01 2.1.2) */
+/* OSTA CS0 Charspec (UDF 2.50 2.1.2) */
 #define UDF_CHAR_SET_TYPE              0
 #define UDF_CHAR_SET_INFO              "OSTA Compressed Unicode"
 
-/* Entity Identifier (UDF 2.01 2.1.5) */
-/* Identifiers (UDF 2.01 2.1.5.2) */
+/* Entity Identifier (UDF 2.50 2.1.5) */
+/* Identifiers (UDF 2.50 2.1.5.2) */
 #define UDF_ID_DEVELOPER               "*Linux UDFFS"
 #define        UDF_ID_COMPLIANT                "*OSTA UDF Compliant"
 #define UDF_ID_LV_INFO                 "*UDF LV Info"
@@ -59,8 +59,9 @@
 #define UDF_ID_SPARABLE                        "*UDF Sparable Partition"
 #define UDF_ID_ALLOC                   "*UDF Virtual Alloc Tbl"
 #define UDF_ID_SPARING                 "*UDF Sparing Table"
+#define UDF_ID_METADATA                        "*UDF Metadata Partition"
 
-/* Identifier Suffix (UDF 2.01 2.1.5.3) */
+/* Identifier Suffix (UDF 2.50 2.1.5.3) */
 #define IS_DF_HARD_WRITE_PROTECT       0x01
 #define IS_DF_SOFT_WRITE_PROTECT       0x02
 
@@ -84,8 +85,8 @@ struct appIdentSuffix
        uint8_t         impUse[8];
 } __attribute__ ((packed));
 
-/* Logical Volume Integrity Descriptor (UDF 2.01 2.2.6) */
-/* Implementation Use (UDF 2.01 2.2.6.4) */
+/* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */
+/* Implementation Use (UDF 2.50 2.2.6.4) */
 struct logicalVolIntegrityDescImpUse
 {
        regid           impIdent;
@@ -97,8 +98,8 @@ struct logicalVolIntegrityDescImpUse
        uint8_t         impUse[0];
 } __attribute__ ((packed));
 
-/* Implementation Use Volume Descriptor (UDF 2.01 2.2.7) */
-/* Implementation Use (UDF 2.01 2.2.7.2) */
+/* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */
+/* Implementation Use (UDF 2.50 2.2.7.2) */
 struct impUseVolDescImpUse
 {
        charspec        LVICharset;
@@ -120,7 +121,7 @@ struct udfPartitionMap2
        uint16_t        partitionNum;
 } __attribute__ ((packed));
 
-/* Virtual Partition Map (UDF 2.01 2.2.8) */
+/* Virtual Partition Map (UDF 2.50 2.2.8) */
 struct virtualPartitionMap
 {
        uint8_t         partitionMapType;
@@ -132,7 +133,7 @@ struct virtualPartitionMap
        uint8_t         reserved2[24];
 } __attribute__ ((packed));
 
-/* Sparable Partition Map (UDF 2.01 2.2.9) */
+/* Sparable Partition Map (UDF 2.50 2.2.9) */
 struct sparablePartitionMap
 {
        uint8_t         partitionMapType;
@@ -148,25 +149,43 @@ struct sparablePartitionMap
        uint32_t        locSparingTable[4];
 } __attribute__ ((packed));
 
+/* Metadata Partition Map (UDF 2.4.0 2.2.10) */
+struct metadataPartitionMap
+{
+       uint8_t         partitionMapType;
+       uint8_t         partitionMapLength;
+       uint8_t         reserved1[2];
+       regid           partIdent;
+       uint16_t        volSeqNum;
+       uint16_t        partitionNum;
+       uint32_t        metadataFileLoc;
+       uint32_t        metadataMirrorFileLoc;
+       uint32_t        metadataBitmapFileLoc;
+       uint32_t        allocUnitSize;
+       uint16_t        alignUnitSize;
+       uint8_t         flags;
+       uint8_t         reserved2[5];
+} __attribute__ ((packed));
+
 /* Virtual Allocation Table (UDF 1.5 2.2.10) */
 struct virtualAllocationTable15
 {
        uint32_t        VirtualSector[0];
-       regid           ident;
-       uint32_t        previousVATICB;
+       regid           vatIdent;
+       uint32_t        previousVATICBLoc;
 } __attribute__ ((packed));  
 
 #define ICBTAG_FILE_TYPE_VAT15         0x00U
 
-/* Virtual Allocation Table (UDF 2.01 2.2.10) */
+/* Virtual Allocation Table (UDF 2.50 2.2.11) */
 struct virtualAllocationTable20
 {
        uint16_t        lengthHeader;
        uint16_t        lengthImpUse;
        dstring         logicalVolIdent[128];
-       uint32_t        previousVatICBLoc;
-       uint32_t        numFIDSFiles;
-       uint32_t        numFIDSDirectories;
+       uint32_t        previousVATICBLoc;
+       uint32_t        numFiles;
+       uint32_t        numDirs;
        uint16_t        minReadRevision;
        uint16_t        minWriteRevision;
        uint16_t        maxWriteRevision;
@@ -177,7 +196,7 @@ struct virtualAllocationTable20
 
 #define ICBTAG_FILE_TYPE_VAT20         0xF8U
 
-/* Sparing Table (UDF 2.01 2.2.11) */
+/* Sparing Table (UDF 2.50 2.2.12) */
 struct sparingEntry
 {
        uint32_t        origLocation;
@@ -195,7 +214,12 @@ struct sparingTable
                        mapEntry[0];
 } __attribute__ ((packed));
 
-/* struct long_ad ICB - ADImpUse (UDF 2.01 2.2.4.3) */
+/* Metadata File (and Metadata Mirror File) (UDF 2.50 2.2.13.1) */
+#define ICBTAG_FILE_TYPE_MAIN          0xFA
+#define ICBTAG_FILE_TYPE_MIRROR                0xFB
+#define ICBTAG_FILE_TYPE_BITMAP                0xFC
+
+/* struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */
 struct allocDescImpUse
 {
        uint16_t        flags;
@@ -204,18 +228,18 @@ struct allocDescImpUse
 
 #define AD_IU_EXT_ERASED               0x0001
 
-/* Real-Time Files (UDF 2.01 6.11) */
+/* Real-Time Files (UDF 2.50 6.11) */
 #define ICBTAG_FILE_TYPE_REALTIME      0xF9U
 
-/* Implementation Use Extended Attribute (UDF 2.01 3.3.4.5) */
-/* FreeEASpace (UDF 2.01 3.3.4.5.1.1) */
+/* Implementation Use Extended Attribute (UDF 2.50 3.3.4.5) */
+/* FreeEASpace (UDF 2.50 3.3.4.5.1.1) */
 struct freeEaSpace
 {
        uint16_t        headerChecksum;
        uint8_t         freeEASpace[0];
 } __attribute__ ((packed));
 
-/* DVD Copyright Management Information (UDF 2.01 3.3.4.5.1.2) */
+/* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */
 struct DVDCopyrightImpUse 
 {
        uint16_t        headerChecksum;
@@ -224,21 +248,21 @@ struct DVDCopyrightImpUse
        uint8_t         protectionSystemInfo[4];
 } __attribute__ ((packed));
 
-/* Application Use Extended Attribute (UDF 2.01 3.3.4.6) */
-/* FreeAppEASpace (UDF 2.01 3.3.4.6.1) */
+/* Application Use Extended Attribute (UDF 2.50 3.3.4.6) */
+/* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */
 struct freeAppEASpace
 {
        uint16_t        headerChecksum;
        uint8_t         freeEASpace[0];
 } __attribute__ ((packed));
 
-/* UDF Defined System Stream (UDF 2.01 3.3.7) */
+/* UDF Defined System Stream (UDF 2.50 3.3.7) */
 #define UDF_ID_UNIQUE_ID               "*UDF Unique ID Mapping Data"
 #define UDF_ID_NON_ALLOC               "*UDF Non-Allocatable Space"
 #define UDF_ID_POWER_CAL               "*UDF Power Cal Table"
 #define UDF_ID_BACKUP                  "*UDF Backup"
 
-/* Operating System Identifiers (UDF 2.01 6.3) */
+/* Operating System Identifiers (UDF 2.50 6.3) */
 #define UDF_OS_CLASS_UNDEF             0x00U
 #define UDF_OS_CLASS_DOS               0x01U
 #define UDF_OS_CLASS_OS2               0x02U
@@ -254,6 +278,7 @@ struct freeAppEASpace
 #define UDF_OS_ID_DOS                  0x00U
 #define UDF_OS_ID_OS2                  0x00U
 #define UDF_OS_ID_MAC                  0x00U
+#define UDF_OS_ID_MAX_OSX              0x01U
 #define UDF_OS_ID_UNIX                 0x00U
 #define UDF_OS_ID_AIX                  0x01U
 #define UDF_OS_ID_SOLARIS              0x02U
index 584833bdd0d0d1ff3577c868e9fd81fa48c21f0b..d23edb52ca537447f5dde1f9ce9590e2bd1a32ac 100644 (file)
@@ -26,7 +26,7 @@
  *  Each contributing author retains all rights to their own work.
  *
  *  (C) 1998 Dave Boynton
- *  (C) 1998-2001 Ben Fennema
+ *  (C) 1998-2004 Ben Fennema
  *  (C) 2000 Stelias Computing Inc
  *
  * HISTORY
@@ -57,6 +57,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/vmalloc.h>
 #include <asm/byteorder.h>
 
 #include <linux/udf_fs.h>
@@ -133,7 +134,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
        struct udf_inode_info *ei = (struct udf_inode_info *) foo;
 
        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
+           SLAB_CTOR_CONSTRUCTOR)
+       {
                ei->i_ext.i_data = NULL;
                inode_init_once(&ei->vfs_inode);
        }
@@ -324,106 +326,106 @@ udf_parse_options(char *options, struct udf_options *uopt)
        if (!options)
                return 1;
 
-       while ((p = strsep(&options, ",")) != NULL) {
+       while ((p = strsep(&options, ",")) != NULL)
+       {
                substring_t args[MAX_OPT_ARGS];
                int token;
                if (!*p)
                        continue;
 
                token = match_token(p, tokens, args);
-               switch (token) {
-               case Opt_novrs:
-                       uopt->novrs = 1;
-                       break;
-               case Opt_bs:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       uopt->blocksize = option;
-                       break;
-               case Opt_unhide:
-                       uopt->flags |= (1 << UDF_FLAG_UNHIDE);
-                       break;
-               case Opt_undelete:
-                       uopt->flags |= (1 << UDF_FLAG_UNDELETE);
-                       break;
-               case Opt_noadinicb:
-                       uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
-                       break;
-               case Opt_adinicb:
-                       uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
-                       break;
-               case Opt_shortad:
-                       uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
-                       break;
-               case Opt_longad:
-                       uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
-                       break;
-               case Opt_gid:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->gid = option;
-                       break;
-               case Opt_uid:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->uid = option;
-                       break;
-               case Opt_umask:
-                       if (match_octal(args, &option))
-                               return 0;
-                       uopt->umask = option;
-                       break;
-               case Opt_nostrict:
-                       uopt->flags &= ~(1 << UDF_FLAG_STRICT);
-                       break;
-               case Opt_session:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->session = option;
-                       break;
-               case Opt_lastblock:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->lastblock = option;
-                       break;
-               case Opt_anchor:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->anchor = option;
-                       break;
-               case Opt_volume:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->volume = option;
-                       break;
-               case Opt_partition:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->partition = option;
-                       break;
-               case Opt_fileset:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->fileset = option;
-                       break;
-               case Opt_rootdir:
-                       if (match_int(args, &option))
-                               return 0;
-                       uopt->rootdir = option;
-                       break;
-               case Opt_utf8:
-                       uopt->flags |= (1 << UDF_FLAG_UTF8);
-                       break;
+               switch (token)
+               {
+                       case Opt_novrs:
+                               uopt->novrs = 1;
+                       case Opt_bs:
+                               if (match_int(&args[0], &option))
+                                       return 0;
+                               uopt->blocksize = option;
+                               break;
+                       case Opt_unhide:
+                               uopt->flags |= (1 << UDF_FLAG_UNHIDE);
+                               break;
+                       case Opt_undelete:
+                               uopt->flags |= (1 << UDF_FLAG_UNDELETE);
+                               break;
+                       case Opt_noadinicb:
+                               uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
+                               break;
+                       case Opt_adinicb:
+                               uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
+                               break;
+                       case Opt_shortad:
+                               uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
+                               break;
+                       case Opt_longad:
+                               uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
+                               break;
+                       case Opt_gid:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->gid = option;
+                               break;
+                       case Opt_uid:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->uid = option;
+                               break;
+                       case Opt_umask:
+                               if (match_octal(args, &option))
+                                       return 0;
+                               uopt->umask = option;
+                               break;
+                       case Opt_nostrict:
+                               uopt->flags &= ~(1 << UDF_FLAG_STRICT);
+                               break;
+                       case Opt_session:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->session = option;
+                               break;
+                       case Opt_lastblock:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->lastblock = option;
+                               break;
+                       case Opt_anchor:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->anchor = option;
+                               break;
+                       case Opt_volume:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->volume = option;
+                               break;
+                       case Opt_partition:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->partition = option;
+                               break;
+                       case Opt_fileset:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->fileset = option;
+                               break;
+                       case Opt_rootdir:
+                               if (match_int(args, &option))
+                                       return 0;
+                               uopt->rootdir = option;
+                               break;
+                       case Opt_utf8:
+                               uopt->flags |= (1 << UDF_FLAG_UTF8);
+                               break;
 #if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
-               case Opt_iocharset:
-                       uopt->nls_map = load_nls(args[0].from);
-                       uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
-                       break;
+                       case Opt_iocharset:
+                               uopt->nls_map = load_nls(args[0].from);
+                               uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
+                               break;
 #endif
-               default:
-                       printk(KERN_ERR "udf: bad mount option \"%s\" "
-                                       "or missing value\n",
-                               p);
+                       default:
+                               printk(KERN_ERR "udf: bad mount option \"%s\" "
+                                               "or missing value\n", p);
                        return 0;
                }
        }
@@ -1651,23 +1653,9 @@ error_out:
                if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
                        iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
                if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
-               {
-                       for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_uspace); i++)
-                       {
-                               if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i))
-                                       udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i));
-                       }
-                       kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
-               }
+                       UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace);
                if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
-               {
-                       for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_fspace); i++)
-                       {
-                               if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i))
-                                       udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i));
-                       }
-                       kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
-               }
+                       UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace);
                if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
                {
                        for (i=0; i<4; i++)
@@ -1743,23 +1731,9 @@ udf_put_super(struct super_block *sb)
                if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
                        iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
                if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
-               {
-                       for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_uspace); i++)
-                       {
-                               if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i))
-                                       udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i));
-                       }
-                       kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
-               }
+                       UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace);
                if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
-               {
-                       for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_fspace); i++)
-                       {
-                               if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i))
-                                       udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i));
-                       }
-                       kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
-               }
+                       UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace);
                if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
                {
                        for (i=0; i<4; i++)
@@ -1804,7 +1778,7 @@ udf_statfs(struct super_block *sb, struct kstatfs *buf)
                le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + buf->f_bfree;
        buf->f_ffree = buf->f_bfree;
        /* __kernel_fsid_t f_fsid */
-       buf->f_namelen = UDF_NAME_LEN;
+       buf->f_namelen = UDF_NAME_LEN-2;
 
        return 0;
 }
index 16e64daf61d1b3f2becc06ea16efd5914a48beb0..b51ea9cf079901f073f52d4f663911cac4bc3cff 100644 (file)
@@ -15,7 +15,7 @@
  *             ftp://prep.ai.mit.edu/pub/gnu/GPL
  *     Each contributing author retains all rights to their own work.
  *
- *  (C) 1999-2001 Ben Fennema
+ *  (C) 1999-2004 Ben Fennema
  *  (C) 1999 Stelias Computing Inc
  *
  * HISTORY
@@ -66,6 +66,67 @@ static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
        }
 }
 
+void udf_discard_prealloc(struct inode * inode)
+{
+       lb_addr bloc, eloc;
+       uint32_t extoffset = 0, elen, nelen;
+       uint64_t lbcount = 0;
+       int8_t etype = -1, netype;
+       struct buffer_head *bh = NULL;
+       int adsize;
+
+       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
+               inode->i_size == UDF_I_LENEXTENTS(inode))
+       {
+               return;
+       }
+
+       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
+               adsize = sizeof(short_ad);
+       else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
+               adsize = sizeof(long_ad);
+       else
+               adsize = 0;
+
+       bloc = UDF_I_LOCATION(inode);
+
+       while ((netype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+       {
+               etype = netype;
+               lbcount += elen;
+               if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
+               {
+                       nelen = elen - (lbcount - inode->i_size);
+                       extent_trunc(inode, bloc, extoffset-adsize, eloc, etype, elen, bh, nelen);
+                       lbcount = inode->i_size;
+               }
+       }
+       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
+       {
+               extoffset -= adsize;
+               lbcount -= elen;
+               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
+               if (!bh)
+               {
+                       UDF_I_LENALLOC(inode) = extoffset - udf_file_entry_alloc_offset(inode);
+                       mark_inode_dirty(inode);
+               }
+               else
+               {
+                       struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+                       aed->lengthAllocDescs = cpu_to_le32(extoffset - sizeof(struct allocExtDesc));
+                       if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
+                               udf_update_tag(bh->b_data, extoffset);
+                       else
+                               udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(bh, inode);
+               }
+       }
+       UDF_I_LENEXTENTS(inode) = lbcount;
+
+       udf_release_data(bh);
+}
+
 void udf_truncate_extents(struct inode * inode)
 {
        lb_addr bloc, eloc, neloc = { 0, 0 };
index 88bda177205b40c9c4154197e0678473e2671061..0e54922daa0917ef802a73edf998f467c7b09c9d 100644 (file)
@@ -64,13 +64,14 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
 {\
        int nr_groups = ((UDF_SB_PARTLEN((X),(Y)) + (sizeof(struct spaceBitmapDesc) << 3) +\
                ((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\
-       UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(sizeof(struct udf_bitmap) +\
-               sizeof(struct buffer_head *) * nr_groups,\
-               GFP_KERNEL);\
+       int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * nr_groups);\
+       if (size <= PAGE_SIZE)\
+               UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(size, GFP_KERNEL);\
+       else\
+               UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = vmalloc(size);\
        if (UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap != NULL)\
        {\
-               memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00,\
-                       sizeof(struct udf_bitmap) + sizeof(struct buffer_head *) * nr_groups);\
+               memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00, size);\
                UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\
                        (struct buffer_head **)(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap + 1);\
                UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups = nr_groups;\
@@ -81,6 +82,21 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
        }\
 }
 
+#define UDF_SB_FREE_BITMAP(X,Y,Z)\
+{\
+       int i;\
+       int nr_groups = UDF_SB_BITMAP_NR_GROUPS(X,Y,Z);\
+       int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * nr_groups);\
+       for (i=0; i<nr_groups; i++)\
+       {\
+               if (UDF_SB_BITMAP(X,Y,Z,i))\
+                       udf_release_data(UDF_SB_BITMAP(X,Y,Z,i));\
+       }\
+       if (size <= PAGE_SIZE)\
+               kfree(UDF_SB_PARTMAPS(X)[Y].Z.s_bitmap);\
+       else\
+               vfree(UDF_SB_PARTMAPS(X)[Y].Z.s_bitmap);\
+}
 
 #define UDF_QUERY_FLAG(X,Y)                    ( UDF_SB(X)->s_flags & ( 1 << (Y) ) )
 #define UDF_SET_FLAG(X,Y)                      ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) )
@@ -99,7 +115,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
 #define UDF_SB_PARTFUNC(X,Y)                   ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func )
 #define UDF_SB_PARTFLAGS(X,Y)                  ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_flags )
 #define UDF_SB_BITMAP(X,Y,Z,I)                 ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap[I] )
-#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups )
+#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z)         ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups )
 
 #define UDF_SB_VOLIDENT(X)                     ( UDF_SB(X)->s_volident )
 #define UDF_SB_NUMPARTS(X)                     ( UDF_SB(X)->s_partitions )
index 683e900e3a8fd91a6679df131c100cc513767d6b..ecff2e19f397f5dcf6bbe2a49bbe38941b93714a 100644 (file)
@@ -21,7 +21,7 @@
 #define UDF_EXTENT_FLAG_MASK   0xC0000000
 
 #define UDF_NAME_PAD           4
-#define UDF_NAME_LEN           255
+#define UDF_NAME_LEN           256
 #define UDF_PATH_LEN           1023
 
 #define udf_file_entry_alloc_offset(inode)\
@@ -59,13 +59,6 @@ struct udf_fileident_bh
        int eoffset;
 };
 
-struct udf_directory_record
-{
-       uint32_t        d_parent;
-       uint32_t        d_inode;
-       uint32_t        d_name[255];
-};
-
 struct udf_vds_record
 {
        uint32_t block;
@@ -81,7 +74,7 @@ struct generic_desc
 struct ustr
 {
        uint8_t u_cmpID;
-       uint8_t u_name[UDF_NAME_LEN];
+       uint8_t u_name[UDF_NAME_LEN-2];
        uint8_t u_len;
 };
 
@@ -116,19 +109,16 @@ extern int8_t udf_insert_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, s
 extern int8_t udf_delete_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
 extern int8_t udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
 extern int8_t udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, 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_tgetblk(struct super_block *, int);
 extern struct buffer_head *udf_tread(struct super_block *, int);
-extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t, struct buffer_head **);
-extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t, struct buffer_head **);
+extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t);
+extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t);
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
 extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
 extern void udf_release_data(struct buffer_head *);
-extern uint32_t udf64_low32(uint64_t);
-extern uint32_t udf64_high32(uint64_t);
 extern void udf_update_tag(char *, int);
 extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
 
@@ -154,6 +144,7 @@ extern void udf_free_inode(struct inode *);
 extern struct inode * udf_new_inode (struct inode *, int, int *);
 
 /* truncate.c */
+extern void udf_discard_prealloc(struct inode *);
 extern void udf_truncate_extents(struct inode *);
 
 /* balloc.c */
index 5f9e87f1cc479c5521fb160dd446a30a2ed33abb..5a80efd8debc9b7357668743a45411618c6c4d64 100644 (file)
@@ -36,7 +36,7 @@ static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
 
 static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
 {
-       if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
+       if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN-2) )
                return 0;
        memset(dest, 0, sizeof(struct ustr));
        memcpy(dest->u_name, src, strlen);
@@ -181,14 +181,14 @@ int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
 static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
 {
        unsigned c, i, max_val, utf_char;
-       int utf_cnt;
-       int u_len = 0;
+       int utf_cnt, u_len;
 
        memset(ocu, 0, sizeof(dstring) * length);
        ocu[0] = 8;
        max_val = 0xffU;
 
 try_again:
+       u_len = 0U;
        utf_char = 0U;
        utf_cnt = 0U;
        for (i = 0U; i < utf->u_len; i++)
@@ -264,8 +264,8 @@ try_again:
        if (utf_cnt)
        {
 error_out:
-               printk(KERN_ERR "udf: bad UTF-8 character\n");
-               return 0;
+               ocu[++u_len] = '?';
+               printk(KERN_DEBUG "udf: bad UTF-8 character\n");
        }
 
        ocu[length - 1] = (uint8_t)u_len + 1;
@@ -318,21 +318,21 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, i
 {
        unsigned len, i, max_val;
        uint16_t uni_char;
-       int uni_cnt;
-       int u_len = 0;
+       int u_len;
 
        memset(ocu, 0, sizeof(dstring) * length);
        ocu[0] = 8;
        max_val = 0xffU;
 
 try_again:
-       uni_char = 0U;
-       uni_cnt = 0U;
+       u_len = 0U;
        for (i = 0U; i < uni->u_len; i++)
        {
                len = nls->char2uni(&uni->u_name[i], uni->u_len-i, &uni_char);
+               if (len <= 0)
+                       continue;
 
-               if (len == 2 && max_val == 0xff)
+               if (uni_char > max_val)
                {
                        max_val = 0xffffU;
                        ocu[0] = (uint8_t)0x10U;
@@ -340,11 +340,9 @@ try_again:
                }
                
                if (max_val == 0xffffU)
-               {
                        ocu[++u_len] = (uint8_t)(uni_char >> 8);
-                       i++;
-               }
                ocu[++u_len] = (uint8_t)(uni_char & 0xffU);
+               i += len - 1;
        }
 
        ocu[length - 1] = (uint8_t)u_len + 1;
index 45c1a58688abe4d3bda04ae19e919bc41e785335..4f19d23eb9414e5314089fbd05e265656d1821a0 100644 (file)
@@ -8,7 +8,7 @@
  *  OSTA-UDF(tm) = Optical Storage Technology Association
  *  Universal Disk Format.
  *
- *  This code is based on version 2.00 of the UDF specification,
+ *  This code is based on version 2.50 of the UDF specification,
  *  and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
  *    http://www.osta.org/ *    http://www.ecma.ch/
  *    http://www.iso.org/
@@ -24,7 +24,7 @@
  *             ftp://prep.ai.mit.edu/pub/gnu/GPL
  *     Each contributing author retains all rights to their own work.
  *
- *  (C) 1999-2000 Ben Fennema
+ *  (C) 1999-2004 Ben Fennema
  *  (C) 1999-2000 Stelias Computing Inc
  *
  * HISTORY
@@ -37,8 +37,8 @@
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS    8
 
-#define UDFFS_DATE                     "2002/11/15"
-#define UDFFS_VERSION                  "0.9.7"
+#define UDFFS_DATE                     "2004/29/09"
+#define UDFFS_VERSION                  "0.9.8.1"
 
 #define UDFFS_DEBUG