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 ...@@ -975,8 +975,7 @@ N: Ben Fennema
E: bfennema@falcon.csc.calpoly.edu E: bfennema@falcon.csc.calpoly.edu
W: http://www.csc.calpoly.edu/~bfennema W: http://www.csc.calpoly.edu/~bfennema
D: UDF filesystem D: UDF filesystem
S: 21760 Irma Lyle Drive S: (ask for current address)
S: Los Gatos, CA 95033-8942
S: USA S: USA
N: Jrgen Fischer N: Jrgen Fischer
......
* *
* ./Documentation/filesystems/udf.txt * ./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, If you encounter problems with reading UDF discs using this driver,
please report them to linux_udf@hpesjro.fc.hp.com, which is the please report them to linux_udf@hpesjro.fc.hp.com, which is the
...@@ -47,15 +47,11 @@ The following expect a offset from the partition root. ...@@ -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: For the latest version and toolset see:
http://www.csc.calpoly.edu/~bfennema/udf.html
http://linux-udf.sourceforge.net/ http://linux-udf.sourceforge.net/
Documentation on UDF and ECMA 167 is available FREE from: Documentation on UDF and ECMA 167 is available FREE from:
http://www.osta.org/ http://www.osta.org/
http://www.ecma.ch/ http://www.ecma-international.org/
Ben Fennema <bfennema@falcon.csc.calpoly.edu> Ben Fennema <bfennema@falcon.csc.calpoly.edu>
...@@ -2037,8 +2037,6 @@ S: Maintained ...@@ -2037,8 +2037,6 @@ S: Maintained
UDF FILESYSTEM UDF FILESYSTEM
P: Ben Fennema P: Ben Fennema
M: bfennema@falcon.csc.calpoly.edu M: bfennema@falcon.csc.calpoly.edu
P: Dave Boynton
M: dave@trylinux.com
L: linux_udf@hpesjro.fc.hp.com L: linux_udf@hpesjro.fc.hp.com
W: http://linux-udf.sourceforge.net W: http://linux-udf.sourceforge.net
S: Maintained S: Maintained
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL * ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work. * Each contributing author retains all rights to their own work.
* *
* (C) 1998-2001 Ben Fennema * (C) 1998-2004 Ben Fennema
* *
* HISTORY * HISTORY
* *
...@@ -111,7 +111,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d ...@@ -111,7 +111,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
int block, iblock; int block, iblock;
loff_t nf_pos = filp->f_pos - 1; loff_t nf_pos = filp->f_pos - 1;
int flen; int flen;
char fname[255]; char fname[UDF_NAME_LEN];
char *nameptr; char *nameptr;
uint16_t liu; uint16_t liu;
uint8_t lfi; uint8_t lfi;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Each contributing author retains all rights to their own work. * Each contributing author retains all rights to their own work.
* *
* (C) 1998-1999 Dave Boynton * (C) 1998-1999 Dave Boynton
* (C) 1998-2001 Ben Fennema * (C) 1998-2004 Ben Fennema
* (C) 1999-2000 Stelias Computing Inc * (C) 1999-2000 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -247,9 +247,9 @@ static int udf_release_file(struct inode * inode, struct file * filp) ...@@ -247,9 +247,9 @@ static int udf_release_file(struct inode * inode, struct file * filp)
{ {
if (filp->f_mode & FMODE_WRITE) if (filp->f_mode & FMODE_WRITE)
{ {
lock_kernel(); down(&inode->i_sem);
udf_discard_prealloc(inode); udf_discard_prealloc(inode);
unlock_kernel(); up(&inode->i_sem);
} }
return 0; return 0;
} }
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Each contributing author retains all rights to their own work. * Each contributing author retains all rights to their own work.
* *
* (C) 1998 Dave Boynton * (C) 1998 Dave Boynton
* (C) 1998-2001 Ben Fennema * (C) 1998-2004 Ben Fennema
* (C) 1999-2000 Stelias Computing Inc * (C) 1999-2000 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -84,9 +84,9 @@ void udf_put_inode(struct inode * inode) ...@@ -84,9 +84,9 @@ void udf_put_inode(struct inode * inode)
{ {
if (!(inode->i_sb->s_flags & MS_RDONLY)) if (!(inode->i_sb->s_flags & MS_RDONLY))
{ {
lock_kernel(); down(&inode->i_sem);
udf_discard_prealloc(inode); udf_discard_prealloc(inode);
unlock_kernel(); up(&inode->i_sem);
} }
} }
...@@ -130,15 +130,6 @@ void udf_clear_inode(struct inode *inode) ...@@ -130,15 +130,6 @@ void udf_clear_inode(struct inode *inode)
UDF_I_DATA(inode) = NULL; 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) static int udf_writepage(struct page *page, struct writeback_control *wbc)
{ {
return block_write_full_page(page, udf_get_block, 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, ...@@ -516,11 +507,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
else else
lastblock = 1; lastblock = 1;
} }
udf_release_data(nbh);
if (!pbh)
pbh = cbh;
else
udf_release_data(cbh); udf_release_data(cbh);
udf_release_data(nbh);
/* if the current extent is not recorded but allocated, get the /* if the current extent is not recorded but allocated, get the
block in the extent corresponding to the requested block */ 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 ...@@ -595,7 +583,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
int curr = *c; int curr = *c;
int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) + int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits; 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) if (blen == 1)
; ;
...@@ -612,7 +600,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl ...@@ -612,7 +600,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
if (offset) 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); udf_free_blocks(inode->i_sb, inode, laarr[curr].extLocation, 0, offset);
laarr[curr].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | 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 ...@@ -621,7 +609,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
laarr[curr].extLocation.partitionReferenceNum = 0; laarr[curr].extLocation.partitionReferenceNum = 0;
} }
else else
laarr[curr].extLength = type | laarr[curr].extLength = (etype << 30) |
(offset << inode->i_sb->s_blocksize_bits); (offset << inode->i_sb->s_blocksize_bits);
curr ++; curr ++;
(*c) ++; (*c) ++;
...@@ -629,7 +617,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl ...@@ -629,7 +617,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
} }
laarr[curr].extLocation.logicalBlockNum = newblocknum; 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 = laarr[curr].extLocation.partitionReferenceNum =
UDF_I_LOCATION(inode).partitionReferenceNum; UDF_I_LOCATION(inode).partitionReferenceNum;
laarr[curr].extLength = EXT_RECORDED_ALLOCATED | laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
...@@ -638,9 +626,9 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl ...@@ -638,9 +626,9 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
if (blen != offset + 1) 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].extLocation.logicalBlockNum += (offset + 1);
laarr[curr].extLength = type | laarr[curr].extLength = (etype << 30) |
((blen - (offset + 1)) << inode->i_sb->s_blocksize_bits); ((blen - (offset + 1)) << inode->i_sb->s_blocksize_bits);
curr ++; curr ++;
(*endnum) ++; (*endnum) ++;
...@@ -761,8 +749,8 @@ static void udf_merge_extents(struct inode *inode, ...@@ -761,8 +749,8 @@ static void udf_merge_extents(struct inode *inode,
laarr[i+1].extLength = (laarr[i+1].extLength - laarr[i+1].extLength = (laarr[i+1].extLength -
(laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1); UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1);
laarr[i].extLength = (UDF_EXTENT_LENGTH_MASK + 1) - laarr[i].extLength = (laarr[i].extLength & UDF_EXTENT_FLAG_MASK) +
inode->i_sb->s_blocksize; (UDF_EXTENT_LENGTH_MASK + 1) - inode->i_sb->s_blocksize;
laarr[i+1].extLocation.logicalBlockNum = laarr[i+1].extLocation.logicalBlockNum =
laarr[i].extLocation.logicalBlockNum + laarr[i].extLocation.logicalBlockNum +
((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >> ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >>
...@@ -781,6 +769,47 @@ static void udf_merge_extents(struct inode *inode, ...@@ -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) ...@@ -1014,7 +1043,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
struct extendedFileEntry *efe; struct extendedFileEntry *efe;
time_t convtime; time_t convtime;
long convtime_usec; long convtime_usec;
int offset, alen; int offset;
fe = (struct fileEntry *)bh->b_data; fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)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) ...@@ -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_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs); UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);
offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode); offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
alen = offset + UDF_I_LENALLOC(inode);
} }
else else
{ {
...@@ -1170,7 +1198,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -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_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs); UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);
offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode); offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
alen = offset + UDF_I_LENALLOC(inode);
} }
switch (fe->icbTag.fileType) switch (fe->icbTag.fileType)
...@@ -1211,6 +1238,11 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -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); init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
break; break;
} }
case ICBTAG_FILE_TYPE_SOCKET:
{
init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
break;
}
case ICBTAG_FILE_TYPE_SYMLINK: case ICBTAG_FILE_TYPE_SYMLINK:
{ {
inode->i_data.a_ops = &udf_symlink_aops; inode->i_data.a_ops = &udf_symlink_aops;
...@@ -1228,19 +1260,16 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -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)) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
{ {
struct buffer_head *tbh = NULL;
struct deviceSpec *dsea = struct deviceSpec *dsea =
(struct deviceSpec *) (struct deviceSpec *)
udf_get_extendedattr(inode, 12, 1, &tbh); udf_get_extendedattr(inode, 12, 1);
if (dsea) if (dsea)
{ {
init_special_inode(inode, inode->i_mode, MKDEV( init_special_inode(inode, inode->i_mode, MKDEV(
le32_to_cpu(dsea->majorDeviceIdent), le32_to_cpu(dsea->majorDeviceIdent),
le32_to_cpu(dsea->minorDeviceIdent) le32_to_cpu(dsea->minorDeviceIdent)));
));
/* Developer ID ??? */ /* Developer ID ??? */
udf_release_data(tbh);
} }
else else
{ {
...@@ -1372,17 +1401,16 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1372,17 +1401,16 @@ udf_update_inode(struct inode *inode, int do_sync)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
{ {
regid *eid; regid *eid;
struct buffer_head *tbh = NULL;
struct deviceSpec *dsea = struct deviceSpec *dsea =
(struct deviceSpec *) (struct deviceSpec *)
udf_get_extendedattr(inode, 12, 1, &tbh); udf_get_extendedattr(inode, 12, 1);
if (!dsea) if (!dsea)
{ {
dsea = (struct deviceSpec *) dsea = (struct deviceSpec *)
udf_add_extendedattr(inode, udf_add_extendedattr(inode,
sizeof(struct deviceSpec) + sizeof(struct deviceSpec) +
sizeof(regid), 12, 0x3, &tbh); sizeof(regid), 12, 0x3);
dsea->attrType = 12; dsea->attrType = 12;
dsea->attrSubtype = 1; dsea->attrSubtype = 1;
dsea->attrLength = sizeof(struct deviceSpec) + dsea->attrLength = sizeof(struct deviceSpec) +
...@@ -1396,8 +1424,6 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1396,8 +1424,6 @@ udf_update_inode(struct inode *inode, int do_sync)
eid->identSuffix[1] = UDF_OS_ID_LINUX; eid->identSuffix[1] = UDF_OS_ID_LINUX;
dsea->majorDeviceIdent = cpu_to_le32(imajor(inode)); dsea->majorDeviceIdent = cpu_to_le32(imajor(inode));
dsea->minorDeviceIdent = cpu_to_le32(iminor(inode)); dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));
mark_buffer_dirty_inode(tbh, inode);
udf_release_data(tbh);
} }
if (UDF_I_EFE(inode) == 0) if (UDF_I_EFE(inode) == 0)
...@@ -1493,6 +1519,8 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1493,6 +1519,8 @@ udf_update_inode(struct inode *inode, int do_sync)
fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR; fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;
else if (S_ISFIFO(inode->i_mode)) else if (S_ISFIFO(inode->i_mode))
fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO; 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) | icbflags = UDF_I_ALLOCTYPE(inode) |
((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) | ((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, ...@@ -1625,7 +1653,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
int err, loffset; int err, loffset;
lb_addr obloc = *bloc; 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))) obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
{ {
return -1; return -1;
...@@ -1833,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -1833,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
if (!(*extoffset)) if (!(*extoffset))
*extoffset = sizeof(struct allocExtDesc); *extoffset = sizeof(struct allocExtDesc);
ptr = (*bh)->b_data + *extoffset; 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)) switch (UDF_I_ALLOCTYPE(inode))
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Each contributing author retains all rights to their own work. * Each contributing author retains all rights to their own work.
* *
* (C) 1998 Dave Boynton * (C) 1998 Dave Boynton
* (C) 1998-2001 Ben Fennema * (C) 1998-2004 Ben Fennema
* (C) 1999-2000 Stelias Computing Inc * (C) 1999-2000 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -34,18 +34,6 @@ ...@@ -34,18 +34,6 @@
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.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 * extern struct buffer_head *
udf_tgetblk(struct super_block *sb, int block) udf_tgetblk(struct super_block *sb, int block)
{ {
...@@ -66,42 +54,24 @@ udf_tread(struct super_block *sb, int block) ...@@ -66,42 +54,24 @@ udf_tread(struct super_block *sb, int block)
extern struct genericFormat * extern struct genericFormat *
udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type, 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; uint8_t *ea = NULL, *ad = NULL;
long_ad eaicb;
int offset; int offset;
uint16_t crclen;
int i;
*bh = udf_tread(inode->i_sb, inode->i_ino); ea = UDF_I_DATA(inode);
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];
if (UDF_I_LENEATTR(inode)) if (UDF_I_LENEATTR(inode))
offset += UDF_I_LENEATTR(inode); ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
else else
{
ad = ea;
size += sizeof(struct extendedAttrHeaderDesc); size += sizeof(struct extendedAttrHeaderDesc);
}
ad = &(*bh)->b_data[offset]; offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
if (UDF_I_LENALLOC(inode)) UDF_I_LENALLOC(inode);
offset += UDF_I_LENALLOC(inode);
offset = inode->i_sb->s_blocksize - offset;
/* TODO - Check for FreeEASpace */ /* TODO - Check for FreeEASpace */
...@@ -121,7 +91,6 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type, ...@@ -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 || if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
{ {
udf_release_data(*bh);
return NULL; return NULL;
} }
} }
...@@ -130,8 +99,11 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type, ...@@ -130,8 +99,11 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
size -= sizeof(struct extendedAttrHeaderDesc); size -= sizeof(struct extendedAttrHeaderDesc);
UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc); UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD); eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
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.descVersion = cpu_to_le16(2);
eahd->descTag.tagSerialNum = cpu_to_le16(1); eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum); eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF); eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
eahd->appAttrLocation = 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, ...@@ -169,45 +141,30 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
} }
} }
/* rewrite CRC + checksum of eahd */ /* 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; UDF_I_LENEATTR(inode) += size;
return (struct genericFormat *)&ea[offset]; return (struct genericFormat *)&ea[offset];
} }
if (loc & 0x02) if (loc & 0x02)
{ {
} }
udf_release_data(*bh);
return NULL; return NULL;
} }
extern struct genericFormat * extern struct genericFormat *
udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype, udf_get_extendedattr(struct inode *inode, uint32_t type, uint8_t subtype)
struct buffer_head **bh)
{ {
struct genericFormat *gaf; struct genericFormat *gaf;
uint8_t *ea = NULL; uint8_t *ea = NULL;
long_ad eaicb;
uint32_t offset; uint32_t offset;
*bh = udf_tread(inode->i_sb, inode->i_ino); ea = UDF_I_DATA(inode);
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;
}
if (UDF_I_LENEATTR(inode)) if (UDF_I_LENEATTR(inode))
{ {
...@@ -218,7 +175,6 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype, ...@@ -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 || if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum) le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
{ {
udf_release_data(*bh);
return NULL; return NULL;
} }
...@@ -238,12 +194,6 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype, ...@@ -238,12 +194,6 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
offset += le32_to_cpu(gaf->attrLength); offset += le32_to_cpu(gaf->attrLength);
} }
} }
udf_release_data(*bh);
if (eaicb.extLength)
{
/* TODO */
}
return NULL; return NULL;
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL * ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work. * 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 * (C) 1999-2000 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -36,11 +36,11 @@ ...@@ -36,11 +36,11 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/buffer_head.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 0;
return !memcmp(name, qs->name, len); return !memcmp(name1, name2, len1);
} }
int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
...@@ -154,8 +154,8 @@ udf_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -154,8 +154,8 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
{ {
struct fileIdentDesc *fi=NULL; struct fileIdentDesc *fi=NULL;
loff_t f_pos; loff_t f_pos;
int block, flen; int block, namelen;
char fname[255]; char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
char *nameptr; char *nameptr;
uint8_t lfi; uint8_t lfi;
uint16_t liu; uint16_t liu;
...@@ -167,6 +167,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -167,6 +167,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
if (!dir) if (!dir)
return NULL; 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); f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2; fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
...@@ -250,15 +253,12 @@ udf_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -250,15 +253,12 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
if (!lfi) if (!lfi)
continue; 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); udf_release_data(bh);
return fi; return fi;
} }
} }
}
if (fibh->sbh != fibh->ebh) if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh); udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh); udf_release_data(fibh->sbh);
...@@ -306,7 +306,7 @@ udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) ...@@ -306,7 +306,7 @@ udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
struct udf_fileident_bh fibh; 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); return ERR_PTR(-ENAMETOOLONG);
lock_kernel(); lock_kernel();
...@@ -353,7 +353,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -353,7 +353,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN]; char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
int namelen; int namelen;
loff_t f_pos; loff_t f_pos;
int flen;
char *nameptr; char *nameptr;
loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2; loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
int nfidlen; int nfidlen;
...@@ -481,8 +480,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -481,8 +480,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (!lfi || !dentry) if (!lfi || !dentry)
continue; continue;
if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) && if (udf_match(namelen, name, lfi, nameptr))
udf_match(flen, fname, &(dentry->d_name)))
{ {
if (fibh->sbh != fibh->ebh) if (fibh->sbh != fibh->ebh)
udf_release_data(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 ...@@ -674,8 +672,8 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t
{ {
struct inode * inode; struct inode * inode;
struct udf_fileident_bh fibh; struct udf_fileident_bh fibh;
int err;
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
int err;
if (!old_valid_dev(rdev)) if (!old_valid_dev(rdev))
return -EINVAL; return -EINVAL;
...@@ -721,8 +719,8 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode) ...@@ -721,8 +719,8 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{ {
struct inode * inode; struct inode * inode;
struct udf_fileident_bh fibh; struct udf_fileident_bh fibh;
int err;
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
int err;
lock_kernel(); lock_kernel();
err = -EMLINK; err = -EMLINK;
...@@ -1119,8 +1117,8 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir, ...@@ -1119,8 +1117,8 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
struct udf_fileident_bh fibh; struct udf_fileident_bh fibh;
int err;
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
int err;
lock_kernel(); lock_kernel();
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
......
/* /*
* osta_udf.h * 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 * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -37,12 +37,12 @@ ...@@ -37,12 +37,12 @@
#ifndef _OSTA_UDF_H #ifndef _OSTA_UDF_H
#define _OSTA_UDF_H 1 #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_TYPE 0
#define UDF_CHAR_SET_INFO "OSTA Compressed Unicode" #define UDF_CHAR_SET_INFO "OSTA Compressed Unicode"
/* Entity Identifier (UDF 2.01 2.1.5) */ /* Entity Identifier (UDF 2.50 2.1.5) */
/* Identifiers (UDF 2.01 2.1.5.2) */ /* Identifiers (UDF 2.50 2.1.5.2) */
#define UDF_ID_DEVELOPER "*Linux UDFFS" #define UDF_ID_DEVELOPER "*Linux UDFFS"
#define UDF_ID_COMPLIANT "*OSTA UDF Compliant" #define UDF_ID_COMPLIANT "*OSTA UDF Compliant"
#define UDF_ID_LV_INFO "*UDF LV Info" #define UDF_ID_LV_INFO "*UDF LV Info"
...@@ -59,8 +59,9 @@ ...@@ -59,8 +59,9 @@
#define UDF_ID_SPARABLE "*UDF Sparable Partition" #define UDF_ID_SPARABLE "*UDF Sparable Partition"
#define UDF_ID_ALLOC "*UDF Virtual Alloc Tbl" #define UDF_ID_ALLOC "*UDF Virtual Alloc Tbl"
#define UDF_ID_SPARING "*UDF Sparing Table" #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_HARD_WRITE_PROTECT 0x01
#define IS_DF_SOFT_WRITE_PROTECT 0x02 #define IS_DF_SOFT_WRITE_PROTECT 0x02
...@@ -84,8 +85,8 @@ struct appIdentSuffix ...@@ -84,8 +85,8 @@ struct appIdentSuffix
uint8_t impUse[8]; uint8_t impUse[8];
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Logical Volume Integrity Descriptor (UDF 2.01 2.2.6) */ /* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */
/* Implementation Use (UDF 2.01 2.2.6.4) */ /* Implementation Use (UDF 2.50 2.2.6.4) */
struct logicalVolIntegrityDescImpUse struct logicalVolIntegrityDescImpUse
{ {
regid impIdent; regid impIdent;
...@@ -97,8 +98,8 @@ struct logicalVolIntegrityDescImpUse ...@@ -97,8 +98,8 @@ struct logicalVolIntegrityDescImpUse
uint8_t impUse[0]; uint8_t impUse[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Implementation Use Volume Descriptor (UDF 2.01 2.2.7) */ /* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */
/* Implementation Use (UDF 2.01 2.2.7.2) */ /* Implementation Use (UDF 2.50 2.2.7.2) */
struct impUseVolDescImpUse struct impUseVolDescImpUse
{ {
charspec LVICharset; charspec LVICharset;
...@@ -120,7 +121,7 @@ struct udfPartitionMap2 ...@@ -120,7 +121,7 @@ struct udfPartitionMap2
uint16_t partitionNum; uint16_t partitionNum;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Virtual Partition Map (UDF 2.01 2.2.8) */ /* Virtual Partition Map (UDF 2.50 2.2.8) */
struct virtualPartitionMap struct virtualPartitionMap
{ {
uint8_t partitionMapType; uint8_t partitionMapType;
...@@ -132,7 +133,7 @@ struct virtualPartitionMap ...@@ -132,7 +133,7 @@ struct virtualPartitionMap
uint8_t reserved2[24]; uint8_t reserved2[24];
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Sparable Partition Map (UDF 2.01 2.2.9) */ /* Sparable Partition Map (UDF 2.50 2.2.9) */
struct sparablePartitionMap struct sparablePartitionMap
{ {
uint8_t partitionMapType; uint8_t partitionMapType;
...@@ -148,25 +149,43 @@ struct sparablePartitionMap ...@@ -148,25 +149,43 @@ struct sparablePartitionMap
uint32_t locSparingTable[4]; uint32_t locSparingTable[4];
} __attribute__ ((packed)); } __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) */ /* Virtual Allocation Table (UDF 1.5 2.2.10) */
struct virtualAllocationTable15 struct virtualAllocationTable15
{ {
uint32_t VirtualSector[0]; uint32_t VirtualSector[0];
regid ident; regid vatIdent;
uint32_t previousVATICB; uint32_t previousVATICBLoc;
} __attribute__ ((packed)); } __attribute__ ((packed));
#define ICBTAG_FILE_TYPE_VAT15 0x00U #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 struct virtualAllocationTable20
{ {
uint16_t lengthHeader; uint16_t lengthHeader;
uint16_t lengthImpUse; uint16_t lengthImpUse;
dstring logicalVolIdent[128]; dstring logicalVolIdent[128];
uint32_t previousVatICBLoc; uint32_t previousVATICBLoc;
uint32_t numFIDSFiles; uint32_t numFiles;
uint32_t numFIDSDirectories; uint32_t numDirs;
uint16_t minReadRevision; uint16_t minReadRevision;
uint16_t minWriteRevision; uint16_t minWriteRevision;
uint16_t maxWriteRevision; uint16_t maxWriteRevision;
...@@ -177,7 +196,7 @@ struct virtualAllocationTable20 ...@@ -177,7 +196,7 @@ struct virtualAllocationTable20
#define ICBTAG_FILE_TYPE_VAT20 0xF8U #define ICBTAG_FILE_TYPE_VAT20 0xF8U
/* Sparing Table (UDF 2.01 2.2.11) */ /* Sparing Table (UDF 2.50 2.2.12) */
struct sparingEntry struct sparingEntry
{ {
uint32_t origLocation; uint32_t origLocation;
...@@ -195,7 +214,12 @@ struct sparingTable ...@@ -195,7 +214,12 @@ struct sparingTable
mapEntry[0]; mapEntry[0];
} __attribute__ ((packed)); } __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 struct allocDescImpUse
{ {
uint16_t flags; uint16_t flags;
...@@ -204,18 +228,18 @@ struct allocDescImpUse ...@@ -204,18 +228,18 @@ struct allocDescImpUse
#define AD_IU_EXT_ERASED 0x0001 #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 #define ICBTAG_FILE_TYPE_REALTIME 0xF9U
/* Implementation Use Extended Attribute (UDF 2.01 3.3.4.5) */ /* Implementation Use Extended Attribute (UDF 2.50 3.3.4.5) */
/* FreeEASpace (UDF 2.01 3.3.4.5.1.1) */ /* FreeEASpace (UDF 2.50 3.3.4.5.1.1) */
struct freeEaSpace struct freeEaSpace
{ {
uint16_t headerChecksum; uint16_t headerChecksum;
uint8_t freeEASpace[0]; uint8_t freeEASpace[0];
} __attribute__ ((packed)); } __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 struct DVDCopyrightImpUse
{ {
uint16_t headerChecksum; uint16_t headerChecksum;
...@@ -224,21 +248,21 @@ struct DVDCopyrightImpUse ...@@ -224,21 +248,21 @@ struct DVDCopyrightImpUse
uint8_t protectionSystemInfo[4]; uint8_t protectionSystemInfo[4];
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Application Use Extended Attribute (UDF 2.01 3.3.4.6) */ /* Application Use Extended Attribute (UDF 2.50 3.3.4.6) */
/* FreeAppEASpace (UDF 2.01 3.3.4.6.1) */ /* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */
struct freeAppEASpace struct freeAppEASpace
{ {
uint16_t headerChecksum; uint16_t headerChecksum;
uint8_t freeEASpace[0]; uint8_t freeEASpace[0];
} __attribute__ ((packed)); } __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_UNIQUE_ID "*UDF Unique ID Mapping Data"
#define UDF_ID_NON_ALLOC "*UDF Non-Allocatable Space" #define UDF_ID_NON_ALLOC "*UDF Non-Allocatable Space"
#define UDF_ID_POWER_CAL "*UDF Power Cal Table" #define UDF_ID_POWER_CAL "*UDF Power Cal Table"
#define UDF_ID_BACKUP "*UDF Backup" #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_UNDEF 0x00U
#define UDF_OS_CLASS_DOS 0x01U #define UDF_OS_CLASS_DOS 0x01U
#define UDF_OS_CLASS_OS2 0x02U #define UDF_OS_CLASS_OS2 0x02U
...@@ -254,6 +278,7 @@ struct freeAppEASpace ...@@ -254,6 +278,7 @@ struct freeAppEASpace
#define UDF_OS_ID_DOS 0x00U #define UDF_OS_ID_DOS 0x00U
#define UDF_OS_ID_OS2 0x00U #define UDF_OS_ID_OS2 0x00U
#define UDF_OS_ID_MAC 0x00U #define UDF_OS_ID_MAC 0x00U
#define UDF_OS_ID_MAX_OSX 0x01U
#define UDF_OS_ID_UNIX 0x00U #define UDF_OS_ID_UNIX 0x00U
#define UDF_OS_ID_AIX 0x01U #define UDF_OS_ID_AIX 0x01U
#define UDF_OS_ID_SOLARIS 0x02U #define UDF_OS_ID_SOLARIS 0x02U
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Each contributing author retains all rights to their own work. * Each contributing author retains all rights to their own work.
* *
* (C) 1998 Dave Boynton * (C) 1998 Dave Boynton
* (C) 1998-2001 Ben Fennema * (C) 1998-2004 Ben Fennema
* (C) 2000 Stelias Computing Inc * (C) 2000 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/vmalloc.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/udf_fs.h> #include <linux/udf_fs.h>
...@@ -133,7 +134,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) ...@@ -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; struct udf_inode_info *ei = (struct udf_inode_info *) foo;
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) { SLAB_CTOR_CONSTRUCTOR)
{
ei->i_ext.i_data = NULL; ei->i_ext.i_data = NULL;
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
} }
...@@ -324,17 +326,18 @@ udf_parse_options(char *options, struct udf_options *uopt) ...@@ -324,17 +326,18 @@ udf_parse_options(char *options, struct udf_options *uopt)
if (!options) if (!options)
return 1; return 1;
while ((p = strsep(&options, ",")) != NULL) { while ((p = strsep(&options, ",")) != NULL)
{
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
int token; int token;
if (!*p) if (!*p)
continue; continue;
token = match_token(p, tokens, args); token = match_token(p, tokens, args);
switch (token) { switch (token)
{
case Opt_novrs: case Opt_novrs:
uopt->novrs = 1; uopt->novrs = 1;
break;
case Opt_bs: case Opt_bs:
if (match_int(&args[0], &option)) if (match_int(&args[0], &option))
return 0; return 0;
...@@ -422,8 +425,7 @@ udf_parse_options(char *options, struct udf_options *uopt) ...@@ -422,8 +425,7 @@ udf_parse_options(char *options, struct udf_options *uopt)
#endif #endif
default: default:
printk(KERN_ERR "udf: bad mount option \"%s\" " printk(KERN_ERR "udf: bad mount option \"%s\" "
"or missing value\n", "or missing value\n", p);
p);
return 0; return 0;
} }
} }
...@@ -1651,23 +1653,9 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -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) 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); 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) if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
{ UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace);
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);
}
if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP) if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
{ UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace);
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);
}
if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15) if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
{ {
for (i=0; i<4; i++) for (i=0; i<4; i++)
...@@ -1743,23 +1731,9 @@ udf_put_super(struct super_block *sb) ...@@ -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) 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); 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) if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
{ UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace);
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);
}
if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP) if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
{ UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace);
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);
}
if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15) if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
{ {
for (i=0; i<4; i++) for (i=0; i<4; i++)
...@@ -1804,7 +1778,7 @@ udf_statfs(struct super_block *sb, struct kstatfs *buf) ...@@ -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; le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + buf->f_bfree;
buf->f_ffree = buf->f_bfree; buf->f_ffree = buf->f_bfree;
/* __kernel_fsid_t f_fsid */ /* __kernel_fsid_t f_fsid */
buf->f_namelen = UDF_NAME_LEN; buf->f_namelen = UDF_NAME_LEN-2;
return 0; return 0;
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL * ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work. * 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 * (C) 1999 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -66,6 +66,67 @@ static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset, ...@@ -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) void udf_truncate_extents(struct inode * inode)
{ {
lb_addr bloc, eloc, neloc = { 0, 0 }; lb_addr bloc, eloc, neloc = { 0, 0 };
......
...@@ -64,13 +64,14 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb) ...@@ -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) +\ int nr_groups = ((UDF_SB_PARTLEN((X),(Y)) + (sizeof(struct spaceBitmapDesc) << 3) +\
((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\ ((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\
UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(sizeof(struct udf_bitmap) +\ int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * nr_groups);\
sizeof(struct buffer_head *) * nr_groups,\ if (size <= PAGE_SIZE)\
GFP_KERNEL);\ 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)\ if (UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap != NULL)\
{\ {\
memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00,\ memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00, size);\
sizeof(struct udf_bitmap) + sizeof(struct buffer_head *) * nr_groups);\
UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\ UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\
(struct buffer_head **)(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap + 1);\ (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;\ 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) ...@@ -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_QUERY_FLAG(X,Y) ( UDF_SB(X)->s_flags & ( 1 << (Y) ) )
#define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) ) #define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) )
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#define UDF_EXTENT_FLAG_MASK 0xC0000000 #define UDF_EXTENT_FLAG_MASK 0xC0000000
#define UDF_NAME_PAD 4 #define UDF_NAME_PAD 4
#define UDF_NAME_LEN 255 #define UDF_NAME_LEN 256
#define UDF_PATH_LEN 1023 #define UDF_PATH_LEN 1023
#define udf_file_entry_alloc_offset(inode)\ #define udf_file_entry_alloc_offset(inode)\
...@@ -59,13 +59,6 @@ struct udf_fileident_bh ...@@ -59,13 +59,6 @@ struct udf_fileident_bh
int eoffset; int eoffset;
}; };
struct udf_directory_record
{
uint32_t d_parent;
uint32_t d_inode;
uint32_t d_name[255];
};
struct udf_vds_record struct udf_vds_record
{ {
uint32_t block; uint32_t block;
...@@ -81,7 +74,7 @@ struct generic_desc ...@@ -81,7 +74,7 @@ struct generic_desc
struct ustr struct ustr
{ {
uint8_t u_cmpID; uint8_t u_cmpID;
uint8_t u_name[UDF_NAME_LEN]; uint8_t u_name[UDF_NAME_LEN-2];
uint8_t u_len; uint8_t u_len;
}; };
...@@ -116,19 +109,16 @@ extern int8_t udf_insert_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, s ...@@ -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_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_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 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 */ /* misc.c */
extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref); 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_tgetblk(struct super_block *, int);
extern struct buffer_head *udf_tread(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_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t);
extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t, struct buffer_head **); 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_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 struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
extern void udf_release_data(struct buffer_head *); 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_update_tag(char *, int);
extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, 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 *); ...@@ -154,6 +144,7 @@ extern void udf_free_inode(struct inode *);
extern struct inode * udf_new_inode (struct inode *, int, int *); extern struct inode * udf_new_inode (struct inode *, int, int *);
/* truncate.c */ /* truncate.c */
extern void udf_discard_prealloc(struct inode *);
extern void udf_truncate_extents(struct inode *); extern void udf_truncate_extents(struct inode *);
/* balloc.c */ /* balloc.c */
......
...@@ -36,7 +36,7 @@ static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); ...@@ -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) 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; return 0;
memset(dest, 0, sizeof(struct ustr)); memset(dest, 0, sizeof(struct ustr));
memcpy(dest->u_name, src, strlen); memcpy(dest->u_name, src, strlen);
...@@ -181,14 +181,14 @@ int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i) ...@@ -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) static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
{ {
unsigned c, i, max_val, utf_char; unsigned c, i, max_val, utf_char;
int utf_cnt; int utf_cnt, u_len;
int u_len = 0;
memset(ocu, 0, sizeof(dstring) * length); memset(ocu, 0, sizeof(dstring) * length);
ocu[0] = 8; ocu[0] = 8;
max_val = 0xffU; max_val = 0xffU;
try_again: try_again:
u_len = 0U;
utf_char = 0U; utf_char = 0U;
utf_cnt = 0U; utf_cnt = 0U;
for (i = 0U; i < utf->u_len; i++) for (i = 0U; i < utf->u_len; i++)
...@@ -264,8 +264,8 @@ static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length) ...@@ -264,8 +264,8 @@ static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
if (utf_cnt) if (utf_cnt)
{ {
error_out: error_out:
printk(KERN_ERR "udf: bad UTF-8 character\n"); ocu[++u_len] = '?';
return 0; printk(KERN_DEBUG "udf: bad UTF-8 character\n");
} }
ocu[length - 1] = (uint8_t)u_len + 1; 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 ...@@ -318,21 +318,21 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, i
{ {
unsigned len, i, max_val; unsigned len, i, max_val;
uint16_t uni_char; uint16_t uni_char;
int uni_cnt; int u_len;
int u_len = 0;
memset(ocu, 0, sizeof(dstring) * length); memset(ocu, 0, sizeof(dstring) * length);
ocu[0] = 8; ocu[0] = 8;
max_val = 0xffU; max_val = 0xffU;
try_again: try_again:
uni_char = 0U; u_len = 0U;
uni_cnt = 0U;
for (i = 0U; i < uni->u_len; i++) for (i = 0U; i < uni->u_len; i++)
{ {
len = nls->char2uni(&uni->u_name[i], uni->u_len-i, &uni_char); 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; max_val = 0xffffU;
ocu[0] = (uint8_t)0x10U; ocu[0] = (uint8_t)0x10U;
...@@ -340,11 +340,9 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, i ...@@ -340,11 +340,9 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, i
} }
if (max_val == 0xffffU) if (max_val == 0xffffU)
{
ocu[++u_len] = (uint8_t)(uni_char >> 8); ocu[++u_len] = (uint8_t)(uni_char >> 8);
i++;
}
ocu[++u_len] = (uint8_t)(uni_char & 0xffU); ocu[++u_len] = (uint8_t)(uni_char & 0xffU);
i += len - 1;
} }
ocu[length - 1] = (uint8_t)u_len + 1; ocu[length - 1] = (uint8_t)u_len + 1;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* OSTA-UDF(tm) = Optical Storage Technology Association * OSTA-UDF(tm) = Optical Storage Technology Association
* Universal Disk Format. * 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]. * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
* http://www.osta.org/ * http://www.ecma.ch/ * http://www.osta.org/ * http://www.ecma.ch/
* http://www.iso.org/ * http://www.iso.org/
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL * ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work. * 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 * (C) 1999-2000 Stelias Computing Inc
* *
* HISTORY * HISTORY
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
#define UDF_PREALLOCATE #define UDF_PREALLOCATE
#define UDF_DEFAULT_PREALLOC_BLOCKS 8 #define UDF_DEFAULT_PREALLOC_BLOCKS 8
#define UDFFS_DATE "2002/11/15" #define UDFFS_DATE "2004/29/09"
#define UDFFS_VERSION "0.9.7" #define UDFFS_VERSION "0.9.8.1"
#define UDFFS_DEBUG #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