Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6: (41 commits) udf: use crc_itu_t from lib instead of udf_crc udf: Fix compilation warnings when UDF debug is on udf: Fix bug in VAT mapping code udf: Add read-only support for 2.50 UDF media udf: Fix handling of multisession media udf: Mount filesystem read-only if it has pseudooverwrite partition udf: Handle VAT packed inside inode properly udf: Allow loading of VAT inode udf: Fix detection of VAT version udf: Silence warning about accesses beyond end of device udf: Improve anchor block detection udf: Cleanup anchor block detection. udf: Move processing of virtual partitions udf: Move filling of partition descriptor info into a separate function udf: Improve error recovery on mount udf: Cleanup volume descriptor sequence processing udf: fix anchor point detection udf: Remove declarations of arrays of size UDF_NAME_LEN (256 bytes) udf: Remove checking of existence of filename in udf_add_entry() udf: Mark udf_process_sequence() as noinline ...
This commit is contained in:
commit
62429f4340
26 changed files with 1170 additions and 1558 deletions
|
@ -689,6 +689,7 @@ config ZISOFS
|
|||
|
||||
config UDF_FS
|
||||
tristate "UDF file system support"
|
||||
select CRC_ITU_T
|
||||
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
|
||||
|
|
|
@ -6,4 +6,4 @@ obj-$(CONFIG_UDF_FS) += udf.o
|
|||
|
||||
udf-objs := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \
|
||||
partition.o super.o truncate.o symlink.o fsync.o \
|
||||
crc.o directory.o misc.o udftime.o unicode.o
|
||||
directory.o misc.o udftime.o unicode.o
|
||||
|
|
|
@ -149,8 +149,7 @@ static bool udf_add_free_space(struct udf_sb_info *sbi,
|
|||
return false;
|
||||
|
||||
lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
|
||||
lvid->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu(
|
||||
lvid->freeSpaceTable[partition]) + cnt);
|
||||
le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -589,9 +588,7 @@ static void udf_table_free_blocks(struct super_block *sb,
|
|||
sptr = oepos.bh->b_data + epos.offset;
|
||||
aed = (struct allocExtDesc *)
|
||||
oepos.bh->b_data;
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(le32_to_cpu(
|
||||
aed->lengthAllocDescs) +
|
||||
le32_add_cpu(&aed->lengthAllocDescs,
|
||||
adsize);
|
||||
} else {
|
||||
sptr = iinfo->i_ext.i_data +
|
||||
|
@ -645,9 +642,7 @@ static void udf_table_free_blocks(struct super_block *sb,
|
|||
mark_inode_dirty(table);
|
||||
} else {
|
||||
aed = (struct allocExtDesc *)epos.bh->b_data;
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(le32_to_cpu(
|
||||
aed->lengthAllocDescs) + adsize);
|
||||
le32_add_cpu(&aed->lengthAllocDescs, adsize);
|
||||
udf_update_tag(epos.bh->b_data, epos.offset);
|
||||
mark_buffer_dirty(epos.bh);
|
||||
}
|
||||
|
|
172
fs/udf/crc.c
172
fs/udf/crc.c
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* crc.c
|
||||
*
|
||||
* PURPOSE
|
||||
* Routines to generate, calculate, and test a 16-bit CRC.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories
|
||||
* and Ned W. Rhodes of Software Systems Group. It has been published in
|
||||
* "Design and Validation of Computer Protocols", Prentice Hall,
|
||||
* Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4.
|
||||
*
|
||||
* Copyright is held by AT&T.
|
||||
*
|
||||
* AT&T gives permission for the free use of the CRC source code.
|
||||
*
|
||||
* COPYRIGHT
|
||||
* This file is distributed under the terms of the GNU General Public
|
||||
* License (GPL). Copies of the GPL can be obtained from:
|
||||
* ftp://prep.ai.mit.edu/pub/gnu/GPL
|
||||
* Each contributing author retains all rights to their own work.
|
||||
*/
|
||||
|
||||
#include "udfdecl.h"
|
||||
|
||||
static uint16_t crc_table[256] = {
|
||||
0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U,
|
||||
0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU,
|
||||
0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U,
|
||||
0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU,
|
||||
0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U,
|
||||
0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU,
|
||||
0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U,
|
||||
0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU,
|
||||
0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U,
|
||||
0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU,
|
||||
0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U,
|
||||
0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU,
|
||||
0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U,
|
||||
0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U,
|
||||
0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U,
|
||||
0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U,
|
||||
0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU,
|
||||
0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U,
|
||||
0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU,
|
||||
0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U,
|
||||
0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU,
|
||||
0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U,
|
||||
0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU,
|
||||
0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U,
|
||||
0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU,
|
||||
0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U,
|
||||
0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU,
|
||||
0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U,
|
||||
0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U,
|
||||
0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U,
|
||||
0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U,
|
||||
0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U
|
||||
};
|
||||
|
||||
/*
|
||||
* udf_crc
|
||||
*
|
||||
* PURPOSE
|
||||
* Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory.
|
||||
* The polynomial used is: x^16 + x^12 + x^15 + 1
|
||||
*
|
||||
* PRE-CONDITIONS
|
||||
* data Pointer to the data block.
|
||||
* size Size of the data block.
|
||||
*
|
||||
* POST-CONDITIONS
|
||||
* <return> CRC of the data block.
|
||||
*
|
||||
* HISTORY
|
||||
* July 21, 1997 - Andrew E. Mileski
|
||||
* Adapted from OSTA-UDF(tm) 1.50 standard.
|
||||
*/
|
||||
uint16_t udf_crc(uint8_t *data, uint32_t size, uint16_t crc)
|
||||
{
|
||||
while (size--)
|
||||
crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
#if defined(TEST)
|
||||
|
||||
/*
|
||||
* PURPOSE
|
||||
* Test udf_crc()
|
||||
*
|
||||
* HISTORY
|
||||
* July 21, 1997 - Andrew E. Mileski
|
||||
* Adapted from OSTA-UDF(tm) 1.50 standard.
|
||||
*/
|
||||
|
||||
unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U };
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned short x;
|
||||
|
||||
x = udf_crc(bytes, sizeof bytes);
|
||||
printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(TEST) */
|
||||
|
||||
/****************************************************************************/
|
||||
#if defined(GENERATE)
|
||||
|
||||
/*
|
||||
* PURPOSE
|
||||
* Generate a table for fast 16-bit CRC calculations (any polynomial).
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The ITU-T V.41 polynomial is 010041.
|
||||
*
|
||||
* HISTORY
|
||||
* July 21, 1997 - Andrew E. Mileski
|
||||
* Adapted from OSTA-UDF(tm) 1.50 standard.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned long crc, poly;
|
||||
int n, i;
|
||||
|
||||
/* Get the polynomial */
|
||||
sscanf(argv[1], "%lo", &poly);
|
||||
if (poly & 0xffff0000U) {
|
||||
fprintf(stderr, "polynomial is too large\en");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("/* CRC 0%o */\n", poly);
|
||||
|
||||
/* Create a table */
|
||||
printf("static unsigned short crc_table[256] = {\n");
|
||||
for (n = 0; n < 256; n++) {
|
||||
if (n % 8 == 0)
|
||||
printf("\t");
|
||||
crc = n << 8;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (crc & 0x8000U)
|
||||
crc = (crc << 1) ^ poly;
|
||||
else
|
||||
crc <<= 1;
|
||||
crc &= 0xFFFFU;
|
||||
}
|
||||
if (n == 255)
|
||||
printf("0x%04xU ", crc);
|
||||
else
|
||||
printf("0x%04xU, ", crc);
|
||||
if (n % 8 == 7)
|
||||
printf("\n");
|
||||
}
|
||||
printf("};\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(GENERATE) */
|
83
fs/udf/dir.c
83
fs/udf/dir.c
|
@ -39,13 +39,13 @@
|
|||
static int do_udf_readdir(struct inode *dir, struct file *filp,
|
||||
filldir_t filldir, void *dirent)
|
||||
{
|
||||
struct udf_fileident_bh fibh;
|
||||
struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
|
||||
struct fileIdentDesc *fi = NULL;
|
||||
struct fileIdentDesc cfi;
|
||||
int block, iblock;
|
||||
loff_t nf_pos = (filp->f_pos - 1) << 2;
|
||||
int flen;
|
||||
char fname[UDF_NAME_LEN];
|
||||
char *fname = NULL;
|
||||
char *nameptr;
|
||||
uint16_t liu;
|
||||
uint8_t lfi;
|
||||
|
@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
|
|||
kernel_lb_addr eloc;
|
||||
uint32_t elen;
|
||||
sector_t offset;
|
||||
int i, num;
|
||||
int i, num, ret = 0;
|
||||
unsigned int dt_type;
|
||||
struct extent_position epos = { NULL, 0, {0, 0} };
|
||||
struct udf_inode_info *iinfo;
|
||||
|
||||
if (nf_pos >= size)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
||||
if (!fname) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nf_pos == 0)
|
||||
nf_pos = udf_ext0_offset(dir);
|
||||
|
||||
fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
|
||||
iinfo = UDF_I(dir);
|
||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||
fibh.sbh = fibh.ebh = NULL;
|
||||
} else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
|
||||
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
|
||||
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
|
||||
if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
|
||||
&epos, &eloc, &elen, &offset)
|
||||
!= (EXT_RECORDED_ALLOCATED >> 30)) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
|
||||
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
|
||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
|
||||
|
@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
|
|||
}
|
||||
|
||||
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
|
||||
brelse(epos.bh);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
|
||||
|
@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
|
|||
brelse(bha[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
brelse(epos.bh);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
while (nf_pos < size) {
|
||||
|
@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
|
|||
|
||||
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
|
||||
&elen, &offset);
|
||||
if (!fi) {
|
||||
if (fibh.sbh != fibh.ebh)
|
||||
brelse(fibh.ebh);
|
||||
brelse(fibh.sbh);
|
||||
brelse(epos.bh);
|
||||
return 0;
|
||||
}
|
||||
if (!fi)
|
||||
goto out;
|
||||
|
||||
liu = le16_to_cpu(cfi.lengthOfImpUse);
|
||||
lfi = cfi.lengthFileIdent;
|
||||
|
@ -167,53 +168,23 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
|
|||
dt_type = DT_UNKNOWN;
|
||||
}
|
||||
|
||||
if (flen) {
|
||||
if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
|
||||
if (fibh.sbh != fibh.ebh)
|
||||
brelse(fibh.ebh);
|
||||
brelse(fibh.sbh);
|
||||
brelse(epos.bh);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (flen && filldir(dirent, fname, flen, filp->f_pos,
|
||||
iblock, dt_type) < 0)
|
||||
goto out;
|
||||
} /* end while */
|
||||
|
||||
filp->f_pos = (nf_pos >> 2) + 1;
|
||||
|
||||
out:
|
||||
if (fibh.sbh != fibh.ebh)
|
||||
brelse(fibh.ebh);
|
||||
brelse(fibh.sbh);
|
||||
brelse(epos.bh);
|
||||
kfree(fname);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* udf_readdir
|
||||
*
|
||||
* PURPOSE
|
||||
* Read a directory entry.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Optional - sys_getdents() will return -ENOTDIR if this routine is not
|
||||
* available.
|
||||
*
|
||||
* Refer to sys_getdents() in fs/readdir.c
|
||||
* sys_getdents() -> .
|
||||
*
|
||||
* PRE-CONDITIONS
|
||||
* filp Pointer to directory file.
|
||||
* buf Pointer to directory entry buffer.
|
||||
* filldir Pointer to filldir function.
|
||||
*
|
||||
* POST-CONDITIONS
|
||||
* <return> >=0 on success.
|
||||
*
|
||||
* HISTORY
|
||||
* July 1, 1997 - Andrew E. Mileski
|
||||
* Written, tested, and released.
|
||||
*/
|
||||
|
||||
static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
{
|
||||
struct inode *dir = filp->f_path.dentry->d_inode;
|
||||
|
|
|
@ -70,19 +70,6 @@ typedef struct {
|
|||
uint8_t microseconds;
|
||||
} __attribute__ ((packed)) timestamp;
|
||||
|
||||
typedef struct {
|
||||
uint16_t typeAndTimezone;
|
||||
int16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
uint8_t centiseconds;
|
||||
uint8_t hundredsOfMicroseconds;
|
||||
uint8_t microseconds;
|
||||
} __attribute__ ((packed)) kernel_timestamp;
|
||||
|
||||
/* Type and Time Zone (ECMA 167r3 1/7.3.1) */
|
||||
#define TIMESTAMP_TYPE_MASK 0xF000
|
||||
#define TIMESTAMP_TYPE_CUT 0x0000
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "udfdecl.h"
|
||||
#include <linux/fs.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h> /* memset */
|
||||
|
@ -144,40 +143,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* udf_ioctl
|
||||
*
|
||||
* PURPOSE
|
||||
* Issue an ioctl.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Optional - sys_ioctl() will return -ENOTTY if this routine is not
|
||||
* available, and the ioctl cannot be handled without filesystem help.
|
||||
*
|
||||
* sys_ioctl() handles these ioctls that apply only to regular files:
|
||||
* FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
|
||||
* These ioctls are also handled by sys_ioctl():
|
||||
* FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
|
||||
* All other ioctls are passed to the filesystem.
|
||||
*
|
||||
* Refer to sys_ioctl() in fs/ioctl.c
|
||||
* sys_ioctl() -> .
|
||||
*
|
||||
* PRE-CONDITIONS
|
||||
* inode Pointer to inode that ioctl was issued on.
|
||||
* filp Pointer to file that ioctl was issued on.
|
||||
* cmd The ioctl command.
|
||||
* arg The ioctl argument [can be interpreted as a
|
||||
* user-space pointer if desired].
|
||||
*
|
||||
* POST-CONDITIONS
|
||||
* <return> Success (>=0) or an error code (<=0) that
|
||||
* sys_ioctl() will return.
|
||||
*
|
||||
* HISTORY
|
||||
* July 1, 1997 - Andrew E. Mileski
|
||||
* Written, tested, and released.
|
||||
*/
|
||||
int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
|
@ -225,18 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* udf_release_file
|
||||
*
|
||||
* PURPOSE
|
||||
* Called when all references to the file are closed
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Discard prealloced blocks
|
||||
*
|
||||
* HISTORY
|
||||
*
|
||||
*/
|
||||
static int udf_release_file(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (filp->f_mode & FMODE_WRITE) {
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "udfdecl.h"
|
||||
#include <linux/fs.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -47,11 +46,9 @@ void udf_free_inode(struct inode *inode)
|
|||
struct logicalVolIntegrityDescImpUse *lvidiu =
|
||||
udf_sb_lvidiu(sbi);
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
lvidiu->numDirs =
|
||||
cpu_to_le32(le32_to_cpu(lvidiu->numDirs) - 1);
|
||||
le32_add_cpu(&lvidiu->numDirs, -1);
|
||||
else
|
||||
lvidiu->numFiles =
|
||||
cpu_to_le32(le32_to_cpu(lvidiu->numFiles) - 1);
|
||||
le32_add_cpu(&lvidiu->numFiles, -1);
|
||||
|
||||
mark_buffer_dirty(sbi->s_lvid_bh);
|
||||
}
|
||||
|
@ -105,11 +102,9 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
|
|||
lvhd = (struct logicalVolHeaderDesc *)
|
||||
(lvid->logicalVolContentsUse);
|
||||
if (S_ISDIR(mode))
|
||||
lvidiu->numDirs =
|
||||
cpu_to_le32(le32_to_cpu(lvidiu->numDirs) + 1);
|
||||
le32_add_cpu(&lvidiu->numDirs, 1);
|
||||
else
|
||||
lvidiu->numFiles =
|
||||
cpu_to_le32(le32_to_cpu(lvidiu->numFiles) + 1);
|
||||
le32_add_cpu(&lvidiu->numFiles, 1);
|
||||
iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID);
|
||||
if (!(++uniqueID & 0x00000000FFFFFFFFUL))
|
||||
uniqueID += 16;
|
||||
|
|
178
fs/udf/inode.c
178
fs/udf/inode.c
|
@ -37,6 +37,7 @@
|
|||
#include <linux/buffer_head.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
#include "udf_sb.h"
|
||||
|
@ -66,22 +67,7 @@ static void udf_update_extents(struct inode *,
|
|||
struct extent_position *);
|
||||
static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
|
||||
|
||||
/*
|
||||
* udf_delete_inode
|
||||
*
|
||||
* PURPOSE
|
||||
* Clean-up before the specified inode is destroyed.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This routine is called when the kernel destroys an inode structure
|
||||
* ie. when iput() finds i_count == 0.
|
||||
*
|
||||
* HISTORY
|
||||
* July 1, 1997 - Andrew E. Mileski
|
||||
* Written, tested, and released.
|
||||
*
|
||||
* Called at the last iput() if i_nlink is zero.
|
||||
*/
|
||||
|
||||
void udf_delete_inode(struct inode *inode)
|
||||
{
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
|
@ -323,9 +309,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
|
|||
|
||||
lock_kernel();
|
||||
|
||||
if (block < 0)
|
||||
goto abort_negative;
|
||||
|
||||
iinfo = UDF_I(inode);
|
||||
if (block == iinfo->i_next_alloc_block + 1) {
|
||||
iinfo->i_next_alloc_block++;
|
||||
|
@ -347,10 +330,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
|
|||
abort:
|
||||
unlock_kernel();
|
||||
return err;
|
||||
|
||||
abort_negative:
|
||||
udf_warning(inode->i_sb, "udf_get_block", "block < 0");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
static struct buffer_head *udf_getblk(struct inode *inode, long block,
|
||||
|
@ -1116,16 +1095,16 @@ static void __udf_read_inode(struct inode *inode)
|
|||
fe = (struct fileEntry *)bh->b_data;
|
||||
|
||||
if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
|
||||
struct buffer_head *ibh = NULL, *nbh = NULL;
|
||||
struct indirectEntry *ie;
|
||||
struct buffer_head *ibh;
|
||||
|
||||
ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1,
|
||||
&ident);
|
||||
if (ident == TAG_IDENT_IE) {
|
||||
if (ibh) {
|
||||
if (ident == TAG_IDENT_IE && ibh) {
|
||||
struct buffer_head *nbh = NULL;
|
||||
kernel_lb_addr loc;
|
||||
ie = (struct indirectEntry *)ibh->b_data;
|
||||
struct indirectEntry *ie;
|
||||
|
||||
ie = (struct indirectEntry *)ibh->b_data;
|
||||
loc = lelb_to_cpu(ie->indirectICB.extLocation);
|
||||
|
||||
if (ie->indirectICB.extLength &&
|
||||
|
@ -1141,17 +1120,11 @@ static void __udf_read_inode(struct inode *inode)
|
|||
brelse(nbh);
|
||||
__udf_read_inode(inode);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
brelse(nbh);
|
||||
}
|
||||
}
|
||||
brelse(ibh);
|
||||
}
|
||||
} else {
|
||||
brelse(ibh);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
brelse(ibh);
|
||||
}
|
||||
} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
|
||||
printk(KERN_ERR "udf: unsupported strategy type: %d\n",
|
||||
le16_to_cpu(fe->icbTag.strategyType));
|
||||
|
@ -1168,8 +1141,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||
{
|
||||
struct fileEntry *fe;
|
||||
struct extendedFileEntry *efe;
|
||||
time_t convtime;
|
||||
long convtime_usec;
|
||||
int offset;
|
||||
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
|
||||
struct udf_inode_info *iinfo = UDF_I(inode);
|
||||
|
@ -1257,29 +1228,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
|
||||
(inode->i_sb->s_blocksize_bits - 9);
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(fe->accessTime))) {
|
||||
inode->i_atime.tv_sec = convtime;
|
||||
inode->i_atime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
|
||||
inode->i_atime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(fe->modificationTime))) {
|
||||
inode->i_mtime.tv_sec = convtime;
|
||||
inode->i_mtime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&inode->i_mtime,
|
||||
fe->modificationTime))
|
||||
inode->i_mtime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(fe->attrTime))) {
|
||||
inode->i_ctime.tv_sec = convtime;
|
||||
inode->i_ctime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
|
||||
inode->i_ctime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
iinfo->i_unique = le64_to_cpu(fe->uniqueID);
|
||||
iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
|
||||
|
@ -1289,37 +1246,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||
inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
|
||||
(inode->i_sb->s_blocksize_bits - 9);
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(efe->accessTime))) {
|
||||
inode->i_atime.tv_sec = convtime;
|
||||
inode->i_atime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
|
||||
inode->i_atime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(efe->modificationTime))) {
|
||||
inode->i_mtime.tv_sec = convtime;
|
||||
inode->i_mtime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&inode->i_mtime,
|
||||
efe->modificationTime))
|
||||
inode->i_mtime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(efe->createTime))) {
|
||||
iinfo->i_crtime.tv_sec = convtime;
|
||||
iinfo->i_crtime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
|
||||
iinfo->i_crtime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
if (udf_stamp_to_time(&convtime, &convtime_usec,
|
||||
lets_to_cpu(efe->attrTime))) {
|
||||
inode->i_ctime.tv_sec = convtime;
|
||||
inode->i_ctime.tv_nsec = convtime_usec * 1000;
|
||||
} else {
|
||||
if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
|
||||
inode->i_ctime = sbi->s_record_time;
|
||||
}
|
||||
|
||||
iinfo->i_unique = le64_to_cpu(efe->uniqueID);
|
||||
iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
|
||||
|
@ -1338,6 +1276,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||
case ICBTAG_FILE_TYPE_REALTIME:
|
||||
case ICBTAG_FILE_TYPE_REGULAR:
|
||||
case ICBTAG_FILE_TYPE_UNDEF:
|
||||
case ICBTAG_FILE_TYPE_VAT20:
|
||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||
inode->i_data.a_ops = &udf_adinicb_aops;
|
||||
else
|
||||
|
@ -1363,6 +1302,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||
inode->i_op = &page_symlink_inode_operations;
|
||||
inode->i_mode = S_IFLNK | S_IRWXUGO;
|
||||
break;
|
||||
case ICBTAG_FILE_TYPE_MAIN:
|
||||
udf_debug("METADATA FILE-----\n");
|
||||
break;
|
||||
case ICBTAG_FILE_TYPE_MIRROR:
|
||||
udf_debug("METADATA MIRROR FILE-----\n");
|
||||
break;
|
||||
case ICBTAG_FILE_TYPE_BITMAP:
|
||||
udf_debug("METADATA BITMAP FILE-----\n");
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
|
||||
"file type=%d\n", inode->i_ino,
|
||||
|
@ -1416,21 +1364,6 @@ static mode_t udf_convert_permissions(struct fileEntry *fe)
|
|||
return mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* udf_write_inode
|
||||
*
|
||||
* PURPOSE
|
||||
* Write out the specified inode.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This routine is called whenever an inode is synced.
|
||||
* Currently this routine is just a placeholder.
|
||||
*
|
||||
* HISTORY
|
||||
* July 1, 1997 - Andrew E. Mileski
|
||||
* Written, tested, and released.
|
||||
*/
|
||||
|
||||
int udf_write_inode(struct inode *inode, int sync)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1455,7 +1388,6 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
|||
uint32_t udfperms;
|
||||
uint16_t icbflags;
|
||||
uint16_t crclen;
|
||||
kernel_timestamp cpu_time;
|
||||
int err = 0;
|
||||
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
|
||||
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
|
||||
|
@ -1488,9 +1420,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
|||
iinfo->i_location.
|
||||
logicalBlockNum);
|
||||
use->descTag.descCRCLength = cpu_to_le16(crclen);
|
||||
use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use +
|
||||
sizeof(tag), crclen,
|
||||
0));
|
||||
use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
|
||||
sizeof(tag),
|
||||
crclen));
|
||||
use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
|
||||
|
||||
mark_buffer_dirty(bh);
|
||||
|
@ -1558,12 +1490,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
|||
(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
|
||||
(blocksize_bits - 9));
|
||||
|
||||
if (udf_time_to_stamp(&cpu_time, inode->i_atime))
|
||||
fe->accessTime = cpu_to_lets(cpu_time);
|
||||
if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
|
||||
fe->modificationTime = cpu_to_lets(cpu_time);
|
||||
if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
|
||||
fe->attrTime = cpu_to_lets(cpu_time);
|
||||
udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
|
||||
udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
|
||||
udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
|
||||
memset(&(fe->impIdent), 0, sizeof(regid));
|
||||
strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
|
||||
fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
|
||||
|
@ -1598,14 +1527,10 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
|||
iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec))
|
||||
iinfo->i_crtime = inode->i_ctime;
|
||||
|
||||
if (udf_time_to_stamp(&cpu_time, inode->i_atime))
|
||||
efe->accessTime = cpu_to_lets(cpu_time);
|
||||
if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
|
||||
efe->modificationTime = cpu_to_lets(cpu_time);
|
||||
if (udf_time_to_stamp(&cpu_time, iinfo->i_crtime))
|
||||
efe->createTime = cpu_to_lets(cpu_time);
|
||||
if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
|
||||
efe->attrTime = cpu_to_lets(cpu_time);
|
||||
udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
|
||||
udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
|
||||
udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
|
||||
udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
|
||||
|
||||
memset(&(efe->impIdent), 0, sizeof(regid));
|
||||
strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
|
||||
|
@ -1660,8 +1585,8 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
|||
crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc -
|
||||
sizeof(tag);
|
||||
fe->descTag.descCRCLength = cpu_to_le16(crclen);
|
||||
fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag),
|
||||
crclen, 0));
|
||||
fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag),
|
||||
crclen));
|
||||
fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
|
||||
|
||||
/* write the data blocks */
|
||||
|
@ -1778,9 +1703,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
|
|||
|
||||
if (epos->bh) {
|
||||
aed = (struct allocExtDesc *)epos->bh->b_data;
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(le32_to_cpu(
|
||||
aed->lengthAllocDescs) + adsize);
|
||||
le32_add_cpu(&aed->lengthAllocDescs, adsize);
|
||||
} else {
|
||||
iinfo->i_lenAlloc += adsize;
|
||||
mark_inode_dirty(inode);
|
||||
|
@ -1830,9 +1753,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
|
|||
mark_inode_dirty(inode);
|
||||
} else {
|
||||
aed = (struct allocExtDesc *)epos->bh->b_data;
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) +
|
||||
adsize);
|
||||
le32_add_cpu(&aed->lengthAllocDescs, adsize);
|
||||
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
|
||||
UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
|
||||
udf_update_tag(epos->bh->b_data,
|
||||
|
@ -2046,9 +1967,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
|
|||
mark_inode_dirty(inode);
|
||||
} else {
|
||||
aed = (struct allocExtDesc *)oepos.bh->b_data;
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
|
||||
(2 * adsize));
|
||||
le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
|
||||
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
|
||||
UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
|
||||
udf_update_tag(oepos.bh->b_data,
|
||||
|
@ -2065,9 +1984,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
|
|||
mark_inode_dirty(inode);
|
||||
} else {
|
||||
aed = (struct allocExtDesc *)oepos.bh->b_data;
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
|
||||
adsize);
|
||||
le32_add_cpu(&aed->lengthAllocDescs, -adsize);
|
||||
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
|
||||
UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
|
||||
udf_update_tag(oepos.bh->b_data,
|
||||
|
@ -2095,11 +2012,6 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
|
|||
int8_t etype;
|
||||
struct udf_inode_info *iinfo;
|
||||
|
||||
if (block < 0) {
|
||||
printk(KERN_ERR "udf: inode_bmap: block < 0\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iinfo = UDF_I(inode);
|
||||
pos->offset = 0;
|
||||
pos->block = iinfo->i_location;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/cdrom.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <linux/udf_fs.h>
|
||||
#include "udf_sb.h"
|
||||
|
||||
unsigned int udf_get_last_session(struct super_block *sb)
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
#include "udf_sb.h"
|
||||
|
@ -136,8 +136,8 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
|
|||
/* 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.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
|
||||
sizeof(tag), crclen));
|
||||
eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
|
||||
iinfo->i_lenEAttr += size;
|
||||
return (struct genericFormat *)&ea[offset];
|
||||
|
@ -204,16 +204,15 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
|
|||
{
|
||||
tag *tag_p;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
|
||||
/* Read the block */
|
||||
if (block == 0xFFFFFFFF)
|
||||
return NULL;
|
||||
|
||||
bh = udf_tread(sb, block + sbi->s_session);
|
||||
bh = udf_tread(sb, block);
|
||||
if (!bh) {
|
||||
udf_debug("block=%d, location=%d: read failed\n",
|
||||
block + sbi->s_session, location);
|
||||
block, location);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -223,8 +222,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
|
|||
|
||||
if (location != le32_to_cpu(tag_p->tagLocation)) {
|
||||
udf_debug("location mismatch block %u, tag %u != %u\n",
|
||||
block + sbi->s_session,
|
||||
le32_to_cpu(tag_p->tagLocation), location);
|
||||
block, le32_to_cpu(tag_p->tagLocation), location);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
@ -244,13 +242,13 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
|
|||
|
||||
/* Verify the descriptor CRC */
|
||||
if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
|
||||
le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
|
||||
le16_to_cpu(tag_p->descCRCLength), 0))
|
||||
le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
|
||||
bh->b_data + sizeof(tag),
|
||||
le16_to_cpu(tag_p->descCRCLength)))
|
||||
return bh;
|
||||
|
||||
udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
|
||||
block + sbi->s_session, le16_to_cpu(tag_p->descCRC),
|
||||
le16_to_cpu(tag_p->descCRCLength));
|
||||
udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
|
||||
le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
|
||||
|
||||
error_out:
|
||||
brelse(bh);
|
||||
|
@ -270,7 +268,7 @@ void udf_update_tag(char *data, int length)
|
|||
length -= sizeof(tag);
|
||||
|
||||
tptr->descCRCLength = cpu_to_le16(length);
|
||||
tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
|
||||
tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length));
|
||||
tptr->tagChecksum = udf_tag_checksum(tptr);
|
||||
}
|
||||
|
||||
|
|
216
fs/udf/namei.c
216
fs/udf/namei.c
|
@ -31,6 +31,7 @@
|
|||
#include <linux/smp_lock.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
|
||||
static inline int udf_match(int len1, const char *name1, int len2,
|
||||
const char *name2)
|
||||
|
@ -97,25 +98,23 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
|
|||
memset(fibh->ebh->b_data, 0x00, padlen + offset);
|
||||
}
|
||||
|
||||
crc = udf_crc((uint8_t *)cfi + sizeof(tag),
|
||||
sizeof(struct fileIdentDesc) - sizeof(tag), 0);
|
||||
crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag),
|
||||
sizeof(struct fileIdentDesc) - sizeof(tag));
|
||||
|
||||
if (fibh->sbh == fibh->ebh) {
|
||||
crc = udf_crc((uint8_t *)sfi->impUse,
|
||||
crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
|
||||
crclen + sizeof(tag) -
|
||||
sizeof(struct fileIdentDesc), crc);
|
||||
sizeof(struct fileIdentDesc));
|
||||
} else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
|
||||
crc = udf_crc(fibh->ebh->b_data +
|
||||
crc = crc_itu_t(crc, fibh->ebh->b_data +
|
||||
sizeof(struct fileIdentDesc) +
|
||||
fibh->soffset,
|
||||
crclen + sizeof(tag) -
|
||||
sizeof(struct fileIdentDesc),
|
||||
crc);
|
||||
sizeof(struct fileIdentDesc));
|
||||
} else {
|
||||
crc = udf_crc((uint8_t *)sfi->impUse,
|
||||
-fibh->soffset - sizeof(struct fileIdentDesc),
|
||||
crc);
|
||||
crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
|
||||
crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
|
||||
-fibh->soffset - sizeof(struct fileIdentDesc));
|
||||
crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
|
||||
}
|
||||
|
||||
cfi->descTag.descCRC = cpu_to_le16(crc);
|
||||
|
@ -149,7 +148,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||
struct fileIdentDesc *fi = NULL;
|
||||
loff_t f_pos;
|
||||
int block, flen;
|
||||
char fname[UDF_NAME_LEN];
|
||||
char *fname = NULL;
|
||||
char *nameptr;
|
||||
uint8_t lfi;
|
||||
uint16_t liu;
|
||||
|
@ -163,12 +162,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||
size = udf_ext0_offset(dir) + dir->i_size;
|
||||
f_pos = udf_ext0_offset(dir);
|
||||
|
||||
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
|
||||
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||
fibh->sbh = fibh->ebh = NULL;
|
||||
else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
|
||||
&epos, &eloc, &elen, &offset) ==
|
||||
(EXT_RECORDED_ALLOCATED >> 30)) {
|
||||
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
|
||||
if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
|
||||
if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
|
||||
&eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
|
||||
goto out_err;
|
||||
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
|
||||
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
|
||||
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
|
||||
|
@ -179,25 +178,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||
offset = 0;
|
||||
|
||||
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
|
||||
if (!fibh->sbh) {
|
||||
brelse(epos.bh);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
brelse(epos.bh);
|
||||
return NULL;
|
||||
if (!fibh->sbh)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
||||
if (!fname)
|
||||
goto out_err;
|
||||
|
||||
while (f_pos < size) {
|
||||
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
|
||||
&elen, &offset);
|
||||
if (!fi) {
|
||||
if (fibh->sbh != fibh->ebh)
|
||||
brelse(fibh->ebh);
|
||||
brelse(fibh->sbh);
|
||||
brelse(epos.bh);
|
||||
return NULL;
|
||||
}
|
||||
if (!fi)
|
||||
goto out_err;
|
||||
|
||||
liu = le16_to_cpu(cfi->lengthOfImpUse);
|
||||
lfi = cfi->lengthFileIdent;
|
||||
|
@ -237,53 +230,22 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||
|
||||
flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
|
||||
if (flen && udf_match(flen, fname, dentry->d_name.len,
|
||||
dentry->d_name.name)) {
|
||||
brelse(epos.bh);
|
||||
return fi;
|
||||
}
|
||||
dentry->d_name.name))
|
||||
goto out_ok;
|
||||
}
|
||||
|
||||
out_err:
|
||||
fi = NULL;
|
||||
if (fibh->sbh != fibh->ebh)
|
||||
brelse(fibh->ebh);
|
||||
brelse(fibh->sbh);
|
||||
out_ok:
|
||||
brelse(epos.bh);
|
||||
kfree(fname);
|
||||
|
||||
return NULL;
|
||||
return fi;
|
||||
}
|
||||
|
||||
/*
|
||||
* udf_lookup
|
||||
*
|
||||
* PURPOSE
|
||||
* Look-up the inode for a given name.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Required - lookup_dentry() will return -ENOTDIR if this routine is not
|
||||
* available for a directory. The filesystem is useless if this routine is
|
||||
* not available for at least the filesystem's root directory.
|
||||
*
|
||||
* This routine is passed an incomplete dentry - it must be completed by
|
||||
* calling d_add(dentry, inode). If the name does not exist, then the
|
||||
* specified inode must be set to null. An error should only be returned
|
||||
* when the lookup fails for a reason other than the name not existing.
|
||||
* Note that the directory inode semaphore is held during the call.
|
||||
*
|
||||
* Refer to lookup_dentry() in fs/namei.c
|
||||
* lookup_dentry() -> lookup() -> real_lookup() -> .
|
||||
*
|
||||
* PRE-CONDITIONS
|
||||
* dir Pointer to inode of parent directory.
|
||||
* dentry Pointer to dentry to complete.
|
||||
* nd Pointer to lookup nameidata
|
||||
*
|
||||
* POST-CONDITIONS
|
||||
* <return> Zero on success.
|
||||
*
|
||||
* HISTORY
|
||||
* July 1, 1997 - Andrew E. Mileski
|
||||
* Written, tested, and released.
|
||||
*/
|
||||
|
||||
static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nd)
|
||||
{
|
||||
|
@ -336,11 +298,9 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct fileIdentDesc *fi = NULL;
|
||||
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
|
||||
char *name = NULL;
|
||||
int namelen;
|
||||
loff_t f_pos;
|
||||
int flen;
|
||||
char *nameptr;
|
||||
loff_t size = udf_ext0_offset(dir) + dir->i_size;
|
||||
int nfidlen;
|
||||
uint8_t lfi;
|
||||
|
@ -352,16 +312,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
struct extent_position epos = {};
|
||||
struct udf_inode_info *dinfo;
|
||||
|
||||
fibh->sbh = fibh->ebh = NULL;
|
||||
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
||||
if (!name) {
|
||||
*err = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (dentry) {
|
||||
if (!dentry->d_name.len) {
|
||||
*err = -EINVAL;
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
namelen = udf_put_filename(sb, dentry->d_name.name, name,
|
||||
dentry->d_name.len);
|
||||
if (!namelen) {
|
||||
*err = -ENAMETOOLONG;
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
} else {
|
||||
namelen = 0;
|
||||
|
@ -373,11 +340,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
|
||||
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
|
||||
dinfo = UDF_I(dir);
|
||||
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||
fibh->sbh = fibh->ebh = NULL;
|
||||
else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
|
||||
&epos, &eloc, &elen, &offset) ==
|
||||
(EXT_RECORDED_ALLOCATED >> 30)) {
|
||||
if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
|
||||
if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
|
||||
&eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
|
||||
block = udf_get_lb_pblock(dir->i_sb,
|
||||
dinfo->i_location, 0);
|
||||
fibh->soffset = fibh->eoffset = sb->s_blocksize;
|
||||
goto add;
|
||||
}
|
||||
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
|
||||
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
|
||||
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
|
||||
|
@ -389,17 +359,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
|
||||
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
|
||||
if (!fibh->sbh) {
|
||||
brelse(epos.bh);
|
||||
*err = -EIO;
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
block = dinfo->i_location.logicalBlockNum;
|
||||
} else {
|
||||
block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
|
||||
fibh->sbh = fibh->ebh = NULL;
|
||||
fibh->soffset = fibh->eoffset = sb->s_blocksize;
|
||||
goto add;
|
||||
}
|
||||
|
||||
while (f_pos < size) {
|
||||
|
@ -407,41 +371,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
&elen, &offset);
|
||||
|
||||
if (!fi) {
|
||||
if (fibh->sbh != fibh->ebh)
|
||||
brelse(fibh->ebh);
|
||||
brelse(fibh->sbh);
|
||||
brelse(epos.bh);
|
||||
*err = -EIO;
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
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 {
|
||||
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 (((sizeof(struct fileIdentDesc) +
|
||||
liu + lfi + 3) & ~3) == nfidlen) {
|
||||
brelse(epos.bh);
|
||||
cfi->descTag.tagSerialNum = cpu_to_le16(1);
|
||||
cfi->fileVersionNum = cpu_to_le16(1);
|
||||
cfi->fileCharacteristics = 0;
|
||||
|
@ -449,27 +388,13 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
cfi->lengthOfImpUse = cpu_to_le16(0);
|
||||
if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
|
||||
name))
|
||||
return fi;
|
||||
goto out_ok;
|
||||
else {
|
||||
*err = -EIO;
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!lfi || !dentry)
|
||||
continue;
|
||||
|
||||
flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
|
||||
if (flen && udf_match(flen, fname, dentry->d_name.len,
|
||||
dentry->d_name.name)) {
|
||||
if (fibh->sbh != fibh->ebh)
|
||||
brelse(fibh->ebh);
|
||||
brelse(fibh->sbh);
|
||||
brelse(epos.bh);
|
||||
*err = -EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
add:
|
||||
|
@ -496,7 +421,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
fibh->sbh = fibh->ebh =
|
||||
udf_expand_dir_adinicb(dir, &block, err);
|
||||
if (!fibh->sbh)
|
||||
return NULL;
|
||||
goto out_err;
|
||||
epos.block = dinfo->i_location;
|
||||
epos.offset = udf_file_entry_alloc_offset(dir);
|
||||
/* Load extent udf_expand_dir_adinicb() has created */
|
||||
|
@ -537,11 +462,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
dir->i_sb->s_blocksize_bits);
|
||||
fibh->ebh = udf_bread(dir,
|
||||
f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
|
||||
if (!fibh->ebh) {
|
||||
brelse(epos.bh);
|
||||
brelse(fibh->sbh);
|
||||
return NULL;
|
||||
}
|
||||
if (!fibh->ebh)
|
||||
goto out_err;
|
||||
|
||||
if (!fibh->soffset) {
|
||||
if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
|
||||
|
@ -572,20 +494,25 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
|||
cfi->lengthFileIdent = namelen;
|
||||
cfi->lengthOfImpUse = cpu_to_le16(0);
|
||||
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
|
||||
brelse(epos.bh);
|
||||
dir->i_size += nfidlen;
|
||||
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||
dinfo->i_lenAlloc += nfidlen;
|
||||
mark_inode_dirty(dir);
|
||||
return fi;
|
||||
goto out_ok;
|
||||
} else {
|
||||
brelse(epos.bh);
|
||||
*err = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
out_err:
|
||||
fi = NULL;
|
||||
if (fibh->sbh != fibh->ebh)
|
||||
brelse(fibh->ebh);
|
||||
brelse(fibh->sbh);
|
||||
*err = -EIO;
|
||||
return NULL;
|
||||
}
|
||||
out_ok:
|
||||
brelse(epos.bh);
|
||||
kfree(name);
|
||||
return fi;
|
||||
}
|
||||
|
||||
static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
|
||||
|
@ -940,7 +867,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||
char *ea;
|
||||
int err;
|
||||
int block;
|
||||
char name[UDF_NAME_LEN];
|
||||
char *name = NULL;
|
||||
int namelen;
|
||||
struct buffer_head *bh;
|
||||
struct udf_inode_info *iinfo;
|
||||
|
@ -950,6 +877,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||
if (!inode)
|
||||
goto out;
|
||||
|
||||
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
||||
if (!name) {
|
||||
err = -ENOMEM;
|
||||
goto out_no_entry;
|
||||
}
|
||||
|
||||
iinfo = UDF_I(inode);
|
||||
inode->i_mode = S_IFLNK | S_IRWXUGO;
|
||||
inode->i_data.a_ops = &udf_symlink_aops;
|
||||
|
@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||
err = 0;
|
||||
|
||||
out:
|
||||
kfree(name);
|
||||
unlock_kernel();
|
||||
return err;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
|
@ -55,11 +54,10 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
|
|||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
struct udf_part_map *map;
|
||||
struct udf_virtual_data *vdata;
|
||||
struct udf_inode_info *iinfo;
|
||||
struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode);
|
||||
|
||||
map = &sbi->s_partmaps[partition];
|
||||
vdata = &map->s_type_specific.s_virtual;
|
||||
index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
|
||||
|
||||
if (block > vdata->s_num_entries) {
|
||||
udf_debug("Trying to access block beyond end of VAT "
|
||||
|
@ -67,6 +65,12 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
|
|||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||
loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data +
|
||||
vdata->s_start_offset))[block]);
|
||||
goto translate;
|
||||
}
|
||||
index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
|
||||
if (block >= index) {
|
||||
block -= index;
|
||||
newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
|
||||
|
@ -89,7 +93,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
|
|||
|
||||
brelse(bh);
|
||||
|
||||
iinfo = UDF_I(sbi->s_vat_inode);
|
||||
translate:
|
||||
if (iinfo->i_location.partitionReferenceNum == partition) {
|
||||
udf_debug("recursive call to udf_get_pblock!\n");
|
||||
return 0xFFFFFFFF;
|
||||
|
@ -263,3 +267,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
|
||||
uint16_t partition, uint32_t offset)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct udf_part_map *map;
|
||||
kernel_lb_addr eloc;
|
||||
uint32_t elen;
|
||||
sector_t ext_offset;
|
||||
struct extent_position epos = {};
|
||||
uint32_t phyblock;
|
||||
|
||||
if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
|
||||
(EXT_RECORDED_ALLOCATED >> 30))
|
||||
phyblock = 0xFFFFFFFF;
|
||||
else {
|
||||
map = &UDF_SB(sb)->s_partmaps[partition];
|
||||
/* map to sparable/physical partition desc */
|
||||
phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
|
||||
map->s_partition_num, ext_offset + offset);
|
||||
}
|
||||
|
||||
brelse(epos.bh);
|
||||
return phyblock;
|
||||
}
|
||||
|
||||
uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
|
||||
uint16_t partition, uint32_t offset)
|
||||
{
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
struct udf_part_map *map;
|
||||
struct udf_meta_data *mdata;
|
||||
uint32_t retblk;
|
||||
struct inode *inode;
|
||||
|
||||
udf_debug("READING from METADATA\n");
|
||||
|
||||
map = &sbi->s_partmaps[partition];
|
||||
mdata = &map->s_type_specific.s_metadata;
|
||||
inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
|
||||
|
||||
/* We shouldn't mount such media... */
|
||||
BUG_ON(!inode);
|
||||
retblk = udf_try_read_meta(inode, block, partition, offset);
|
||||
if (retblk == 0xFFFFFFFF) {
|
||||
udf_warning(sb, __func__, "error reading from METADATA, "
|
||||
"trying to read from MIRROR");
|
||||
inode = mdata->s_mirror_fe;
|
||||
if (!inode)
|
||||
return 0xFFFFFFFF;
|
||||
retblk = udf_try_read_meta(inode, block, partition, offset);
|
||||
}
|
||||
|
||||
return retblk;
|
||||
}
|
||||
|
|
1124
fs/udf/super.c
1124
fs/udf/super.c
File diff suppressed because it is too large
Load diff
|
@ -23,7 +23,6 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/stat.h>
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "udfdecl.h"
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
|
@ -180,6 +179,24 @@ void udf_discard_prealloc(struct inode *inode)
|
|||
brelse(epos.bh);
|
||||
}
|
||||
|
||||
static void udf_update_alloc_ext_desc(struct inode *inode,
|
||||
struct extent_position *epos,
|
||||
u32 lenalloc)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
|
||||
struct allocExtDesc *aed = (struct allocExtDesc *) (epos->bh->b_data);
|
||||
int len = sizeof(struct allocExtDesc);
|
||||
|
||||
aed->lengthAllocDescs = cpu_to_le32(lenalloc);
|
||||
if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || sbi->s_udfrev >= 0x0201)
|
||||
len += lenalloc;
|
||||
|
||||
udf_update_tag(epos->bh->b_data, len);
|
||||
mark_buffer_dirty_inode(epos->bh, inode);
|
||||
}
|
||||
|
||||
void udf_truncate_extents(struct inode *inode)
|
||||
{
|
||||
struct extent_position epos;
|
||||
|
@ -187,7 +204,6 @@ void udf_truncate_extents(struct inode *inode)
|
|||
uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
|
||||
int8_t etype;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset;
|
||||
loff_t byte_offset;
|
||||
int adsize;
|
||||
|
@ -224,35 +240,15 @@ void udf_truncate_extents(struct inode *inode)
|
|||
if (indirect_ext_len) {
|
||||
/* We managed to free all extents in the
|
||||
* indirect extent - free it too */
|
||||
if (!epos.bh)
|
||||
BUG();
|
||||
BUG_ON(!epos.bh);
|
||||
udf_free_blocks(sb, inode, epos.block,
|
||||
0, indirect_ext_len);
|
||||
} else {
|
||||
if (!epos.bh) {
|
||||
iinfo->i_lenAlloc =
|
||||
lenalloc;
|
||||
} else if (!epos.bh) {
|
||||
iinfo->i_lenAlloc = lenalloc;
|
||||
mark_inode_dirty(inode);
|
||||
} else {
|
||||
struct allocExtDesc *aed =
|
||||
(struct allocExtDesc *)
|
||||
(epos.bh->b_data);
|
||||
int len =
|
||||
sizeof(struct allocExtDesc);
|
||||
|
||||
aed->lengthAllocDescs =
|
||||
cpu_to_le32(lenalloc);
|
||||
if (!UDF_QUERY_FLAG(sb,
|
||||
UDF_FLAG_STRICT) ||
|
||||
sbi->s_udfrev >= 0x0201)
|
||||
len += lenalloc;
|
||||
|
||||
udf_update_tag(epos.bh->b_data,
|
||||
len);
|
||||
mark_buffer_dirty_inode(
|
||||
epos.bh, inode);
|
||||
}
|
||||
}
|
||||
} else
|
||||
udf_update_alloc_ext_desc(inode,
|
||||
&epos, lenalloc);
|
||||
brelse(epos.bh);
|
||||
epos.offset = sizeof(struct allocExtDesc);
|
||||
epos.block = eloc;
|
||||
|
@ -272,29 +268,14 @@ void udf_truncate_extents(struct inode *inode)
|
|||
}
|
||||
|
||||
if (indirect_ext_len) {
|
||||
if (!epos.bh)
|
||||
BUG();
|
||||
BUG_ON(!epos.bh);
|
||||
udf_free_blocks(sb, inode, epos.block, 0,
|
||||
indirect_ext_len);
|
||||
} else {
|
||||
if (!epos.bh) {
|
||||
} else if (!epos.bh) {
|
||||
iinfo->i_lenAlloc = lenalloc;
|
||||
mark_inode_dirty(inode);
|
||||
} else {
|
||||
struct allocExtDesc *aed =
|
||||
(struct allocExtDesc *)(epos.bh->b_data);
|
||||
aed->lengthAllocDescs = cpu_to_le32(lenalloc);
|
||||
if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) ||
|
||||
sbi->s_udfrev >= 0x0201)
|
||||
udf_update_tag(epos.bh->b_data,
|
||||
lenalloc +
|
||||
sizeof(struct allocExtDesc));
|
||||
else
|
||||
udf_update_tag(epos.bh->b_data,
|
||||
sizeof(struct allocExtDesc));
|
||||
mark_buffer_dirty_inode(epos.bh, inode);
|
||||
}
|
||||
}
|
||||
} else
|
||||
udf_update_alloc_ext_desc(inode, &epos, lenalloc);
|
||||
} else if (inode->i_size) {
|
||||
if (byte_offset) {
|
||||
kernel_long_ad extent;
|
||||
|
|
|
@ -1,10 +1,32 @@
|
|||
#ifndef __LINUX_UDF_I_H
|
||||
#define __LINUX_UDF_I_H
|
||||
#ifndef _UDF_I_H
|
||||
#define _UDF_I_H
|
||||
|
||||
struct udf_inode_info {
|
||||
struct timespec i_crtime;
|
||||
/* Physical address of inode */
|
||||
kernel_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; /* extendedFileEntry */
|
||||
unsigned i_use : 1; /* unallocSpaceEntry */
|
||||
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;
|
||||
};
|
||||
|
||||
#include <linux/udf_fs_i.h>
|
||||
static inline struct udf_inode_info *UDF_I(struct inode *inode)
|
||||
{
|
||||
return list_entry(inode, struct udf_inode_info, vfs_inode);
|
||||
}
|
||||
|
||||
#endif /* !defined(_LINUX_UDF_I_H) */
|
||||
#endif /* _UDF_I_H) */
|
||||
|
|
109
fs/udf/udf_sb.h
109
fs/udf/udf_sb.h
|
@ -1,10 +1,12 @@
|
|||
#ifndef __LINUX_UDF_SB_H
|
||||
#define __LINUX_UDF_SB_H
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/* Since UDF 2.01 is ISO 13346 based... */
|
||||
#define UDF_SUPER_MAGIC 0x15013346
|
||||
|
||||
#define UDF_MAX_READ_VERSION 0x0201
|
||||
#define UDF_MAX_READ_VERSION 0x0250
|
||||
#define UDF_MAX_WRITE_VERSION 0x0201
|
||||
|
||||
#define UDF_FLAG_USE_EXTENDED_FE 0
|
||||
|
@ -38,6 +40,111 @@
|
|||
#define UDF_PART_FLAG_REWRITABLE 0x0040
|
||||
#define UDF_PART_FLAG_OVERWRITABLE 0x0080
|
||||
|
||||
#define UDF_MAX_BLOCK_LOADED 8
|
||||
|
||||
#define UDF_TYPE1_MAP15 0x1511U
|
||||
#define UDF_VIRTUAL_MAP15 0x1512U
|
||||
#define UDF_VIRTUAL_MAP20 0x2012U
|
||||
#define UDF_SPARABLE_MAP15 0x1522U
|
||||
#define UDF_METADATA_MAP25 0x2511U
|
||||
|
||||
#pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */
|
||||
|
||||
struct udf_meta_data {
|
||||
__u32 s_meta_file_loc;
|
||||
__u32 s_mirror_file_loc;
|
||||
__u32 s_bitmap_file_loc;
|
||||
__u32 s_alloc_unit_size;
|
||||
__u16 s_align_unit_size;
|
||||
__u8 s_dup_md_flag;
|
||||
struct inode *s_metadata_fe;
|
||||
struct inode *s_mirror_fe;
|
||||
struct inode *s_bitmap_fe;
|
||||
};
|
||||
|
||||
struct udf_sparing_data {
|
||||
__u16 s_packet_len;
|
||||
struct buffer_head *s_spar_map[4];
|
||||
};
|
||||
|
||||
struct udf_virtual_data {
|
||||
__u32 s_num_entries;
|
||||
__u16 s_start_offset;
|
||||
};
|
||||
|
||||
struct udf_bitmap {
|
||||
__u32 s_extLength;
|
||||
__u32 s_extPosition;
|
||||
__u16 s_nr_groups;
|
||||
struct buffer_head **s_block_bitmap;
|
||||
};
|
||||
|
||||
struct udf_part_map {
|
||||
union {
|
||||
struct udf_bitmap *s_bitmap;
|
||||
struct inode *s_table;
|
||||
} s_uspace;
|
||||
union {
|
||||
struct udf_bitmap *s_bitmap;
|
||||
struct inode *s_table;
|
||||
} s_fspace;
|
||||
__u32 s_partition_root;
|
||||
__u32 s_partition_len;
|
||||
__u16 s_partition_type;
|
||||
__u16 s_partition_num;
|
||||
union {
|
||||
struct udf_sparing_data s_sparing;
|
||||
struct udf_virtual_data s_virtual;
|
||||
struct udf_meta_data s_metadata;
|
||||
} s_type_specific;
|
||||
__u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
|
||||
__u16 s_volumeseqnum;
|
||||
__u16 s_partition_flags;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
struct udf_sb_info {
|
||||
struct udf_part_map *s_partmaps;
|
||||
__u8 s_volume_ident[32];
|
||||
|
||||
/* Overall info */
|
||||
__u16 s_partitions;
|
||||
__u16 s_partition;
|
||||
|
||||
/* Sector headers */
|
||||
__s32 s_session;
|
||||
__u32 s_anchor[3];
|
||||
__u32 s_last_block;
|
||||
|
||||
struct buffer_head *s_lvid_bh;
|
||||
|
||||
/* Default permissions */
|
||||
mode_t s_umask;
|
||||
gid_t s_gid;
|
||||
uid_t s_uid;
|
||||
|
||||
/* Root Info */
|
||||
struct timespec s_record_time;
|
||||
|
||||
/* Fileset Info */
|
||||
__u16 s_serial_number;
|
||||
|
||||
/* highest UDF revision we have recorded to this media */
|
||||
__u16 s_udfrev;
|
||||
|
||||
/* Miscellaneous flags */
|
||||
__u32 s_flags;
|
||||
|
||||
/* Encoding info */
|
||||
struct nls_table *s_nls_map;
|
||||
|
||||
/* VAT inode */
|
||||
struct inode *s_vat_inode;
|
||||
|
||||
struct mutex s_alloc_mutex;
|
||||
};
|
||||
|
||||
static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
|
||||
{
|
||||
return sb->s_fs_info;
|
||||
|
|
|
@ -1,17 +1,37 @@
|
|||
#ifndef __UDF_DECL_H
|
||||
#define __UDF_DECL_H
|
||||
|
||||
#include <linux/udf_fs.h>
|
||||
#include "ecma_167.h"
|
||||
#include "osta_udf.h"
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/udf_fs_i.h>
|
||||
#include <linux/udf_fs_sb.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/udf_fs_i.h>
|
||||
|
||||
#include "udf_sb.h"
|
||||
#include "udfend.h"
|
||||
#include "udf_i.h"
|
||||
|
||||
#define UDF_PREALLOCATE
|
||||
#define UDF_DEFAULT_PREALLOC_BLOCKS 8
|
||||
|
||||
#define UDFFS_DEBUG
|
||||
|
||||
#ifdef UDFFS_DEBUG
|
||||
#define udf_debug(f, a...) \
|
||||
do { \
|
||||
printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
|
||||
__FILE__, __LINE__, __func__); \
|
||||
printk(f, ##a); \
|
||||
} while (0)
|
||||
#else
|
||||
#define udf_debug(f, a...) /**/
|
||||
#endif
|
||||
|
||||
#define udf_info(f, a...) \
|
||||
printk(KERN_INFO "UDF-fs INFO " f, ##a);
|
||||
|
||||
|
||||
#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
|
||||
#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
|
||||
|
@ -23,16 +43,24 @@
|
|||
#define UDF_NAME_LEN 256
|
||||
#define UDF_PATH_LEN 1023
|
||||
|
||||
#define udf_file_entry_alloc_offset(inode)\
|
||||
(UDF_I(inode)->i_use ?\
|
||||
sizeof(struct unallocSpaceEntry) :\
|
||||
((UDF_I(inode)->i_efe ?\
|
||||
sizeof(struct extendedFileEntry) :\
|
||||
sizeof(struct fileEntry)) + UDF_I(inode)->i_lenEAttr))
|
||||
static inline size_t udf_file_entry_alloc_offset(struct inode *inode)
|
||||
{
|
||||
struct udf_inode_info *iinfo = UDF_I(inode);
|
||||
if (iinfo->i_use)
|
||||
return sizeof(struct unallocSpaceEntry);
|
||||
else if (iinfo->i_efe)
|
||||
return sizeof(struct extendedFileEntry) + iinfo->i_lenEAttr;
|
||||
else
|
||||
return sizeof(struct fileEntry) + iinfo->i_lenEAttr;
|
||||
}
|
||||
|
||||
#define udf_ext0_offset(inode)\
|
||||
(UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ?\
|
||||
udf_file_entry_alloc_offset(inode) : 0)
|
||||
static inline size_t udf_ext0_offset(struct inode *inode)
|
||||
{
|
||||
if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||
return udf_file_entry_alloc_offset(inode);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset))
|
||||
|
||||
|
@ -83,7 +111,6 @@ struct extent_position {
|
|||
};
|
||||
|
||||
/* super.c */
|
||||
extern void udf_error(struct super_block *, const char *, const char *, ...);
|
||||
extern void udf_warning(struct super_block *, const char *, const char *, ...);
|
||||
|
||||
/* namei.c */
|
||||
|
@ -150,6 +177,8 @@ extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t,
|
|||
uint32_t);
|
||||
extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t,
|
||||
uint32_t);
|
||||
extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t,
|
||||
uint32_t);
|
||||
extern int udf_relocate_blocks(struct super_block *, long, long *);
|
||||
|
||||
/* unicode.c */
|
||||
|
@ -157,7 +186,7 @@ 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 *);
|
||||
extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);
|
||||
|
||||
/* ialloc.c */
|
||||
extern void udf_free_inode(struct inode *);
|
||||
|
@ -191,11 +220,9 @@ extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize,
|
|||
extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int);
|
||||
extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int);
|
||||
|
||||
/* crc.c */
|
||||
extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
|
||||
|
||||
/* udftime.c */
|
||||
extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
|
||||
extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
|
||||
extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest,
|
||||
timestamp src);
|
||||
extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src);
|
||||
|
||||
#endif /* __UDF_DECL_H */
|
||||
|
|
|
@ -24,17 +24,6 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
|
|||
return out;
|
||||
}
|
||||
|
||||
static inline kernel_timestamp lets_to_cpu(timestamp in)
|
||||
{
|
||||
kernel_timestamp out;
|
||||
|
||||
memcpy(&out, &in, sizeof(timestamp));
|
||||
out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
|
||||
out.year = le16_to_cpu(in.year);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline short_ad lesa_to_cpu(short_ad in)
|
||||
{
|
||||
short_ad out;
|
||||
|
@ -85,15 +74,4 @@ static inline kernel_extent_ad leea_to_cpu(extent_ad in)
|
|||
return out;
|
||||
}
|
||||
|
||||
static inline timestamp cpu_to_lets(kernel_timestamp in)
|
||||
{
|
||||
timestamp out;
|
||||
|
||||
memcpy(&out, &in, sizeof(timestamp));
|
||||
out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone);
|
||||
out.year = cpu_to_le16(in.year);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif /* __UDF_ENDIAN_H */
|
||||
|
|
|
@ -85,39 +85,38 @@ extern struct timezone sys_tz;
|
|||
#define SECS_PER_HOUR (60 * 60)
|
||||
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
|
||||
|
||||
time_t *udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
|
||||
struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src)
|
||||
{
|
||||
int yday;
|
||||
uint8_t type = src.typeAndTimezone >> 12;
|
||||
u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
|
||||
u16 year = le16_to_cpu(src.year);
|
||||
uint8_t type = typeAndTimezone >> 12;
|
||||
int16_t offset;
|
||||
|
||||
if (type == 1) {
|
||||
offset = src.typeAndTimezone << 4;
|
||||
offset = typeAndTimezone << 4;
|
||||
/* sign extent offset */
|
||||
offset = (offset >> 4);
|
||||
if (offset == -2047) /* unspecified offset */
|
||||
offset = 0;
|
||||
} else {
|
||||
} else
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if ((src.year < EPOCH_YEAR) ||
|
||||
(src.year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
|
||||
*dest = -1;
|
||||
*dest_usec = -1;
|
||||
if ((year < EPOCH_YEAR) ||
|
||||
(year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
|
||||
return NULL;
|
||||
}
|
||||
*dest = year_seconds[src.year - EPOCH_YEAR];
|
||||
*dest -= offset * 60;
|
||||
dest->tv_sec = year_seconds[year - EPOCH_YEAR];
|
||||
dest->tv_sec -= offset * 60;
|
||||
|
||||
yday = ((__mon_yday[__isleap(src.year)][src.month - 1]) + src.day - 1);
|
||||
*dest += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
|
||||
*dest_usec = src.centiseconds * 10000 +
|
||||
src.hundredsOfMicroseconds * 100 + src.microseconds;
|
||||
yday = ((__mon_yday[__isleap(year)][src.month - 1]) + src.day - 1);
|
||||
dest->tv_sec += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
|
||||
dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
|
||||
src.hundredsOfMicroseconds * 100 + src.microseconds);
|
||||
return dest;
|
||||
}
|
||||
|
||||
kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
|
||||
timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts)
|
||||
{
|
||||
long int days, rem, y;
|
||||
const unsigned short int *ip;
|
||||
|
@ -128,7 +127,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
|
|||
if (!dest)
|
||||
return NULL;
|
||||
|
||||
dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
|
||||
dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
|
||||
|
||||
ts.tv_sec += offset * 60;
|
||||
days = ts.tv_sec / SECS_PER_DAY;
|
||||
|
@ -151,7 +150,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
|
|||
- LEAPS_THRU_END_OF(y - 1));
|
||||
y = yg;
|
||||
}
|
||||
dest->year = y;
|
||||
dest->year = cpu_to_le16(y);
|
||||
ip = __mon_yday[__isleap(y)];
|
||||
for (y = 11; days < (long int)ip[y]; --y)
|
||||
continue;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/string.h> /* for memset */
|
||||
#include <linux/nls.h>
|
||||
#include <linux/udf_fs.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
|
||||
#include "udf_sb.h"
|
||||
|
||||
|
@ -49,14 +49,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
|
|||
{
|
||||
int usesize;
|
||||
|
||||
if ((!dest) || (!ptr) || (!size))
|
||||
if (!dest || !ptr || !size)
|
||||
return -1;
|
||||
BUG_ON(size < 2);
|
||||
|
||||
memset(dest, 0, sizeof(struct ustr));
|
||||
usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
|
||||
usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name));
|
||||
usesize = min(usesize, size - 2);
|
||||
dest->u_cmpID = ptr[0];
|
||||
dest->u_len = ptr[size - 1];
|
||||
memcpy(dest->u_name, ptr + 1, usesize - 1);
|
||||
dest->u_len = usesize;
|
||||
memcpy(dest->u_name, ptr + 1, usesize);
|
||||
memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -83,9 +85,6 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
|
|||
* PURPOSE
|
||||
* Convert OSTA Compressed Unicode to the UTF-8 equivalent.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This routine is only called by udf_filldir().
|
||||
*
|
||||
* PRE-CONDITIONS
|
||||
* utf Pointer to UTF-8 output buffer.
|
||||
* ocu Pointer to OSTA Compressed Unicode input buffer
|
||||
|
@ -99,43 +98,39 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
|
|||
* November 12, 1997 - Andrew E. Mileski
|
||||
* Written, tested, and released.
|
||||
*/
|
||||
int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
|
||||
int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
|
||||
{
|
||||
uint8_t *ocu;
|
||||
uint32_t c;
|
||||
const uint8_t *ocu;
|
||||
uint8_t cmp_id, ocu_len;
|
||||
int i;
|
||||
|
||||
ocu = ocu_i->u_name;
|
||||
|
||||
ocu_len = ocu_i->u_len;
|
||||
cmp_id = ocu_i->u_cmpID;
|
||||
utf_o->u_len = 0;
|
||||
|
||||
if (ocu_len == 0) {
|
||||
memset(utf_o, 0, sizeof(struct ustr));
|
||||
utf_o->u_cmpID = 0;
|
||||
utf_o->u_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((cmp_id != 8) && (cmp_id != 16)) {
|
||||
cmp_id = ocu_i->u_cmpID;
|
||||
if (cmp_id != 8 && cmp_id != 16) {
|
||||
memset(utf_o, 0, sizeof(struct ustr));
|
||||
printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
|
||||
cmp_id, ocu_i->u_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ocu = ocu_i->u_name;
|
||||
utf_o->u_len = 0;
|
||||
for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
|
||||
|
||||
/* Expand OSTA compressed Unicode to Unicode */
|
||||
c = ocu[i++];
|
||||
uint32_t c = ocu[i++];
|
||||
if (cmp_id == 16)
|
||||
c = (c << 8) | ocu[i++];
|
||||
|
||||
/* Compress Unicode to UTF-8 */
|
||||
if (c < 0x80U) {
|
||||
if (c < 0x80U)
|
||||
utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
|
||||
} else if (c < 0x800U) {
|
||||
else if (c < 0x800U) {
|
||||
utf_o->u_name[utf_o->u_len++] =
|
||||
(uint8_t)(0xc0 | (c >> 6));
|
||||
utf_o->u_name[utf_o->u_len++] =
|
||||
|
@ -255,35 +250,32 @@ static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
|
|||
}
|
||||
|
||||
static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
|
||||
struct ustr *ocu_i)
|
||||
const struct ustr *ocu_i)
|
||||
{
|
||||
uint8_t *ocu;
|
||||
uint32_t c;
|
||||
const uint8_t *ocu;
|
||||
uint8_t cmp_id, ocu_len;
|
||||
int i;
|
||||
|
||||
ocu = ocu_i->u_name;
|
||||
|
||||
ocu_len = ocu_i->u_len;
|
||||
cmp_id = ocu_i->u_cmpID;
|
||||
utf_o->u_len = 0;
|
||||
|
||||
if (ocu_len == 0) {
|
||||
memset(utf_o, 0, sizeof(struct ustr));
|
||||
utf_o->u_cmpID = 0;
|
||||
utf_o->u_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((cmp_id != 8) && (cmp_id != 16)) {
|
||||
cmp_id = ocu_i->u_cmpID;
|
||||
if (cmp_id != 8 && cmp_id != 16) {
|
||||
memset(utf_o, 0, sizeof(struct ustr));
|
||||
printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
|
||||
cmp_id, ocu_i->u_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ocu = ocu_i->u_name;
|
||||
utf_o->u_len = 0;
|
||||
for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
|
||||
/* Expand OSTA compressed Unicode to Unicode */
|
||||
c = ocu[i++];
|
||||
uint32_t c = ocu[i++];
|
||||
if (cmp_id == 16)
|
||||
c = (c << 8) | ocu[i++];
|
||||
|
||||
|
@ -463,7 +455,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
|
|||
} else if (newIndex > 250)
|
||||
newIndex = 250;
|
||||
newName[newIndex++] = CRC_MARK;
|
||||
valueCRC = udf_crc(fidName, fidNameLen, 0);
|
||||
valueCRC = crc_itu_t(0, fidName, fidNameLen);
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
|
||||
newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
|
||||
|
|
|
@ -150,6 +150,7 @@ header-y += tiocl.h
|
|||
header-y += tipc.h
|
||||
header-y += tipc_config.h
|
||||
header-y += toshiba.h
|
||||
header-y += udf_fs_i.h
|
||||
header-y += ultrasound.h
|
||||
header-y += un.h
|
||||
header-y += utime.h
|
||||
|
@ -334,7 +335,6 @@ unifdef-y += time.h
|
|||
unifdef-y += timex.h
|
||||
unifdef-y += tty.h
|
||||
unifdef-y += types.h
|
||||
unifdef-y += udf_fs_i.h
|
||||
unifdef-y += udp.h
|
||||
unifdef-y += uinput.h
|
||||
unifdef-y += uio.h
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* udf_fs.h
|
||||
*
|
||||
* PURPOSE
|
||||
* Included by fs/filesystems.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* OSTA-UDF(tm) = Optical Storage Technology Association
|
||||
* Universal Disk Format.
|
||||
*
|
||||
* 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/
|
||||
*
|
||||
* COPYRIGHT
|
||||
* This file is distributed under the terms of the GNU General Public
|
||||
* License (GPL). Copies of the GPL can be obtained from:
|
||||
* ftp://prep.ai.mit.edu/pub/gnu/GPL
|
||||
* Each contributing author retains all rights to their own work.
|
||||
*
|
||||
* (C) 1999-2004 Ben Fennema
|
||||
* (C) 1999-2000 Stelias Computing Inc
|
||||
*
|
||||
* HISTORY
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _UDF_FS_H
|
||||
#define _UDF_FS_H 1
|
||||
|
||||
#define UDF_PREALLOCATE
|
||||
#define UDF_DEFAULT_PREALLOC_BLOCKS 8
|
||||
|
||||
#undef UDFFS_DEBUG
|
||||
|
||||
#ifdef UDFFS_DEBUG
|
||||
#define udf_debug(f, a...) \
|
||||
do { \
|
||||
printk (KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
printk (f, ##a); \
|
||||
} while (0)
|
||||
#else
|
||||
#define udf_debug(f, a...) /**/
|
||||
#endif
|
||||
|
||||
#define udf_info(f, a...) \
|
||||
printk (KERN_INFO "UDF-fs INFO " f, ##a);
|
||||
|
||||
#endif /* _UDF_FS_H */
|
|
@ -9,41 +9,10 @@
|
|||
* ftp://prep.ai.mit.edu/pub/gnu/GPL
|
||||
* Each contributing author retains all rights to their own work.
|
||||
*/
|
||||
|
||||
#ifndef _UDF_FS_I_H
|
||||
#define _UDF_FS_I_H 1
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct udf_inode_info
|
||||
{
|
||||
struct timespec i_crtime;
|
||||
/* Physical address of inode */
|
||||
kernel_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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* exported IOCTLs, we have 'l', 0x40-0x7f */
|
||||
|
||||
#define UDF_GETEASIZE _IOR('l', 0x40, int)
|
||||
#define UDF_GETEABLOCK _IOR('l', 0x41, void *)
|
||||
#define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* udf_fs_sb.h
|
||||
*
|
||||
* This include file is for the Linux kernel/module.
|
||||
*
|
||||
* COPYRIGHT
|
||||
* This file is distributed under the terms of the GNU General Public
|
||||
* License (GPL). Copies of the GPL can be obtained from:
|
||||
* ftp://prep.ai.mit.edu/pub/gnu/GPL
|
||||
* Each contributing author retains all rights to their own work.
|
||||
*/
|
||||
|
||||
#ifndef _UDF_FS_SB_H
|
||||
#define _UDF_FS_SB_H 1
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define UDF_MAX_BLOCK_LOADED 8
|
||||
|
||||
#define UDF_TYPE1_MAP15 0x1511U
|
||||
#define UDF_VIRTUAL_MAP15 0x1512U
|
||||
#define UDF_VIRTUAL_MAP20 0x2012U
|
||||
#define UDF_SPARABLE_MAP15 0x1522U
|
||||
|
||||
struct udf_sparing_data
|
||||
{
|
||||
__u16 s_packet_len;
|
||||
struct buffer_head *s_spar_map[4];
|
||||
};
|
||||
|
||||
struct udf_virtual_data
|
||||
{
|
||||
__u32 s_num_entries;
|
||||
__u16 s_start_offset;
|
||||
};
|
||||
|
||||
struct udf_bitmap
|
||||
{
|
||||
__u32 s_extLength;
|
||||
__u32 s_extPosition;
|
||||
__u16 s_nr_groups;
|
||||
struct buffer_head **s_block_bitmap;
|
||||
};
|
||||
|
||||
struct udf_part_map
|
||||
{
|
||||
union
|
||||
{
|
||||
struct udf_bitmap *s_bitmap;
|
||||
struct inode *s_table;
|
||||
} s_uspace;
|
||||
union
|
||||
{
|
||||
struct udf_bitmap *s_bitmap;
|
||||
struct inode *s_table;
|
||||
} s_fspace;
|
||||
__u32 s_partition_root;
|
||||
__u32 s_partition_len;
|
||||
__u16 s_partition_type;
|
||||
__u16 s_partition_num;
|
||||
union
|
||||
{
|
||||
struct udf_sparing_data s_sparing;
|
||||
struct udf_virtual_data s_virtual;
|
||||
} s_type_specific;
|
||||
__u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
|
||||
__u16 s_volumeseqnum;
|
||||
__u16 s_partition_flags;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
struct udf_sb_info
|
||||
{
|
||||
struct udf_part_map *s_partmaps;
|
||||
__u8 s_volume_ident[32];
|
||||
|
||||
/* Overall info */
|
||||
__u16 s_partitions;
|
||||
__u16 s_partition;
|
||||
|
||||
/* Sector headers */
|
||||
__s32 s_session;
|
||||
__u32 s_anchor[4];
|
||||
__u32 s_last_block;
|
||||
|
||||
struct buffer_head *s_lvid_bh;
|
||||
|
||||
/* Default permissions */
|
||||
mode_t s_umask;
|
||||
gid_t s_gid;
|
||||
uid_t s_uid;
|
||||
|
||||
/* Root Info */
|
||||
struct timespec s_record_time;
|
||||
|
||||
/* Fileset Info */
|
||||
__u16 s_serial_number;
|
||||
|
||||
/* highest UDF revision we have recorded to this media */
|
||||
__u16 s_udfrev;
|
||||
|
||||
/* Miscellaneous flags */
|
||||
__u32 s_flags;
|
||||
|
||||
/* Encoding info */
|
||||
struct nls_table *s_nls_map;
|
||||
|
||||
/* VAT inode */
|
||||
struct inode *s_vat_inode;
|
||||
|
||||
struct mutex s_alloc_mutex;
|
||||
};
|
||||
|
||||
#endif /* _UDF_FS_SB_H */
|
Loading…
Reference in a new issue