From: Ben Fennema - 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 --- CREDITS | 3 Documentation/filesystems/udf.txt | 12 -- MAINTAINERS | 2 fs/udf/dir.c | 4 fs/udf/file.c | 6 - fs/udf/inode.c | 106 +++++++++++------ fs/udf/misc.c | 100 ++++------------ fs/udf/namei.c | 36 ++---- fs/udf/osta_udf.h | 81 ++++++++----- fs/udf/super.c | 227 ++++++++++++++++---------------------- fs/udf/truncate.c | 63 ++++++++++ fs/udf/udf_sb.h | 28 +++- fs/udf/udfdecl.h | 19 --- fs/udf/unicode.c | 24 +--- include/linux/udf_fs.h | 8 - 15 files changed, 376 insertions(+), 343 deletions(-) diff -puN CREDITS~udffs-update CREDITS --- 25/CREDITS~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/CREDITS 2004-02-29 20:40:17.000000000 -0800 @@ -984,8 +984,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 diff -puN Documentation/filesystems/udf.txt~udffs-update Documentation/filesystems/udf.txt --- 25/Documentation/filesystems/udf.txt~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/Documentation/filesystems/udf.txt 2004-02-29 20:40:17.000000000 -0800 @@ -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 supporte 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 p ------------------------------------------------------------------------------- -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 diff -puN fs/udf/dir.c~udffs-update fs/udf/dir.c --- 25/fs/udf/dir.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/dir.c 2004-02-29 20:40:17.000000000 -0800 @@ -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, struc 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; diff -puN fs/udf/file.c~udffs-update fs/udf/file.c --- 25/fs/udf/file.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/file.c 2004-02-29 20:40:17.000000000 -0800 @@ -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 { if (filp->f_mode & FMODE_WRITE) { - lock_kernel(); + down(&inode->i_sem); udf_discard_prealloc(inode); - unlock_kernel(); + up(&inode->i_sem); } return 0; } diff -puN fs/udf/inode.c~udffs-update fs/udf/inode.c --- 25/fs/udf/inode.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/inode.c 2004-02-29 20:40:17.000000000 -0800 @@ -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 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 ino 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 ino 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 ino 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 ino } 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 ino 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 ino 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 ino } } } + 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 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 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 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 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 } 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, in 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, in 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, in 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, 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 *in 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)) diff -puN fs/udf/misc.c~udffs-update fs/udf/misc.c --- 25/fs/udf/misc.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/misc.c 2004-02-29 20:40:17.000000000 -0800 @@ -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 @@ -34,18 +34,6 @@ #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 bl 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 * inod 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 * inod 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 * inod } } /* 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 * inod 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 * inod offset += le32_to_cpu(gaf->attrLength); } } - - udf_release_data(*bh); - if (eaicb.extLength) - { - /* TODO */ - } return NULL; } diff -puN fs/udf/namei.c~udffs-update fs/udf/namei.c --- 25/fs/udf/namei.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/namei.c 2004-02-29 20:40:17.000000000 -0800 @@ -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 @@ -36,11 +36,11 @@ #include #include -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 { 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 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 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 den 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 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 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 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 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_ { 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<i_nlink))-1) diff -puN fs/udf/osta_udf.h~udffs-update fs/udf/osta_udf.h --- 25/fs/udf/osta_udf.h~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/osta_udf.h 2004-02-29 20:40:17.000000000 -0800 @@ -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 + * Copyright (c) 2001-2004 Ben Fennema * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,12 +37,12 @@ #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 diff -puN fs/udf/super.c~udffs-update fs/udf/super.c --- 25/fs/udf/super.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/super.c 2004-02-29 20:40:17.000000000 -0800 @@ -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 @@ -133,7 +133,8 @@ static void init_once(void * foo, kmem_c 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 +325,106 @@ udf_parse_options(char *options, struct 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 +1652,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; inumDirs)) : 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; } diff -puN fs/udf/truncate.c~udffs-update fs/udf/truncate.c --- 25/fs/udf/truncate.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/truncate.c 2004-02-29 20:40:17.000000000 -0800 @@ -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 * } } +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 }; diff -puN fs/udf/udfdecl.h~udffs-update fs/udf/udfdecl.h --- 25/fs/udf/udfdecl.h~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/udfdecl.h 2004-02-29 20:40:17.000000000 -0800 @@ -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 ino 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 */ diff -puN fs/udf/udf_sb.h~udffs-update fs/udf/udf_sb.h --- 25/fs/udf/udf_sb.h~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/udf_sb.h 2004-02-29 20:40:17.000000000 -0800 @@ -64,13 +64,14 @@ static inline struct udf_sb_info *UDF_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 }\ } +#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; is_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 #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 ) diff -puN fs/udf/unicode.c~udffs-update fs/udf/unicode.c --- 25/fs/udf/unicode.c~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/fs/udf/unicode.c 2004-02-29 20:40:17.000000000 -0800 @@ -36,7 +36,7 @@ static int udf_translate_to_linux(uint8_ 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, st 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 { 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; diff -puN include/linux/udf_fs.h~udffs-update include/linux/udf_fs.h --- 25/include/linux/udf_fs.h~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/include/linux/udf_fs.h 2004-02-29 20:40:17.000000000 -0800 @@ -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 diff -puN MAINTAINERS~udffs-update MAINTAINERS --- 25/MAINTAINERS~udffs-update 2004-02-29 20:40:17.000000000 -0800 +++ 25-akpm/MAINTAINERS 2004-02-29 20:40:17.000000000 -0800 @@ -2043,8 +2043,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 _