If you haven't heard about all of this before, it's safe to say N.
config UDF_FS
- tristate "UDF file system support (read only)"
+ tristate "UDF file system support"
---help---
This is the new file system used on some CD-ROMs and DVDs. Say Y if
you intend to mount DVD discs or CDRW's written in packet mode, or
- if written to by other UDF utilities, such as DirectCD. This UDF
- file system support is read-only. If you want to write to UDF
- file systems on some media, you need to say Y to "UDF read-write
- support" below in addition. Please read
- <file:Documentation/filesystems/udf.txt>.
+ if written to by other UDF utilities, such as DirectCD.
+ Please read <file:Documentation/filesystems/udf.txt>.
This file system support is also available as a module ( = code
which can be inserted in and removed from the running kernel
If unsure, say N.
-config UDF_RW
- bool "UDF write support (DANGEROUS)"
- depends on UDF_FS && EXPERIMENTAL
- help
- Say Y if you want to test write support for UDF file systems.
- Due to lack of support for writing to CDR/CDRW's, this option
- is only supported for hard discs, DVD-RAM, and loopback files.
-
config UFS_FS
tristate "UFS file system support (read only)"
---help---
elen = 0;
obloc = nbloc = UDF_I_LOCATION(table);
- obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0));
- atomic_inc(&nbh->b_count);
+ obh = nbh = NULL;
while (count && (etype =
udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
}
- if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+ if (nbh != obh)
{
i = -1;
obloc = nbloc;
{
loffset = nextoffset;
aed->lengthAllocDescs = cpu_to_le32(adsize);
- sptr = (obh)->b_data + nextoffset - adsize;
+ if (obh)
+ sptr = UDF_I_DATA(inode) + nextoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
+ else
+ sptr = obh->b_data + nextoffset - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize);
nextoffset = sizeof(struct allocExtDesc) + adsize;
aed->lengthAllocDescs = cpu_to_le32(0);
sptr = (obh)->b_data + nextoffset;
nextoffset = sizeof(struct allocExtDesc);
-
- if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
+
+ if (obh)
{
aed = (struct allocExtDesc *)(obh)->b_data;
aed->lengthAllocDescs =
break;
}
}
- udf_update_tag(obh->b_data, loffset);
- mark_buffer_dirty(obh);
+ if (obh)
+ {
+ udf_update_tag(obh->b_data, loffset);
+ mark_buffer_dirty(obh);
+ }
+ else
+ mark_inode_dirty(table);
}
if (elen) /* It's possible that stealing the block emptied the extent */
{
udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
- if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
+ if (!nbh)
{
UDF_I_LENALLOC(table) += adsize;
mark_inode_dirty(table);
extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table);
- bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
+ bh = NULL;
eloc.logicalBlockNum = 0xFFFFFFFF;
while (first_block != eloc.logicalBlockNum && (etype =
extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table);
- goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
- atomic_inc(&goal_bh->b_count);
+ goal_bh = bh = NULL;
while (spread && (etype =
udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
if ( filp->f_pos == 0 )
{
- if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
+ if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
+ {
unlock_kernel();
return 0;
}
filp->f_pos ++;
}
-
+
result = do_udf_readdir(dir, filp, filldir, dirent);
UPDATE_ATIME(dir);
unlock_kernel();
nf_pos = (udf_ext0_offset(dir) >> 2);
fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
- if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
+ if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ fibh.sbh = fibh.ebh = NULL;
+ else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{
offset >>= dir->i_sb->s_blocksize_bits;
}
else
offset = 0;
- }
- else
- {
- udf_release_data(bh);
- return -ENOENT;
- }
-
- if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
- {
- udf_release_data(bh);
- return -EIO;
- }
- if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
- {
- i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
- if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
- i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
- for (num=0; i>0; i--)
+ if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
- block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
- tmp = udf_tgetblk(dir->i_sb, block);
- if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
- bha[num++] = tmp;
- else
- brelse(tmp);
+ udf_release_data(bh);
+ return -EIO;
}
- if (num)
+
+ if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
{
- ll_rw_block(READA, num, bha);
- for (i=0; i<num; i++)
- brelse(bha[i]);
+ i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
+ if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
+ i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
+ for (num=0; i>0; i--)
+ {
+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
+ tmp = udf_tgetblk(dir->i_sb, block);
+ if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
+ bha[num++] = tmp;
+ else
+ brelse(tmp);
+ }
+ if (num)
+ {
+ ll_rw_block(READA, num, bha);
+ for (i=0; i<num; i++)
+ brelse(bha[i]);
+ }
}
}
+ else
+ {
+ udf_release_data(bh);
+ return -ENOENT;
+ }
while ( nf_pos < size )
{
*/
#include "udfdecl.h"
+#include "udf_i.h"
#include <linux/fs.h>
#include <linux/string.h>
fibh->soffset = fibh->eoffset;
+ if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ {
+ fi = udf_get_fileident(UDF_I_DATA(dir) -
+ (UDF_I_EFE(dir) ?
+ sizeof(struct extendedFileEntry) :
+ sizeof(struct fileEntry)),
+ dir->i_sb->s_blocksize, &(fibh->eoffset));
+
+ if (!fi)
+ return NULL;
+
+ *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
+
+ memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
+
+ return fi;
+ }
+
if (fibh->eoffset == dir->i_sb->s_blocksize)
{
int lextoffset = *extoffset;
}
short_ad *
-udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
+udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
{
- short_ad * sa;
- uint8_t * ptr;
+ short_ad *sa;
- if ( (!buffer) || (!offset) )
+ if ( (!ptr) || (!offset) )
{
printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
return NULL;
}
- ptr = (uint8_t *)buffer;
-
- if ( (*offset > 0) && (*offset < maxoffset) )
- ptr += *offset;
- else
+ if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
return NULL;
-
- if ((sa = (short_ad *)ptr)->extLength == 0)
+ else if ((sa = (short_ad *)ptr)->extLength == 0)
return NULL;
- else if (inc)
- (*offset) += sizeof(short_ad);
+
+ if (inc)
+ *offset += sizeof(short_ad);
return sa;
}
long_ad *
-udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
+udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc)
{
- long_ad * la;
- uint8_t * ptr;
+ long_ad *la;
- if ( (!buffer) || !(offset) )
+ if ( (!ptr) || (!offset) )
{
printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
return NULL;
}
- ptr = (uint8_t *)buffer;
-
- if ( (*offset > 0) && (*offset < maxoffset) )
- ptr += *offset;
- else
+ if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
return NULL;
-
- if ((la = (long_ad *)ptr)->extLength == 0)
+ else if ((la = (long_ad *)ptr)->extLength == 0)
return NULL;
- else if (inc)
- (*offset) += sizeof(long_ad);
+
+ if (inc)
+ *offset += sizeof(long_ad);
return la;
}
static int udf_adinicb_readpage(struct file *file, struct page * page)
{
struct inode *inode = page->mapping->host;
-
- struct buffer_head *bh;
- int block;
char *kaddr;
- int err = 0;
if (!PageLocked(page))
PAGE_BUG(page);
kaddr = kmap(page);
memset(kaddr, 0, PAGE_CACHE_SIZE);
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = sb_bread(inode->i_sb, block);
- if (!bh)
- {
- SetPageError(page);
- err = -EIO;
- goto out;
- }
- memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
- brelse(bh);
+ memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
flush_dcache_page(page);
SetPageUptodate(page);
-out:
kunmap(page);
unlock_page(page);
- return err;
+ return 0;
}
static int udf_adinicb_writepage(struct page *page)
{
struct inode *inode = page->mapping->host;
-
- struct buffer_head *bh;
- int block;
char *kaddr;
- int err = 0;
if (!PageLocked(page))
PAGE_BUG(page);
kaddr = kmap(page);
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = sb_bread(inode->i_sb, block);
- if (!bh)
- {
- SetPageError(page);
- err = -EIO;
- goto out;
- }
- memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
- mark_buffer_dirty(bh);
- brelse(bh);
+ memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
+ mark_inode_dirty(inode);
SetPageUptodate(page);
-out:
kunmap(page);
unlock_page(page);
- return err;
+ return 0;
}
static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
struct inode *inode = page->mapping->host;
-
- struct buffer_head *bh;
- int block;
char *kaddr = page_address(page);
- int err = 0;
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = sb_bread(inode->i_sb, block);
- if (!bh)
- {
- SetPageError(page);
- err = -EIO;
- goto out;
- }
- memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
+ memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
kaddr + offset, to - offset);
- mark_buffer_dirty(bh);
- brelse(bh);
+ mark_inode_dirty(inode);
SetPageUptodate(page);
-out:
kunmap(page);
/* only one page here */
if (to > inode->i_size)
inode->i_size = to;
- return err;
+ return 0;
}
struct address_space_operations udf_adinicb_aops = {
unsigned long arg)
{
int result = -EINVAL;
- struct buffer_head *bh = NULL;
- long_ad eaicb;
- uint8_t *ea = NULL;
if ( permission(inode, MAY_READ) != 0 )
{
return -EINVAL;
}
- /* first, do ioctls that don't need to udf_read */
switch (cmd)
{
case UDF_GETVOLIDENT:
return result;
}
- }
-
- /* ok, we need to read the inode */
- bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
-
- if (!bh)
- {
- udf_debug("bread failed (inode=%ld)\n", inode->i_ino);
- return -EIO;
- }
-
- if (UDF_I_EXTENDED_FE(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;
- }
-
- switch (cmd)
- {
case UDF_GETEASIZE:
result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
break;
case UDF_GETEABLOCK:
- result = copy_to_user((char *)arg, ea,
+ result = copy_to_user((char *)arg, UDF_I_DATA(inode),
UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
break;
}
- udf_release_data(bh);
return result;
}
#include <linux/quotaops.h>
#include <linux/udf_fs.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#include "udf_i.h"
#include "udf_sb.h"
inode->i_blocks = 0;
UDF_I_LENEATTR(inode) = 0;
UDF_I_LENALLOC(inode) = 0;
+ UDF_I_USE(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
{
- UDF_I_EXTENDED_FE(inode) = 1;
+ UDF_I_EFE(inode) = 1;
UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
+ UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+ memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
}
else
- UDF_I_EXTENDED_FE(inode) = 0;
+ {
+ UDF_I_EFE(inode) = 0;
+ UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+ memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+ }
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
UDF_I_CRTIME(inode) = CURRENT_TIME;
UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
UDF_I_UCRTIME(inode) = CURRENT_UTIME;
- UDF_I_NEW_INODE(inode) = 1;
insert_inode_hash(inode);
mark_inode_dirty(inode);
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
+#include <linux/slab.h>
#include "udf_i.h"
#include "udf_sb.h"
clear_inode(inode);
}
+void udf_clear_inode(struct inode *inode)
+{
+ kfree(UDF_I_DATA(inode));
+}
+
void udf_discard_prealloc(struct inode * inode)
{
if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
{
- struct buffer_head *bh = NULL;
struct page *page;
char *kaddr;
- int block;
/* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops;
return;
}
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = udf_tread(inode->i_sb, block);
- if (!bh)
- return;
page = grab_cache_page(inode->i_mapping, 0);
if (!PageLocked(page))
PAGE_BUG(page);
kaddr = kmap(page);
memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
- memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
+ memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
UDF_I_LENALLOC(inode));
flush_dcache_page(page);
SetPageUptodate(page);
kunmap(page);
}
- memset(bh->b_data + udf_file_entry_alloc_offset(inode),
- 0, UDF_I_LENALLOC(inode));
+ memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
+ UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
- mark_buffer_dirty_inode(bh, inode);
- udf_release_data(bh);
if (inode->i_data.a_ops->writepage(page) == -EAGAIN)
__set_page_dirty_nobuffers(page);
struct buffer_head *sbh = NULL, *dbh = NULL;
lb_addr bloc, eloc;
uint32_t elen, extoffset;
+ uint8_t alloctype;
struct udf_fileident_bh sfibh, dfibh;
loff_t f_pos = udf_ext0_offset(inode) >> 2;
int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
struct fileIdentDesc cfi, *sfi, *dfi;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ alloctype = ICBTAG_FLAG_AD_SHORT;
+ else
+ alloctype = ICBTAG_FLAG_AD_LONG;
+
if (!inode->i_size)
{
- if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
- UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
- else
- UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
+ UDF_I_ALLOCTYPE(inode) = alloctype;
mark_inode_dirty(inode);
return NULL;
}
UDF_I_LOCATION(inode).partitionReferenceNum, 0);
if (!newblock)
return NULL;
- sbh = udf_tread(inode->i_sb, inode->i_ino);
- if (!sbh)
- return NULL;
dbh = udf_tgetblk(inode->i_sb, newblock);
if (!dbh)
return NULL;
mark_buffer_dirty_inode(dbh, inode);
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
- sfibh.sbh = sfibh.ebh = sbh;
+ sbh = sfibh.sbh = sfibh.ebh = NULL;
dfibh.soffset = dfibh.eoffset = 0;
dfibh.sbh = dfibh.ebh = dbh;
while ( (f_pos < size) )
{
+ UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
if (!sfi)
{
- udf_release_data(sbh);
udf_release_data(dbh);
return NULL;
}
+ UDF_I_ALLOCTYPE(inode) = alloctype;
sfi->descTag.tagLocation = *block;
dfibh.soffset = dfibh.eoffset;
dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
sfi->fileIdent + sfi->lengthOfImpUse))
{
- udf_release_data(sbh);
+ UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
udf_release_data(dbh);
return NULL;
}
}
mark_buffer_dirty_inode(dbh, inode);
- memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
- 0, UDF_I_LENALLOC(inode));
-
+ memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0;
- if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
- UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
- else
- UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
bloc = UDF_I_LOCATION(inode);
eloc.logicalBlockNum = *block;
eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
/* UniqueID stuff */
- mark_buffer_dirty(sbh);
udf_release_data(sbh);
mark_inode_dirty(inode);
return dbh;
if (elen > numalloc)
{
- laarr[c].extLength -=
+ laarr[i].extLength -=
(numalloc << inode->i_sb->s_blocksize_bits);
numalloc = 0;
}
void udf_truncate(struct inode * inode)
{
int offset;
- struct buffer_head *bh;
int err;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
}
else
{
- offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
- udf_file_entry_alloc_offset(inode);
-
- if ((bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0))))
- {
- memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
- mark_buffer_dirty(bh);
- udf_release_data(bh);
- }
+ offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
+ memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - udf_file_entry_alloc_offset(inode));
UDF_I_LENALLOC(inode) = inode->i_size;
}
}
long convtime_usec;
int offset, alen;
- UDF_I_NEW_INODE(inode) = 0;
-
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE)
- UDF_I_EXTENDED_FE(inode) = 1;
+ {
+ UDF_I_EFE(inode) = 1;
+ UDF_I_USE(inode) = 0;
+ UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+ memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
+ }
else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
- UDF_I_EXTENDED_FE(inode) = 0;
+ {
+ UDF_I_EFE(inode) = 0;
+ UDF_I_USE(inode) = 0;
+ UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+ memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+ }
else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
{
+ UDF_I_EFE(inode) = 0;
+ UDF_I_USE(inode) = 1;
UDF_I_LENALLOC(inode) =
le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
+ UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+ memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
return;
}
inode->i_mode = udf_convert_permissions(fe);
inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
- if (UDF_I_EXTENDED_FE(inode) == 0)
+ if (UDF_I_EFE(inode) == 0)
{
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
udf_debug("bread failure\n");
return -EIO;
}
+
+ memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
+
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
- if (UDF_I_NEW_INODE(inode) == 1)
- {
- if (UDF_I_EXTENDED_FE(inode) == 0)
- memset(bh->b_data, 0x00, sizeof(struct fileEntry));
- else
- memset(bh->b_data, 0x00, sizeof(struct extendedFileEntry));
- memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
- UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
- udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
- UDF_I_NEW_INODE(inode) = 0;
- }
if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
{
(struct unallocSpaceEntry *)bh->b_data;
use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
+ memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
sizeof(tag);
use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
udf_release_data(tbh);
}
- if (UDF_I_EXTENDED_FE(inode) == 0)
+ if (UDF_I_EFE(inode) == 0)
{
+ memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
fe->logicalBlocksRecorded = cpu_to_le64(
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
(inode->i_sb->s_blocksize_bits - 9));
}
else
{
+ memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
efe->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64(
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
long_ad *lad = NULL;
struct allocExtDesc *aed;
int8_t etype;
+ uint8_t *ptr;
- if (!(*bh))
- {
- if (!(*bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
- {
- udf_debug("reading block %d failed!\n",
- udf_get_lb_pblock(inode->i_sb, *bloc, 0));
- return -1;
- }
- }
+ if (!*bh)
+ ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+ else
+ ptr = (*bh)->b_data + *extoffset;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
{
loffset = *extoffset;
aed->lengthAllocDescs = cpu_to_le32(adsize);
- sptr = (*bh)->b_data + *extoffset - adsize;
+ sptr = ptr - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize);
*extoffset = sizeof(struct allocExtDesc) + adsize;
{
loffset = *extoffset + adsize;
aed->lengthAllocDescs = cpu_to_le32(0);
- sptr = (*bh)->b_data + *extoffset;
+ sptr = ptr;
*extoffset = sizeof(struct allocExtDesc);
- if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+ if (*bh)
{
aed = (struct allocExtDesc *)(*bh)->b_data;
aed->lengthAllocDescs =
break;
}
}
- if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
- udf_update_tag((*bh)->b_data, loffset);
+ if (*bh)
+ {
+ if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
+ udf_update_tag((*bh)->b_data, loffset);
+ else
+ udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
+ mark_buffer_dirty_inode(*bh, inode);
+ udf_release_data(*bh);
+ }
else
- udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
- mark_buffer_dirty_inode(*bh, inode);
- udf_release_data(*bh);
+ mark_inode_dirty(inode);
*bh = nbh;
}
etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
- if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
+ if (!*bh)
{
UDF_I_LENALLOC(inode) += adsize;
mark_inode_dirty(inode);
lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
{
int adsize;
- short_ad *sad = NULL;
- long_ad *lad = NULL;
+ uint8_t *ptr;
- if (!(bh))
- {
- if (!(bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, bloc, 0))))
- {
- udf_debug("reading block %d failed!\n",
- udf_get_lb_pblock(inode->i_sb, bloc, 0));
- return -1;
- }
- }
+ if (!bh)
+ ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
else
+ {
+ ptr = bh->b_data + *extoffset;
atomic_inc(&bh->b_count);
-
- 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
- return -1;
+ }
switch (UDF_I_ALLOCTYPE(inode))
{
case ICBTAG_FLAG_AD_SHORT:
{
- sad = (short_ad *)((bh)->b_data + *extoffset);
+ short_ad *sad = (short_ad *)ptr;
sad->extLength = cpu_to_le32(elen);
sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
+ adsize = sizeof(short_ad);
break;
}
case ICBTAG_FLAG_AD_LONG:
{
- lad = (long_ad *)((bh)->b_data + *extoffset);
+ long_ad *lad = (long_ad *)ptr;
lad->extLength = cpu_to_le32(elen);
lad->extLocation = cpu_to_lelb(eloc);
memset(lad->impUse, 0x00, sizeof(lad->impUse));
+ adsize = sizeof(long_ad);
break;
}
+ default:
+ return -1;
}
- if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+ if (bh)
{
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
{
le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
}
mark_buffer_dirty_inode(bh, inode);
+ udf_release_data(bh);
}
else
- {
mark_inode_dirty(inode);
- mark_buffer_dirty(bh);
- }
if (inc)
*extoffset += adsize;
- udf_release_data(bh);
return (elen >> 30);
}
int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
{
- uint16_t tagIdent;
- int pos, alen;
int8_t etype;
- if (!(*bh))
+ while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
+ (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
{
- if (!(*bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
+ *bloc = *eloc;
+ *extoffset = sizeof(struct allocExtDesc);
+ udf_release_data(*bh);
+ if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0));
}
}
- tagIdent = le16_to_cpu(((tag *)(*bh)->b_data)->tagIdent);
-
- if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
- {
- if (tagIdent == TAG_IDENT_FE || tagIdent == TAG_IDENT_EFE ||
- UDF_I_NEW_INODE(inode))
- {
- pos = udf_file_entry_alloc_offset(inode);
- alen = UDF_I_LENALLOC(inode) + pos;
- }
- else if (tagIdent == TAG_IDENT_USE)
- {
- pos = sizeof(struct unallocSpaceEntry);
- alen = UDF_I_LENALLOC(inode) + pos;
- }
- else
- return -1;
- }
- else if (tagIdent == TAG_IDENT_AED)
- {
- struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
-
- pos = sizeof(struct allocExtDesc);
- alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
- }
- else
- return -1;
-
- if (!(*extoffset))
- *extoffset = pos;
-
- switch (UDF_I_ALLOCTYPE(inode))
- {
- case ICBTAG_FLAG_AD_SHORT:
- {
- short_ad *sad;
-
- if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
- return -1;
-
- if ((etype = le32_to_cpu(sad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
- {
- bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
- *extoffset = 0;
- udf_release_data(*bh);
- *bh = NULL;
- return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
- }
- else
- {
- eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
- eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
- *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
- }
- break;
- }
- case ICBTAG_FLAG_AD_LONG:
- {
- long_ad *lad;
-
- if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
- return -1;
-
- if ((etype = le32_to_cpu(lad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
- {
- *bloc = lelb_to_cpu(lad->extLocation);
- *extoffset = 0;
- udf_release_data(*bh);
- *bh = NULL;
- return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
- }
- else
- {
- *eloc = lelb_to_cpu(lad->extLocation);
- *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
- }
- break;
- }
- case ICBTAG_FLAG_AD_IN_ICB:
- {
- if (UDF_I_LENALLOC(inode) == 0)
- return -1;
- etype = (EXT_RECORDED_ALLOCATED >> 30);
- *eloc = UDF_I_LOCATION(inode);
- *elen = UDF_I_LENALLOC(inode);
- break;
- }
- default:
- {
- udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
- return -1;
- }
- }
- if (*elen)
- return etype;
-
- udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
- inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *elen, etype, *extoffset);
- if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
- *extoffset -= sizeof(short_ad);
- else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
- *extoffset -= sizeof(long_ad);
- return -1;
+ return etype;
}
int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
{
- int pos, alen;
+ int alen;
int8_t etype;
+ uint8_t *ptr;
- if (!(*bh))
- {
- if (!(*bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
- {
- udf_debug("reading block %d failed!\n",
- udf_get_lb_pblock(inode->i_sb, *bloc, 0));
- return -1;
- }
- }
-
- if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
+ if (!*bh)
{
- if (!(UDF_I_EXTENDED_FE(inode)))
- pos = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
- else
- pos = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
- alen = UDF_I_LENALLOC(inode) + pos;
+ if (!(*extoffset))
+ *extoffset = udf_file_entry_alloc_offset(inode);
+ ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+ alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
}
else
{
- struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
-
- pos = sizeof(struct allocExtDesc);
- alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
+ if (!(*extoffset))
+ *extoffset = sizeof(struct allocExtDesc);
+ ptr = (*bh)->b_data + *extoffset;
+ alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
}
- if (!(*extoffset))
- *extoffset = pos;
-
switch (UDF_I_ALLOCTYPE(inode))
{
case ICBTAG_FLAG_AD_SHORT:
{
short_ad *sad;
- if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
+ if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
return -1;
etype = le32_to_cpu(sad->extLength) >> 30;
{
long_ad *lad;
- if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
+ if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
return -1;
etype = le32_to_cpu(lad->extLength) >> 30;
return -1;
}
}
- if (*elen)
- return etype;
- udf_debug("Empty Extent!\n");
- if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
- *extoffset -= sizeof(short_ad);
- else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
- *extoffset -= sizeof(long_ad);
- return -1;
+ return etype;
}
int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
uint32_t oelen;
int8_t etype;
- if (!bh)
- {
- if (!(bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, bloc, 0))))
- {
- udf_debug("reading block %d failed!\n",
- udf_get_lb_pblock(inode->i_sb, bloc, 0));
- return -1;
- }
- }
- else
+ if (bh)
atomic_inc(&bh->b_count);
while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
int8_t etype;
struct allocExtDesc *aed;
- if (!(nbh))
+ if (nbh)
{
- if (!(nbh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, nbloc, 0))))
- {
- udf_debug("reading block %d failed!\n",
- udf_get_lb_pblock(inode->i_sb, nbloc, 0));
- return -1;
- }
- }
- else
atomic_inc(&nbh->b_count);
- atomic_inc(&nbh->b_count);
+ atomic_inc(&nbh->b_count);
+ }
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
{
udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
- if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+ if (obh != nbh)
{
obloc = nbloc;
udf_release_data(obh);
memset(&eloc, 0x00, sizeof(lb_addr));
elen = 0;
- if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+ if (nbh != obh)
{
udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
- if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+ if (!obh)
{
UDF_I_LENALLOC(inode) -= (adsize * 2);
mark_inode_dirty(inode);
else
{
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
- if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+ if (!obh)
{
UDF_I_LENALLOC(inode) -= adsize;
mark_inode_dirty(inode);
ret = 0;
unlock_kernel();
-
- if (bh)
- udf_release_data(bh);
+ udf_release_data(bh);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
return udf_fixed_to_variable(ret);
udf_get_last_block(struct super_block *sb)
{
struct block_device *bdev = sb->s_bdev;
- int ret;
unsigned long lblock = 0;
- ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
-
- if (ret) /* Hard Disk */
- {
+ if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock))
lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits;
- }
if (lblock)
return lblock - 1;
*bh = udf_tread(inode->i_sb, inode->i_ino);
- if (UDF_I_EXTENDED_FE(inode) == 0)
+ if (UDF_I_EFE(inode) == 0)
{
struct fileEntry *fe;
*bh = udf_tread(inode->i_sb, inode->i_ino);
- if (UDF_I_EXTENDED_FE(inode) == 0)
+ if (UDF_I_EFE(inode) == 0)
{
struct fileEntry *fe;
if (block == 0xFFFFFFFF)
return NULL;
- bh = udf_tread(sb, block);
+ bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
if (!bh)
{
- udf_debug("block=%d, location=%d: read failed\n", block, location);
+ udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
return NULL;
}
if ( location != le32_to_cpu(tag_p->tagLocation) )
{
udf_debug("location mismatch block %u, tag %u != %u\n",
- block, le32_to_cpu(tag_p->tagLocation), location);
+ block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
goto error_out;
}
return bh;
}
udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
- block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
+ block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
error_out:
brelse(bh);
uint8_t lfi = cfi->lengthFileIdent;
int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
sizeof(struct fileIdentDesc);
+ int adinicb = 0;
+
+ if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
+ adinicb = 1;
offset = fibh->soffset + sizeof(struct fileIdentDesc);
if (impuse)
{
- if (offset + liu < 0)
+ if (adinicb || (offset + liu < 0))
memcpy((uint8_t *)sfi->impUse, impuse, liu);
else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, impuse, liu);
if (fileident)
{
- if (offset + lfi < 0)
+ if (adinicb || (offset + lfi < 0))
memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, fileident, lfi);
offset += lfi;
- if (offset + padlen < 0)
+ if (adinicb || (offset + padlen < 0))
memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
else if (offset >= 0)
memset(fibh->ebh->b_data + offset, 0x00, padlen);
checksum += ((uint8_t *)&cfi->descTag)[i];
cfi->descTag.tagChecksum = checksum;
- if (sizeof(struct fileIdentDesc) <= -fibh->soffset)
+ if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset))
memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
else
{
sizeof(struct fileIdentDesc) + fibh->soffset);
}
- if (fibh->sbh != fibh->ebh)
- mark_buffer_dirty_inode(fibh->ebh, inode);
- mark_buffer_dirty_inode(fibh->sbh, inode);
+ if (adinicb)
+ mark_inode_dirty(inode);
+ else
+ {
+ if (fibh->sbh != fibh->ebh)
+ mark_buffer_dirty_inode(fibh->ebh, inode);
+ mark_buffer_dirty_inode(fibh->sbh, inode);
+ }
return 0;
}
f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
- if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+ if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ fibh->sbh = fibh->ebh = NULL;
+ else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{
offset >>= dir->i_sb->s_blocksize_bits;
}
else
offset = 0;
+
+ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
+ {
+ udf_release_data(bh);
+ return NULL;
+ }
}
else
{
return NULL;
}
- if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
- {
- udf_release_data(bh);
- return NULL;
- }
-
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
{
lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
inode = udf_iget(dir->i_sb, lb);
- if (!inode) {
+ if (!inode)
+ {
unlock_kernel();
return ERR_PTR(-EACCES);
}
udf_release_data(fibh.sbh);
inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
- if ( !inode ) {
+ if ( !inode )
+ {
unlock_kernel();
return ERR_PTR(-EACCES);
}
{
struct super_block *sb;
struct fileIdentDesc *fi=NULL;
- struct ustr unifilename;
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
int namelen;
loff_t f_pos;
return NULL;
}
- if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
+ if ( !(namelen = udf_put_filename(sb, dentry->d_name.name, name, dentry->d_name.len)))
{
*err = -ENAMETOOLONG;
return NULL;
}
-
- if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
- {
- if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
- {
- *err = -ENAMETOOLONG;
- return NULL;
- }
- }
- else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
- {
- if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, name, &unifilename, UDF_NAME_LEN)) )
- {
- *err = -ENAMETOOLONG;
- return NULL;
- }
- }
- else
- return NULL;
}
else
namelen = 0;
f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
- if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+ if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ fibh->sbh = fibh->ebh = NULL;
+ else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{
offset >>= dir->i_sb->s_blocksize_bits;
*err = -EIO;
return NULL;
}
-
+
block = UDF_I_LOCATION(dir).logicalBlockNum;
-
- while ( (f_pos < size) )
+
+ }
+ else
+ {
+ block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
+ fibh->sbh = fibh->ebh = NULL;
+ fibh->soffset = fibh->eoffset = sb->s_blocksize;
+ goto add;
+ }
+
+ while ( (f_pos < size) )
+ {
+ fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+
+ if (!fi)
{
- fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-
- if (!fi)
- {
- if (fibh->sbh != fibh->ebh)
- udf_release_data(fibh->ebh);
- udf_release_data(fibh->sbh);
- udf_release_data(bh);
- *err = -EIO;
- return NULL;
- }
-
- liu = le16_to_cpu(cfi->lengthOfImpUse);
- lfi = cfi->lengthFileIdent;
-
- if (fibh->sbh == fibh->ebh)
- nameptr = fi->fileIdent + liu;
+ if (fibh->sbh != fibh->ebh)
+ udf_release_data(fibh->ebh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(bh);
+ *err = -EIO;
+ return NULL;
+ }
+
+ liu = le16_to_cpu(cfi->lengthOfImpUse);
+ lfi = cfi->lengthFileIdent;
+
+ if (fibh->sbh == fibh->ebh)
+ nameptr = fi->fileIdent + liu;
+ else
+ {
+ int poffset; /* Unpaded ending offset */
+
+ poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
+
+ if (poffset >= lfi)
+ nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
else
{
- int poffset; /* Unpaded ending offset */
-
- poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
-
- if (poffset >= lfi)
- nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
- else
- {
- nameptr = fname;
- memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
- memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
- }
+ nameptr = fname;
+ memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
+ memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
}
-
- if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
+ }
+
+ if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
+ {
+ if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
{
- if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
+ udf_release_data(bh);
+ cfi->descTag.tagSerialNum = cpu_to_le16(1);
+ cfi->fileVersionNum = cpu_to_le16(1);
+ cfi->fileCharacteristics = 0;
+ cfi->lengthFileIdent = namelen;
+ cfi->lengthOfImpUse = cpu_to_le16(0);
+ if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
+ return fi;
+ else
{
- udf_release_data(bh);
- cfi->descTag.tagSerialNum = cpu_to_le16(1);
- cfi->fileVersionNum = cpu_to_le16(1);
- cfi->fileCharacteristics = 0;
- cfi->lengthFileIdent = namelen;
- cfi->lengthOfImpUse = cpu_to_le16(0);
- if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
- return fi;
- else
- {
- *err = -EIO;
- return NULL;
- }
+ *err = -EIO;
+ return NULL;
}
}
+ }
- if (!lfi || !dentry)
- continue;
+ if (!lfi || !dentry)
+ continue;
- if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
- udf_match(flen, fname, &(dentry->d_name)))
- {
- if (fibh->sbh != fibh->ebh)
- udf_release_data(fibh->ebh);
- udf_release_data(fibh->sbh);
- udf_release_data(bh);
- *err = -EEXIST;
- return NULL;
- }
- }
- }
- else
- {
- block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
- if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
+ udf_match(flen, fname, &(dentry->d_name)))
{
- fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
- fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
- }
- else
- {
- fibh->sbh = fibh->ebh = NULL;
- fibh->soffset = fibh->eoffset = sb->s_blocksize;
+ if (fibh->sbh != fibh->ebh)
+ udf_release_data(fibh->ebh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(bh);
+ *err = -EEXIST;
+ return NULL;
}
}
+add:
f_pos += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
fibh->sbh = fibh->ebh;
}
- if (UDF_I_ALLOCTYPE(dir) != ICBTAG_FLAG_AD_IN_ICB)
+ if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ {
+ block = UDF_I_LOCATION(dir).logicalBlockNum;
+ fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir));
+ }
+ else
+ {
block = eloc.logicalBlockNum + ((elen - 1) >>
dir->i_sb->s_blocksize_bits);
- else
- block = UDF_I_LOCATION(dir).logicalBlockNum;
-
- fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
+ fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
+ }
}
else
{
lock_kernel();
inode = udf_new_inode(dir, mode, &err);
- if (!inode) {
+ if (!inode)
+ {
unlock_kernel();
return err;
}
f_pos = (udf_ext0_offset(dir) >> 2);
fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
- if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+
+ if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+ fibh.sbh = fibh.ebh = NULL;
+ else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{
offset >>= dir->i_sb->s_blocksize_bits;
}
else
offset = 0;
+
+ if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
+ {
+ udf_release_data(bh);
+ return 0;
+ }
}
else
{
return 0;
}
- if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
- return 0;
while ( (f_pos < size) )
{
if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)
{
+ if (fibh.sbh != fibh.ebh)
+ udf_release_data(fibh.ebh);
+ udf_release_data(fibh.sbh);
udf_release_data(bh);
return 0;
}
char *ea;
int err;
int block;
+ char name[UDF_NAME_LEN];
+ int namelen;
lock_kernel();
if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
set_buffer_uptodate(bh);
unlock_buffer(bh);
mark_buffer_dirty_inode(bh, inode);
+ ea = bh->b_data + udf_ext0_offset(inode);
}
else
- {
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = udf_tread(inode->i_sb, block);
- }
- ea = bh->b_data + udf_ext0_offset(inode);
+ ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
pc = (struct pathComponent *)ea;
pc->componentType = 5;
pc->lengthComponentIdent = 0;
pc->componentFileVersionNum = 0;
- if (pc->componentIdent[0] == '.')
+ if (compstart[0] == '.')
{
- if (pc->lengthComponentIdent == 1)
+ if ((symname-compstart) == 1)
pc->componentType = 4;
- else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
+ else if ((symname-compstart) == 2 && compstart[1] == '.')
pc->componentType = 3;
}
if (pc->componentType == 5)
{
- if (elen + sizeof(struct pathComponent) + symname - compstart > eoffset)
+ if ( !(namelen = udf_put_filename(inode->i_sb, compstart, name, symname-compstart)))
+ goto out_no_entry;
+
+ if (elen + sizeof(struct pathComponent) + namelen > eoffset)
goto out_no_entry;
else
- pc->lengthComponentIdent = symname - compstart;
+ pc->lengthComponentIdent = namelen;
- memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
+ memcpy(pc->componentIdent, name, namelen);
}
elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
struct fileIdentDesc cfi, *fi;
lock_kernel();
- if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) {
+ if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
+ {
unlock_kernel();
return -EMLINK;
}
- if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
+ if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
+ {
unlock_kernel();
return err;
}
goto end_rename;
}
retval = -EIO;
- dir_bh = udf_bread(old_inode, 0, 0, &retval);
- if (!dir_bh)
- goto end_rename;
- dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
+ if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
+ {
+ dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
+ (UDF_I_EFE(old_inode) ?
+ sizeof(struct extendedFileEntry) :
+ sizeof(struct fileEntry)),
+ old_inode->i_sb->s_blocksize, &offset);
+ }
+ else
+ {
+ dir_bh = udf_bread(old_inode, 0, 0, &retval);
+ if (!dir_bh)
+ goto end_rename;
+ dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
+ }
if (!dir_fi)
goto end_rename;
if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
mark_inode_dirty(old_dir);
- if (dir_bh)
+ if (dir_fi)
{
dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
{
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) */
struct logicalVolIntegrityDescImpUse
SLAB_CTOR_CONSTRUCTOR)
inode_init_once(&ei->vfs_inode);
}
-
+
static int init_inodecache(void)
{
udf_inode_cachep = kmem_cache_create("udf_inode_cache",
.write_inode = udf_write_inode,
.put_inode = udf_put_inode,
.delete_inode = udf_delete_inode,
+ .clear_inode = udf_clear_inode,
.put_super = udf_put_super,
.write_super = udf_write_super,
.statfs = udf_statfs,
if (!options)
return 1;
- while ((opt = strsep(&options, ",")) != NULL) {
+ while ((opt = strsep(&options, ",")) != NULL)
+ {
if (!*opt)
continue;
/* Make "opt=val" into two strings */
UDF_SB(sb)->s_gid = uopt.gid;
UDF_SB(sb)->s_umask = uopt.umask;
-#if UDFFS_RW != 1
- *flags |= MS_RDONLY;
-#endif
-
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (*flags & MS_RDONLY)
{
if (location == last[i] - UDF_SB_SESSION(sb))
{
- lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
- UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
+ lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb);
+ UDF_SB_ANCHOR(sb)[1] = last[i] - 256 - UDF_SB_SESSION(sb);
}
else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
{
UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
- lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
- UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
+ lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb);
+ UDF_SB_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb);
}
else
udf_debug("Anchor found at block %d, location mismatch %d.\n",
else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
{
lastblock = last[i];
- UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
+ UDF_SB_ANCHOR(sb)[3] = 512;
}
else
{
if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
{
UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
- UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb);
+ UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation);
if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY;
if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE)
sb->s_fs_info = sbi;
memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
-#if UDFFS_RW != 1
- sb->s_flags |= MS_RDONLY;
-#endif
-
if (!udf_parse_options((char *)options, &uopt))
goto error_out;
UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
UDF_SB_ANCHOR(sb)[2] = uopt.anchor;
- UDF_SB_ANCHOR(sb)[3] = UDF_SB_SESSION(sb) + 256;
+ UDF_SB_ANCHOR(sb)[3] = 256;
if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
{
{
timestamp ts;
udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
- udf_info("UDF %s-%s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
- UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE,
+ udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+ UDFFS_VERSION, UDFFS_DATE,
UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
ts.typeAndTimezone);
}
static int
udf_statfs(struct super_block *sb, struct statfs *buf)
{
- lock_kernel();
-
buf->f_type = UDF_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
/* __kernel_fsid_t f_fsid */
buf->f_namelen = UDF_NAME_LEN;
- unlock_kernel();
-
return 0;
}
uint16_t ident;
struct spaceBitmapDesc *bm;
+ lock_kernel();
+
loc.logicalBlockNum = bitmap->s_extPosition;
loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
bh = udf_read_ptagged(sb, loc, 0, &ident);
if (!bh)
{
printk(KERN_ERR "udf: udf_count_free failed\n");
- return 0;
+ goto out;
}
else if (ident != TAG_IDENT_SBD)
{
udf_release_data(bh);
printk(KERN_ERR "udf: udf_count_free failed\n");
- return 0;
+ goto out;
}
bm = (struct spaceBitmapDesc *)bh->b_data;
if (!bh)
{
udf_debug("read failed\n");
- return accum;
+ goto out;
}
index = 0;
ptr = (uint8_t *)bh->b_data;
}
}
udf_release_data(bh);
+
+out:
+ unlock_kernel();
+
return accum;
}
int8_t etype;
struct buffer_head *bh = NULL;
+ lock_kernel();
+
bloc = UDF_I_LOCATION(table);
extoffset = sizeof(struct unallocSpaceEntry);
accum += (elen >> table->i_sb->s_blocksize_bits);
}
udf_release_data(bh);
+
+ unlock_kernel();
+
return accum;
}
#include <linux/buffer_head.h>
#include "udf_i.h"
-static void udf_pc_to_char(char *from, int fromlen, char *to)
+static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen, char *to)
{
struct pathComponent *pc;
int elen = 0;
/* that would be . - just ignore */
break;
case 5:
- memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
- p += pc->lengthComponentIdent;
+ p += udf_get_filename(sb, pc->componentIdent, p, pc->lengthComponentIdent);
*p++ = '/';
+ break;
}
elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
}
char *symlink;
int err = -EIO;
char *p = kmap(page);
-
+
lock_kernel();
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
- {
- bh = udf_tread(inode->i_sb, inode->i_ino);
-
- if (!bh)
- goto out;
-
- symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
- }
+ symlink = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
else
{
bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
symlink = bh->b_data;
}
- udf_pc_to_char(symlink, inode->i_size, p);
+ udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
udf_release_data(bh);
unlock_kernel();
else
lenalloc = extoffset - adsize;
- if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+ if (!bh)
lenalloc -= udf_file_entry_alloc_offset(inode);
else
lenalloc -= sizeof(struct allocExtDesc);
extoffset = 0;
if (lelen)
{
- if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
- memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
+ if (!bh)
+ BUG();
else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
}
else
{
- if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+ if (!bh)
{
UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode);
}
udf_release_data(bh);
- bh = NULL;
-
+ extoffset = sizeof(struct allocExtDesc);
bloc = eloc;
+ bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
if (elen)
lelen = (elen + inode->i_sb->s_blocksize - 1) >>
inode->i_sb->s_blocksize_bits;
if (lelen)
{
- if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
- memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
+ if (!bh)
+ BUG();
else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
}
else
{
- if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+ if (!bh)
{
UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode);
#define UDF_I_LENEXTENTS(X) ( UDF_I(X)->i_lenExtents )
#define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique )
#define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type )
-#define UDF_I_EXTENDED_FE(X) ( UDF_I(X)->i_extended_fe )
-#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat_4096 )
-#define UDF_I_NEW_INODE(X) ( UDF_I(X)->i_new_inode )
+#define UDF_I_EFE(X) ( UDF_I(X)->i_efe )
+#define UDF_I_USE(X) ( UDF_I(X)->i_use )
+#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat4096 )
#define UDF_I_NEXT_ALLOC_BLOCK(X) ( UDF_I(X)->i_next_alloc_block )
#define UDF_I_NEXT_ALLOC_GOAL(X) ( UDF_I(X)->i_next_alloc_goal )
#define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime )
#define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime )
#define UDF_I_CRTIME(X) ( UDF_I(X)->i_crtime )
#define UDF_I_UCRTIME(X) ( UDF_I(X)->i_ucrtime )
+#define UDF_I_SAD(X) ( UDF_I(X)->i_ext.i_sad )
+#define UDF_I_LAD(X) ( UDF_I(X)->i_ext.i_lad )
+#define UDF_I_DATA(X) ( UDF_I(X)->i_ext.i_data )
#endif /* !defined(_LINUX_UDF_I_H) */
#include <linux/version.h>
#endif
-#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
-#define CONFIG_UDF_FS_MODULE
-#endif
-
#include "udfend.h"
#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
#define CURRENT_UTIME (xtime.tv_nsec / 1000)
#define udf_file_entry_alloc_offset(inode)\
- ((UDF_I_EXTENDED_FE(inode) ?\
- sizeof(struct extendedFileEntry) :\
- sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode))
+ (UDF_I_USE(inode) ?\
+ sizeof(struct unallocSpaceEntry) :\
+ ((UDF_I_EFE(inode) ?\
+ sizeof(struct extendedFileEntry) :\
+ sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)))
#define udf_ext0_offset(inode)\
(UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\
extern void udf_read_inode(struct inode *);
extern void udf_put_inode(struct inode *);
extern void udf_delete_inode(struct inode *);
+extern void udf_clear_inode(struct inode *);
extern void udf_write_inode(struct inode *, int);
extern long udf_block_map(struct inode *, long);
extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
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);
/* lowlevel.c */
extern unsigned int udf_get_last_session(struct super_block *);
/* unicode.c */
extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
+extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, int);
+extern int udf_build_ustr(struct ustr *, dstring *, int);
+extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
/* ialloc.c */
extern void udf_free_inode(struct inode *);
/* directory.c */
extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-
-/* unicode.c */
-extern int udf_ustr_to_dchars(uint8_t *, const struct ustr *, int);
-extern int udf_ustr_to_char(uint8_t *, const struct ustr *, int);
-extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
-extern int udf_dchars_to_ustr(struct ustr *, const uint8_t *, int);
-extern int udf_char_to_ustr(struct ustr *, const uint8_t *, int);
-extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
-extern int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
-extern int udf_build_ustr(struct ustr *, dstring *, int);
-extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
-extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
-extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
-extern int udf_CS0toNLS(struct nls_table *, struct ustr *, struct ustr *);
-extern int udf_NLStoCS0(struct nls_table *, dstring *, struct ustr *, int);
+extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
+extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
+extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
+extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
+extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
/* crc.c */
extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
-/* misc.c */
-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);
-
/* udftime.c */
extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
-/* directory.c */
-extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
-extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
-extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
-extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
-
#endif /* __UDF_DECL_H */
#include "udf_sb.h"
-int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen)
-{
- if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
- return 0;
- memcpy(dest+1, src->u_name, src->u_len);
- dest[0] = src->u_cmpID;
- return src->u_len + 1;
-}
-
-int udf_ustr_to_char(uint8_t *dest, const struct ustr *src, int strlen)
-{
- if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
- return 0;
- memcpy(dest, src->u_name, src->u_len);
- return src->u_len;
-}
-
-int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
-{
- if ( udf_ustr_to_dchars(dest, src, dlength-1) )
- {
- dest[dlength-1] = src->u_len + 1;
- return dlength;
- }
- else
- return 0;
-}
-
-int udf_dchars_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
-{
- if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
- return 0;
- memset(dest, 0, sizeof(struct ustr));
- memcpy(dest->u_name, src+1, strlen-1);
- dest->u_cmpID = src[0];
- dest->u_len = strlen-1;
- return strlen-1;
-}
+static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
-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) )
return 0;
return strlen;
}
-
-int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
-{
- if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
- return dlength;
- else
- return 0;
-}
-
/*
* udf_build_ustr
*/
/*
* udf_build_ustr_exact
*/
-int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
{
if ( (!dest) || (!ptr) || (!exactsize) )
return -1;
* November 12, 1997 - Andrew E. Mileski
* Written, tested, and released.
*/
-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;
int utf_cnt;
return u_len + 1;
}
-int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
+static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
{
uint8_t *ocu;
uint32_t c;
return utf_o->u_len;
}
-int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
+static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
{
unsigned len, i, max_val;
uint16_t uni_char;
return 0;
}
+int udf_put_filename(struct super_block *sb, const uint8_t *sname, uint8_t *dname, int flen)
+{
+ struct ustr unifilename;
+ int namelen;
+
+ if ( !(udf_char_to_ustr(&unifilename, sname, flen)) )
+ {
+ return 0;
+ }
+
+ if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
+ {
+ if ( !(namelen = udf_UTF8toCS0(dname, &unifilename, UDF_NAME_LEN)) )
+ {
+ return 0;
+ }
+ }
+ else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+ {
+ if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, dname, &unifilename, UDF_NAME_LEN)) )
+ {
+ return 0;
+ }
+ }
+ else
+ return 0;
+
+ return namelen;
+}
+
#define ILLEGAL_CHAR_MARK '_'
#define EXT_MARK '.'
#define CRC_MARK '#'
#define EXT_SIZE 5
-int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
+static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
{
int index, newIndex = 0, needsCRC = 0;
int extIndex = 0, newExtIndex = 0, hasExt = 0;
#ifndef _UDF_FS_H
#define _UDF_FS_H 1
-#include <linux/config.h>
-
#define UDF_PREALLOCATE
#define UDF_DEFAULT_PREALLOC_BLOCKS 8
-#define UDFFS_DATE "2002/03/11"
-#define UDFFS_VERSION "0.9.6"
-
-#if !defined(UDFFS_RW)
-
-#if defined(CONFIG_UDF_RW)
-#define UDFFS_RW 1
-#else /* !defined(CONFIG_UDF_RW) */
-#define UDFFS_RW 0
-#endif /* defined(CONFIG_UDF_RW) */
-
-#endif /* !defined(UDFFS_RW) */
+#define UDFFS_DATE "2002/11/15"
+#define UDFFS_VERSION "0.9.7"
#define UDFFS_DEBUG
#ifndef _ECMA_167_H
typedef struct
{
- __u32 logicalBlockNum;
- __u16 partitionReferenceNum;
+ __u32 logicalBlockNum;
+ __u16 partitionReferenceNum;
} __attribute__ ((packed)) lb_addr;
+
+typedef struct
+{
+ __u32 extLength;
+ __u32 extPosition;
+} __attribute__ ((packed)) short_ad;
+
+typedef struct
+{
+ __u32 extLength;
+ lb_addr extLocation;
+ __u8 impUse[6];
+} __attribute__ ((packed)) long_ad;
#endif
struct udf_inode_info
{
- long i_umtime;
- long i_uctime;
- long i_crtime;
- long i_ucrtime;
+ long i_umtime;
+ long i_uctime;
+ long i_crtime;
+ long i_ucrtime;
/* Physical address of inode */
- lb_addr i_location;
- __u64 i_unique;
- __u32 i_lenEAttr;
- __u32 i_lenAlloc;
- __u64 i_lenExtents;
- __u32 i_next_alloc_block;
- __u32 i_next_alloc_goal;
- unsigned i_alloc_type : 3;
- unsigned i_extended_fe : 1;
- unsigned i_strat_4096 : 1;
- unsigned i_new_inode : 1;
- unsigned reserved : 26;
+ lb_addr i_location;
+ __u64 i_unique;
+ __u32 i_lenEAttr;
+ __u32 i_lenAlloc;
+ __u64 i_lenExtents;
+ __u32 i_next_alloc_block;
+ __u32 i_next_alloc_goal;
+ unsigned i_alloc_type : 3;
+ unsigned i_efe : 1;
+ unsigned i_use : 1;
+ unsigned i_strat4096 : 1;
+ unsigned reserved : 26;
+ union
+ {
+ short_ad *i_sad;
+ long_ad *i_lad;
+ __u8 *i_data;
+ } i_ext;
struct inode vfs_inode;
};