E: bfennema@falcon.csc.calpoly.edu
W: http://www.csc.calpoly.edu/~bfennema
D: UDF filesystem
-S: 21760 Irma Lyle Drive
-S: Los Gatos, CA 95033-8942
+S: (ask for current address)
S: USA
N: Jürgen Fischer
*
* ./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
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)
-------------------------------------------------------------------------------
-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>
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
* 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
*
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;
* 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
{
if (filp->f_mode & FMODE_WRITE)
{
- lock_kernel();
+ down(&inode->i_sem);
udf_discard_prealloc(inode);
- unlock_kernel();
+ up(&inode->i_sem);
}
return 0;
}
* 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
{
if (!(inode->i_sb->s_flags & MS_RDONLY))
{
- lock_kernel();
+ down(&inode->i_sem);
udf_discard_prealloc(inode);
- unlock_kernel();
+ up(&inode->i_sem);
}
}
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);
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 */
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)
;
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 |
laarr[curr].extLocation.partitionReferenceNum = 0;
}
else
- laarr[curr].extLength = type |
+ laarr[curr].extLength = (etype << 30) |
(offset << inode->i_sb->s_blocksize_bits);
curr ++;
(*c) ++;
}
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 |
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) ++;
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) >>
}
}
}
+ 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;
+ }
}
}
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;
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
{
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)
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;
}
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
{
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) +
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)
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) |
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;
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))
* Each contributing author retains all rights to their own work.
*
* (C) 1998 Dave Boynton
- * (C) 1998-2001 Ben Fennema
+ * (C) 1998-2004 Ben Fennema
* (C) 1999-2000 Stelias Computing Inc
*
* HISTORY
#include "udf_i.h"
#include "udf_sb.h"
-uint32_t
-udf64_low32(uint64_t indat)
-{
- return indat & 0x00000000FFFFFFFFULL;
-}
-
-uint32_t
-udf64_high32(uint64_t indat)
-{
- return indat >> 32;
-}
-
extern struct buffer_head *
udf_tgetblk(struct super_block *sb, int block)
{
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 */
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;
}
}
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);
}
}
/* 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))
{
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;
}
offset += le32_to_cpu(gaf->attrLength);
}
}
-
- udf_release_data(*bh);
- if (eaicb.extLength)
- {
- /* TODO */
- }
return NULL;
}
* ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work.
*
- * (C) 1998-2001 Ben Fennema
+ * (C) 1998-2004 Ben Fennema
* (C) 1999-2000 Stelias Computing Inc
*
* HISTORY
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
-static inline int udf_match(int len, const char * const name, struct qstr *qs)
+static inline int udf_match(int len1, const char *name1, int len2, const char *name2)
{
- if (len != qs->len)
+ if (len1 != len2)
return 0;
- return !memcmp(name, qs->name, len);
+ return !memcmp(name1, name2, len1);
}
int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
{
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;
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;
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)
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();
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;
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);
{
struct inode * inode;
struct udf_fileident_bh fibh;
- int err;
struct fileIdentDesc cfi, *fi;
+ int err;
if (!old_valid_dev(rdev))
return -EINVAL;
{
struct inode * inode;
struct udf_fileident_bh fibh;
- int err;
struct fileIdentDesc cfi, *fi;
+ int err;
lock_kernel();
err = -EMLINK;
{
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
#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"
#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
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;
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;
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;
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;
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;
#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;
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;
#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;
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
#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
* 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
#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>
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);
}
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;
}
}
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++)
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++)
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;
}
* 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
}
}
+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 };
{\
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;\
}\
}
+#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) ) )
#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 )
#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)\
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;
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;
};
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);
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 */
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);
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++)
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;
{
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;
}
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;
* 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/
* 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
#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