Commit 5cc6e01a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] UDF filesystem update

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
parent 5289ba41
......@@ -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: Jrgen Fischer
......
*
* ./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>
......@@ -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
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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))
......
......@@ -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 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;
}
......
......@@ -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 <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)
......
/*
* 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
......@@ -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
......
......@@ -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 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
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;
}
......
......@@ -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 };
......
......@@ -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 )
......
......@@ -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 */
......
......@@ -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 @@ static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
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 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, i
}
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;
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment