diff options
Diffstat (limited to 'ANDROID_3.4.5/fs/udf')
-rw-r--r-- | ANDROID_3.4.5/fs/udf/Kconfig | 18 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/Makefile | 9 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/balloc.c | 825 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/dir.c | 210 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/directory.c | 241 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/ecma_167.h | 796 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/file.c | 249 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/ialloc.c | 133 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/inode.c | 2172 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/lowlevel.c | 67 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/misc.c | 299 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/namei.c | 1322 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/osta_udf.h | 279 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/partition.c | 339 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/super.c | 2320 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/symlink.c | 125 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/truncate.c | 287 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/udf_i.h | 46 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/udf_sb.h | 185 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/udfdecl.h | 250 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/udfend.h | 77 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/udftime.c | 172 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/udf/unicode.c | 493 |
23 files changed, 0 insertions, 10914 deletions
diff --git a/ANDROID_3.4.5/fs/udf/Kconfig b/ANDROID_3.4.5/fs/udf/Kconfig deleted file mode 100644 index 0e0e99bd..00000000 --- a/ANDROID_3.4.5/fs/udf/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -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 - if written to by other UDF utilities, such as DirectCD. - Please read <file:Documentation/filesystems/udf.txt>. - - To compile this file system support as a module, choose M here: the - module will be called udf. - - If unsure, say N. - -config UDF_NLS - bool - default y - depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y) diff --git a/ANDROID_3.4.5/fs/udf/Makefile b/ANDROID_3.4.5/fs/udf/Makefile deleted file mode 100644 index eb880f66..00000000 --- a/ANDROID_3.4.5/fs/udf/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the linux udf-filesystem routines. -# - -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 \ - directory.o misc.o udftime.o unicode.o diff --git a/ANDROID_3.4.5/fs/udf/balloc.c b/ANDROID_3.4.5/fs/udf/balloc.c deleted file mode 100644 index 1ba2baaf..00000000 --- a/ANDROID_3.4.5/fs/udf/balloc.c +++ /dev/null @@ -1,825 +0,0 @@ -/* - * balloc.c - * - * PURPOSE - * Block allocation handling routines for the OSTA-UDF(tm) filesystem. - * - * 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-2001 Ben Fennema - * (C) 1999 Stelias Computing Inc - * - * HISTORY - * - * 02/24/99 blf Created. - * - */ - -#include "udfdecl.h" - -#include <linux/buffer_head.h> -#include <linux/bitops.h> - -#include "udf_i.h" -#include "udf_sb.h" - -#define udf_clear_bit __test_and_clear_bit_le -#define udf_set_bit __test_and_set_bit_le -#define udf_test_bit test_bit_le -#define udf_find_next_one_bit find_next_bit_le - -static int read_block_bitmap(struct super_block *sb, - struct udf_bitmap *bitmap, unsigned int block, - unsigned long bitmap_nr) -{ - struct buffer_head *bh = NULL; - int retval = 0; - struct kernel_lb_addr loc; - - loc.logicalBlockNum = bitmap->s_extPosition; - loc.partitionReferenceNum = UDF_SB(sb)->s_partition; - - bh = udf_tread(sb, udf_get_lb_pblock(sb, &loc, block)); - if (!bh) - retval = -EIO; - - bitmap->s_block_bitmap[bitmap_nr] = bh; - return retval; -} - -static int __load_block_bitmap(struct super_block *sb, - struct udf_bitmap *bitmap, - unsigned int block_group) -{ - int retval = 0; - int nr_groups = bitmap->s_nr_groups; - - if (block_group >= nr_groups) { - udf_debug("block_group (%d) > nr_groups (%d)\n", - block_group, nr_groups); - } - - if (bitmap->s_block_bitmap[block_group]) { - return block_group; - } else { - retval = read_block_bitmap(sb, bitmap, block_group, - block_group); - if (retval < 0) - return retval; - return block_group; - } -} - -static inline int load_block_bitmap(struct super_block *sb, - struct udf_bitmap *bitmap, - unsigned int block_group) -{ - int slot; - - slot = __load_block_bitmap(sb, bitmap, block_group); - - if (slot < 0) - return slot; - - if (!bitmap->s_block_bitmap[slot]) - return -EIO; - - return slot; -} - -static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct logicalVolIntegrityDesc *lvid; - - if (!sbi->s_lvid_bh) - return; - - lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; - le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); - udf_updated_lvid(sb); -} - -static void udf_bitmap_free_blocks(struct super_block *sb, - struct udf_bitmap *bitmap, - struct kernel_lb_addr *bloc, - uint32_t offset, - uint32_t count) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct buffer_head *bh = NULL; - struct udf_part_map *partmap; - unsigned long block; - unsigned long block_group; - unsigned long bit; - unsigned long i; - int bitmap_nr; - unsigned long overflow; - - mutex_lock(&sbi->s_alloc_mutex); - partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; - if (bloc->logicalBlockNum + count < count || - (bloc->logicalBlockNum + count) > partmap->s_partition_len) { - udf_debug("%d < %d || %d + %d > %d\n", - bloc->logicalBlockNum, 0, - bloc->logicalBlockNum, count, - partmap->s_partition_len); - goto error_return; - } - - block = bloc->logicalBlockNum + offset + - (sizeof(struct spaceBitmapDesc) << 3); - - do { - overflow = 0; - block_group = block >> (sb->s_blocksize_bits + 3); - bit = block % (sb->s_blocksize << 3); - - /* - * Check to see if we are freeing blocks across a group boundary. - */ - if (bit + count > (sb->s_blocksize << 3)) { - overflow = bit + count - (sb->s_blocksize << 3); - count -= overflow; - } - bitmap_nr = load_block_bitmap(sb, bitmap, block_group); - if (bitmap_nr < 0) - goto error_return; - - bh = bitmap->s_block_bitmap[bitmap_nr]; - for (i = 0; i < count; i++) { - if (udf_set_bit(bit + i, bh->b_data)) { - udf_debug("bit %ld already set\n", bit + i); - udf_debug("byte=%2x\n", - ((char *)bh->b_data)[(bit + i) >> 3]); - } - } - udf_add_free_space(sb, sbi->s_partition, count); - mark_buffer_dirty(bh); - if (overflow) { - block += count; - count = overflow; - } - } while (overflow); - -error_return: - mutex_unlock(&sbi->s_alloc_mutex); -} - -static int udf_bitmap_prealloc_blocks(struct super_block *sb, - struct udf_bitmap *bitmap, - uint16_t partition, uint32_t first_block, - uint32_t block_count) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - int alloc_count = 0; - int bit, block, block_group, group_start; - int nr_groups, bitmap_nr; - struct buffer_head *bh; - __u32 part_len; - - mutex_lock(&sbi->s_alloc_mutex); - part_len = sbi->s_partmaps[partition].s_partition_len; - if (first_block >= part_len) - goto out; - - if (first_block + block_count > part_len) - block_count = part_len - first_block; - - do { - nr_groups = udf_compute_nr_groups(sb, partition); - block = first_block + (sizeof(struct spaceBitmapDesc) << 3); - block_group = block >> (sb->s_blocksize_bits + 3); - group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc); - - bitmap_nr = load_block_bitmap(sb, bitmap, block_group); - if (bitmap_nr < 0) - goto out; - bh = bitmap->s_block_bitmap[bitmap_nr]; - - bit = block % (sb->s_blocksize << 3); - - while (bit < (sb->s_blocksize << 3) && block_count > 0) { - if (!udf_clear_bit(bit, bh->b_data)) - goto out; - block_count--; - alloc_count++; - bit++; - block++; - } - mark_buffer_dirty(bh); - } while (block_count > 0); - -out: - udf_add_free_space(sb, partition, -alloc_count); - mutex_unlock(&sbi->s_alloc_mutex); - return alloc_count; -} - -static int udf_bitmap_new_block(struct super_block *sb, - struct udf_bitmap *bitmap, uint16_t partition, - uint32_t goal, int *err) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - int newbit, bit = 0, block, block_group, group_start; - int end_goal, nr_groups, bitmap_nr, i; - struct buffer_head *bh = NULL; - char *ptr; - int newblock = 0; - - *err = -ENOSPC; - mutex_lock(&sbi->s_alloc_mutex); - -repeat: - if (goal >= sbi->s_partmaps[partition].s_partition_len) - goal = 0; - - nr_groups = bitmap->s_nr_groups; - block = goal + (sizeof(struct spaceBitmapDesc) << 3); - block_group = block >> (sb->s_blocksize_bits + 3); - group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc); - - bitmap_nr = load_block_bitmap(sb, bitmap, block_group); - if (bitmap_nr < 0) - goto error_return; - bh = bitmap->s_block_bitmap[bitmap_nr]; - ptr = memscan((char *)bh->b_data + group_start, 0xFF, - sb->s_blocksize - group_start); - - if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) { - bit = block % (sb->s_blocksize << 3); - if (udf_test_bit(bit, bh->b_data)) - goto got_block; - - end_goal = (bit + 63) & ~63; - bit = udf_find_next_one_bit(bh->b_data, end_goal, bit); - if (bit < end_goal) - goto got_block; - - ptr = memscan((char *)bh->b_data + (bit >> 3), 0xFF, - sb->s_blocksize - ((bit + 7) >> 3)); - newbit = (ptr - ((char *)bh->b_data)) << 3; - if (newbit < sb->s_blocksize << 3) { - bit = newbit; - goto search_back; - } - - newbit = udf_find_next_one_bit(bh->b_data, - sb->s_blocksize << 3, bit); - if (newbit < sb->s_blocksize << 3) { - bit = newbit; - goto got_block; - } - } - - for (i = 0; i < (nr_groups * 2); i++) { - block_group++; - if (block_group >= nr_groups) - block_group = 0; - group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc); - - bitmap_nr = load_block_bitmap(sb, bitmap, block_group); - if (bitmap_nr < 0) - goto error_return; - bh = bitmap->s_block_bitmap[bitmap_nr]; - if (i < nr_groups) { - ptr = memscan((char *)bh->b_data + group_start, 0xFF, - sb->s_blocksize - group_start); - if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) { - bit = (ptr - ((char *)bh->b_data)) << 3; - break; - } - } else { - bit = udf_find_next_one_bit(bh->b_data, - sb->s_blocksize << 3, - group_start << 3); - if (bit < sb->s_blocksize << 3) - break; - } - } - if (i >= (nr_groups * 2)) { - mutex_unlock(&sbi->s_alloc_mutex); - return newblock; - } - if (bit < sb->s_blocksize << 3) - goto search_back; - else - bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, - group_start << 3); - if (bit >= sb->s_blocksize << 3) { - mutex_unlock(&sbi->s_alloc_mutex); - return 0; - } - -search_back: - i = 0; - while (i < 7 && bit > (group_start << 3) && - udf_test_bit(bit - 1, bh->b_data)) { - ++i; - --bit; - } - -got_block: - newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) - - (sizeof(struct spaceBitmapDesc) << 3); - - if (!udf_clear_bit(bit, bh->b_data)) { - udf_debug("bit already cleared for block %d\n", bit); - goto repeat; - } - - mark_buffer_dirty(bh); - - udf_add_free_space(sb, partition, -1); - mutex_unlock(&sbi->s_alloc_mutex); - *err = 0; - return newblock; - -error_return: - *err = -EIO; - mutex_unlock(&sbi->s_alloc_mutex); - return 0; -} - -static void udf_table_free_blocks(struct super_block *sb, - struct inode *table, - struct kernel_lb_addr *bloc, - uint32_t offset, - uint32_t count) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct udf_part_map *partmap; - uint32_t start, end; - uint32_t elen; - struct kernel_lb_addr eloc; - struct extent_position oepos, epos; - int8_t etype; - int i; - struct udf_inode_info *iinfo; - - mutex_lock(&sbi->s_alloc_mutex); - partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; - if (bloc->logicalBlockNum + count < count || - (bloc->logicalBlockNum + count) > partmap->s_partition_len) { - udf_debug("%d < %d || %d + %d > %d\n", - bloc->logicalBlockNum, 0, - bloc->logicalBlockNum, count, - partmap->s_partition_len); - goto error_return; - } - - iinfo = UDF_I(table); - udf_add_free_space(sb, sbi->s_partition, count); - - start = bloc->logicalBlockNum + offset; - end = bloc->logicalBlockNum + offset + count - 1; - - epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry); - elen = 0; - epos.block = oepos.block = iinfo->i_location; - epos.bh = oepos.bh = NULL; - - while (count && - (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { - if (((eloc.logicalBlockNum + - (elen >> sb->s_blocksize_bits)) == start)) { - if ((0x3FFFFFFF - elen) < - (count << sb->s_blocksize_bits)) { - uint32_t tmp = ((0x3FFFFFFF - elen) >> - sb->s_blocksize_bits); - count -= tmp; - start += tmp; - elen = (etype << 30) | - (0x40000000 - sb->s_blocksize); - } else { - elen = (etype << 30) | - (elen + - (count << sb->s_blocksize_bits)); - start += count; - count = 0; - } - udf_write_aext(table, &oepos, &eloc, elen, 1); - } else if (eloc.logicalBlockNum == (end + 1)) { - if ((0x3FFFFFFF - elen) < - (count << sb->s_blocksize_bits)) { - uint32_t tmp = ((0x3FFFFFFF - elen) >> - sb->s_blocksize_bits); - count -= tmp; - end -= tmp; - eloc.logicalBlockNum -= tmp; - elen = (etype << 30) | - (0x40000000 - sb->s_blocksize); - } else { - eloc.logicalBlockNum = start; - elen = (etype << 30) | - (elen + - (count << sb->s_blocksize_bits)); - end -= count; - count = 0; - } - udf_write_aext(table, &oepos, &eloc, elen, 1); - } - - if (epos.bh != oepos.bh) { - i = -1; - oepos.block = epos.block; - brelse(oepos.bh); - get_bh(epos.bh); - oepos.bh = epos.bh; - oepos.offset = 0; - } else { - oepos.offset = epos.offset; - } - } - - if (count) { - /* - * NOTE: we CANNOT use udf_add_aext here, as it can try to - * allocate a new block, and since we hold the super block - * lock already very bad things would happen :) - * - * We copy the behavior of udf_add_aext, but instead of - * trying to allocate a new block close to the existing one, - * we just steal a block from the extent we are trying to add. - * - * It would be nice if the blocks were close together, but it - * isn't required. - */ - - int adsize; - struct short_ad *sad = NULL; - struct long_ad *lad = NULL; - struct allocExtDesc *aed; - - eloc.logicalBlockNum = start; - elen = EXT_RECORDED_ALLOCATED | - (count << sb->s_blocksize_bits); - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else { - brelse(oepos.bh); - brelse(epos.bh); - goto error_return; - } - - if (epos.offset + (2 * adsize) > sb->s_blocksize) { - unsigned char *sptr, *dptr; - int loffset; - - brelse(oepos.bh); - oepos = epos; - - /* Steal a block from the extent being free'd */ - epos.block.logicalBlockNum = eloc.logicalBlockNum; - eloc.logicalBlockNum++; - elen -= sb->s_blocksize; - - epos.bh = udf_tread(sb, - udf_get_lb_pblock(sb, &epos.block, 0)); - if (!epos.bh) { - brelse(oepos.bh); - goto error_return; - } - aed = (struct allocExtDesc *)(epos.bh->b_data); - aed->previousAllocExtLocation = - cpu_to_le32(oepos.block.logicalBlockNum); - if (epos.offset + adsize > sb->s_blocksize) { - loffset = epos.offset; - aed->lengthAllocDescs = cpu_to_le32(adsize); - sptr = iinfo->i_ext.i_data + epos.offset - - adsize; - dptr = epos.bh->b_data + - sizeof(struct allocExtDesc); - memcpy(dptr, sptr, adsize); - epos.offset = sizeof(struct allocExtDesc) + - adsize; - } else { - loffset = epos.offset + adsize; - aed->lengthAllocDescs = cpu_to_le32(0); - if (oepos.bh) { - sptr = oepos.bh->b_data + epos.offset; - aed = (struct allocExtDesc *) - oepos.bh->b_data; - le32_add_cpu(&aed->lengthAllocDescs, - adsize); - } else { - sptr = iinfo->i_ext.i_data + - epos.offset; - iinfo->i_lenAlloc += adsize; - mark_inode_dirty(table); - } - epos.offset = sizeof(struct allocExtDesc); - } - if (sbi->s_udfrev >= 0x0200) - udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, - 3, 1, epos.block.logicalBlockNum, - sizeof(struct tag)); - else - udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, - 2, 1, epos.block.logicalBlockNum, - sizeof(struct tag)); - - switch (iinfo->i_alloc_type) { - case ICBTAG_FLAG_AD_SHORT: - sad = (struct short_ad *)sptr; - sad->extLength = cpu_to_le32( - EXT_NEXT_EXTENT_ALLOCDECS | - sb->s_blocksize); - sad->extPosition = - cpu_to_le32(epos.block.logicalBlockNum); - break; - case ICBTAG_FLAG_AD_LONG: - lad = (struct long_ad *)sptr; - lad->extLength = cpu_to_le32( - EXT_NEXT_EXTENT_ALLOCDECS | - sb->s_blocksize); - lad->extLocation = - cpu_to_lelb(epos.block); - break; - } - if (oepos.bh) { - udf_update_tag(oepos.bh->b_data, loffset); - mark_buffer_dirty(oepos.bh); - } else { - mark_inode_dirty(table); - } - } - - /* It's possible that stealing the block emptied the extent */ - if (elen) { - udf_write_aext(table, &epos, &eloc, elen, 1); - - if (!epos.bh) { - iinfo->i_lenAlloc += adsize; - mark_inode_dirty(table); - } else { - aed = (struct allocExtDesc *)epos.bh->b_data; - le32_add_cpu(&aed->lengthAllocDescs, adsize); - udf_update_tag(epos.bh->b_data, epos.offset); - mark_buffer_dirty(epos.bh); - } - } - } - - brelse(epos.bh); - brelse(oepos.bh); - -error_return: - mutex_unlock(&sbi->s_alloc_mutex); - return; -} - -static int udf_table_prealloc_blocks(struct super_block *sb, - struct inode *table, uint16_t partition, - uint32_t first_block, uint32_t block_count) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - int alloc_count = 0; - uint32_t elen, adsize; - struct kernel_lb_addr eloc; - struct extent_position epos; - int8_t etype = -1; - struct udf_inode_info *iinfo; - - if (first_block >= sbi->s_partmaps[partition].s_partition_len) - return 0; - - iinfo = UDF_I(table); - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - return 0; - - mutex_lock(&sbi->s_alloc_mutex); - epos.offset = sizeof(struct unallocSpaceEntry); - epos.block = iinfo->i_location; - epos.bh = NULL; - eloc.logicalBlockNum = 0xFFFFFFFF; - - while (first_block != eloc.logicalBlockNum && - (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { - udf_debug("eloc=%d, elen=%d, first_block=%d\n", - eloc.logicalBlockNum, elen, first_block); - ; /* empty loop body */ - } - - if (first_block == eloc.logicalBlockNum) { - epos.offset -= adsize; - - alloc_count = (elen >> sb->s_blocksize_bits); - if (alloc_count > block_count) { - alloc_count = block_count; - eloc.logicalBlockNum += alloc_count; - elen -= (alloc_count << sb->s_blocksize_bits); - udf_write_aext(table, &epos, &eloc, - (etype << 30) | elen, 1); - } else - udf_delete_aext(table, epos, eloc, - (etype << 30) | elen); - } else { - alloc_count = 0; - } - - brelse(epos.bh); - - if (alloc_count) - udf_add_free_space(sb, partition, -alloc_count); - mutex_unlock(&sbi->s_alloc_mutex); - return alloc_count; -} - -static int udf_table_new_block(struct super_block *sb, - struct inode *table, uint16_t partition, - uint32_t goal, int *err) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; - uint32_t newblock = 0, adsize; - uint32_t elen, goal_elen = 0; - struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); - struct extent_position epos, goal_epos; - int8_t etype; - struct udf_inode_info *iinfo = UDF_I(table); - - *err = -ENOSPC; - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - return newblock; - - mutex_lock(&sbi->s_alloc_mutex); - if (goal >= sbi->s_partmaps[partition].s_partition_len) - goal = 0; - - /* We search for the closest matching block to goal. If we find - a exact hit, we stop. Otherwise we keep going till we run out - of extents. We store the buffer_head, bloc, and extoffset - of the current closest match and use that when we are done. - */ - epos.offset = sizeof(struct unallocSpaceEntry); - epos.block = iinfo->i_location; - epos.bh = goal_epos.bh = NULL; - - while (spread && - (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { - if (goal >= eloc.logicalBlockNum) { - if (goal < eloc.logicalBlockNum + - (elen >> sb->s_blocksize_bits)) - nspread = 0; - else - nspread = goal - eloc.logicalBlockNum - - (elen >> sb->s_blocksize_bits); - } else { - nspread = eloc.logicalBlockNum - goal; - } - - if (nspread < spread) { - spread = nspread; - if (goal_epos.bh != epos.bh) { - brelse(goal_epos.bh); - goal_epos.bh = epos.bh; - get_bh(goal_epos.bh); - } - goal_epos.block = epos.block; - goal_epos.offset = epos.offset - adsize; - goal_eloc = eloc; - goal_elen = (etype << 30) | elen; - } - } - - brelse(epos.bh); - - if (spread == 0xFFFFFFFF) { - brelse(goal_epos.bh); - mutex_unlock(&sbi->s_alloc_mutex); - return 0; - } - - /* Only allocate blocks from the beginning of the extent. - That way, we only delete (empty) extents, never have to insert an - extent because of splitting */ - /* This works, but very poorly.... */ - - newblock = goal_eloc.logicalBlockNum; - goal_eloc.logicalBlockNum++; - goal_elen -= sb->s_blocksize; - - if (goal_elen) - udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1); - else - udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); - brelse(goal_epos.bh); - - udf_add_free_space(sb, partition, -1); - - mutex_unlock(&sbi->s_alloc_mutex); - *err = 0; - return newblock; -} - -void udf_free_blocks(struct super_block *sb, struct inode *inode, - struct kernel_lb_addr *bloc, uint32_t offset, - uint32_t count) -{ - uint16_t partition = bloc->partitionReferenceNum; - struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; - - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { - udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap, - bloc, offset, count); - } else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { - udf_table_free_blocks(sb, map->s_uspace.s_table, - bloc, offset, count); - } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { - udf_bitmap_free_blocks(sb, map->s_fspace.s_bitmap, - bloc, offset, count); - } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { - udf_table_free_blocks(sb, map->s_fspace.s_table, - bloc, offset, count); - } - - if (inode) { - inode_sub_bytes(inode, - ((sector_t)count) << sb->s_blocksize_bits); - } -} - -inline int udf_prealloc_blocks(struct super_block *sb, - struct inode *inode, - uint16_t partition, uint32_t first_block, - uint32_t block_count) -{ - struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; - sector_t allocated; - - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) - allocated = udf_bitmap_prealloc_blocks(sb, - map->s_uspace.s_bitmap, - partition, first_block, - block_count); - else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) - allocated = udf_table_prealloc_blocks(sb, - map->s_uspace.s_table, - partition, first_block, - block_count); - else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) - allocated = udf_bitmap_prealloc_blocks(sb, - map->s_fspace.s_bitmap, - partition, first_block, - block_count); - else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) - allocated = udf_table_prealloc_blocks(sb, - map->s_fspace.s_table, - partition, first_block, - block_count); - else - return 0; - - if (inode && allocated > 0) - inode_add_bytes(inode, allocated << sb->s_blocksize_bits); - return allocated; -} - -inline int udf_new_block(struct super_block *sb, - struct inode *inode, - uint16_t partition, uint32_t goal, int *err) -{ - struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; - int block; - - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) - block = udf_bitmap_new_block(sb, - map->s_uspace.s_bitmap, - partition, goal, err); - else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) - block = udf_table_new_block(sb, - map->s_uspace.s_table, - partition, goal, err); - else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) - block = udf_bitmap_new_block(sb, - map->s_fspace.s_bitmap, - partition, goal, err); - else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) - block = udf_table_new_block(sb, - map->s_fspace.s_table, - partition, goal, err); - else { - *err = -EIO; - return 0; - } - if (inode && block) - inode_add_bytes(inode, sb->s_blocksize); - return block; -} diff --git a/ANDROID_3.4.5/fs/udf/dir.c b/ANDROID_3.4.5/fs/udf/dir.c deleted file mode 100644 index eb8bfe2b..00000000 --- a/ANDROID_3.4.5/fs/udf/dir.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * dir.c - * - * PURPOSE - * Directory handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998-2004 Ben Fennema - * - * HISTORY - * - * 10/05/98 dgb Split directory operations into its own file - * Implemented directory reads via do_udf_readdir - * 10/06/98 Made directory operations work! - * 11/17/98 Rewrote directory to support ICBTAG_FLAG_AD_LONG - * 11/25/98 blf Rewrote directory handling (readdir+lookup) to support reading - * across blocks. - * 12/12/98 Split out the lookup code to namei.c. bulk of directory - * code now in directory.c:udf_fileident_read. - */ - -#include "udfdecl.h" - -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/buffer_head.h> - -#include "udf_i.h" -#include "udf_sb.h" - -static int do_udf_readdir(struct inode *dir, struct file *filp, - filldir_t filldir, void *dirent) -{ - 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; - unsigned char *fname = NULL; - unsigned char *nameptr; - uint16_t liu; - uint8_t lfi; - loff_t size = udf_ext0_offset(dir) + dir->i_size; - struct buffer_head *tmp, *bha[16]; - struct kernel_lb_addr eloc; - uint32_t elen; - sector_t offset; - 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) - 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) { - 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) - epos.offset -= sizeof(struct short_ad); - else if (iinfo->i_alloc_type == - ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - } else { - offset = 0; - } - - if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { - ret = -EIO; - goto out; - } - - 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--) { - 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]); - } - } - } - - while (nf_pos < size) { - filp->f_pos = (nf_pos >> 2) + 1; - - fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, - &elen, &offset); - if (!fi) - goto out; - - 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 (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE)) - continue; - } - - if ((cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { - if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE)) - continue; - } - - if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) { - iblock = parent_ino(filp->f_path.dentry); - flen = 2; - memcpy(fname, "..", flen); - dt_type = DT_DIR; - } else { - struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); - - iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); - flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); - dt_type = DT_UNKNOWN; - } - - 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 ret; -} - -static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) -{ - struct inode *dir = filp->f_path.dentry->d_inode; - int result; - - if (filp->f_pos == 0) { - if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) { - return 0; - } - filp->f_pos++; - } - - result = do_udf_readdir(dir, filp, filldir, dirent); - return result; -} - -/* readdir and lookup functions */ -const struct file_operations udf_dir_operations = { - .llseek = generic_file_llseek, - .read = generic_read_dir, - .readdir = udf_readdir, - .unlocked_ioctl = udf_ioctl, - .fsync = generic_file_fsync, -}; diff --git a/ANDROID_3.4.5/fs/udf/directory.c b/ANDROID_3.4.5/fs/udf/directory.c deleted file mode 100644 index 3e44f575..00000000 --- a/ANDROID_3.4.5/fs/udf/directory.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * directory.c - * - * PURPOSE - * Directory related functions - * - * 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" -#include "udf_i.h" - -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/buffer_head.h> - -struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, - struct udf_fileident_bh *fibh, - struct fileIdentDesc *cfi, - struct extent_position *epos, - struct kernel_lb_addr *eloc, uint32_t *elen, - sector_t *offset) -{ - struct fileIdentDesc *fi; - int i, num, block; - struct buffer_head *tmp, *bha[16]; - struct udf_inode_info *iinfo = UDF_I(dir); - - fibh->soffset = fibh->eoffset; - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - fi = udf_get_fileident(iinfo->i_ext.i_data - - (iinfo->i_efe ? - sizeof(struct extendedFileEntry) : - sizeof(struct fileEntry)), - dir->i_sb->s_blocksize, - &(fibh->eoffset)); - if (!fi) - return NULL; - - *nf_pos += fibh->eoffset - fibh->soffset; - - memcpy((uint8_t *)cfi, (uint8_t *)fi, - sizeof(struct fileIdentDesc)); - - return fi; - } - - if (fibh->eoffset == dir->i_sb->s_blocksize) { - int lextoffset = epos->offset; - unsigned char blocksize_bits = dir->i_sb->s_blocksize_bits; - - if (udf_next_aext(dir, epos, eloc, elen, 1) != - (EXT_RECORDED_ALLOCATED >> 30)) - return NULL; - - block = udf_get_lb_pblock(dir->i_sb, eloc, *offset); - - (*offset)++; - - if ((*offset << blocksize_bits) >= *elen) - *offset = 0; - else - epos->offset = lextoffset; - - brelse(fibh->sbh); - fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); - if (!fibh->sbh) - return NULL; - fibh->soffset = fibh->eoffset = 0; - - if (!(*offset & ((16 >> (blocksize_bits - 9)) - 1))) { - i = 16 >> (blocksize_bits - 9); - if (i + *offset > (*elen >> blocksize_bits)) - i = (*elen >> 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 if (fibh->sbh != fibh->ebh) { - brelse(fibh->sbh); - fibh->sbh = fibh->ebh; - } - - fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize, - &(fibh->eoffset)); - - if (!fi) - return NULL; - - *nf_pos += fibh->eoffset - fibh->soffset; - - if (fibh->eoffset <= dir->i_sb->s_blocksize) { - memcpy((uint8_t *)cfi, (uint8_t *)fi, - sizeof(struct fileIdentDesc)); - } else if (fibh->eoffset > dir->i_sb->s_blocksize) { - int lextoffset = epos->offset; - - if (udf_next_aext(dir, epos, eloc, elen, 1) != - (EXT_RECORDED_ALLOCATED >> 30)) - return NULL; - - block = udf_get_lb_pblock(dir->i_sb, eloc, *offset); - - (*offset)++; - - if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen) - *offset = 0; - else - epos->offset = lextoffset; - - fibh->soffset -= dir->i_sb->s_blocksize; - fibh->eoffset -= dir->i_sb->s_blocksize; - - fibh->ebh = udf_tread(dir->i_sb, block); - if (!fibh->ebh) - return NULL; - - if (sizeof(struct fileIdentDesc) > -fibh->soffset) { - int fi_len; - - memcpy((uint8_t *)cfi, (uint8_t *)fi, -fibh->soffset); - memcpy((uint8_t *)cfi - fibh->soffset, - fibh->ebh->b_data, - sizeof(struct fileIdentDesc) + fibh->soffset); - - fi_len = (sizeof(struct fileIdentDesc) + - cfi->lengthFileIdent + - le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3; - - *nf_pos += fi_len - (fibh->eoffset - fibh->soffset); - fibh->eoffset = fibh->soffset + fi_len; - } else { - memcpy((uint8_t *)cfi, (uint8_t *)fi, - sizeof(struct fileIdentDesc)); - } - } - return fi; -} - -struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset) -{ - struct fileIdentDesc *fi; - int lengthThisIdent; - uint8_t *ptr; - int padlen; - - if ((!buffer) || (!offset)) { - udf_debug("invalidparms, buffer=%p, offset=%p\n", - buffer, offset); - return NULL; - } - - ptr = buffer; - - if ((*offset > 0) && (*offset < bufsize)) - ptr += *offset; - fi = (struct fileIdentDesc *)ptr; - if (fi->descTag.tagIdent != cpu_to_le16(TAG_IDENT_FID)) { - udf_debug("0x%x != TAG_IDENT_FID\n", - le16_to_cpu(fi->descTag.tagIdent)); - udf_debug("offset: %u sizeof: %lu bufsize: %u\n", - *offset, (unsigned long)sizeof(struct fileIdentDesc), - bufsize); - return NULL; - } - if ((*offset + sizeof(struct fileIdentDesc)) > bufsize) - lengthThisIdent = sizeof(struct fileIdentDesc); - else - lengthThisIdent = sizeof(struct fileIdentDesc) + - fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse); - - /* we need to figure padding, too! */ - padlen = lengthThisIdent % UDF_NAME_PAD; - if (padlen) - lengthThisIdent += (UDF_NAME_PAD - padlen); - *offset = *offset + lengthThisIdent; - - return fi; -} - -struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset, - int inc) -{ - struct short_ad *sa; - - if ((!ptr) || (!offset)) { - pr_err("%s: invalidparms\n", __func__); - return NULL; - } - - if ((*offset + sizeof(struct short_ad)) > maxoffset) - return NULL; - else { - sa = (struct short_ad *)ptr; - if (sa->extLength == 0) - return NULL; - } - - if (inc) - *offset += sizeof(struct short_ad); - return sa; -} - -struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) -{ - struct long_ad *la; - - if ((!ptr) || (!offset)) { - pr_err("%s: invalidparms\n", __func__); - return NULL; - } - - if ((*offset + sizeof(struct long_ad)) > maxoffset) - return NULL; - else { - la = (struct long_ad *)ptr; - if (la->extLength == 0) - return NULL; - } - - if (inc) - *offset += sizeof(struct long_ad); - return la; -} diff --git a/ANDROID_3.4.5/fs/udf/ecma_167.h b/ANDROID_3.4.5/fs/udf/ecma_167.h deleted file mode 100644 index 4792b771..00000000 --- a/ANDROID_3.4.5/fs/udf/ecma_167.h +++ /dev/null @@ -1,796 +0,0 @@ -/* - * ecma_167.h - * - * This file is based on ECMA-167 3rd edition (June 1997) - * http://www.ecma.ch - * - * Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <linux/types.h> - -#ifndef _ECMA_167_H -#define _ECMA_167_H 1 - -/* Character set specification (ECMA 167r3 1/7.2.1) */ -struct charspec { - uint8_t charSetType; - uint8_t charSetInfo[63]; -} __attribute__ ((packed)); - -/* Character Set Type (ECMA 167r3 1/7.2.1.1) */ -#define CHARSPEC_TYPE_CS0 0x00 /* (1/7.2.2) */ -#define CHARSPEC_TYPE_CS1 0x01 /* (1/7.2.3) */ -#define CHARSPEC_TYPE_CS2 0x02 /* (1/7.2.4) */ -#define CHARSPEC_TYPE_CS3 0x03 /* (1/7.2.5) */ -#define CHARSPEC_TYPE_CS4 0x04 /* (1/7.2.6) */ -#define CHARSPEC_TYPE_CS5 0x05 /* (1/7.2.7) */ -#define CHARSPEC_TYPE_CS6 0x06 /* (1/7.2.8) */ -#define CHARSPEC_TYPE_CS7 0x07 /* (1/7.2.9) */ -#define CHARSPEC_TYPE_CS8 0x08 /* (1/7.2.10) */ - -typedef uint8_t dstring; - -/* Timestamp (ECMA 167r3 1/7.3) */ -struct timestamp { - __le16 typeAndTimezone; - __le16 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)); - -/* Type and Time Zone (ECMA 167r3 1/7.3.1) */ -#define TIMESTAMP_TYPE_MASK 0xF000 -#define TIMESTAMP_TYPE_CUT 0x0000 -#define TIMESTAMP_TYPE_LOCAL 0x1000 -#define TIMESTAMP_TYPE_AGREEMENT 0x2000 -#define TIMESTAMP_TIMEZONE_MASK 0x0FFF - -/* Entity identifier (ECMA 167r3 1/7.4) */ -struct regid { - uint8_t flags; - uint8_t ident[23]; - uint8_t identSuffix[8]; -} __attribute__ ((packed)); - -/* Flags (ECMA 167r3 1/7.4.1) */ -#define ENTITYID_FLAGS_DIRTY 0x00 -#define ENTITYID_FLAGS_PROTECTED 0x01 - -/* Volume Structure Descriptor (ECMA 167r3 2/9.1) */ -#define VSD_STD_ID_LEN 5 -struct volStructDesc { - uint8_t structType; - uint8_t stdIdent[VSD_STD_ID_LEN]; - uint8_t structVersion; - uint8_t structData[2041]; -} __attribute__ ((packed)); - -/* Standard Identifier (EMCA 167r2 2/9.1.2) */ -#define VSD_STD_ID_NSR02 "NSR02" /* (3/9.1) */ - -/* Standard Identifier (ECMA 167r3 2/9.1.2) */ -#define VSD_STD_ID_BEA01 "BEA01" /* (2/9.2) */ -#define VSD_STD_ID_BOOT2 "BOOT2" /* (2/9.4) */ -#define VSD_STD_ID_CD001 "CD001" /* (ECMA-119) */ -#define VSD_STD_ID_CDW02 "CDW02" /* (ECMA-168) */ -#define VSD_STD_ID_NSR03 "NSR03" /* (3/9.1) */ -#define VSD_STD_ID_TEA01 "TEA01" /* (2/9.3) */ - -/* Beginning Extended Area Descriptor (ECMA 167r3 2/9.2) */ -struct beginningExtendedAreaDesc { - uint8_t structType; - uint8_t stdIdent[VSD_STD_ID_LEN]; - uint8_t structVersion; - uint8_t structData[2041]; -} __attribute__ ((packed)); - -/* Terminating Extended Area Descriptor (ECMA 167r3 2/9.3) */ -struct terminatingExtendedAreaDesc { - uint8_t structType; - uint8_t stdIdent[VSD_STD_ID_LEN]; - uint8_t structVersion; - uint8_t structData[2041]; -} __attribute__ ((packed)); - -/* Boot Descriptor (ECMA 167r3 2/9.4) */ -struct bootDesc { - uint8_t structType; - uint8_t stdIdent[VSD_STD_ID_LEN]; - uint8_t structVersion; - uint8_t reserved1; - struct regid archType; - struct regid bootIdent; - __le32 bootExtLocation; - __le32 bootExtLength; - __le64 loadAddress; - __le64 startAddress; - struct timestamp descCreationDateAndTime; - __le16 flags; - uint8_t reserved2[32]; - uint8_t bootUse[1906]; -} __attribute__ ((packed)); - -/* Flags (ECMA 167r3 2/9.4.12) */ -#define BOOT_FLAGS_ERASE 0x01 - -/* Extent Descriptor (ECMA 167r3 3/7.1) */ -struct extent_ad { - __le32 extLength; - __le32 extLocation; -} __attribute__ ((packed)); - -struct kernel_extent_ad { - uint32_t extLength; - uint32_t extLocation; -}; - -/* Descriptor Tag (ECMA 167r3 3/7.2) */ -struct tag { - __le16 tagIdent; - __le16 descVersion; - uint8_t tagChecksum; - uint8_t reserved; - __le16 tagSerialNum; - __le16 descCRC; - __le16 descCRCLength; - __le32 tagLocation; -} __attribute__ ((packed)); - -/* Tag Identifier (ECMA 167r3 3/7.2.1) */ -#define TAG_IDENT_PVD 0x0001 -#define TAG_IDENT_AVDP 0x0002 -#define TAG_IDENT_VDP 0x0003 -#define TAG_IDENT_IUVD 0x0004 -#define TAG_IDENT_PD 0x0005 -#define TAG_IDENT_LVD 0x0006 -#define TAG_IDENT_USD 0x0007 -#define TAG_IDENT_TD 0x0008 -#define TAG_IDENT_LVID 0x0009 - -/* NSR Descriptor (ECMA 167r3 3/9.1) */ -struct NSRDesc { - uint8_t structType; - uint8_t stdIdent[VSD_STD_ID_LEN]; - uint8_t structVersion; - uint8_t reserved; - uint8_t structData[2040]; -} __attribute__ ((packed)); - -/* Primary Volume Descriptor (ECMA 167r3 3/10.1) */ -struct primaryVolDesc { - struct tag descTag; - __le32 volDescSeqNum; - __le32 primaryVolDescNum; - dstring volIdent[32]; - __le16 volSeqNum; - __le16 maxVolSeqNum; - __le16 interchangeLvl; - __le16 maxInterchangeLvl; - __le32 charSetList; - __le32 maxCharSetList; - dstring volSetIdent[128]; - struct charspec descCharSet; - struct charspec explanatoryCharSet; - struct extent_ad volAbstract; - struct extent_ad volCopyright; - struct regid appIdent; - struct timestamp recordingDateAndTime; - struct regid impIdent; - uint8_t impUse[64]; - __le32 predecessorVolDescSeqLocation; - __le16 flags; - uint8_t reserved[22]; -} __attribute__ ((packed)); - -/* Flags (ECMA 167r3 3/10.1.21) */ -#define PVD_FLAGS_VSID_COMMON 0x0001 - -/* Anchor Volume Descriptor Pointer (ECMA 167r3 3/10.2) */ -struct anchorVolDescPtr { - struct tag descTag; - struct extent_ad mainVolDescSeqExt; - struct extent_ad reserveVolDescSeqExt; - uint8_t reserved[480]; -} __attribute__ ((packed)); - -/* Volume Descriptor Pointer (ECMA 167r3 3/10.3) */ -struct volDescPtr { - struct tag descTag; - __le32 volDescSeqNum; - struct extent_ad nextVolDescSeqExt; - uint8_t reserved[484]; -} __attribute__ ((packed)); - -/* Implementation Use Volume Descriptor (ECMA 167r3 3/10.4) */ -struct impUseVolDesc { - struct tag descTag; - __le32 volDescSeqNum; - struct regid impIdent; - uint8_t impUse[460]; -} __attribute__ ((packed)); - -/* Partition Descriptor (ECMA 167r3 3/10.5) */ -struct partitionDesc { - struct tag descTag; - __le32 volDescSeqNum; - __le16 partitionFlags; - __le16 partitionNumber; - struct regid partitionContents; - uint8_t partitionContentsUse[128]; - __le32 accessType; - __le32 partitionStartingLocation; - __le32 partitionLength; - struct regid impIdent; - uint8_t impUse[128]; - uint8_t reserved[156]; -} __attribute__ ((packed)); - -/* Partition Flags (ECMA 167r3 3/10.5.3) */ -#define PD_PARTITION_FLAGS_ALLOC 0x0001 - -/* Partition Contents (ECMA 167r2 3/10.5.3) */ -#define PD_PARTITION_CONTENTS_NSR02 "+NSR02" - -/* Partition Contents (ECMA 167r3 3/10.5.5) */ -#define PD_PARTITION_CONTENTS_FDC01 "+FDC01" -#define PD_PARTITION_CONTENTS_CD001 "+CD001" -#define PD_PARTITION_CONTENTS_CDW02 "+CDW02" -#define PD_PARTITION_CONTENTS_NSR03 "+NSR03" - -/* Access Type (ECMA 167r3 3/10.5.7) */ -#define PD_ACCESS_TYPE_NONE 0x00000000 -#define PD_ACCESS_TYPE_READ_ONLY 0x00000001 -#define PD_ACCESS_TYPE_WRITE_ONCE 0x00000002 -#define PD_ACCESS_TYPE_REWRITABLE 0x00000003 -#define PD_ACCESS_TYPE_OVERWRITABLE 0x00000004 - -/* Logical Volume Descriptor (ECMA 167r3 3/10.6) */ -struct logicalVolDesc { - struct tag descTag; - __le32 volDescSeqNum; - struct charspec descCharSet; - dstring logicalVolIdent[128]; - __le32 logicalBlockSize; - struct regid domainIdent; - uint8_t logicalVolContentsUse[16]; - __le32 mapTableLength; - __le32 numPartitionMaps; - struct regid impIdent; - uint8_t impUse[128]; - struct extent_ad integritySeqExt; - uint8_t partitionMaps[0]; -} __attribute__ ((packed)); - -/* Generic Partition Map (ECMA 167r3 3/10.7.1) */ -struct genericPartitionMap { - uint8_t partitionMapType; - uint8_t partitionMapLength; - uint8_t partitionMapping[0]; -} __attribute__ ((packed)); - -/* Partition Map Type (ECMA 167r3 3/10.7.1.1) */ -#define GP_PARTITION_MAP_TYPE_UNDEF 0x00 -#define GP_PARTIITON_MAP_TYPE_1 0x01 -#define GP_PARTITION_MAP_TYPE_2 0x02 - -/* Type 1 Partition Map (ECMA 167r3 3/10.7.2) */ -struct genericPartitionMap1 { - uint8_t partitionMapType; - uint8_t partitionMapLength; - __le16 volSeqNum; - __le16 partitionNum; -} __attribute__ ((packed)); - -/* Type 2 Partition Map (ECMA 167r3 3/10.7.3) */ -struct genericPartitionMap2 { - uint8_t partitionMapType; - uint8_t partitionMapLength; - uint8_t partitionIdent[62]; -} __attribute__ ((packed)); - -/* Unallocated Space Descriptor (ECMA 167r3 3/10.8) */ -struct unallocSpaceDesc { - struct tag descTag; - __le32 volDescSeqNum; - __le32 numAllocDescs; - struct extent_ad allocDescs[0]; -} __attribute__ ((packed)); - -/* Terminating Descriptor (ECMA 167r3 3/10.9) */ -struct terminatingDesc { - struct tag descTag; - uint8_t reserved[496]; -} __attribute__ ((packed)); - -/* Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */ -struct logicalVolIntegrityDesc { - struct tag descTag; - struct timestamp recordingDateAndTime; - __le32 integrityType; - struct extent_ad nextIntegrityExt; - uint8_t logicalVolContentsUse[32]; - __le32 numOfPartitions; - __le32 lengthOfImpUse; - __le32 freeSpaceTable[0]; - __le32 sizeTable[0]; - uint8_t impUse[0]; -} __attribute__ ((packed)); - -/* Integrity Type (ECMA 167r3 3/10.10.3) */ -#define LVID_INTEGRITY_TYPE_OPEN 0x00000000 -#define LVID_INTEGRITY_TYPE_CLOSE 0x00000001 - -/* Recorded Address (ECMA 167r3 4/7.1) */ -struct lb_addr { - __le32 logicalBlockNum; - __le16 partitionReferenceNum; -} __attribute__ ((packed)); - -/* ... and its in-core analog */ -struct kernel_lb_addr { - uint32_t logicalBlockNum; - uint16_t partitionReferenceNum; -}; - -/* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ -struct short_ad { - __le32 extLength; - __le32 extPosition; -} __attribute__ ((packed)); - -/* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ -struct long_ad { - __le32 extLength; - struct lb_addr extLocation; - uint8_t impUse[6]; -} __attribute__ ((packed)); - -struct kernel_long_ad { - uint32_t extLength; - struct kernel_lb_addr extLocation; - uint8_t impUse[6]; -}; - -/* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ -struct ext_ad { - __le32 extLength; - __le32 recordedLength; - __le32 informationLength; - struct lb_addr extLocation; -} __attribute__ ((packed)); - -struct kernel_ext_ad { - uint32_t extLength; - uint32_t recordedLength; - uint32_t informationLength; - struct kernel_lb_addr extLocation; -}; - -/* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */ - -/* Tag Identifier (ECMA 167r3 4/7.2.1) */ -#define TAG_IDENT_FSD 0x0100 -#define TAG_IDENT_FID 0x0101 -#define TAG_IDENT_AED 0x0102 -#define TAG_IDENT_IE 0x0103 -#define TAG_IDENT_TE 0x0104 -#define TAG_IDENT_FE 0x0105 -#define TAG_IDENT_EAHD 0x0106 -#define TAG_IDENT_USE 0x0107 -#define TAG_IDENT_SBD 0x0108 -#define TAG_IDENT_PIE 0x0109 -#define TAG_IDENT_EFE 0x010A - -/* File Set Descriptor (ECMA 167r3 4/14.1) */ -struct fileSetDesc { - struct tag descTag; - struct timestamp recordingDateAndTime; - __le16 interchangeLvl; - __le16 maxInterchangeLvl; - __le32 charSetList; - __le32 maxCharSetList; - __le32 fileSetNum; - __le32 fileSetDescNum; - struct charspec logicalVolIdentCharSet; - dstring logicalVolIdent[128]; - struct charspec fileSetCharSet; - dstring fileSetIdent[32]; - dstring copyrightFileIdent[32]; - dstring abstractFileIdent[32]; - struct long_ad rootDirectoryICB; - struct regid domainIdent; - struct long_ad nextExt; - struct long_ad streamDirectoryICB; - uint8_t reserved[32]; -} __attribute__ ((packed)); - -/* Partition Header Descriptor (ECMA 167r3 4/14.3) */ -struct partitionHeaderDesc { - struct short_ad unallocSpaceTable; - struct short_ad unallocSpaceBitmap; - struct short_ad partitionIntegrityTable; - struct short_ad freedSpaceTable; - struct short_ad freedSpaceBitmap; - uint8_t reserved[88]; -} __attribute__ ((packed)); - -/* File Identifier Descriptor (ECMA 167r3 4/14.4) */ -struct fileIdentDesc { - struct tag descTag; - __le16 fileVersionNum; - uint8_t fileCharacteristics; - uint8_t lengthFileIdent; - struct long_ad icb; - __le16 lengthOfImpUse; - uint8_t impUse[0]; - uint8_t fileIdent[0]; - uint8_t padding[0]; -} __attribute__ ((packed)); - -/* File Characteristics (ECMA 167r3 4/14.4.3) */ -#define FID_FILE_CHAR_HIDDEN 0x01 -#define FID_FILE_CHAR_DIRECTORY 0x02 -#define FID_FILE_CHAR_DELETED 0x04 -#define FID_FILE_CHAR_PARENT 0x08 -#define FID_FILE_CHAR_METADATA 0x10 - -/* Allocation Ext Descriptor (ECMA 167r3 4/14.5) */ -struct allocExtDesc { - struct tag descTag; - __le32 previousAllocExtLocation; - __le32 lengthAllocDescs; -} __attribute__ ((packed)); - -/* ICB Tag (ECMA 167r3 4/14.6) */ -struct icbtag { - __le32 priorRecordedNumDirectEntries; - __le16 strategyType; - __le16 strategyParameter; - __le16 numEntries; - uint8_t reserved; - uint8_t fileType; - struct lb_addr parentICBLocation; - __le16 flags; -} __attribute__ ((packed)); - -/* Strategy Type (ECMA 167r3 4/14.6.2) */ -#define ICBTAG_STRATEGY_TYPE_UNDEF 0x0000 -#define ICBTAG_STRATEGY_TYPE_1 0x0001 -#define ICBTAG_STRATEGY_TYPE_2 0x0002 -#define ICBTAG_STRATEGY_TYPE_3 0x0003 -#define ICBTAG_STRATEGY_TYPE_4 0x0004 - -/* File Type (ECMA 167r3 4/14.6.6) */ -#define ICBTAG_FILE_TYPE_UNDEF 0x00 -#define ICBTAG_FILE_TYPE_USE 0x01 -#define ICBTAG_FILE_TYPE_PIE 0x02 -#define ICBTAG_FILE_TYPE_IE 0x03 -#define ICBTAG_FILE_TYPE_DIRECTORY 0x04 -#define ICBTAG_FILE_TYPE_REGULAR 0x05 -#define ICBTAG_FILE_TYPE_BLOCK 0x06 -#define ICBTAG_FILE_TYPE_CHAR 0x07 -#define ICBTAG_FILE_TYPE_EA 0x08 -#define ICBTAG_FILE_TYPE_FIFO 0x09 -#define ICBTAG_FILE_TYPE_SOCKET 0x0A -#define ICBTAG_FILE_TYPE_TE 0x0B -#define ICBTAG_FILE_TYPE_SYMLINK 0x0C -#define ICBTAG_FILE_TYPE_STREAMDIR 0x0D - -/* Flags (ECMA 167r3 4/14.6.8) */ -#define ICBTAG_FLAG_AD_MASK 0x0007 -#define ICBTAG_FLAG_AD_SHORT 0x0000 -#define ICBTAG_FLAG_AD_LONG 0x0001 -#define ICBTAG_FLAG_AD_EXTENDED 0x0002 -#define ICBTAG_FLAG_AD_IN_ICB 0x0003 -#define ICBTAG_FLAG_SORTED 0x0008 -#define ICBTAG_FLAG_NONRELOCATABLE 0x0010 -#define ICBTAG_FLAG_ARCHIVE 0x0020 -#define ICBTAG_FLAG_SETUID 0x0040 -#define ICBTAG_FLAG_SETGID 0x0080 -#define ICBTAG_FLAG_STICKY 0x0100 -#define ICBTAG_FLAG_CONTIGUOUS 0x0200 -#define ICBTAG_FLAG_SYSTEM 0x0400 -#define ICBTAG_FLAG_TRANSFORMED 0x0800 -#define ICBTAG_FLAG_MULTIVERSIONS 0x1000 -#define ICBTAG_FLAG_STREAM 0x2000 - -/* Indirect Entry (ECMA 167r3 4/14.7) */ -struct indirectEntry { - struct tag descTag; - struct icbtag icbTag; - struct long_ad indirectICB; -} __attribute__ ((packed)); - -/* Terminal Entry (ECMA 167r3 4/14.8) */ -struct terminalEntry { - struct tag descTag; - struct icbtag icbTag; -} __attribute__ ((packed)); - -/* File Entry (ECMA 167r3 4/14.9) */ -struct fileEntry { - struct tag descTag; - struct icbtag icbTag; - __le32 uid; - __le32 gid; - __le32 permissions; - __le16 fileLinkCount; - uint8_t recordFormat; - uint8_t recordDisplayAttr; - __le32 recordLength; - __le64 informationLength; - __le64 logicalBlocksRecorded; - struct timestamp accessTime; - struct timestamp modificationTime; - struct timestamp attrTime; - __le32 checkpoint; - struct long_ad extendedAttrICB; - struct regid impIdent; - __le64 uniqueID; - __le32 lengthExtendedAttr; - __le32 lengthAllocDescs; - uint8_t extendedAttr[0]; - uint8_t allocDescs[0]; -} __attribute__ ((packed)); - -/* Permissions (ECMA 167r3 4/14.9.5) */ -#define FE_PERM_O_EXEC 0x00000001U -#define FE_PERM_O_WRITE 0x00000002U -#define FE_PERM_O_READ 0x00000004U -#define FE_PERM_O_CHATTR 0x00000008U -#define FE_PERM_O_DELETE 0x00000010U -#define FE_PERM_G_EXEC 0x00000020U -#define FE_PERM_G_WRITE 0x00000040U -#define FE_PERM_G_READ 0x00000080U -#define FE_PERM_G_CHATTR 0x00000100U -#define FE_PERM_G_DELETE 0x00000200U -#define FE_PERM_U_EXEC 0x00000400U -#define FE_PERM_U_WRITE 0x00000800U -#define FE_PERM_U_READ 0x00001000U -#define FE_PERM_U_CHATTR 0x00002000U -#define FE_PERM_U_DELETE 0x00004000U - -/* Record Format (ECMA 167r3 4/14.9.7) */ -#define FE_RECORD_FMT_UNDEF 0x00 -#define FE_RECORD_FMT_FIXED_PAD 0x01 -#define FE_RECORD_FMT_FIXED 0x02 -#define FE_RECORD_FMT_VARIABLE8 0x03 -#define FE_RECORD_FMT_VARIABLE16 0x04 -#define FE_RECORD_FMT_VARIABLE16_MSB 0x05 -#define FE_RECORD_FMT_VARIABLE32 0x06 -#define FE_RECORD_FMT_PRINT 0x07 -#define FE_RECORD_FMT_LF 0x08 -#define FE_RECORD_FMT_CR 0x09 -#define FE_RECORD_FMT_CRLF 0x0A -#define FE_RECORD_FMT_LFCR 0x0B - -/* Record Display Attributes (ECMA 167r3 4/14.9.8) */ -#define FE_RECORD_DISPLAY_ATTR_UNDEF 0x00 -#define FE_RECORD_DISPLAY_ATTR_1 0x01 -#define FE_RECORD_DISPLAY_ATTR_2 0x02 -#define FE_RECORD_DISPLAY_ATTR_3 0x03 - -/* Extended Attribute Header Descriptor (ECMA 167r3 4/14.10.1) */ -struct extendedAttrHeaderDesc { - struct tag descTag; - __le32 impAttrLocation; - __le32 appAttrLocation; -} __attribute__ ((packed)); - -/* Generic Format (ECMA 167r3 4/14.10.2) */ -struct genericFormat { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - uint8_t attrData[0]; -} __attribute__ ((packed)); - -/* Character Set Information (ECMA 167r3 4/14.10.3) */ -struct charSetInfo { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le32 escapeSeqLength; - uint8_t charSetType; - uint8_t escapeSeq[0]; -} __attribute__ ((packed)); - -/* Alternate Permissions (ECMA 167r3 4/14.10.4) */ -struct altPerms { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le16 ownerIdent; - __le16 groupIdent; - __le16 permission; -} __attribute__ ((packed)); - -/* File Times Extended Attribute (ECMA 167r3 4/14.10.5) */ -struct fileTimesExtAttr { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le32 dataLength; - __le32 fileTimeExistence; - uint8_t fileTimes; -} __attribute__ ((packed)); - -/* FileTimeExistence (ECMA 167r3 4/14.10.5.6) */ -#define FTE_CREATION 0x00000001 -#define FTE_DELETION 0x00000004 -#define FTE_EFFECTIVE 0x00000008 -#define FTE_BACKUP 0x00000002 - -/* Information Times Extended Attribute (ECMA 167r3 4/14.10.6) */ -struct infoTimesExtAttr { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le32 dataLength; - __le32 infoTimeExistence; - uint8_t infoTimes[0]; -} __attribute__ ((packed)); - -/* Device Specification (ECMA 167r3 4/14.10.7) */ -struct deviceSpec { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le32 impUseLength; - __le32 majorDeviceIdent; - __le32 minorDeviceIdent; - uint8_t impUse[0]; -} __attribute__ ((packed)); - -/* Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */ -struct impUseExtAttr { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le32 impUseLength; - struct regid impIdent; - uint8_t impUse[0]; -} __attribute__ ((packed)); - -/* Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */ -struct appUseExtAttr { - __le32 attrType; - uint8_t attrSubtype; - uint8_t reserved[3]; - __le32 attrLength; - __le32 appUseLength; - struct regid appIdent; - uint8_t appUse[0]; -} __attribute__ ((packed)); - -#define EXTATTR_CHAR_SET 1 -#define EXTATTR_ALT_PERMS 3 -#define EXTATTR_FILE_TIMES 5 -#define EXTATTR_INFO_TIMES 6 -#define EXTATTR_DEV_SPEC 12 -#define EXTATTR_IMP_USE 2048 -#define EXTATTR_APP_USE 65536 - -/* Unallocated Space Entry (ECMA 167r3 4/14.11) */ -struct unallocSpaceEntry { - struct tag descTag; - struct icbtag icbTag; - __le32 lengthAllocDescs; - uint8_t allocDescs[0]; -} __attribute__ ((packed)); - -/* Space Bitmap Descriptor (ECMA 167r3 4/14.12) */ -struct spaceBitmapDesc { - struct tag descTag; - __le32 numOfBits; - __le32 numOfBytes; - uint8_t bitmap[0]; -} __attribute__ ((packed)); - -/* Partition Integrity Entry (ECMA 167r3 4/14.13) */ -struct partitionIntegrityEntry { - struct tag descTag; - struct icbtag icbTag; - struct timestamp recordingDateAndTime; - uint8_t integrityType; - uint8_t reserved[175]; - struct regid impIdent; - uint8_t impUse[256]; -} __attribute__ ((packed)); - -/* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ - -/* Extent Length (ECMA 167r3 4/14.14.1.1) */ -#define EXT_RECORDED_ALLOCATED 0x00000000 -#define EXT_NOT_RECORDED_ALLOCATED 0x40000000 -#define EXT_NOT_RECORDED_NOT_ALLOCATED 0x80000000 -#define EXT_NEXT_EXTENT_ALLOCDECS 0xC0000000 - -/* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ - -/* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ - -/* Logical Volume Header Descriptor (ECMA 167r3 4/14.15) */ -struct logicalVolHeaderDesc { - __le64 uniqueID; - uint8_t reserved[24]; -} __attribute__ ((packed)); - -/* Path Component (ECMA 167r3 4/14.16.1) */ -struct pathComponent { - uint8_t componentType; - uint8_t lengthComponentIdent; - __le16 componentFileVersionNum; - dstring componentIdent[0]; -} __attribute__ ((packed)); - -/* File Entry (ECMA 167r3 4/14.17) */ -struct extendedFileEntry { - struct tag descTag; - struct icbtag icbTag; - __le32 uid; - __le32 gid; - __le32 permissions; - __le16 fileLinkCount; - uint8_t recordFormat; - uint8_t recordDisplayAttr; - __le32 recordLength; - __le64 informationLength; - __le64 objectSize; - __le64 logicalBlocksRecorded; - struct timestamp accessTime; - struct timestamp modificationTime; - struct timestamp createTime; - struct timestamp attrTime; - __le32 checkpoint; - __le32 reserved; - struct long_ad extendedAttrICB; - struct long_ad streamDirectoryICB; - struct regid impIdent; - __le64 uniqueID; - __le32 lengthExtendedAttr; - __le32 lengthAllocDescs; - uint8_t extendedAttr[0]; - uint8_t allocDescs[0]; -} __attribute__ ((packed)); - -#endif /* _ECMA_167_H */ diff --git a/ANDROID_3.4.5/fs/udf/file.c b/ANDROID_3.4.5/fs/udf/file.c deleted file mode 100644 index 7f3f7ba3..00000000 --- a/ANDROID_3.4.5/fs/udf/file.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * file.c - * - * PURPOSE - * File handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998-1999 Dave Boynton - * (C) 1998-2004 Ben Fennema - * (C) 1999-2000 Stelias Computing Inc - * - * HISTORY - * - * 10/02/98 dgb Attempt to integrate into udf.o - * 10/07/98 Switched to using generic_readpage, etc., like isofs - * And it works! - * 12/06/98 blf Added udf_file_read. uses generic_file_read for all cases but - * ICBTAG_FLAG_AD_IN_ICB. - * 04/06/99 64 bit file handling on 32 bit systems taken from ext2 file.c - * 05/12/99 Preliminary file write support - */ - -#include "udfdecl.h" -#include <linux/fs.h> -#include <asm/uaccess.h> -#include <linux/kernel.h> -#include <linux/string.h> /* memset */ -#include <linux/capability.h> -#include <linux/errno.h> -#include <linux/pagemap.h> -#include <linux/buffer_head.h> -#include <linux/aio.h> - -#include "udf_i.h" -#include "udf_sb.h" - -static int udf_adinicb_readpage(struct file *file, struct page *page) -{ - struct inode *inode = page->mapping->host; - char *kaddr; - struct udf_inode_info *iinfo = UDF_I(inode); - - BUG_ON(!PageLocked(page)); - - kaddr = kmap(page); - memset(kaddr, 0, PAGE_CACHE_SIZE); - memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); - flush_dcache_page(page); - SetPageUptodate(page); - kunmap(page); - unlock_page(page); - - return 0; -} - -static int udf_adinicb_writepage(struct page *page, - struct writeback_control *wbc) -{ - struct inode *inode = page->mapping->host; - char *kaddr; - struct udf_inode_info *iinfo = UDF_I(inode); - - BUG_ON(!PageLocked(page)); - - kaddr = kmap(page); - memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, inode->i_size); - mark_inode_dirty(inode); - SetPageUptodate(page); - kunmap(page); - unlock_page(page); - - return 0; -} - -static int udf_adinicb_write_end(struct file *file, - struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) -{ - struct inode *inode = mapping->host; - unsigned offset = pos & (PAGE_CACHE_SIZE - 1); - char *kaddr; - struct udf_inode_info *iinfo = UDF_I(inode); - - kaddr = kmap_atomic(page); - memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset, - kaddr + offset, copied); - kunmap_atomic(kaddr); - - return simple_write_end(file, mapping, pos, len, copied, page, fsdata); -} - -const struct address_space_operations udf_adinicb_aops = { - .readpage = udf_adinicb_readpage, - .writepage = udf_adinicb_writepage, - .write_begin = simple_write_begin, - .write_end = udf_adinicb_write_end, -}; - -static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t ppos) -{ - ssize_t retval; - struct file *file = iocb->ki_filp; - struct inode *inode = file->f_path.dentry->d_inode; - int err, pos; - size_t count = iocb->ki_left; - struct udf_inode_info *iinfo = UDF_I(inode); - - down_write(&iinfo->i_data_sem); - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - if (file->f_flags & O_APPEND) - pos = inode->i_size; - else - pos = ppos; - - if (inode->i_sb->s_blocksize < - (udf_file_entry_alloc_offset(inode) + - pos + count)) { - err = udf_expand_file_adinicb(inode); - if (err) { - udf_debug("udf_expand_adinicb: err=%d\n", err); - return err; - } - } else { - if (pos + count > inode->i_size) - iinfo->i_lenAlloc = pos + count; - else - iinfo->i_lenAlloc = inode->i_size; - up_write(&iinfo->i_data_sem); - } - } else - up_write(&iinfo->i_data_sem); - - retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); - if (retval > 0) - mark_inode_dirty(inode); - - return retval; -} - -long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct inode *inode = filp->f_dentry->d_inode; - long old_block, new_block; - int result = -EINVAL; - - if (inode_permission(inode, MAY_READ) != 0) { - udf_debug("no permission to access inode %lu\n", inode->i_ino); - result = -EPERM; - goto out; - } - - if (!arg) { - udf_debug("invalid argument to udf_ioctl\n"); - result = -EINVAL; - goto out; - } - - switch (cmd) { - case UDF_GETVOLIDENT: - if (copy_to_user((char __user *)arg, - UDF_SB(inode->i_sb)->s_volume_ident, 32)) - result = -EFAULT; - else - result = 0; - goto out; - case UDF_RELOCATE_BLOCKS: - if (!capable(CAP_SYS_ADMIN)) { - result = -EACCES; - goto out; - } - if (get_user(old_block, (long __user *)arg)) { - result = -EFAULT; - goto out; - } - result = udf_relocate_blocks(inode->i_sb, - old_block, &new_block); - if (result == 0) - result = put_user(new_block, (long __user *)arg); - goto out; - case UDF_GETEASIZE: - result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); - goto out; - case UDF_GETEABLOCK: - result = copy_to_user((char __user *)arg, - UDF_I(inode)->i_ext.i_data, - UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; - goto out; - } - -out: - return result; -} - -static int udf_release_file(struct inode *inode, struct file *filp) -{ - if (filp->f_mode & FMODE_WRITE) { - down_write(&UDF_I(inode)->i_data_sem); - udf_discard_prealloc(inode); - udf_truncate_tail_extent(inode); - up_write(&UDF_I(inode)->i_data_sem); - } - return 0; -} - -const struct file_operations udf_file_operations = { - .read = do_sync_read, - .aio_read = generic_file_aio_read, - .unlocked_ioctl = udf_ioctl, - .open = generic_file_open, - .mmap = generic_file_mmap, - .write = do_sync_write, - .aio_write = udf_file_aio_write, - .release = udf_release_file, - .fsync = generic_file_fsync, - .splice_read = generic_file_splice_read, - .llseek = generic_file_llseek, -}; - -static int udf_setattr(struct dentry *dentry, struct iattr *attr) -{ - struct inode *inode = dentry->d_inode; - int error; - - error = inode_change_ok(inode, attr); - if (error) - return error; - - if ((attr->ia_valid & ATTR_SIZE) && - attr->ia_size != i_size_read(inode)) { - error = udf_setsize(inode, attr->ia_size); - if (error) - return error; - } - - setattr_copy(inode, attr); - mark_inode_dirty(inode); - return 0; -} - -const struct inode_operations udf_file_inode_operations = { - .setattr = udf_setattr, -}; diff --git a/ANDROID_3.4.5/fs/udf/ialloc.c b/ANDROID_3.4.5/fs/udf/ialloc.c deleted file mode 100644 index 7e5aae4b..00000000 --- a/ANDROID_3.4.5/fs/udf/ialloc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * ialloc.c - * - * PURPOSE - * Inode allocation handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998-2001 Ben Fennema - * - * HISTORY - * - * 02/24/99 blf Created. - * - */ - -#include "udfdecl.h" -#include <linux/fs.h> -#include <linux/sched.h> -#include <linux/slab.h> - -#include "udf_i.h" -#include "udf_sb.h" - -void udf_free_inode(struct inode *inode) -{ - struct super_block *sb = inode->i_sb; - struct udf_sb_info *sbi = UDF_SB(sb); - - mutex_lock(&sbi->s_alloc_mutex); - if (sbi->s_lvid_bh) { - struct logicalVolIntegrityDescImpUse *lvidiu = - udf_sb_lvidiu(sbi); - if (S_ISDIR(inode->i_mode)) - le32_add_cpu(&lvidiu->numDirs, -1); - else - le32_add_cpu(&lvidiu->numFiles, -1); - udf_updated_lvid(sb); - } - mutex_unlock(&sbi->s_alloc_mutex); - - udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1); -} - -struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) -{ - struct super_block *sb = dir->i_sb; - struct udf_sb_info *sbi = UDF_SB(sb); - struct inode *inode; - int block; - uint32_t start = UDF_I(dir)->i_location.logicalBlockNum; - struct udf_inode_info *iinfo; - struct udf_inode_info *dinfo = UDF_I(dir); - - inode = new_inode(sb); - - if (!inode) { - *err = -ENOMEM; - return NULL; - } - *err = -ENOSPC; - - iinfo = UDF_I(inode); - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) { - iinfo->i_efe = 1; - if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) - sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry), - GFP_KERNEL); - } else { - iinfo->i_efe = 0; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct fileEntry), - GFP_KERNEL); - } - if (!iinfo->i_ext.i_data) { - iput(inode); - *err = -ENOMEM; - return NULL; - } - - block = udf_new_block(dir->i_sb, NULL, - dinfo->i_location.partitionReferenceNum, - start, err); - if (*err) { - iput(inode); - return NULL; - } - - if (sbi->s_lvid_bh) { - struct logicalVolIntegrityDescImpUse *lvidiu; - - iinfo->i_unique = lvid_get_unique_id(sb); - mutex_lock(&sbi->s_alloc_mutex); - lvidiu = udf_sb_lvidiu(sbi); - if (S_ISDIR(mode)) - le32_add_cpu(&lvidiu->numDirs, 1); - else - le32_add_cpu(&lvidiu->numFiles, 1); - udf_updated_lvid(sb); - mutex_unlock(&sbi->s_alloc_mutex); - } - - inode_init_owner(inode, dir, mode); - - iinfo->i_location.logicalBlockNum = block; - iinfo->i_location.partitionReferenceNum = - dinfo->i_location.partitionReferenceNum; - inode->i_ino = udf_get_lb_pblock(sb, &iinfo->i_location, 0); - inode->i_blocks = 0; - iinfo->i_lenEAttr = 0; - iinfo->i_lenAlloc = 0; - iinfo->i_use = 0; - iinfo->i_checkpoint = 1; - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) - iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; - else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) - iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; - else - iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; - inode->i_mtime = inode->i_atime = inode->i_ctime = - iinfo->i_crtime = current_fs_time(inode->i_sb); - insert_inode_hash(inode); - mark_inode_dirty(inode); - - *err = 0; - return inode; -} diff --git a/ANDROID_3.4.5/fs/udf/inode.c b/ANDROID_3.4.5/fs/udf/inode.c deleted file mode 100644 index 7d752800..00000000 --- a/ANDROID_3.4.5/fs/udf/inode.c +++ /dev/null @@ -1,2172 +0,0 @@ -/* - * inode.c - * - * PURPOSE - * Inode handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998 Dave Boynton - * (C) 1998-2004 Ben Fennema - * (C) 1999-2000 Stelias Computing Inc - * - * HISTORY - * - * 10/04/98 dgb Added rudimentary directory functions - * 10/07/98 Fully working udf_block_map! It works! - * 11/25/98 bmap altered to better support extents - * 12/06/98 blf partition support in udf_iget, udf_block_map - * and udf_read_inode - * 12/12/98 rewrote udf_block_map to handle next extents and descs across - * block boundaries (which is not actually allowed) - * 12/20/98 added support for strategy 4096 - * 03/07/99 rewrote udf_block_map (again) - * New funcs, inode_bmap, udf_next_aext - * 04/19/99 Support for writing device EA's for major/minor # - */ - -#include "udfdecl.h" -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/pagemap.h> -#include <linux/buffer_head.h> -#include <linux/writeback.h> -#include <linux/slab.h> -#include <linux/crc-itu-t.h> -#include <linux/mpage.h> - -#include "udf_i.h" -#include "udf_sb.h" - -MODULE_AUTHOR("Ben Fennema"); -MODULE_DESCRIPTION("Universal Disk Format Filesystem"); -MODULE_LICENSE("GPL"); - -#define EXTENT_MERGE_SIZE 5 - -static umode_t udf_convert_permissions(struct fileEntry *); -static int udf_update_inode(struct inode *, int); -static void udf_fill_inode(struct inode *, struct buffer_head *); -static int udf_sync_inode(struct inode *inode); -static int udf_alloc_i_data(struct inode *inode, size_t size); -static sector_t inode_getblk(struct inode *, sector_t, int *, int *); -static int8_t udf_insert_aext(struct inode *, struct extent_position, - struct kernel_lb_addr, uint32_t); -static void udf_split_extents(struct inode *, int *, int, int, - struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); -static void udf_prealloc_extents(struct inode *, int, int, - struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); -static void udf_merge_extents(struct inode *, - struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); -static void udf_update_extents(struct inode *, - struct kernel_long_ad[EXTENT_MERGE_SIZE], int, int, - struct extent_position *); -static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); - - -void udf_evict_inode(struct inode *inode) -{ - struct udf_inode_info *iinfo = UDF_I(inode); - int want_delete = 0; - - if (!inode->i_nlink && !is_bad_inode(inode)) { - want_delete = 1; - udf_setsize(inode, 0); - udf_update_inode(inode, IS_SYNC(inode)); - } else - truncate_inode_pages(&inode->i_data, 0); - invalidate_inode_buffers(inode); - end_writeback(inode); - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && - inode->i_size != iinfo->i_lenExtents) { - udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n", - inode->i_ino, inode->i_mode, - (unsigned long long)inode->i_size, - (unsigned long long)iinfo->i_lenExtents); - } - kfree(iinfo->i_ext.i_data); - iinfo->i_ext.i_data = NULL; - if (want_delete) { - udf_free_inode(inode); - } -} - -static int udf_writepage(struct page *page, struct writeback_control *wbc) -{ - return block_write_full_page(page, udf_get_block, wbc); -} - -static int udf_readpage(struct file *file, struct page *page) -{ - return mpage_readpage(page, udf_get_block); -} - -static int udf_readpages(struct file *file, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages) -{ - return mpage_readpages(mapping, pages, nr_pages, udf_get_block); -} - -static int udf_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) -{ - int ret; - - ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); - if (unlikely(ret)) { - struct inode *inode = mapping->host; - struct udf_inode_info *iinfo = UDF_I(inode); - loff_t isize = inode->i_size; - - if (pos + len > isize) { - truncate_pagecache(inode, pos + len, isize); - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { - down_write(&iinfo->i_data_sem); - udf_truncate_extents(inode); - up_write(&iinfo->i_data_sem); - } - } - } - - return ret; -} - -static sector_t udf_bmap(struct address_space *mapping, sector_t block) -{ - return generic_block_bmap(mapping, block, udf_get_block); -} - -const struct address_space_operations udf_aops = { - .readpage = udf_readpage, - .readpages = udf_readpages, - .writepage = udf_writepage, - .write_begin = udf_write_begin, - .write_end = generic_write_end, - .bmap = udf_bmap, -}; - -/* - * Expand file stored in ICB to a normal one-block-file - * - * This function requires i_data_sem for writing and releases it. - * This function requires i_mutex held - */ -int udf_expand_file_adinicb(struct inode *inode) -{ - struct page *page; - char *kaddr; - struct udf_inode_info *iinfo = UDF_I(inode); - int err; - struct writeback_control udf_wbc = { - .sync_mode = WB_SYNC_NONE, - .nr_to_write = 1, - }; - - if (!iinfo->i_lenAlloc) { - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) - iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; - else - iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; - /* from now on we have normal address_space methods */ - inode->i_data.a_ops = &udf_aops; - up_write(&iinfo->i_data_sem); - mark_inode_dirty(inode); - return 0; - } - /* - * Release i_data_sem so that we can lock a page - page lock ranks - * above i_data_sem. i_mutex still protects us against file changes. - */ - up_write(&iinfo->i_data_sem); - - page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); - if (!page) - return -ENOMEM; - - if (!PageUptodate(page)) { - kaddr = kmap(page); - memset(kaddr + iinfo->i_lenAlloc, 0x00, - PAGE_CACHE_SIZE - iinfo->i_lenAlloc); - memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, - iinfo->i_lenAlloc); - flush_dcache_page(page); - SetPageUptodate(page); - kunmap(page); - } - down_write(&iinfo->i_data_sem); - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, - iinfo->i_lenAlloc); - iinfo->i_lenAlloc = 0; - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) - iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; - else - iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; - /* from now on we have normal address_space methods */ - inode->i_data.a_ops = &udf_aops; - up_write(&iinfo->i_data_sem); - err = inode->i_data.a_ops->writepage(page, &udf_wbc); - if (err) { - /* Restore everything back so that we don't lose data... */ - lock_page(page); - kaddr = kmap(page); - down_write(&iinfo->i_data_sem); - memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, - inode->i_size); - kunmap(page); - unlock_page(page); - iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; - inode->i_data.a_ops = &udf_adinicb_aops; - up_write(&iinfo->i_data_sem); - } - page_cache_release(page); - mark_inode_dirty(inode); - - return err; -} - -struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, - int *err) -{ - int newblock; - struct buffer_head *dbh = NULL; - struct kernel_lb_addr eloc; - uint8_t alloctype; - struct extent_position epos; - - struct udf_fileident_bh sfibh, dfibh; - loff_t f_pos = udf_ext0_offset(inode); - int size = udf_ext0_offset(inode) + inode->i_size; - struct fileIdentDesc cfi, *sfi, *dfi; - struct udf_inode_info *iinfo = UDF_I(inode); - - 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) { - iinfo->i_alloc_type = alloctype; - mark_inode_dirty(inode); - return NULL; - } - - /* alloc block, and copy data to it */ - *block = udf_new_block(inode->i_sb, inode, - iinfo->i_location.partitionReferenceNum, - iinfo->i_location.logicalBlockNum, err); - if (!(*block)) - return NULL; - newblock = udf_get_pblock(inode->i_sb, *block, - iinfo->i_location.partitionReferenceNum, - 0); - if (!newblock) - return NULL; - dbh = udf_tgetblk(inode->i_sb, newblock); - if (!dbh) - return NULL; - lock_buffer(dbh); - memset(dbh->b_data, 0x00, inode->i_sb->s_blocksize); - set_buffer_uptodate(dbh); - unlock_buffer(dbh); - mark_buffer_dirty_inode(dbh, inode); - - sfibh.soffset = sfibh.eoffset = - f_pos & (inode->i_sb->s_blocksize - 1); - sfibh.sbh = sfibh.ebh = NULL; - dfibh.soffset = dfibh.eoffset = 0; - dfibh.sbh = dfibh.ebh = dbh; - while (f_pos < size) { - iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; - sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, - NULL, NULL, NULL); - if (!sfi) { - brelse(dbh); - return NULL; - } - iinfo->i_alloc_type = alloctype; - sfi->descTag.tagLocation = cpu_to_le32(*block); - dfibh.soffset = dfibh.eoffset; - dfibh.eoffset += (sfibh.eoffset - sfibh.soffset); - dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset); - if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse, - sfi->fileIdent + - le16_to_cpu(sfi->lengthOfImpUse))) { - iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; - brelse(dbh); - return NULL; - } - } - mark_buffer_dirty_inode(dbh, inode); - - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0, - iinfo->i_lenAlloc); - iinfo->i_lenAlloc = 0; - eloc.logicalBlockNum = *block; - eloc.partitionReferenceNum = - iinfo->i_location.partitionReferenceNum; - iinfo->i_lenExtents = inode->i_size; - epos.bh = NULL; - epos.block = iinfo->i_location; - epos.offset = udf_file_entry_alloc_offset(inode); - udf_add_aext(inode, &epos, &eloc, inode->i_size, 0); - /* UniqueID stuff */ - - brelse(epos.bh); - mark_inode_dirty(inode); - return dbh; -} - -static int udf_get_block(struct inode *inode, sector_t block, - struct buffer_head *bh_result, int create) -{ - int err, new; - sector_t phys = 0; - struct udf_inode_info *iinfo; - - if (!create) { - phys = udf_block_map(inode, block); - if (phys) - map_bh(bh_result, inode->i_sb, phys); - return 0; - } - - err = -EIO; - new = 0; - iinfo = UDF_I(inode); - - down_write(&iinfo->i_data_sem); - if (block == iinfo->i_next_alloc_block + 1) { - iinfo->i_next_alloc_block++; - iinfo->i_next_alloc_goal++; - } - - - phys = inode_getblk(inode, block, &err, &new); - if (!phys) - goto abort; - - if (new) - set_buffer_new(bh_result); - map_bh(bh_result, inode->i_sb, phys); - -abort: - up_write(&iinfo->i_data_sem); - return err; -} - -static struct buffer_head *udf_getblk(struct inode *inode, long block, - int create, int *err) -{ - struct buffer_head *bh; - struct buffer_head dummy; - - dummy.b_state = 0; - dummy.b_blocknr = -1000; - *err = udf_get_block(inode, block, &dummy, create); - if (!*err && buffer_mapped(&dummy)) { - bh = sb_getblk(inode->i_sb, dummy.b_blocknr); - if (buffer_new(&dummy)) { - lock_buffer(bh); - memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); - set_buffer_uptodate(bh); - unlock_buffer(bh); - mark_buffer_dirty_inode(bh, inode); - } - return bh; - } - - return NULL; -} - -/* Extend the file by 'blocks' blocks, return the number of extents added */ -static int udf_do_extend_file(struct inode *inode, - struct extent_position *last_pos, - struct kernel_long_ad *last_ext, - sector_t blocks) -{ - sector_t add; - int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); - struct super_block *sb = inode->i_sb; - struct kernel_lb_addr prealloc_loc = {}; - int prealloc_len = 0; - struct udf_inode_info *iinfo; - int err; - - /* The previous extent is fake and we should not extend by anything - * - there's nothing to do... */ - if (!blocks && fake) - return 0; - - iinfo = UDF_I(inode); - /* Round the last extent up to a multiple of block size */ - if (last_ext->extLength & (sb->s_blocksize - 1)) { - last_ext->extLength = - (last_ext->extLength & UDF_EXTENT_FLAG_MASK) | - (((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) + - sb->s_blocksize - 1) & ~(sb->s_blocksize - 1)); - iinfo->i_lenExtents = - (iinfo->i_lenExtents + sb->s_blocksize - 1) & - ~(sb->s_blocksize - 1); - } - - /* Last extent are just preallocated blocks? */ - if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == - EXT_NOT_RECORDED_ALLOCATED) { - /* Save the extent so that we can reattach it to the end */ - prealloc_loc = last_ext->extLocation; - prealloc_len = last_ext->extLength; - /* Mark the extent as a hole */ - last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); - last_ext->extLocation.logicalBlockNum = 0; - last_ext->extLocation.partitionReferenceNum = 0; - } - - /* Can we merge with the previous extent? */ - if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == - EXT_NOT_RECORDED_NOT_ALLOCATED) { - add = ((1 << 30) - sb->s_blocksize - - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >> - sb->s_blocksize_bits; - if (add > blocks) - add = blocks; - blocks -= add; - last_ext->extLength += add << sb->s_blocksize_bits; - } - - if (fake) { - udf_add_aext(inode, last_pos, &last_ext->extLocation, - last_ext->extLength, 1); - count++; - } else - udf_write_aext(inode, last_pos, &last_ext->extLocation, - last_ext->extLength, 1); - - /* Managed to do everything necessary? */ - if (!blocks) - goto out; - - /* All further extents will be NOT_RECORDED_NOT_ALLOCATED */ - last_ext->extLocation.logicalBlockNum = 0; - last_ext->extLocation.partitionReferenceNum = 0; - add = (1 << (30-sb->s_blocksize_bits)) - 1; - last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | - (add << sb->s_blocksize_bits); - - /* Create enough extents to cover the whole hole */ - while (blocks > add) { - blocks -= add; - err = udf_add_aext(inode, last_pos, &last_ext->extLocation, - last_ext->extLength, 1); - if (err) - return err; - count++; - } - if (blocks) { - last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | - (blocks << sb->s_blocksize_bits); - err = udf_add_aext(inode, last_pos, &last_ext->extLocation, - last_ext->extLength, 1); - if (err) - return err; - count++; - } - -out: - /* Do we have some preallocated blocks saved? */ - if (prealloc_len) { - err = udf_add_aext(inode, last_pos, &prealloc_loc, - prealloc_len, 1); - if (err) - return err; - last_ext->extLocation = prealloc_loc; - last_ext->extLength = prealloc_len; - count++; - } - - /* last_pos should point to the last written extent... */ - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - last_pos->offset -= sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - last_pos->offset -= sizeof(struct long_ad); - else - return -EIO; - - return count; -} - -static int udf_extend_file(struct inode *inode, loff_t newsize) -{ - - struct extent_position epos; - struct kernel_lb_addr eloc; - uint32_t elen; - int8_t etype; - struct super_block *sb = inode->i_sb; - sector_t first_block = newsize >> sb->s_blocksize_bits, offset; - int adsize; - struct udf_inode_info *iinfo = UDF_I(inode); - struct kernel_long_ad extent; - int err; - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - BUG(); - - etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); - - /* File has extent covering the new size (could happen when extending - * inside a block)? */ - if (etype != -1) - return 0; - if (newsize & (sb->s_blocksize - 1)) - offset++; - /* Extended file just to the boundary of the last file block? */ - if (offset == 0) - return 0; - - /* Truncate is extending the file by 'offset' blocks */ - if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || - (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { - /* File has no extents at all or has empty last - * indirect extent! Create a fake extent... */ - extent.extLocation.logicalBlockNum = 0; - extent.extLocation.partitionReferenceNum = 0; - extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; - } else { - epos.offset -= adsize; - etype = udf_next_aext(inode, &epos, &extent.extLocation, - &extent.extLength, 0); - extent.extLength |= etype << 30; - } - err = udf_do_extend_file(inode, &epos, &extent, offset); - if (err < 0) - goto out; - err = 0; - iinfo->i_lenExtents = newsize; -out: - brelse(epos.bh); - return err; -} - -static sector_t inode_getblk(struct inode *inode, sector_t block, - int *err, int *new) -{ - static sector_t last_block; - struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; - struct extent_position prev_epos, cur_epos, next_epos; - int count = 0, startnum = 0, endnum = 0; - uint32_t elen = 0, tmpelen; - struct kernel_lb_addr eloc, tmpeloc; - int c = 1; - loff_t lbcount = 0, b_off = 0; - uint32_t newblocknum, newblock; - sector_t offset = 0; - int8_t etype; - struct udf_inode_info *iinfo = UDF_I(inode); - int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; - int lastblock = 0; - - *err = 0; - *new = 0; - prev_epos.offset = udf_file_entry_alloc_offset(inode); - prev_epos.block = iinfo->i_location; - prev_epos.bh = NULL; - cur_epos = next_epos = prev_epos; - b_off = (loff_t)block << inode->i_sb->s_blocksize_bits; - - /* find the extent which contains the block we are looking for. - alternate between laarr[0] and laarr[1] for locations of the - current extent, and the previous extent */ - do { - if (prev_epos.bh != cur_epos.bh) { - brelse(prev_epos.bh); - get_bh(cur_epos.bh); - prev_epos.bh = cur_epos.bh; - } - if (cur_epos.bh != next_epos.bh) { - brelse(cur_epos.bh); - get_bh(next_epos.bh); - cur_epos.bh = next_epos.bh; - } - - lbcount += elen; - - prev_epos.block = cur_epos.block; - cur_epos.block = next_epos.block; - - prev_epos.offset = cur_epos.offset; - cur_epos.offset = next_epos.offset; - - etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1); - if (etype == -1) - break; - - c = !c; - - laarr[c].extLength = (etype << 30) | elen; - laarr[c].extLocation = eloc; - - if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) - pgoal = eloc.logicalBlockNum + - ((elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits); - - count++; - } while (lbcount + elen <= b_off); - - b_off -= lbcount; - offset = b_off >> inode->i_sb->s_blocksize_bits; - /* - * Move prev_epos and cur_epos into indirect extent if we are at - * the pointer to it - */ - udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0); - udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0); - - /* if the extent is allocated and recorded, return the block - if the extent is not a multiple of the blocksize, round up */ - - if (etype == (EXT_RECORDED_ALLOCATED >> 30)) { - if (elen & (inode->i_sb->s_blocksize - 1)) { - elen = EXT_RECORDED_ALLOCATED | - ((elen + inode->i_sb->s_blocksize - 1) & - ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, &cur_epos, &eloc, elen, 1); - } - brelse(prev_epos.bh); - brelse(cur_epos.bh); - brelse(next_epos.bh); - newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); - return newblock; - } - - last_block = block; - /* Are we beyond EOF? */ - if (etype == -1) { - int ret; - - if (count) { - if (c) - laarr[0] = laarr[1]; - startnum = 1; - } else { - /* Create a fake extent when there's not one */ - memset(&laarr[0].extLocation, 0x00, - sizeof(struct kernel_lb_addr)); - laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; - /* Will udf_do_extend_file() create real extent from - a fake one? */ - startnum = (offset > 0); - } - /* Create extents for the hole between EOF and offset */ - ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); - if (ret < 0) { - brelse(prev_epos.bh); - brelse(cur_epos.bh); - brelse(next_epos.bh); - *err = ret; - return 0; - } - c = 0; - offset = 0; - count += ret; - /* We are not covered by a preallocated extent? */ - if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != - EXT_NOT_RECORDED_ALLOCATED) { - /* Is there any real extent? - otherwise we overwrite - * the fake one... */ - if (count) - c = !c; - laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | - inode->i_sb->s_blocksize; - memset(&laarr[c].extLocation, 0x00, - sizeof(struct kernel_lb_addr)); - count++; - endnum++; - } - endnum = c + 1; - lastblock = 1; - } else { - endnum = startnum = ((count > 2) ? 2 : count); - - /* if the current extent is in position 0, - swap it with the previous */ - if (!c && count != 1) { - laarr[2] = laarr[0]; - laarr[0] = laarr[1]; - laarr[1] = laarr[2]; - c = 1; - } - - /* if the current block is located in an extent, - read the next extent */ - etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0); - if (etype != -1) { - laarr[c + 1].extLength = (etype << 30) | elen; - laarr[c + 1].extLocation = eloc; - count++; - startnum++; - endnum++; - } else - lastblock = 1; - } - - /* if the current extent is not recorded but allocated, get the - * block in the extent corresponding to the requested block */ - if ((laarr[c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30)) - newblocknum = laarr[c].extLocation.logicalBlockNum + offset; - else { /* otherwise, allocate a new block */ - if (iinfo->i_next_alloc_block == block) - goal = iinfo->i_next_alloc_goal; - - if (!goal) { - if (!(goal = pgoal)) /* XXX: what was intended here? */ - goal = iinfo->i_location.logicalBlockNum + 1; - } - - newblocknum = udf_new_block(inode->i_sb, inode, - iinfo->i_location.partitionReferenceNum, - goal, err); - if (!newblocknum) { - brelse(prev_epos.bh); - *err = -ENOSPC; - return 0; - } - iinfo->i_lenExtents += inode->i_sb->s_blocksize; - } - - /* if the extent the requsted block is located in contains multiple - * blocks, split the extent into at most three extents. blocks prior - * to requested block, requested block, and blocks after requested - * block */ - udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum); - -#ifdef UDF_PREALLOCATE - /* We preallocate blocks only for regular files. It also makes sense - * for directories but there's a problem when to drop the - * preallocation. We might use some delayed work for that but I feel - * it's overengineering for a filesystem like UDF. */ - if (S_ISREG(inode->i_mode)) - udf_prealloc_extents(inode, c, lastblock, laarr, &endnum); -#endif - - /* merge any continuous blocks in laarr */ - udf_merge_extents(inode, laarr, &endnum); - - /* write back the new extents, inserting new extents if the new number - * of extents is greater than the old number, and deleting extents if - * the new number of extents is less than the old number */ - udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); - - brelse(prev_epos.bh); - - newblock = udf_get_pblock(inode->i_sb, newblocknum, - iinfo->i_location.partitionReferenceNum, 0); - if (!newblock) { - *err = -EIO; - return 0; - } - *new = 1; - iinfo->i_next_alloc_block = block; - iinfo->i_next_alloc_goal = newblocknum; - inode->i_ctime = current_fs_time(inode->i_sb); - - if (IS_SYNC(inode)) - udf_sync_inode(inode); - else - mark_inode_dirty(inode); - - return newblock; -} - -static void udf_split_extents(struct inode *inode, int *c, int offset, - int newblocknum, - struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], - int *endnum) -{ - unsigned long blocksize = inode->i_sb->s_blocksize; - unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; - - if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) || - (laarr[*c].extLength >> 30) == - (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) { - int curr = *c; - int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) >> blocksize_bits; - int8_t etype = (laarr[curr].extLength >> 30); - - if (blen == 1) - ; - else if (!offset || blen == offset + 1) { - laarr[curr + 2] = laarr[curr + 1]; - laarr[curr + 1] = laarr[curr]; - } else { - laarr[curr + 3] = laarr[curr + 1]; - laarr[curr + 2] = laarr[curr + 1] = laarr[curr]; - } - - if (offset) { - if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { - udf_free_blocks(inode->i_sb, inode, - &laarr[curr].extLocation, - 0, offset); - laarr[curr].extLength = - EXT_NOT_RECORDED_NOT_ALLOCATED | - (offset << blocksize_bits); - laarr[curr].extLocation.logicalBlockNum = 0; - laarr[curr].extLocation. - partitionReferenceNum = 0; - } else - laarr[curr].extLength = (etype << 30) | - (offset << blocksize_bits); - curr++; - (*c)++; - (*endnum)++; - } - - laarr[curr].extLocation.logicalBlockNum = newblocknum; - if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) - laarr[curr].extLocation.partitionReferenceNum = - UDF_I(inode)->i_location.partitionReferenceNum; - laarr[curr].extLength = EXT_RECORDED_ALLOCATED | - blocksize; - curr++; - - if (blen != offset + 1) { - if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) - laarr[curr].extLocation.logicalBlockNum += - offset + 1; - laarr[curr].extLength = (etype << 30) | - ((blen - (offset + 1)) << blocksize_bits); - curr++; - (*endnum)++; - } - } -} - -static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, - struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], - int *endnum) -{ - int start, length = 0, currlength = 0, i; - - if (*endnum >= (c + 1)) { - if (!lastblock) - return; - else - start = c; - } else { - if ((laarr[c + 1].extLength >> 30) == - (EXT_NOT_RECORDED_ALLOCATED >> 30)) { - start = c + 1; - length = currlength = - (((laarr[c + 1].extLength & - UDF_EXTENT_LENGTH_MASK) + - inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits); - } else - start = c; - } - - for (i = start + 1; i <= *endnum; i++) { - if (i == *endnum) { - if (lastblock) - length += UDF_DEFAULT_PREALLOC_BLOCKS; - } else if ((laarr[i].extLength >> 30) == - (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) { - length += (((laarr[i].extLength & - UDF_EXTENT_LENGTH_MASK) + - inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits); - } else - break; - } - - if (length) { - int next = laarr[start].extLocation.logicalBlockNum + - (((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) + - inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits); - int numalloc = udf_prealloc_blocks(inode->i_sb, inode, - laarr[start].extLocation.partitionReferenceNum, - next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? - length : UDF_DEFAULT_PREALLOC_BLOCKS) - - currlength); - if (numalloc) { - if (start == (c + 1)) - laarr[start].extLength += - (numalloc << - inode->i_sb->s_blocksize_bits); - else { - memmove(&laarr[c + 2], &laarr[c + 1], - sizeof(struct long_ad) * (*endnum - (c + 1))); - (*endnum)++; - laarr[c + 1].extLocation.logicalBlockNum = next; - laarr[c + 1].extLocation.partitionReferenceNum = - laarr[c].extLocation. - partitionReferenceNum; - laarr[c + 1].extLength = - EXT_NOT_RECORDED_ALLOCATED | - (numalloc << - inode->i_sb->s_blocksize_bits); - start = c + 1; - } - - for (i = start + 1; numalloc && i < *endnum; i++) { - int elen = ((laarr[i].extLength & - UDF_EXTENT_LENGTH_MASK) + - inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits; - - if (elen > numalloc) { - laarr[i].extLength -= - (numalloc << - inode->i_sb->s_blocksize_bits); - numalloc = 0; - } else { - numalloc -= elen; - if (*endnum > (i + 1)) - memmove(&laarr[i], - &laarr[i + 1], - sizeof(struct long_ad) * - (*endnum - (i + 1))); - i--; - (*endnum)--; - } - } - UDF_I(inode)->i_lenExtents += - numalloc << inode->i_sb->s_blocksize_bits; - } - } -} - -static void udf_merge_extents(struct inode *inode, - struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], - int *endnum) -{ - int i; - unsigned long blocksize = inode->i_sb->s_blocksize; - unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; - - for (i = 0; i < (*endnum - 1); i++) { - struct kernel_long_ad *li /*l[i]*/ = &laarr[i]; - struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1]; - - if (((li->extLength >> 30) == (lip1->extLength >> 30)) && - (((li->extLength >> 30) == - (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) || - ((lip1->extLocation.logicalBlockNum - - li->extLocation.logicalBlockNum) == - (((li->extLength & UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) >> blocksize_bits)))) { - - if (((li->extLength & UDF_EXTENT_LENGTH_MASK) + - (lip1->extLength & UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) { - lip1->extLength = (lip1->extLength - - (li->extLength & - UDF_EXTENT_LENGTH_MASK) + - UDF_EXTENT_LENGTH_MASK) & - ~(blocksize - 1); - li->extLength = (li->extLength & - UDF_EXTENT_FLAG_MASK) + - (UDF_EXTENT_LENGTH_MASK + 1) - - blocksize; - lip1->extLocation.logicalBlockNum = - li->extLocation.logicalBlockNum + - ((li->extLength & - UDF_EXTENT_LENGTH_MASK) >> - blocksize_bits); - } else { - li->extLength = lip1->extLength + - (((li->extLength & - UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) & ~(blocksize - 1)); - if (*endnum > (i + 2)) - memmove(&laarr[i + 1], &laarr[i + 2], - sizeof(struct long_ad) * - (*endnum - (i + 2))); - i--; - (*endnum)--; - } - } else if (((li->extLength >> 30) == - (EXT_NOT_RECORDED_ALLOCATED >> 30)) && - ((lip1->extLength >> 30) == - (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) { - udf_free_blocks(inode->i_sb, inode, &li->extLocation, 0, - ((li->extLength & - UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) >> blocksize_bits); - li->extLocation.logicalBlockNum = 0; - li->extLocation.partitionReferenceNum = 0; - - if (((li->extLength & UDF_EXTENT_LENGTH_MASK) + - (lip1->extLength & UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) { - lip1->extLength = (lip1->extLength - - (li->extLength & - UDF_EXTENT_LENGTH_MASK) + - UDF_EXTENT_LENGTH_MASK) & - ~(blocksize - 1); - li->extLength = (li->extLength & - UDF_EXTENT_FLAG_MASK) + - (UDF_EXTENT_LENGTH_MASK + 1) - - blocksize; - } else { - li->extLength = lip1->extLength + - (((li->extLength & - UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) & ~(blocksize - 1)); - if (*endnum > (i + 2)) - memmove(&laarr[i + 1], &laarr[i + 2], - sizeof(struct long_ad) * - (*endnum - (i + 2))); - i--; - (*endnum)--; - } - } else if ((li->extLength >> 30) == - (EXT_NOT_RECORDED_ALLOCATED >> 30)) { - udf_free_blocks(inode->i_sb, inode, - &li->extLocation, 0, - ((li->extLength & - UDF_EXTENT_LENGTH_MASK) + - blocksize - 1) >> blocksize_bits); - li->extLocation.logicalBlockNum = 0; - li->extLocation.partitionReferenceNum = 0; - li->extLength = (li->extLength & - UDF_EXTENT_LENGTH_MASK) | - EXT_NOT_RECORDED_NOT_ALLOCATED; - } - } -} - -static void udf_update_extents(struct inode *inode, - struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], - int startnum, int endnum, - struct extent_position *epos) -{ - int start = 0, i; - struct kernel_lb_addr tmploc; - uint32_t tmplen; - - if (startnum > endnum) { - for (i = 0; i < (startnum - endnum); i++) - udf_delete_aext(inode, *epos, laarr[i].extLocation, - laarr[i].extLength); - } else if (startnum < endnum) { - for (i = 0; i < (endnum - startnum); i++) { - udf_insert_aext(inode, *epos, laarr[i].extLocation, - laarr[i].extLength); - udf_next_aext(inode, epos, &laarr[i].extLocation, - &laarr[i].extLength, 1); - start++; - } - } - - for (i = start; i < endnum; i++) { - udf_next_aext(inode, epos, &tmploc, &tmplen, 0); - udf_write_aext(inode, epos, &laarr[i].extLocation, - laarr[i].extLength, 1); - } -} - -struct buffer_head *udf_bread(struct inode *inode, int block, - int create, int *err) -{ - struct buffer_head *bh = NULL; - - bh = udf_getblk(inode, block, create, err); - if (!bh) - return NULL; - - if (buffer_uptodate(bh)) - return bh; - - ll_rw_block(READ, 1, &bh); - - wait_on_buffer(bh); - if (buffer_uptodate(bh)) - return bh; - - brelse(bh); - *err = -EIO; - return NULL; -} - -int udf_setsize(struct inode *inode, loff_t newsize) -{ - int err; - struct udf_inode_info *iinfo; - int bsize = 1 << inode->i_blkbits; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return -EINVAL; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return -EPERM; - - iinfo = UDF_I(inode); - if (newsize > inode->i_size) { - down_write(&iinfo->i_data_sem); - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - if (bsize < - (udf_file_entry_alloc_offset(inode) + newsize)) { - err = udf_expand_file_adinicb(inode); - if (err) - return err; - down_write(&iinfo->i_data_sem); - } else - iinfo->i_lenAlloc = newsize; - } - err = udf_extend_file(inode, newsize); - if (err) { - up_write(&iinfo->i_data_sem); - return err; - } - truncate_setsize(inode, newsize); - up_write(&iinfo->i_data_sem); - } else { - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - down_write(&iinfo->i_data_sem); - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, - 0x00, bsize - newsize - - udf_file_entry_alloc_offset(inode)); - iinfo->i_lenAlloc = newsize; - truncate_setsize(inode, newsize); - up_write(&iinfo->i_data_sem); - goto update_time; - } - err = block_truncate_page(inode->i_mapping, newsize, - udf_get_block); - if (err) - return err; - down_write(&iinfo->i_data_sem); - truncate_setsize(inode, newsize); - udf_truncate_extents(inode); - up_write(&iinfo->i_data_sem); - } -update_time: - inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb); - if (IS_SYNC(inode)) - udf_sync_inode(inode); - else - mark_inode_dirty(inode); - return 0; -} - -static void __udf_read_inode(struct inode *inode) -{ - struct buffer_head *bh = NULL; - struct fileEntry *fe; - uint16_t ident; - struct udf_inode_info *iinfo = UDF_I(inode); - - /* - * Set defaults, but the inode is still incomplete! - * Note: get_new_inode() sets the following on a new inode: - * i_sb = sb - * i_no = ino - * i_flags = sb->s_flags - * i_state = 0 - * clean_inode(): zero fills and sets - * i_count = 1 - * i_nlink = 1 - * i_op = NULL; - */ - bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident); - if (!bh) { - udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino); - make_bad_inode(inode); - return; - } - - if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE && - ident != TAG_IDENT_USE) { - udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n", - inode->i_ino, ident); - brelse(bh); - make_bad_inode(inode); - return; - } - - fe = (struct fileEntry *)bh->b_data; - - if (fe->icbTag.strategyType == cpu_to_le16(4096)) { - struct buffer_head *ibh; - - ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1, - &ident); - if (ident == TAG_IDENT_IE && ibh) { - struct buffer_head *nbh = NULL; - struct kernel_lb_addr loc; - struct indirectEntry *ie; - - ie = (struct indirectEntry *)ibh->b_data; - loc = lelb_to_cpu(ie->indirectICB.extLocation); - - if (ie->indirectICB.extLength && - (nbh = udf_read_ptagged(inode->i_sb, &loc, 0, - &ident))) { - if (ident == TAG_IDENT_FE || - ident == TAG_IDENT_EFE) { - memcpy(&iinfo->i_location, - &loc, - sizeof(struct kernel_lb_addr)); - brelse(bh); - brelse(ibh); - brelse(nbh); - __udf_read_inode(inode); - return; - } - brelse(nbh); - } - } - brelse(ibh); - } else if (fe->icbTag.strategyType != cpu_to_le16(4)) { - udf_err(inode->i_sb, "unsupported strategy type: %d\n", - le16_to_cpu(fe->icbTag.strategyType)); - brelse(bh); - make_bad_inode(inode); - return; - } - udf_fill_inode(inode, bh); - - brelse(bh); -} - -static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) -{ - struct fileEntry *fe; - struct extendedFileEntry *efe; - int offset; - struct udf_sb_info *sbi = UDF_SB(inode->i_sb); - struct udf_inode_info *iinfo = UDF_I(inode); - unsigned int link_count; - - fe = (struct fileEntry *)bh->b_data; - efe = (struct extendedFileEntry *)bh->b_data; - - if (fe->icbTag.strategyType == cpu_to_le16(4)) - iinfo->i_strat4096 = 0; - else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */ - iinfo->i_strat4096 = 1; - - iinfo->i_alloc_type = le16_to_cpu(fe->icbTag.flags) & - ICBTAG_FLAG_AD_MASK; - iinfo->i_unique = 0; - iinfo->i_lenEAttr = 0; - iinfo->i_lenExtents = 0; - iinfo->i_lenAlloc = 0; - iinfo->i_next_alloc_block = 0; - iinfo->i_next_alloc_goal = 0; - if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) { - iinfo->i_efe = 1; - iinfo->i_use = 0; - if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry))) { - make_bad_inode(inode); - return; - } - memcpy(iinfo->i_ext.i_data, - bh->b_data + sizeof(struct extendedFileEntry), - inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry)); - } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { - iinfo->i_efe = 0; - iinfo->i_use = 0; - if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - - sizeof(struct fileEntry))) { - make_bad_inode(inode); - return; - } - memcpy(iinfo->i_ext.i_data, - bh->b_data + sizeof(struct fileEntry), - inode->i_sb->s_blocksize - sizeof(struct fileEntry)); - } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { - iinfo->i_efe = 0; - iinfo->i_use = 1; - iinfo->i_lenAlloc = le32_to_cpu( - ((struct unallocSpaceEntry *)bh->b_data)-> - lengthAllocDescs); - if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - - sizeof(struct unallocSpaceEntry))) { - make_bad_inode(inode); - return; - } - memcpy(iinfo->i_ext.i_data, - bh->b_data + sizeof(struct unallocSpaceEntry), - inode->i_sb->s_blocksize - - sizeof(struct unallocSpaceEntry)); - return; - } - - read_lock(&sbi->s_cred_lock); - inode->i_uid = le32_to_cpu(fe->uid); - if (inode->i_uid == -1 || - UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) || - UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET)) - inode->i_uid = UDF_SB(inode->i_sb)->s_uid; - - inode->i_gid = le32_to_cpu(fe->gid); - if (inode->i_gid == -1 || - UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) || - UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET)) - inode->i_gid = UDF_SB(inode->i_sb)->s_gid; - - if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY && - sbi->s_fmode != UDF_INVALID_MODE) - inode->i_mode = sbi->s_fmode; - else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY && - sbi->s_dmode != UDF_INVALID_MODE) - inode->i_mode = sbi->s_dmode; - else - inode->i_mode = udf_convert_permissions(fe); - inode->i_mode &= ~sbi->s_umask; - read_unlock(&sbi->s_cred_lock); - - link_count = le16_to_cpu(fe->fileLinkCount); - if (!link_count) - link_count = 1; - set_nlink(inode, link_count); - - inode->i_size = le64_to_cpu(fe->informationLength); - iinfo->i_lenExtents = inode->i_size; - - if (iinfo->i_efe == 0) { - inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << - (inode->i_sb->s_blocksize_bits - 9); - - if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime)) - inode->i_atime = sbi->s_record_time; - - if (!udf_disk_stamp_to_time(&inode->i_mtime, - fe->modificationTime)) - inode->i_mtime = sbi->s_record_time; - - 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); - iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); - iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); - offset = sizeof(struct fileEntry) + iinfo->i_lenEAttr; - } else { - inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << - (inode->i_sb->s_blocksize_bits - 9); - - if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime)) - inode->i_atime = sbi->s_record_time; - - if (!udf_disk_stamp_to_time(&inode->i_mtime, - efe->modificationTime)) - inode->i_mtime = sbi->s_record_time; - - if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime)) - iinfo->i_crtime = sbi->s_record_time; - - 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); - iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); - iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); - offset = sizeof(struct extendedFileEntry) + - iinfo->i_lenEAttr; - } - - switch (fe->icbTag.fileType) { - case ICBTAG_FILE_TYPE_DIRECTORY: - inode->i_op = &udf_dir_inode_operations; - inode->i_fop = &udf_dir_operations; - inode->i_mode |= S_IFDIR; - inc_nlink(inode); - break; - 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 - inode->i_data.a_ops = &udf_aops; - inode->i_op = &udf_file_inode_operations; - inode->i_fop = &udf_file_operations; - inode->i_mode |= S_IFREG; - break; - case ICBTAG_FILE_TYPE_BLOCK: - inode->i_mode |= S_IFBLK; - break; - case ICBTAG_FILE_TYPE_CHAR: - inode->i_mode |= S_IFCHR; - break; - case ICBTAG_FILE_TYPE_FIFO: - init_special_inode(inode, inode->i_mode | S_IFIFO, 0); - break; - case ICBTAG_FILE_TYPE_SOCKET: - init_special_inode(inode, inode->i_mode | S_IFSOCK, 0); - break; - case ICBTAG_FILE_TYPE_SYMLINK: - inode->i_data.a_ops = &udf_symlink_aops; - inode->i_op = &udf_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: - udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n", - inode->i_ino, fe->icbTag.fileType); - make_bad_inode(inode); - return; - } - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - struct deviceSpec *dsea = - (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); - if (dsea) { - init_special_inode(inode, inode->i_mode, - MKDEV(le32_to_cpu(dsea->majorDeviceIdent), - le32_to_cpu(dsea->minorDeviceIdent))); - /* Developer ID ??? */ - } else - make_bad_inode(inode); - } -} - -static int udf_alloc_i_data(struct inode *inode, size_t size) -{ - struct udf_inode_info *iinfo = UDF_I(inode); - iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL); - - if (!iinfo->i_ext.i_data) { - udf_err(inode->i_sb, "(ino %ld) no free memory\n", - inode->i_ino); - return -ENOMEM; - } - - return 0; -} - -static umode_t udf_convert_permissions(struct fileEntry *fe) -{ - umode_t mode; - uint32_t permissions; - uint32_t flags; - - permissions = le32_to_cpu(fe->permissions); - flags = le16_to_cpu(fe->icbTag.flags); - - mode = ((permissions) & S_IRWXO) | - ((permissions >> 2) & S_IRWXG) | - ((permissions >> 4) & S_IRWXU) | - ((flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) | - ((flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) | - ((flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0); - - return mode; -} - -int udf_write_inode(struct inode *inode, struct writeback_control *wbc) -{ - return udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL); -} - -static int udf_sync_inode(struct inode *inode) -{ - return udf_update_inode(inode, 1); -} - -static int udf_update_inode(struct inode *inode, int do_sync) -{ - struct buffer_head *bh = NULL; - struct fileEntry *fe; - struct extendedFileEntry *efe; - uint64_t lb_recorded; - uint32_t udfperms; - uint16_t icbflags; - uint16_t crclen; - int err = 0; - struct udf_sb_info *sbi = UDF_SB(inode->i_sb); - unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; - struct udf_inode_info *iinfo = UDF_I(inode); - - bh = udf_tgetblk(inode->i_sb, - udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0)); - if (!bh) { - udf_debug("getblk failure\n"); - return -ENOMEM; - } - - lock_buffer(bh); - memset(bh->b_data, 0, inode->i_sb->s_blocksize); - fe = (struct fileEntry *)bh->b_data; - efe = (struct extendedFileEntry *)bh->b_data; - - if (iinfo->i_use) { - struct unallocSpaceEntry *use = - (struct unallocSpaceEntry *)bh->b_data; - - use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); - memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), - iinfo->i_ext.i_data, inode->i_sb->s_blocksize - - sizeof(struct unallocSpaceEntry)); - use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE); - use->descTag.tagLocation = - cpu_to_le32(iinfo->i_location.logicalBlockNum); - crclen = sizeof(struct unallocSpaceEntry) + - iinfo->i_lenAlloc - sizeof(struct tag); - use->descTag.descCRCLength = cpu_to_le16(crclen); - use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + - sizeof(struct tag), - crclen)); - use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); - - goto out; - } - - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET)) - fe->uid = cpu_to_le32(-1); - else - fe->uid = cpu_to_le32(inode->i_uid); - - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET)) - fe->gid = cpu_to_le32(-1); - else - fe->gid = cpu_to_le32(inode->i_gid); - - udfperms = ((inode->i_mode & S_IRWXO)) | - ((inode->i_mode & S_IRWXG) << 2) | - ((inode->i_mode & S_IRWXU) << 4); - - udfperms |= (le32_to_cpu(fe->permissions) & - (FE_PERM_O_DELETE | FE_PERM_O_CHATTR | - FE_PERM_G_DELETE | FE_PERM_G_CHATTR | - FE_PERM_U_DELETE | FE_PERM_U_CHATTR)); - fe->permissions = cpu_to_le32(udfperms); - - if (S_ISDIR(inode->i_mode)) - fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1); - else - fe->fileLinkCount = cpu_to_le16(inode->i_nlink); - - fe->informationLength = cpu_to_le64(inode->i_size); - - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - struct regid *eid; - struct deviceSpec *dsea = - (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); - if (!dsea) { - dsea = (struct deviceSpec *) - udf_add_extendedattr(inode, - sizeof(struct deviceSpec) + - sizeof(struct regid), 12, 0x3); - dsea->attrType = cpu_to_le32(12); - dsea->attrSubtype = 1; - dsea->attrLength = cpu_to_le32( - sizeof(struct deviceSpec) + - sizeof(struct regid)); - dsea->impUseLength = cpu_to_le32(sizeof(struct regid)); - } - eid = (struct regid *)dsea->impUse; - memset(eid, 0, sizeof(struct regid)); - strcpy(eid->ident, UDF_ID_DEVELOPER); - eid->identSuffix[0] = UDF_OS_CLASS_UNIX; - eid->identSuffix[1] = UDF_OS_ID_LINUX; - dsea->majorDeviceIdent = cpu_to_le32(imajor(inode)); - dsea->minorDeviceIdent = cpu_to_le32(iminor(inode)); - } - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - lb_recorded = 0; /* No extents => no blocks! */ - else - lb_recorded = - (inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >> - (blocksize_bits - 9); - - if (iinfo->i_efe == 0) { - memcpy(bh->b_data + sizeof(struct fileEntry), - iinfo->i_ext.i_data, - inode->i_sb->s_blocksize - sizeof(struct fileEntry)); - fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); - - 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(struct regid)); - strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); - fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; - fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - fe->uniqueID = cpu_to_le64(iinfo->i_unique); - fe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr); - fe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); - fe->checkpoint = cpu_to_le32(iinfo->i_checkpoint); - fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE); - crclen = sizeof(struct fileEntry); - } else { - memcpy(bh->b_data + sizeof(struct extendedFileEntry), - iinfo->i_ext.i_data, - inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry)); - efe->objectSize = cpu_to_le64(inode->i_size); - efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); - - if (iinfo->i_crtime.tv_sec > inode->i_atime.tv_sec || - (iinfo->i_crtime.tv_sec == inode->i_atime.tv_sec && - iinfo->i_crtime.tv_nsec > inode->i_atime.tv_nsec)) - iinfo->i_crtime = inode->i_atime; - - if (iinfo->i_crtime.tv_sec > inode->i_mtime.tv_sec || - (iinfo->i_crtime.tv_sec == inode->i_mtime.tv_sec && - iinfo->i_crtime.tv_nsec > inode->i_mtime.tv_nsec)) - iinfo->i_crtime = inode->i_mtime; - - if (iinfo->i_crtime.tv_sec > inode->i_ctime.tv_sec || - (iinfo->i_crtime.tv_sec == inode->i_ctime.tv_sec && - iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec)) - iinfo->i_crtime = inode->i_ctime; - - 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(struct regid)); - strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); - efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; - efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - efe->uniqueID = cpu_to_le64(iinfo->i_unique); - efe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr); - efe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); - efe->checkpoint = cpu_to_le32(iinfo->i_checkpoint); - efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE); - crclen = sizeof(struct extendedFileEntry); - } - if (iinfo->i_strat4096) { - fe->icbTag.strategyType = cpu_to_le16(4096); - fe->icbTag.strategyParameter = cpu_to_le16(1); - fe->icbTag.numEntries = cpu_to_le16(2); - } else { - fe->icbTag.strategyType = cpu_to_le16(4); - fe->icbTag.numEntries = cpu_to_le16(1); - } - - if (S_ISDIR(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY; - else if (S_ISREG(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR; - else if (S_ISLNK(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_SYMLINK; - else if (S_ISBLK(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_BLOCK; - else if (S_ISCHR(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR; - else if (S_ISFIFO(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO; - else if (S_ISSOCK(inode->i_mode)) - fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET; - - icbflags = iinfo->i_alloc_type | - ((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) | - ((inode->i_mode & S_ISGID) ? ICBTAG_FLAG_SETGID : 0) | - ((inode->i_mode & S_ISVTX) ? ICBTAG_FLAG_STICKY : 0) | - (le16_to_cpu(fe->icbTag.flags) & - ~(ICBTAG_FLAG_AD_MASK | ICBTAG_FLAG_SETUID | - ICBTAG_FLAG_SETGID | ICBTAG_FLAG_STICKY)); - - fe->icbTag.flags = cpu_to_le16(icbflags); - if (sbi->s_udfrev >= 0x0200) - fe->descTag.descVersion = cpu_to_le16(3); - else - fe->descTag.descVersion = cpu_to_le16(2); - fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number); - fe->descTag.tagLocation = cpu_to_le32( - iinfo->i_location.logicalBlockNum); - crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag); - fe->descTag.descCRCLength = cpu_to_le16(crclen); - fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag), - crclen)); - fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); - -out: - set_buffer_uptodate(bh); - unlock_buffer(bh); - - /* write the data blocks */ - mark_buffer_dirty(bh); - if (do_sync) { - sync_dirty_buffer(bh); - if (buffer_write_io_error(bh)) { - udf_warn(inode->i_sb, "IO error syncing udf inode [%08lx]\n", - inode->i_ino); - err = -EIO; - } - } - brelse(bh); - - return err; -} - -struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) -{ - unsigned long block = udf_get_lb_pblock(sb, ino, 0); - struct inode *inode = iget_locked(sb, block); - - if (!inode) - return NULL; - - if (inode->i_state & I_NEW) { - memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); - __udf_read_inode(inode); - unlock_new_inode(inode); - } - - if (is_bad_inode(inode)) - goto out_iput; - - if (ino->logicalBlockNum >= UDF_SB(sb)-> - s_partmaps[ino->partitionReferenceNum].s_partition_len) { - udf_debug("block=%d, partition=%d out of range\n", - ino->logicalBlockNum, ino->partitionReferenceNum); - make_bad_inode(inode); - goto out_iput; - } - - return inode; - - out_iput: - iput(inode); - return NULL; -} - -int udf_add_aext(struct inode *inode, struct extent_position *epos, - struct kernel_lb_addr *eloc, uint32_t elen, int inc) -{ - int adsize; - struct short_ad *sad = NULL; - struct long_ad *lad = NULL; - struct allocExtDesc *aed; - uint8_t *ptr; - struct udf_inode_info *iinfo = UDF_I(inode); - - if (!epos->bh) - ptr = iinfo->i_ext.i_data + epos->offset - - udf_file_entry_alloc_offset(inode) + - iinfo->i_lenEAttr; - else - ptr = epos->bh->b_data + epos->offset; - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - return -EIO; - - if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) { - unsigned char *sptr, *dptr; - struct buffer_head *nbh; - int err, loffset; - struct kernel_lb_addr obloc = epos->block; - - epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL, - obloc.partitionReferenceNum, - obloc.logicalBlockNum, &err); - if (!epos->block.logicalBlockNum) - return -ENOSPC; - nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, - &epos->block, - 0)); - if (!nbh) - return -EIO; - lock_buffer(nbh); - memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize); - set_buffer_uptodate(nbh); - unlock_buffer(nbh); - mark_buffer_dirty_inode(nbh, inode); - - aed = (struct allocExtDesc *)(nbh->b_data); - if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) - aed->previousAllocExtLocation = - cpu_to_le32(obloc.logicalBlockNum); - if (epos->offset + adsize > inode->i_sb->s_blocksize) { - loffset = epos->offset; - aed->lengthAllocDescs = cpu_to_le32(adsize); - sptr = ptr - adsize; - dptr = nbh->b_data + sizeof(struct allocExtDesc); - memcpy(dptr, sptr, adsize); - epos->offset = sizeof(struct allocExtDesc) + adsize; - } else { - loffset = epos->offset + adsize; - aed->lengthAllocDescs = cpu_to_le32(0); - sptr = ptr; - epos->offset = sizeof(struct allocExtDesc); - - if (epos->bh) { - aed = (struct allocExtDesc *)epos->bh->b_data; - le32_add_cpu(&aed->lengthAllocDescs, adsize); - } else { - iinfo->i_lenAlloc += adsize; - mark_inode_dirty(inode); - } - } - if (UDF_SB(inode->i_sb)->s_udfrev >= 0x0200) - udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1, - epos->block.logicalBlockNum, sizeof(struct tag)); - else - udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1, - epos->block.logicalBlockNum, sizeof(struct tag)); - switch (iinfo->i_alloc_type) { - case ICBTAG_FLAG_AD_SHORT: - sad = (struct short_ad *)sptr; - sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | - inode->i_sb->s_blocksize); - sad->extPosition = - cpu_to_le32(epos->block.logicalBlockNum); - break; - case ICBTAG_FLAG_AD_LONG: - lad = (struct long_ad *)sptr; - lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | - inode->i_sb->s_blocksize); - lad->extLocation = cpu_to_lelb(epos->block); - memset(lad->impUse, 0x00, sizeof(lad->impUse)); - break; - } - if (epos->bh) { - 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, loffset); - else - udf_update_tag(epos->bh->b_data, - sizeof(struct allocExtDesc)); - mark_buffer_dirty_inode(epos->bh, inode); - brelse(epos->bh); - } else { - mark_inode_dirty(inode); - } - epos->bh = nbh; - } - - udf_write_aext(inode, epos, eloc, elen, inc); - - if (!epos->bh) { - iinfo->i_lenAlloc += adsize; - mark_inode_dirty(inode); - } else { - aed = (struct allocExtDesc *)epos->bh->b_data; - 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, - epos->offset + (inc ? 0 : adsize)); - else - udf_update_tag(epos->bh->b_data, - sizeof(struct allocExtDesc)); - mark_buffer_dirty_inode(epos->bh, inode); - } - - return 0; -} - -void udf_write_aext(struct inode *inode, struct extent_position *epos, - struct kernel_lb_addr *eloc, uint32_t elen, int inc) -{ - int adsize; - uint8_t *ptr; - struct short_ad *sad; - struct long_ad *lad; - struct udf_inode_info *iinfo = UDF_I(inode); - - if (!epos->bh) - ptr = iinfo->i_ext.i_data + epos->offset - - udf_file_entry_alloc_offset(inode) + - iinfo->i_lenEAttr; - else - ptr = epos->bh->b_data + epos->offset; - - switch (iinfo->i_alloc_type) { - case ICBTAG_FLAG_AD_SHORT: - sad = (struct short_ad *)ptr; - sad->extLength = cpu_to_le32(elen); - sad->extPosition = cpu_to_le32(eloc->logicalBlockNum); - adsize = sizeof(struct short_ad); - break; - case ICBTAG_FLAG_AD_LONG: - lad = (struct long_ad *)ptr; - lad->extLength = cpu_to_le32(elen); - lad->extLocation = cpu_to_lelb(*eloc); - memset(lad->impUse, 0x00, sizeof(lad->impUse)); - adsize = sizeof(struct long_ad); - break; - default: - return; - } - - if (epos->bh) { - if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || - UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) { - struct allocExtDesc *aed = - (struct allocExtDesc *)epos->bh->b_data; - udf_update_tag(epos->bh->b_data, - le32_to_cpu(aed->lengthAllocDescs) + - sizeof(struct allocExtDesc)); - } - mark_buffer_dirty_inode(epos->bh, inode); - } else { - mark_inode_dirty(inode); - } - - if (inc) - epos->offset += adsize; -} - -int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, - struct kernel_lb_addr *eloc, uint32_t *elen, int inc) -{ - int8_t etype; - - while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) == - (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { - int block; - epos->block = *eloc; - epos->offset = sizeof(struct allocExtDesc); - brelse(epos->bh); - block = udf_get_lb_pblock(inode->i_sb, &epos->block, 0); - epos->bh = udf_tread(inode->i_sb, block); - if (!epos->bh) { - udf_debug("reading block %d failed!\n", block); - return -1; - } - } - - return etype; -} - -int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, - struct kernel_lb_addr *eloc, uint32_t *elen, int inc) -{ - int alen; - int8_t etype; - uint8_t *ptr; - struct short_ad *sad; - struct long_ad *lad; - struct udf_inode_info *iinfo = UDF_I(inode); - - if (!epos->bh) { - if (!epos->offset) - epos->offset = udf_file_entry_alloc_offset(inode); - ptr = iinfo->i_ext.i_data + epos->offset - - udf_file_entry_alloc_offset(inode) + - iinfo->i_lenEAttr; - alen = udf_file_entry_alloc_offset(inode) + - iinfo->i_lenAlloc; - } else { - if (!epos->offset) - epos->offset = sizeof(struct allocExtDesc); - ptr = epos->bh->b_data + epos->offset; - alen = sizeof(struct allocExtDesc) + - le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)-> - lengthAllocDescs); - } - - switch (iinfo->i_alloc_type) { - case ICBTAG_FLAG_AD_SHORT: - sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc); - if (!sad) - return -1; - etype = le32_to_cpu(sad->extLength) >> 30; - eloc->logicalBlockNum = le32_to_cpu(sad->extPosition); - eloc->partitionReferenceNum = - iinfo->i_location.partitionReferenceNum; - *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK; - break; - case ICBTAG_FLAG_AD_LONG: - lad = udf_get_filelongad(ptr, alen, &epos->offset, inc); - if (!lad) - return -1; - etype = le32_to_cpu(lad->extLength) >> 30; - *eloc = lelb_to_cpu(lad->extLocation); - *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK; - break; - default: - udf_debug("alloc_type = %d unsupported\n", iinfo->i_alloc_type); - return -1; - } - - return etype; -} - -static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, - struct kernel_lb_addr neloc, uint32_t nelen) -{ - struct kernel_lb_addr oeloc; - uint32_t oelen; - int8_t etype; - - if (epos.bh) - get_bh(epos.bh); - - while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) { - udf_write_aext(inode, &epos, &neloc, nelen, 1); - neloc = oeloc; - nelen = (etype << 30) | oelen; - } - udf_add_aext(inode, &epos, &neloc, nelen, 1); - brelse(epos.bh); - - return (nelen >> 30); -} - -int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, - struct kernel_lb_addr eloc, uint32_t elen) -{ - struct extent_position oepos; - int adsize; - int8_t etype; - struct allocExtDesc *aed; - struct udf_inode_info *iinfo; - - if (epos.bh) { - get_bh(epos.bh); - get_bh(epos.bh); - } - - iinfo = UDF_I(inode); - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - adsize = 0; - - oepos = epos; - if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1) - return -1; - - while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { - udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1); - if (oepos.bh != epos.bh) { - oepos.block = epos.block; - brelse(oepos.bh); - get_bh(epos.bh); - oepos.bh = epos.bh; - oepos.offset = epos.offset - adsize; - } - } - memset(&eloc, 0x00, sizeof(struct kernel_lb_addr)); - elen = 0; - - if (epos.bh != oepos.bh) { - udf_free_blocks(inode->i_sb, inode, &epos.block, 0, 1); - udf_write_aext(inode, &oepos, &eloc, elen, 1); - udf_write_aext(inode, &oepos, &eloc, elen, 1); - if (!oepos.bh) { - iinfo->i_lenAlloc -= (adsize * 2); - mark_inode_dirty(inode); - } else { - aed = (struct allocExtDesc *)oepos.bh->b_data; - 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, - oepos.offset - (2 * adsize)); - else - udf_update_tag(oepos.bh->b_data, - sizeof(struct allocExtDesc)); - mark_buffer_dirty_inode(oepos.bh, inode); - } - } else { - udf_write_aext(inode, &oepos, &eloc, elen, 1); - if (!oepos.bh) { - iinfo->i_lenAlloc -= adsize; - mark_inode_dirty(inode); - } else { - aed = (struct allocExtDesc *)oepos.bh->b_data; - 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, - epos.offset - adsize); - else - udf_update_tag(oepos.bh->b_data, - sizeof(struct allocExtDesc)); - mark_buffer_dirty_inode(oepos.bh, inode); - } - } - - brelse(epos.bh); - brelse(oepos.bh); - - return (elen >> 30); -} - -int8_t inode_bmap(struct inode *inode, sector_t block, - struct extent_position *pos, struct kernel_lb_addr *eloc, - uint32_t *elen, sector_t *offset) -{ - unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; - loff_t lbcount = 0, bcount = - (loff_t) block << blocksize_bits; - int8_t etype; - struct udf_inode_info *iinfo; - - iinfo = UDF_I(inode); - pos->offset = 0; - pos->block = iinfo->i_location; - pos->bh = NULL; - *elen = 0; - - do { - etype = udf_next_aext(inode, pos, eloc, elen, 1); - if (etype == -1) { - *offset = (bcount - lbcount) >> blocksize_bits; - iinfo->i_lenExtents = lbcount; - return -1; - } - lbcount += *elen; - } while (lbcount <= bcount); - - *offset = (bcount + *elen - lbcount) >> blocksize_bits; - - return etype; -} - -long udf_block_map(struct inode *inode, sector_t block) -{ - struct kernel_lb_addr eloc; - uint32_t elen; - sector_t offset; - struct extent_position epos = {}; - int ret; - - down_read(&UDF_I(inode)->i_data_sem); - - if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == - (EXT_RECORDED_ALLOCATED >> 30)) - ret = udf_get_lb_pblock(inode->i_sb, &eloc, offset); - else - ret = 0; - - up_read(&UDF_I(inode)->i_data_sem); - brelse(epos.bh); - - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV)) - return udf_fixed_to_variable(ret); - else - return ret; -} diff --git a/ANDROID_3.4.5/fs/udf/lowlevel.c b/ANDROID_3.4.5/fs/udf/lowlevel.c deleted file mode 100644 index 6583fe9b..00000000 --- a/ANDROID_3.4.5/fs/udf/lowlevel.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * lowlevel.c - * - * PURPOSE - * Low Level Device Routines for the UDF filesystem - * - * 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-2001 Ben Fennema - * - * HISTORY - * - * 03/26/99 blf Created. - */ - -#include "udfdecl.h" - -#include <linux/blkdev.h> -#include <linux/cdrom.h> -#include <asm/uaccess.h> - -#include "udf_sb.h" - -unsigned int udf_get_last_session(struct super_block *sb) -{ - struct cdrom_multisession ms_info; - unsigned int vol_desc_start; - struct block_device *bdev = sb->s_bdev; - int i; - - vol_desc_start = 0; - ms_info.addr_format = CDROM_LBA; - i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long)&ms_info); - - if (i == 0) { - udf_debug("XA disk: %s, vol_desc_start=%d\n", - ms_info.xa_flag ? "yes" : "no", ms_info.addr.lba); - if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ - vol_desc_start = ms_info.addr.lba; - } else { - udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i); - } - return vol_desc_start; -} - -unsigned long udf_get_last_block(struct super_block *sb) -{ - struct block_device *bdev = sb->s_bdev; - unsigned long lblock = 0; - - /* - * ioctl failed or returned obviously bogus value? - * Try using the device size... - */ - if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock) || - lblock == 0) - lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits; - - if (lblock) - return lblock - 1; - else - return 0; -} diff --git a/ANDROID_3.4.5/fs/udf/misc.c b/ANDROID_3.4.5/fs/udf/misc.c deleted file mode 100644 index c175b4da..00000000 --- a/ANDROID_3.4.5/fs/udf/misc.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * misc.c - * - * PURPOSE - * Miscellaneous routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998 Dave Boynton - * (C) 1998-2004 Ben Fennema - * (C) 1999-2000 Stelias Computing Inc - * - * HISTORY - * - * 04/19/99 blf partial support for reading/writing specific EA's - */ - -#include "udfdecl.h" - -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/buffer_head.h> -#include <linux/crc-itu-t.h> - -#include "udf_i.h" -#include "udf_sb.h" - -struct buffer_head *udf_tgetblk(struct super_block *sb, int block) -{ - if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) - return sb_getblk(sb, udf_fixed_to_variable(block)); - else - return sb_getblk(sb, block); -} - -struct buffer_head *udf_tread(struct super_block *sb, int block) -{ - if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) - return sb_bread(sb, udf_fixed_to_variable(block)); - else - return sb_bread(sb, block); -} - -struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, - uint32_t type, uint8_t loc) -{ - uint8_t *ea = NULL, *ad = NULL; - int offset; - uint16_t crclen; - struct udf_inode_info *iinfo = UDF_I(inode); - - ea = iinfo->i_ext.i_data; - if (iinfo->i_lenEAttr) { - ad = iinfo->i_ext.i_data + iinfo->i_lenEAttr; - } else { - ad = ea; - size += sizeof(struct extendedAttrHeaderDesc); - } - - offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) - - iinfo->i_lenAlloc; - - /* TODO - Check for FreeEASpace */ - - if (loc & 0x01 && offset >= size) { - struct extendedAttrHeaderDesc *eahd; - eahd = (struct extendedAttrHeaderDesc *)ea; - - if (iinfo->i_lenAlloc) - memmove(&ad[size], ad, iinfo->i_lenAlloc); - - if (iinfo->i_lenEAttr) { - /* check checksum/crc */ - if (eahd->descTag.tagIdent != - cpu_to_le16(TAG_IDENT_EAHD) || - le32_to_cpu(eahd->descTag.tagLocation) != - iinfo->i_location.logicalBlockNum) - return NULL; - } else { - struct udf_sb_info *sbi = UDF_SB(inode->i_sb); - - size -= sizeof(struct extendedAttrHeaderDesc); - iinfo->i_lenEAttr += - sizeof(struct extendedAttrHeaderDesc); - eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD); - if (sbi->s_udfrev >= 0x0200) - eahd->descTag.descVersion = cpu_to_le16(3); - else - eahd->descTag.descVersion = cpu_to_le16(2); - eahd->descTag.tagSerialNum = - cpu_to_le16(sbi->s_serial_number); - eahd->descTag.tagLocation = cpu_to_le32( - iinfo->i_location.logicalBlockNum); - eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF); - eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF); - } - - offset = iinfo->i_lenEAttr; - if (type < 2048) { - if (le32_to_cpu(eahd->appAttrLocation) < - iinfo->i_lenEAttr) { - uint32_t aal = - le32_to_cpu(eahd->appAttrLocation); - memmove(&ea[offset - aal + size], - &ea[aal], offset - aal); - offset -= aal; - eahd->appAttrLocation = - cpu_to_le32(aal + size); - } - if (le32_to_cpu(eahd->impAttrLocation) < - iinfo->i_lenEAttr) { - uint32_t ial = - le32_to_cpu(eahd->impAttrLocation); - memmove(&ea[offset - ial + size], - &ea[ial], offset - ial); - offset -= ial; - eahd->impAttrLocation = - cpu_to_le32(ial + size); - } - } else if (type < 65536) { - if (le32_to_cpu(eahd->appAttrLocation) < - iinfo->i_lenEAttr) { - uint32_t aal = - le32_to_cpu(eahd->appAttrLocation); - memmove(&ea[offset - aal + size], - &ea[aal], offset - aal); - offset -= aal; - eahd->appAttrLocation = - cpu_to_le32(aal + size); - } - } - /* rewrite CRC + checksum of eahd */ - crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(struct tag); - eahd->descTag.descCRCLength = cpu_to_le16(crclen); - eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd + - sizeof(struct tag), crclen)); - eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); - iinfo->i_lenEAttr += size; - return (struct genericFormat *)&ea[offset]; - } - if (loc & 0x02) - ; - - return NULL; -} - -struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, - uint8_t subtype) -{ - struct genericFormat *gaf; - uint8_t *ea = NULL; - uint32_t offset; - struct udf_inode_info *iinfo = UDF_I(inode); - - ea = iinfo->i_ext.i_data; - - if (iinfo->i_lenEAttr) { - struct extendedAttrHeaderDesc *eahd; - eahd = (struct extendedAttrHeaderDesc *)ea; - - /* check checksum/crc */ - if (eahd->descTag.tagIdent != - cpu_to_le16(TAG_IDENT_EAHD) || - le32_to_cpu(eahd->descTag.tagLocation) != - iinfo->i_location.logicalBlockNum) - return NULL; - - if (type < 2048) - offset = sizeof(struct extendedAttrHeaderDesc); - else if (type < 65536) - offset = le32_to_cpu(eahd->impAttrLocation); - else - offset = le32_to_cpu(eahd->appAttrLocation); - - while (offset < iinfo->i_lenEAttr) { - gaf = (struct genericFormat *)&ea[offset]; - if (le32_to_cpu(gaf->attrType) == type && - gaf->attrSubtype == subtype) - return gaf; - else - offset += le32_to_cpu(gaf->attrLength); - } - } - - return NULL; -} - -/* - * udf_read_tagged - * - * PURPOSE - * Read the first block of a tagged descriptor. - * - * HISTORY - * July 1, 1997 - Andrew E. Mileski - * Written, tested, and released. - */ -struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, - uint32_t location, uint16_t *ident) -{ - struct tag *tag_p; - struct buffer_head *bh = NULL; - u8 checksum; - - /* Read the block */ - if (block == 0xFFFFFFFF) - return NULL; - - bh = udf_tread(sb, block); - if (!bh) { - udf_err(sb, "read failed, block=%u, location=%d\n", - block, location); - return NULL; - } - - tag_p = (struct tag *)(bh->b_data); - - *ident = le16_to_cpu(tag_p->tagIdent); - - 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); - goto error_out; - } - - /* Verify the tag checksum */ - checksum = udf_tag_checksum(tag_p); - if (checksum != tag_p->tagChecksum) { - udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n", - block, checksum, tag_p->tagChecksum); - goto error_out; - } - - /* Verify the tag version */ - if (tag_p->descVersion != cpu_to_le16(0x0002U) && - tag_p->descVersion != cpu_to_le16(0x0003U)) { - udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n", - le16_to_cpu(tag_p->descVersion), block); - goto error_out; - } - - /* Verify the descriptor CRC */ - if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize || - le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, - bh->b_data + sizeof(struct tag), - le16_to_cpu(tag_p->descCRCLength))) - 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)); -error_out: - brelse(bh); - return NULL; -} - -struct buffer_head *udf_read_ptagged(struct super_block *sb, - struct kernel_lb_addr *loc, - uint32_t offset, uint16_t *ident) -{ - return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), - loc->logicalBlockNum + offset, ident); -} - -void udf_update_tag(char *data, int length) -{ - struct tag *tptr = (struct tag *)data; - length -= sizeof(struct tag); - - tptr->descCRCLength = cpu_to_le16(length); - tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(struct tag), length)); - tptr->tagChecksum = udf_tag_checksum(tptr); -} - -void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, - uint32_t loc, int length) -{ - struct tag *tptr = (struct tag *)data; - tptr->tagIdent = cpu_to_le16(ident); - tptr->descVersion = cpu_to_le16(version); - tptr->tagSerialNum = cpu_to_le16(snum); - tptr->tagLocation = cpu_to_le32(loc); - udf_update_tag(data, length); -} - -u8 udf_tag_checksum(const struct tag *t) -{ - u8 *data = (u8 *)t; - u8 checksum = 0; - int i; - for (i = 0; i < sizeof(struct tag); ++i) - if (i != 4) /* position of checksum */ - checksum += data[i]; - return checksum; -} diff --git a/ANDROID_3.4.5/fs/udf/namei.c b/ANDROID_3.4.5/fs/udf/namei.c deleted file mode 100644 index 38de8f23..00000000 --- a/ANDROID_3.4.5/fs/udf/namei.c +++ /dev/null @@ -1,1322 +0,0 @@ -/* - * namei.c - * - * PURPOSE - * Inode name handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998-2004 Ben Fennema - * (C) 1999-2000 Stelias Computing Inc - * - * HISTORY - * - * 12/12/98 blf Created. Split out the lookup code from dir.c - * 04/19/99 blf link, mknod, symlink support - */ - -#include "udfdecl.h" - -#include "udf_i.h" -#include "udf_sb.h" -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/buffer_head.h> -#include <linux/sched.h> -#include <linux/crc-itu-t.h> -#include <linux/exportfs.h> - -static inline int udf_match(int len1, const unsigned char *name1, int len2, - const unsigned char *name2) -{ - if (len1 != len2) - return 0; - - return !memcmp(name1, name2, len1); -} - -int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, - struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh, - uint8_t *impuse, uint8_t *fileident) -{ - uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(struct tag); - uint16_t crc; - int offset; - uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse); - uint8_t lfi = cfi->lengthFileIdent; - int padlen = fibh->eoffset - fibh->soffset - liu - lfi - - sizeof(struct fileIdentDesc); - int adinicb = 0; - - if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - adinicb = 1; - - offset = fibh->soffset + sizeof(struct fileIdentDesc); - - if (impuse) { - if (adinicb || (offset + liu < 0)) { - memcpy((uint8_t *)sfi->impUse, impuse, liu); - } else if (offset >= 0) { - memcpy(fibh->ebh->b_data + offset, impuse, liu); - } else { - memcpy((uint8_t *)sfi->impUse, impuse, -offset); - memcpy(fibh->ebh->b_data, impuse - offset, - liu + offset); - } - } - - offset += liu; - - if (fileident) { - 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); - } else { - memcpy((uint8_t *)sfi->fileIdent + liu, fileident, - -offset); - memcpy(fibh->ebh->b_data, fileident - offset, - lfi + offset); - } - } - - offset += lfi; - - 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); - } else { - memset((uint8_t *)sfi->padding + liu + lfi, 0x00, -offset); - memset(fibh->ebh->b_data, 0x00, padlen + offset); - } - - crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(struct tag), - sizeof(struct fileIdentDesc) - sizeof(struct tag)); - - if (fibh->sbh == fibh->ebh) { - crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, - crclen + sizeof(struct tag) - - sizeof(struct fileIdentDesc)); - } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { - crc = crc_itu_t(crc, fibh->ebh->b_data + - sizeof(struct fileIdentDesc) + - fibh->soffset, - crclen + sizeof(struct tag) - - sizeof(struct fileIdentDesc)); - } else { - 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); - cfi->descTag.descCRCLength = cpu_to_le16(crclen); - cfi->descTag.tagChecksum = udf_tag_checksum(&cfi->descTag); - - if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset)) { - memcpy((uint8_t *)sfi, (uint8_t *)cfi, - sizeof(struct fileIdentDesc)); - } else { - memcpy((uint8_t *)sfi, (uint8_t *)cfi, -fibh->soffset); - memcpy(fibh->ebh->b_data, (uint8_t *)cfi - fibh->soffset, - sizeof(struct fileIdentDesc) + fibh->soffset); - } - - 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; -} - -static struct fileIdentDesc *udf_find_entry(struct inode *dir, - const struct qstr *child, - struct udf_fileident_bh *fibh, - struct fileIdentDesc *cfi) -{ - struct fileIdentDesc *fi = NULL; - loff_t f_pos; - int block, flen; - unsigned char *fname = NULL; - unsigned char *nameptr; - uint8_t lfi; - uint16_t liu; - loff_t size; - struct kernel_lb_addr eloc; - uint32_t elen; - sector_t offset; - struct extent_position epos = {}; - struct udf_inode_info *dinfo = UDF_I(dir); - int isdotdot = child->len == 2 && - child->name[0] == '.' && child->name[1] == '.'; - - size = udf_ext0_offset(dir) + dir->i_size; - f_pos = udf_ext0_offset(dir); - - fibh->sbh = fibh->ebh = NULL; - 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) - epos.offset -= sizeof(struct short_ad); - else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - } else - offset = 0; - - fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); - 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) - 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 = (uint8_t *)(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 (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE)) - continue; - } - - if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { - if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE)) - continue; - } - - if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) && - isdotdot) - goto out_ok; - - if (!lfi) - continue; - - flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); - if (flen && udf_match(flen, fname, child->len, child->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 fi; -} - -static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) -{ - struct inode *inode = NULL; - struct fileIdentDesc cfi; - struct udf_fileident_bh fibh; - - if (dentry->d_name.len > UDF_NAME_LEN - 2) - return ERR_PTR(-ENAMETOOLONG); - -#ifdef UDF_RECOVERY - /* temporary shorthand for specifying files by inode number */ - if (!strncmp(dentry->d_name.name, ".B=", 3)) { - struct kernel_lb_addr lb = { - .logicalBlockNum = 0, - .partitionReferenceNum = - simple_strtoul(dentry->d_name.name + 3, - NULL, 0), - }; - inode = udf_iget(dir->i_sb, lb); - if (!inode) { - return ERR_PTR(-EACCES); - } - } else -#endif /* UDF_RECOVERY */ - - if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) { - struct kernel_lb_addr loc; - - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - - loc = lelb_to_cpu(cfi.icb.extLocation); - inode = udf_iget(dir->i_sb, &loc); - if (!inode) { - return ERR_PTR(-EACCES); - } - } - - return d_splice_alias(inode, dentry); -} - -static struct fileIdentDesc *udf_add_entry(struct inode *dir, - struct dentry *dentry, - struct udf_fileident_bh *fibh, - struct fileIdentDesc *cfi, int *err) -{ - struct super_block *sb = dir->i_sb; - struct fileIdentDesc *fi = NULL; - unsigned char *name = NULL; - int namelen; - loff_t f_pos; - loff_t size = udf_ext0_offset(dir) + dir->i_size; - int nfidlen; - uint8_t lfi; - uint16_t liu; - int block; - struct kernel_lb_addr eloc; - uint32_t elen = 0; - sector_t offset; - 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; - goto out_err; - } - namelen = udf_put_filename(sb, dentry->d_name.name, name, - dentry->d_name.len); - if (!namelen) { - *err = -ENAMETOOLONG; - goto out_err; - } - } else { - namelen = 0; - } - - nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3; - - f_pos = udf_ext0_offset(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) { - 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) - epos.offset -= sizeof(struct short_ad); - else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - } else - offset = 0; - - fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); - if (!fibh->sbh) { - *err = -EIO; - goto out_err; - } - - block = dinfo->i_location.logicalBlockNum; - } - - while (f_pos < size) { - fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, - &elen, &offset); - - if (!fi) { - *err = -EIO; - goto out_err; - } - - liu = le16_to_cpu(cfi->lengthOfImpUse); - lfi = cfi->lengthFileIdent; - - if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { - if (((sizeof(struct fileIdentDesc) + - liu + lfi + 3) & ~3) == nfidlen) { - 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)) - goto out_ok; - else { - *err = -EIO; - goto out_err; - } - } - } - } - -add: - f_pos += nfidlen; - - if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && - sb->s_blocksize - fibh->eoffset < nfidlen) { - brelse(epos.bh); - epos.bh = NULL; - fibh->soffset -= udf_ext0_offset(dir); - fibh->eoffset -= udf_ext0_offset(dir); - f_pos -= udf_ext0_offset(dir); - if (fibh->sbh != fibh->ebh) - brelse(fibh->ebh); - brelse(fibh->sbh); - fibh->sbh = fibh->ebh = - udf_expand_dir_adinicb(dir, &block, err); - if (!fibh->sbh) - goto out_err; - epos.block = dinfo->i_location; - epos.offset = udf_file_entry_alloc_offset(dir); - /* Load extent udf_expand_dir_adinicb() has created */ - udf_current_aext(dir, &epos, &eloc, &elen, 1); - } - - /* Entry fits into current block? */ - if (sb->s_blocksize - fibh->eoffset >= nfidlen) { - fibh->soffset = fibh->eoffset; - fibh->eoffset += nfidlen; - if (fibh->sbh != fibh->ebh) { - brelse(fibh->sbh); - fibh->sbh = fibh->ebh; - } - - if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - block = dinfo->i_location.logicalBlockNum; - fi = (struct fileIdentDesc *) - (dinfo->i_ext.i_data + - fibh->soffset - - udf_ext0_offset(dir) + - dinfo->i_lenEAttr); - } else { - block = eloc.logicalBlockNum + - ((elen - 1) >> - dir->i_sb->s_blocksize_bits); - fi = (struct fileIdentDesc *) - (fibh->sbh->b_data + fibh->soffset); - } - } else { - /* Round up last extent in the file */ - elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); - if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(struct short_ad); - else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - udf_write_aext(dir, &epos, &eloc, elen, 1); - dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize - - 1) & ~(sb->s_blocksize - 1); - - fibh->soffset = fibh->eoffset - sb->s_blocksize; - fibh->eoffset += nfidlen - sb->s_blocksize; - if (fibh->sbh != fibh->ebh) { - brelse(fibh->sbh); - fibh->sbh = fibh->ebh; - } - - block = eloc.logicalBlockNum + ((elen - 1) >> - dir->i_sb->s_blocksize_bits); - fibh->ebh = udf_bread(dir, - f_pos >> dir->i_sb->s_blocksize_bits, 1, err); - if (!fibh->ebh) - goto out_err; - /* Extents could have been merged, invalidate our position */ - brelse(epos.bh); - epos.bh = NULL; - epos.block = dinfo->i_location; - epos.offset = udf_file_entry_alloc_offset(dir); - - if (!fibh->soffset) { - /* Find the freshly allocated block */ - while (udf_next_aext(dir, &epos, &eloc, &elen, 1) == - (EXT_RECORDED_ALLOCATED >> 30)) - ; - block = eloc.logicalBlockNum + ((elen - 1) >> - dir->i_sb->s_blocksize_bits); - brelse(fibh->sbh); - fibh->sbh = fibh->ebh; - fi = (struct fileIdentDesc *)(fibh->sbh->b_data); - } else { - fi = (struct fileIdentDesc *) - (fibh->sbh->b_data + sb->s_blocksize + - fibh->soffset); - } - } - - memset(cfi, 0, sizeof(struct fileIdentDesc)); - if (UDF_SB(sb)->s_udfrev >= 0x0200) - udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, - sizeof(struct tag)); - else - udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, - sizeof(struct tag)); - cfi->fileVersionNum = cpu_to_le16(1); - cfi->lengthFileIdent = namelen; - cfi->lengthOfImpUse = cpu_to_le16(0); - if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { - dir->i_size += nfidlen; - if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - dinfo->i_lenAlloc += nfidlen; - else { - /* Find the last extent and truncate it to proper size */ - while (udf_next_aext(dir, &epos, &eloc, &elen, 1) == - (EXT_RECORDED_ALLOCATED >> 30)) - ; - elen -= dinfo->i_lenExtents - dir->i_size; - if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(struct short_ad); - else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - udf_write_aext(dir, &epos, &eloc, elen, 1); - dinfo->i_lenExtents = dir->i_size; - } - - mark_inode_dirty(dir); - goto out_ok; - } else { - *err = -EIO; - goto out_err; - } - -out_err: - fi = NULL; - if (fibh->sbh != fibh->ebh) - brelse(fibh->ebh); - brelse(fibh->sbh); -out_ok: - brelse(epos.bh); - kfree(name); - return fi; -} - -static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, - struct udf_fileident_bh *fibh, - struct fileIdentDesc *cfi) -{ - cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED; - - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) - memset(&(cfi->icb), 0x00, sizeof(struct long_ad)); - - return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); -} - -static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, - struct nameidata *nd) -{ - struct udf_fileident_bh fibh; - struct inode *inode; - struct fileIdentDesc cfi, *fi; - int err; - struct udf_inode_info *iinfo; - - inode = udf_new_inode(dir, mode, &err); - if (!inode) { - return err; - } - - iinfo = UDF_I(inode); - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - inode->i_data.a_ops = &udf_adinicb_aops; - else - inode->i_data.a_ops = &udf_aops; - inode->i_op = &udf_file_inode_operations; - inode->i_fop = &udf_file_operations; - mark_inode_dirty(inode); - - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); - if (!fi) { - inode_dec_link_count(inode); - iput(inode); - return err; - } - cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); - cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = - cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); - if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - mark_inode_dirty(dir); - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - d_instantiate(dentry, inode); - - return 0; -} - -static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t rdev) -{ - struct inode *inode; - struct udf_fileident_bh fibh; - struct fileIdentDesc cfi, *fi; - int err; - struct udf_inode_info *iinfo; - - if (!old_valid_dev(rdev)) - return -EINVAL; - - err = -EIO; - inode = udf_new_inode(dir, mode, &err); - if (!inode) - goto out; - - iinfo = UDF_I(inode); - init_special_inode(inode, mode, rdev); - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); - if (!fi) { - inode_dec_link_count(inode); - iput(inode); - return err; - } - cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); - cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = - cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); - if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - mark_inode_dirty(dir); - mark_inode_dirty(inode); - - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - d_instantiate(dentry, inode); - err = 0; - -out: - return err; -} - -static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - struct inode *inode; - struct udf_fileident_bh fibh; - struct fileIdentDesc cfi, *fi; - int err; - struct udf_inode_info *dinfo = UDF_I(dir); - struct udf_inode_info *iinfo; - - err = -EIO; - inode = udf_new_inode(dir, S_IFDIR | mode, &err); - if (!inode) - goto out; - - iinfo = UDF_I(inode); - inode->i_op = &udf_dir_inode_operations; - inode->i_fop = &udf_dir_operations; - fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err); - if (!fi) { - inode_dec_link_count(inode); - iput(inode); - goto out; - } - set_nlink(inode, 2); - cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); - cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location); - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = - cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL); - cfi.fileCharacteristics = - FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT; - udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL); - brelse(fibh.sbh); - mark_inode_dirty(inode); - - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); - if (!fi) { - clear_nlink(inode); - mark_inode_dirty(inode); - iput(inode); - goto out; - } - cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); - cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = - cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); - cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY; - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); - inc_nlink(dir); - mark_inode_dirty(dir); - d_instantiate(dentry, inode); - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - err = 0; - -out: - return err; -} - -static int empty_dir(struct inode *dir) -{ - struct fileIdentDesc *fi, cfi; - struct udf_fileident_bh fibh; - loff_t f_pos; - loff_t size = udf_ext0_offset(dir) + dir->i_size; - int block; - struct kernel_lb_addr eloc; - uint32_t elen; - sector_t offset; - struct extent_position epos = {}; - struct udf_inode_info *dinfo = UDF_I(dir); - - 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)) { - 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) - epos.offset -= sizeof(struct short_ad); - else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(struct long_ad); - } else - offset = 0; - - fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block); - if (!fibh.sbh) { - brelse(epos.bh); - return 0; - } - } else { - brelse(epos.bh); - return 0; - } - - 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 0; - } - - if (cfi.lengthFileIdent && - (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) { - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - brelse(epos.bh); - return 0; - } - } - - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - brelse(epos.bh); - - return 1; -} - -static int udf_rmdir(struct inode *dir, struct dentry *dentry) -{ - int retval; - struct inode *inode = dentry->d_inode; - struct udf_fileident_bh fibh; - struct fileIdentDesc *fi, cfi; - struct kernel_lb_addr tloc; - - retval = -ENOENT; - fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); - if (!fi) - goto out; - - retval = -EIO; - tloc = lelb_to_cpu(cfi.icb.extLocation); - if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino) - goto end_rmdir; - retval = -ENOTEMPTY; - if (!empty_dir(inode)) - goto end_rmdir; - retval = udf_delete_entry(dir, fi, &fibh, &cfi); - if (retval) - goto end_rmdir; - if (inode->i_nlink != 2) - udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)\n", - inode->i_nlink); - clear_nlink(inode); - inode->i_size = 0; - inode_dec_link_count(dir); - inode->i_ctime = dir->i_ctime = dir->i_mtime = - current_fs_time(dir->i_sb); - mark_inode_dirty(dir); - -end_rmdir: - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - -out: - return retval; -} - -static int udf_unlink(struct inode *dir, struct dentry *dentry) -{ - int retval; - struct inode *inode = dentry->d_inode; - struct udf_fileident_bh fibh; - struct fileIdentDesc *fi; - struct fileIdentDesc cfi; - struct kernel_lb_addr tloc; - - retval = -ENOENT; - fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); - if (!fi) - goto out; - - retval = -EIO; - tloc = lelb_to_cpu(cfi.icb.extLocation); - if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino) - goto end_unlink; - - if (!inode->i_nlink) { - udf_debug("Deleting nonexistent file (%lu), %d\n", - inode->i_ino, inode->i_nlink); - set_nlink(inode, 1); - } - retval = udf_delete_entry(dir, fi, &fibh, &cfi); - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); - mark_inode_dirty(dir); - inode_dec_link_count(inode); - inode->i_ctime = dir->i_ctime; - retval = 0; - -end_unlink: - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - -out: - return retval; -} - -static int udf_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - struct inode *inode; - struct pathComponent *pc; - const char *compstart; - struct udf_fileident_bh fibh; - struct extent_position epos = {}; - int eoffset, elen = 0; - struct fileIdentDesc *fi; - struct fileIdentDesc cfi; - uint8_t *ea; - int err; - int block; - unsigned char *name = NULL; - int namelen; - struct udf_inode_info *iinfo; - struct super_block *sb = dir->i_sb; - - inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err); - if (!inode) - goto out; - - iinfo = UDF_I(inode); - down_write(&iinfo->i_data_sem); - name = kmalloc(UDF_NAME_LEN, GFP_NOFS); - if (!name) { - err = -ENOMEM; - goto out_no_entry; - } - - inode->i_data.a_ops = &udf_symlink_aops; - inode->i_op = &udf_symlink_inode_operations; - - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { - struct kernel_lb_addr eloc; - uint32_t bsize; - - block = udf_new_block(sb, inode, - iinfo->i_location.partitionReferenceNum, - iinfo->i_location.logicalBlockNum, &err); - if (!block) - goto out_no_entry; - epos.block = iinfo->i_location; - epos.offset = udf_file_entry_alloc_offset(inode); - epos.bh = NULL; - eloc.logicalBlockNum = block; - eloc.partitionReferenceNum = - iinfo->i_location.partitionReferenceNum; - bsize = sb->s_blocksize; - iinfo->i_lenExtents = bsize; - udf_add_aext(inode, &epos, &eloc, bsize, 0); - brelse(epos.bh); - - block = udf_get_pblock(sb, block, - iinfo->i_location.partitionReferenceNum, - 0); - epos.bh = udf_tgetblk(sb, block); - lock_buffer(epos.bh); - memset(epos.bh->b_data, 0x00, bsize); - set_buffer_uptodate(epos.bh); - unlock_buffer(epos.bh); - mark_buffer_dirty_inode(epos.bh, inode); - ea = epos.bh->b_data + udf_ext0_offset(inode); - } else - ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr; - - eoffset = sb->s_blocksize - udf_ext0_offset(inode); - pc = (struct pathComponent *)ea; - - if (*symname == '/') { - do { - symname++; - } while (*symname == '/'); - - pc->componentType = 1; - pc->lengthComponentIdent = 0; - pc->componentFileVersionNum = 0; - elen += sizeof(struct pathComponent); - } - - err = -ENAMETOOLONG; - - while (*symname) { - if (elen + sizeof(struct pathComponent) > eoffset) - goto out_no_entry; - - pc = (struct pathComponent *)(ea + elen); - - compstart = symname; - - do { - symname++; - } while (*symname && *symname != '/'); - - pc->componentType = 5; - pc->lengthComponentIdent = 0; - pc->componentFileVersionNum = 0; - if (compstart[0] == '.') { - if ((symname - compstart) == 1) - pc->componentType = 4; - else if ((symname - compstart) == 2 && - compstart[1] == '.') - pc->componentType = 3; - } - - if (pc->componentType == 5) { - namelen = udf_put_filename(sb, compstart, name, - symname - compstart); - if (!namelen) - goto out_no_entry; - - if (elen + sizeof(struct pathComponent) + namelen > - eoffset) - goto out_no_entry; - else - pc->lengthComponentIdent = namelen; - - memcpy(pc->componentIdent, name, namelen); - } - - elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; - - if (*symname) { - do { - symname++; - } while (*symname == '/'); - } - } - - brelse(epos.bh); - inode->i_size = elen; - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - iinfo->i_lenAlloc = inode->i_size; - else - udf_truncate_tail_extent(inode); - mark_inode_dirty(inode); - - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); - if (!fi) - goto out_no_entry; - cfi.icb.extLength = cpu_to_le32(sb->s_blocksize); - cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); - if (UDF_SB(inode->i_sb)->s_lvid_bh) { - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = - cpu_to_le32(lvid_get_unique_id(sb)); - } - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); - if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - mark_inode_dirty(dir); - up_write(&iinfo->i_data_sem); - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - d_instantiate(dentry, inode); - err = 0; - -out: - kfree(name); - return err; - -out_no_entry: - up_write(&iinfo->i_data_sem); - inode_dec_link_count(inode); - iput(inode); - goto out; -} - -static int udf_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry) -{ - struct inode *inode = old_dentry->d_inode; - struct udf_fileident_bh fibh; - struct fileIdentDesc cfi, *fi; - int err; - - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); - if (!fi) { - return err; - } - cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); - cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location); - if (UDF_SB(inode->i_sb)->s_lvid_bh) { - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = - cpu_to_le32(lvid_get_unique_id(inode->i_sb)); - } - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); - if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - mark_inode_dirty(dir); - - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - inc_nlink(inode); - inode->i_ctime = current_fs_time(inode->i_sb); - mark_inode_dirty(inode); - ihold(inode); - d_instantiate(dentry, inode); - - return 0; -} - -/* Anybody can rename anything with this: the permission checks are left to the - * higher-level routines. - */ -static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - struct inode *old_inode = old_dentry->d_inode; - struct inode *new_inode = new_dentry->d_inode; - struct udf_fileident_bh ofibh, nfibh; - struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL; - struct fileIdentDesc ocfi, ncfi; - struct buffer_head *dir_bh = NULL; - int retval = -ENOENT; - struct kernel_lb_addr tloc; - struct udf_inode_info *old_iinfo = UDF_I(old_inode); - - ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); - if (ofi) { - if (ofibh.sbh != ofibh.ebh) - brelse(ofibh.ebh); - brelse(ofibh.sbh); - } - tloc = lelb_to_cpu(ocfi.icb.extLocation); - if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) - != old_inode->i_ino) - goto end_rename; - - nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi); - if (nfi) { - if (!new_inode) { - if (nfibh.sbh != nfibh.ebh) - brelse(nfibh.ebh); - brelse(nfibh.sbh); - nfi = NULL; - } - } - if (S_ISDIR(old_inode->i_mode)) { - int offset = udf_ext0_offset(old_inode); - - if (new_inode) { - retval = -ENOTEMPTY; - if (!empty_dir(new_inode)) - goto end_rename; - } - retval = -EIO; - if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - dir_fi = udf_get_fileident( - old_iinfo->i_ext.i_data - - (old_iinfo->i_efe ? - 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; - tloc = lelb_to_cpu(dir_fi->icb.extLocation); - if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) != - old_dir->i_ino) - goto end_rename; - } - if (!nfi) { - nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, - &retval); - if (!nfi) - goto end_rename; - } - - /* - * Like most other Unix systems, set the ctime for inodes on a - * rename. - */ - old_inode->i_ctime = current_fs_time(old_inode->i_sb); - mark_inode_dirty(old_inode); - - /* - * ok, that's it - */ - ncfi.fileVersionNum = ocfi.fileVersionNum; - ncfi.fileCharacteristics = ocfi.fileCharacteristics; - memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(struct long_ad)); - udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL); - - /* The old fid may have moved - find it again */ - ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); - udf_delete_entry(old_dir, ofi, &ofibh, &ocfi); - - if (new_inode) { - new_inode->i_ctime = current_fs_time(new_inode->i_sb); - inode_dec_link_count(new_inode); - } - old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb); - mark_inode_dirty(old_dir); - - if (dir_fi) { - dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location); - udf_update_tag((char *)dir_fi, - (sizeof(struct fileIdentDesc) + - le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3); - if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) - mark_inode_dirty(old_inode); - else - mark_buffer_dirty_inode(dir_bh, old_inode); - - inode_dec_link_count(old_dir); - if (new_inode) - inode_dec_link_count(new_inode); - else { - inc_nlink(new_dir); - mark_inode_dirty(new_dir); - } - } - - if (ofi) { - if (ofibh.sbh != ofibh.ebh) - brelse(ofibh.ebh); - brelse(ofibh.sbh); - } - - retval = 0; - -end_rename: - brelse(dir_bh); - if (nfi) { - if (nfibh.sbh != nfibh.ebh) - brelse(nfibh.ebh); - brelse(nfibh.sbh); - } - - return retval; -} - -static struct dentry *udf_get_parent(struct dentry *child) -{ - struct kernel_lb_addr tloc; - struct inode *inode = NULL; - struct qstr dotdot = {.name = "..", .len = 2}; - struct fileIdentDesc cfi; - struct udf_fileident_bh fibh; - - if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi)) - goto out_unlock; - - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); - - tloc = lelb_to_cpu(cfi.icb.extLocation); - inode = udf_iget(child->d_inode->i_sb, &tloc); - if (!inode) - goto out_unlock; - - return d_obtain_alias(inode); -out_unlock: - return ERR_PTR(-EACCES); -} - - -static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, - u16 partref, __u32 generation) -{ - struct inode *inode; - struct kernel_lb_addr loc; - - if (block == 0) - return ERR_PTR(-ESTALE); - - loc.logicalBlockNum = block; - loc.partitionReferenceNum = partref; - inode = udf_iget(sb, &loc); - - if (inode == NULL) - return ERR_PTR(-ENOMEM); - - if (generation && inode->i_generation != generation) { - iput(inode); - return ERR_PTR(-ESTALE); - } - return d_obtain_alias(inode); -} - -static struct dentry *udf_fh_to_dentry(struct super_block *sb, - struct fid *fid, int fh_len, int fh_type) -{ - if ((fh_len != 3 && fh_len != 5) || - (fh_type != FILEID_UDF_WITH_PARENT && - fh_type != FILEID_UDF_WITHOUT_PARENT)) - return NULL; - - return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref, - fid->udf.generation); -} - -static struct dentry *udf_fh_to_parent(struct super_block *sb, - struct fid *fid, int fh_len, int fh_type) -{ - if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT) - return NULL; - - return udf_nfs_get_inode(sb, fid->udf.parent_block, - fid->udf.parent_partref, - fid->udf.parent_generation); -} -static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, - int connectable) -{ - int len = *lenp; - struct inode *inode = de->d_inode; - struct kernel_lb_addr location = UDF_I(inode)->i_location; - struct fid *fid = (struct fid *)fh; - int type = FILEID_UDF_WITHOUT_PARENT; - - if (connectable && (len < 5)) { - *lenp = 5; - return 255; - } else if (len < 3) { - *lenp = 3; - return 255; - } - - *lenp = 3; - fid->udf.block = location.logicalBlockNum; - fid->udf.partref = location.partitionReferenceNum; - fid->udf.generation = inode->i_generation; - - if (connectable && !S_ISDIR(inode->i_mode)) { - spin_lock(&de->d_lock); - inode = de->d_parent->d_inode; - location = UDF_I(inode)->i_location; - fid->udf.parent_block = location.logicalBlockNum; - fid->udf.parent_partref = location.partitionReferenceNum; - fid->udf.parent_generation = inode->i_generation; - spin_unlock(&de->d_lock); - *lenp = 5; - type = FILEID_UDF_WITH_PARENT; - } - - return type; -} - -const struct export_operations udf_export_ops = { - .encode_fh = udf_encode_fh, - .fh_to_dentry = udf_fh_to_dentry, - .fh_to_parent = udf_fh_to_parent, - .get_parent = udf_get_parent, -}; - -const struct inode_operations udf_dir_inode_operations = { - .lookup = udf_lookup, - .create = udf_create, - .link = udf_link, - .unlink = udf_unlink, - .symlink = udf_symlink, - .mkdir = udf_mkdir, - .rmdir = udf_rmdir, - .mknod = udf_mknod, - .rename = udf_rename, -}; -const struct inode_operations udf_symlink_inode_operations = { - .readlink = generic_readlink, - .follow_link = page_follow_link_light, - .put_link = page_put_link, -}; diff --git a/ANDROID_3.4.5/fs/udf/osta_udf.h b/ANDROID_3.4.5/fs/udf/osta_udf.h deleted file mode 100644 index fbff7465..00000000 --- a/ANDROID_3.4.5/fs/udf/osta_udf.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * osta_udf.h - * - * This file is based on OSTA UDF(tm) 2.50 (April 30, 2003) - * http://www.osta.org - * - * Copyright (c) 2001-2004 Ben Fennema <bfennema@falcon.csc.calpoly.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ecma_167.h" - -#ifndef _OSTA_UDF_H -#define _OSTA_UDF_H 1 - -/* OSTA CS0 Charspec (UDF 2.50 2.1.2) */ -#define UDF_CHAR_SET_TYPE 0 -#define UDF_CHAR_SET_INFO "OSTA Compressed Unicode" - -/* Entity Identifier (UDF 2.50 2.1.5) */ -/* Identifiers (UDF 2.50 2.1.5.2) */ -#define UDF_ID_DEVELOPER "*Linux UDFFS" -#define UDF_ID_COMPLIANT "*OSTA UDF Compliant" -#define UDF_ID_LV_INFO "*UDF LV Info" -#define UDF_ID_FREE_EA "*UDF FreeEASpace" -#define UDF_ID_FREE_APP_EA "*UDF FreeAppEASpace" -#define UDF_ID_DVD_CGMS "*UDF DVD CGMS Info" -#define UDF_ID_OS2_EA "*UDF OS/2 EA" -#define UDF_ID_OS2_EA_LENGTH "*UDF OS/2 EALength" -#define UDF_ID_MAC_VOLUME "*UDF Mac VolumeInfo" -#define UDF_ID_MAC_FINDER "*UDF Mac FinderInfo" -#define UDF_ID_MAC_UNIQUE "*UDF Mac UniqueIDTable" -#define UDF_ID_MAC_RESOURCE "*UDF Mac ResourceFork" -#define UDF_ID_VIRTUAL "*UDF Virtual Partition" -#define UDF_ID_SPARABLE "*UDF Sparable Partition" -#define UDF_ID_ALLOC "*UDF Virtual Alloc Tbl" -#define UDF_ID_SPARING "*UDF Sparing Table" -#define UDF_ID_METADATA "*UDF Metadata Partition" - -/* Identifier Suffix (UDF 2.50 2.1.5.3) */ -#define IS_DF_HARD_WRITE_PROTECT 0x01 -#define IS_DF_SOFT_WRITE_PROTECT 0x02 - -struct UDFIdentSuffix { - __le16 UDFRevision; - uint8_t OSClass; - uint8_t OSIdentifier; - uint8_t reserved[4]; -} __attribute__ ((packed)); - -struct impIdentSuffix { - uint8_t OSClass; - uint8_t OSIdentifier; - uint8_t reserved[6]; -} __attribute__ ((packed)); - -struct appIdentSuffix { - uint8_t impUse[8]; -} __attribute__ ((packed)); - -/* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */ -/* Implementation Use (UDF 2.50 2.2.6.4) */ -struct logicalVolIntegrityDescImpUse { - struct regid impIdent; - __le32 numFiles; - __le32 numDirs; - __le16 minUDFReadRev; - __le16 minUDFWriteRev; - __le16 maxUDFWriteRev; - uint8_t impUse[0]; -} __attribute__ ((packed)); - -/* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */ -/* Implementation Use (UDF 2.50 2.2.7.2) */ -struct impUseVolDescImpUse { - struct charspec LVICharset; - dstring logicalVolIdent[128]; - dstring LVInfo1[36]; - dstring LVInfo2[36]; - dstring LVInfo3[36]; - struct regid impIdent; - uint8_t impUse[128]; -} __attribute__ ((packed)); - -struct udfPartitionMap2 { - uint8_t partitionMapType; - uint8_t partitionMapLength; - uint8_t reserved1[2]; - struct regid partIdent; - __le16 volSeqNum; - __le16 partitionNum; -} __attribute__ ((packed)); - -/* Virtual Partition Map (UDF 2.50 2.2.8) */ -struct virtualPartitionMap { - uint8_t partitionMapType; - uint8_t partitionMapLength; - uint8_t reserved1[2]; - struct regid partIdent; - __le16 volSeqNum; - __le16 partitionNum; - uint8_t reserved2[24]; -} __attribute__ ((packed)); - -/* Sparable Partition Map (UDF 2.50 2.2.9) */ -struct sparablePartitionMap { - uint8_t partitionMapType; - uint8_t partitionMapLength; - uint8_t reserved1[2]; - struct regid partIdent; - __le16 volSeqNum; - __le16 partitionNum; - __le16 packetLength; - uint8_t numSparingTables; - uint8_t reserved2[1]; - __le32 sizeSparingTable; - __le32 locSparingTable[4]; -} __attribute__ ((packed)); - -/* Metadata Partition Map (UDF 2.4.0 2.2.10) */ -struct metadataPartitionMap { - uint8_t partitionMapType; - uint8_t partitionMapLength; - uint8_t reserved1[2]; - struct regid partIdent; - __le16 volSeqNum; - __le16 partitionNum; - __le32 metadataFileLoc; - __le32 metadataMirrorFileLoc; - __le32 metadataBitmapFileLoc; - __le32 allocUnitSize; - __le16 alignUnitSize; - uint8_t flags; - uint8_t reserved2[5]; -} __attribute__ ((packed)); - -/* Virtual Allocation Table (UDF 1.5 2.2.10) */ -struct virtualAllocationTable15 { - __le32 VirtualSector[0]; - struct regid vatIdent; - __le32 previousVATICBLoc; -} __attribute__ ((packed)); - -#define ICBTAG_FILE_TYPE_VAT15 0x00U - -/* Virtual Allocation Table (UDF 2.50 2.2.11) */ -struct virtualAllocationTable20 { - __le16 lengthHeader; - __le16 lengthImpUse; - dstring logicalVolIdent[128]; - __le32 previousVATICBLoc; - __le32 numFiles; - __le32 numDirs; - __le16 minReadRevision; - __le16 minWriteRevision; - __le16 maxWriteRevision; - __le16 reserved; - uint8_t impUse[0]; - __le32 vatEntry[0]; -} __attribute__ ((packed)); - -#define ICBTAG_FILE_TYPE_VAT20 0xF8U - -/* Sparing Table (UDF 2.50 2.2.12) */ -struct sparingEntry { - __le32 origLocation; - __le32 mappedLocation; -} __attribute__ ((packed)); - -struct sparingTable { - struct tag descTag; - struct regid sparingIdent; - __le16 reallocationTableLen; - __le16 reserved; - __le32 sequenceNum; - struct sparingEntry - mapEntry[0]; -} __attribute__ ((packed)); - -/* Metadata File (and Metadata Mirror File) (UDF 2.50 2.2.13.1) */ -#define ICBTAG_FILE_TYPE_MAIN 0xFA -#define ICBTAG_FILE_TYPE_MIRROR 0xFB -#define ICBTAG_FILE_TYPE_BITMAP 0xFC - -/* struct struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */ -struct allocDescImpUse { - __le16 flags; - uint8_t impUse[4]; -} __attribute__ ((packed)); - -#define AD_IU_EXT_ERASED 0x0001 - -/* Real-Time Files (UDF 2.50 6.11) */ -#define ICBTAG_FILE_TYPE_REALTIME 0xF9U - -/* Implementation Use Extended Attribute (UDF 2.50 3.3.4.5) */ -/* FreeEASpace (UDF 2.50 3.3.4.5.1.1) */ -struct freeEaSpace { - __le16 headerChecksum; - uint8_t freeEASpace[0]; -} __attribute__ ((packed)); - -/* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */ -struct DVDCopyrightImpUse { - __le16 headerChecksum; - uint8_t CGMSInfo; - uint8_t dataType; - uint8_t protectionSystemInfo[4]; -} __attribute__ ((packed)); - -/* Application Use Extended Attribute (UDF 2.50 3.3.4.6) */ -/* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */ -struct freeAppEASpace { - __le16 headerChecksum; - uint8_t freeEASpace[0]; -} __attribute__ ((packed)); - -/* UDF Defined System Stream (UDF 2.50 3.3.7) */ -#define UDF_ID_UNIQUE_ID "*UDF Unique ID Mapping Data" -#define UDF_ID_NON_ALLOC "*UDF Non-Allocatable Space" -#define UDF_ID_POWER_CAL "*UDF Power Cal Table" -#define UDF_ID_BACKUP "*UDF Backup" - -/* Operating System Identifiers (UDF 2.50 6.3) */ -#define UDF_OS_CLASS_UNDEF 0x00U -#define UDF_OS_CLASS_DOS 0x01U -#define UDF_OS_CLASS_OS2 0x02U -#define UDF_OS_CLASS_MAC 0x03U -#define UDF_OS_CLASS_UNIX 0x04U -#define UDF_OS_CLASS_WIN9X 0x05U -#define UDF_OS_CLASS_WINNT 0x06U -#define UDF_OS_CLASS_OS400 0x07U -#define UDF_OS_CLASS_BEOS 0x08U -#define UDF_OS_CLASS_WINCE 0x09U - -#define UDF_OS_ID_UNDEF 0x00U -#define UDF_OS_ID_DOS 0x00U -#define UDF_OS_ID_OS2 0x00U -#define UDF_OS_ID_MAC 0x00U -#define UDF_OS_ID_MAX_OSX 0x01U -#define UDF_OS_ID_UNIX 0x00U -#define UDF_OS_ID_AIX 0x01U -#define UDF_OS_ID_SOLARIS 0x02U -#define UDF_OS_ID_HPUX 0x03U -#define UDF_OS_ID_IRIX 0x04U -#define UDF_OS_ID_LINUX 0x05U -#define UDF_OS_ID_MKLINUX 0x06U -#define UDF_OS_ID_FREEBSD 0x07U -#define UDF_OS_ID_WIN9X 0x00U -#define UDF_OS_ID_WINNT 0x00U -#define UDF_OS_ID_OS400 0x00U -#define UDF_OS_ID_BEOS 0x00U -#define UDF_OS_ID_WINCE 0x00U - -#endif /* _OSTA_UDF_H */ diff --git a/ANDROID_3.4.5/fs/udf/partition.c b/ANDROID_3.4.5/fs/udf/partition.c deleted file mode 100644 index d6caf01a..00000000 --- a/ANDROID_3.4.5/fs/udf/partition.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * partition.c - * - * PURPOSE - * Partition handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998-2001 Ben Fennema - * - * HISTORY - * - * 12/06/98 blf Created file. - * - */ - -#include "udfdecl.h" -#include "udf_sb.h" -#include "udf_i.h" - -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/buffer_head.h> -#include <linux/mutex.h> - -uint32_t udf_get_pblock(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; - if (partition >= sbi->s_partitions) { - udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n", - block, partition, offset); - return 0xFFFFFFFF; - } - map = &sbi->s_partmaps[partition]; - if (map->s_partition_func) - return map->s_partition_func(sb, block, partition, offset); - else - return map->s_partition_root + block + offset; -} - -uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, - uint16_t partition, uint32_t offset) -{ - struct buffer_head *bh = NULL; - uint32_t newblock; - uint32_t index; - uint32_t loc; - struct udf_sb_info *sbi = UDF_SB(sb); - struct udf_part_map *map; - struct udf_virtual_data *vdata; - struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode); - - map = &sbi->s_partmaps[partition]; - vdata = &map->s_type_specific.s_virtual; - - if (block > vdata->s_num_entries) { - udf_debug("Trying to access block beyond end of VAT (%d max %d)\n", - block, vdata->s_num_entries); - 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))); - index = block % (sb->s_blocksize / sizeof(uint32_t)); - } else { - newblock = 0; - index = vdata->s_start_offset / sizeof(uint32_t) + block; - } - - loc = udf_block_map(sbi->s_vat_inode, newblock); - - bh = sb_bread(sb, loc); - if (!bh) { - udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n", - sb, block, partition, loc, index); - return 0xFFFFFFFF; - } - - loc = le32_to_cpu(((__le32 *)bh->b_data)[index]); - - brelse(bh); - -translate: - if (iinfo->i_location.partitionReferenceNum == partition) { - udf_debug("recursive call to udf_get_pblock!\n"); - return 0xFFFFFFFF; - } - - return udf_get_pblock(sb, loc, - iinfo->i_location.partitionReferenceNum, - offset); -} - -inline uint32_t udf_get_pblock_virt20(struct super_block *sb, uint32_t block, - uint16_t partition, uint32_t offset) -{ - return udf_get_pblock_virt15(sb, block, partition, offset); -} - -uint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block, - uint16_t partition, uint32_t offset) -{ - int i; - struct sparingTable *st = NULL; - struct udf_sb_info *sbi = UDF_SB(sb); - struct udf_part_map *map; - uint32_t packet; - struct udf_sparing_data *sdata; - - map = &sbi->s_partmaps[partition]; - sdata = &map->s_type_specific.s_sparing; - packet = (block + offset) & ~(sdata->s_packet_len - 1); - - for (i = 0; i < 4; i++) { - if (sdata->s_spar_map[i] != NULL) { - st = (struct sparingTable *) - sdata->s_spar_map[i]->b_data; - break; - } - } - - if (st) { - for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) { - struct sparingEntry *entry = &st->mapEntry[i]; - u32 origLoc = le32_to_cpu(entry->origLocation); - if (origLoc >= 0xFFFFFFF0) - break; - else if (origLoc == packet) - return le32_to_cpu(entry->mappedLocation) + - ((block + offset) & - (sdata->s_packet_len - 1)); - else if (origLoc > packet) - break; - } - } - - return map->s_partition_root + block + offset; -} - -int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) -{ - struct udf_sparing_data *sdata; - struct sparingTable *st = NULL; - struct sparingEntry mapEntry; - uint32_t packet; - int i, j, k, l; - struct udf_sb_info *sbi = UDF_SB(sb); - u16 reallocationTableLen; - struct buffer_head *bh; - int ret = 0; - - mutex_lock(&sbi->s_alloc_mutex); - for (i = 0; i < sbi->s_partitions; i++) { - struct udf_part_map *map = &sbi->s_partmaps[i]; - if (old_block > map->s_partition_root && - old_block < map->s_partition_root + map->s_partition_len) { - sdata = &map->s_type_specific.s_sparing; - packet = (old_block - map->s_partition_root) & - ~(sdata->s_packet_len - 1); - - for (j = 0; j < 4; j++) - if (sdata->s_spar_map[j] != NULL) { - st = (struct sparingTable *) - sdata->s_spar_map[j]->b_data; - break; - } - - if (!st) { - ret = 1; - goto out; - } - - reallocationTableLen = - le16_to_cpu(st->reallocationTableLen); - for (k = 0; k < reallocationTableLen; k++) { - struct sparingEntry *entry = &st->mapEntry[k]; - u32 origLoc = le32_to_cpu(entry->origLocation); - - if (origLoc == 0xFFFFFFFF) { - for (; j < 4; j++) { - int len; - bh = sdata->s_spar_map[j]; - if (!bh) - continue; - - st = (struct sparingTable *) - bh->b_data; - entry->origLocation = - cpu_to_le32(packet); - len = - sizeof(struct sparingTable) + - reallocationTableLen * - sizeof(struct sparingEntry); - udf_update_tag((char *)st, len); - mark_buffer_dirty(bh); - } - *new_block = le32_to_cpu( - entry->mappedLocation) + - ((old_block - - map->s_partition_root) & - (sdata->s_packet_len - 1)); - ret = 0; - goto out; - } else if (origLoc == packet) { - *new_block = le32_to_cpu( - entry->mappedLocation) + - ((old_block - - map->s_partition_root) & - (sdata->s_packet_len - 1)); - ret = 0; - goto out; - } else if (origLoc > packet) - break; - } - - for (l = k; l < reallocationTableLen; l++) { - struct sparingEntry *entry = &st->mapEntry[l]; - u32 origLoc = le32_to_cpu(entry->origLocation); - - if (origLoc != 0xFFFFFFFF) - continue; - - for (; j < 4; j++) { - bh = sdata->s_spar_map[j]; - if (!bh) - continue; - - st = (struct sparingTable *)bh->b_data; - mapEntry = st->mapEntry[l]; - mapEntry.origLocation = - cpu_to_le32(packet); - memmove(&st->mapEntry[k + 1], - &st->mapEntry[k], - (l - k) * - sizeof(struct sparingEntry)); - st->mapEntry[k] = mapEntry; - udf_update_tag((char *)st, - sizeof(struct sparingTable) + - reallocationTableLen * - sizeof(struct sparingEntry)); - mark_buffer_dirty(bh); - } - *new_block = - le32_to_cpu( - st->mapEntry[k].mappedLocation) + - ((old_block - map->s_partition_root) & - (sdata->s_packet_len - 1)); - ret = 0; - goto out; - } - - ret = 1; - goto out; - } /* if old_block */ - } - - if (i == sbi->s_partitions) { - /* outside of partitions */ - /* for now, fail =) */ - ret = 1; - } - -out: - mutex_unlock(&sbi->s_alloc_mutex); - return ret; -} - -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; - struct 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 && mdata->s_metadata_fe) { - udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n"); - if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { - mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, - mdata->s_mirror_file_loc, map->s_partition_num); - mdata->s_flags |= MF_MIRROR_FE_LOADED; - } - - inode = mdata->s_mirror_fe; - if (!inode) - return 0xFFFFFFFF; - retblk = udf_try_read_meta(inode, block, partition, offset); - } - - return retblk; -} diff --git a/ANDROID_3.4.5/fs/udf/super.c b/ANDROID_3.4.5/fs/udf/super.c deleted file mode 100644 index 8d86a870..00000000 --- a/ANDROID_3.4.5/fs/udf/super.c +++ /dev/null @@ -1,2320 +0,0 @@ -/* - * super.c - * - * PURPOSE - * Super block routines for the OSTA-UDF(tm) filesystem. - * - * DESCRIPTION - * OSTA-UDF(tm) = Optical Storage Technology Association - * Universal Disk Format. - * - * This code is based on version 2.00 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) 1998 Dave Boynton - * (C) 1998-2004 Ben Fennema - * (C) 2000 Stelias Computing Inc - * - * HISTORY - * - * 09/24/98 dgb changed to allow compiling outside of kernel, and - * added some debugging. - * 10/01/98 dgb updated to allow (some) possibility of compiling w/2.0.34 - * 10/16/98 attempting some multi-session support - * 10/17/98 added freespace count for "df" - * 11/11/98 gr added novrs option - * 11/26/98 dgb added fileset,anchor mount options - * 12/06/98 blf really hosed things royally. vat/sparing support. sequenced - * vol descs. rewrote option handling based on isofs - * 12/20/98 find the free space bitmap (if it exists) - */ - -#include "udfdecl.h" - -#include <linux/blkdev.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/parser.h> -#include <linux/stat.h> -#include <linux/cdrom.h> -#include <linux/nls.h> -#include <linux/buffer_head.h> -#include <linux/vfs.h> -#include <linux/vmalloc.h> -#include <linux/errno.h> -#include <linux/mount.h> -#include <linux/seq_file.h> -#include <linux/bitmap.h> -#include <linux/crc-itu-t.h> -#include <linux/log2.h> -#include <asm/byteorder.h> - -#include "udf_sb.h" -#include "udf_i.h" - -#include <linux/init.h> -#include <asm/uaccess.h> - -#define VDS_POS_PRIMARY_VOL_DESC 0 -#define VDS_POS_UNALLOC_SPACE_DESC 1 -#define VDS_POS_LOGICAL_VOL_DESC 2 -#define VDS_POS_PARTITION_DESC 3 -#define VDS_POS_IMP_USE_VOL_DESC 4 -#define VDS_POS_VOL_DESC_PTR 5 -#define VDS_POS_TERMINATING_DESC 6 -#define VDS_POS_LENGTH 7 - -#define UDF_DEFAULT_BLOCKSIZE 2048 - -enum { UDF_MAX_LINKS = 0xffff }; - -/* These are the "meat" - everything else is stuffing */ -static int udf_fill_super(struct super_block *, void *, int); -static void udf_put_super(struct super_block *); -static int udf_sync_fs(struct super_block *, int); -static int udf_remount_fs(struct super_block *, int *, char *); -static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad); -static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *, - struct kernel_lb_addr *); -static void udf_load_fileset(struct super_block *, struct buffer_head *, - struct kernel_lb_addr *); -static void udf_open_lvid(struct super_block *); -static void udf_close_lvid(struct super_block *); -static unsigned int udf_count_free(struct super_block *); -static int udf_statfs(struct dentry *, struct kstatfs *); -static int udf_show_options(struct seq_file *, struct dentry *); - -struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi) -{ - struct logicalVolIntegrityDesc *lvid = - (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; - __u32 number_of_partitions = le32_to_cpu(lvid->numOfPartitions); - __u32 offset = number_of_partitions * 2 * - sizeof(uint32_t)/sizeof(uint8_t); - return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]); -} - -/* UDF filesystem type */ -static struct dentry *udf_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return mount_bdev(fs_type, flags, dev_name, data, udf_fill_super); -} - -static struct file_system_type udf_fstype = { - .owner = THIS_MODULE, - .name = "udf", - .mount = udf_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, -}; - -static struct kmem_cache *udf_inode_cachep; - -static struct inode *udf_alloc_inode(struct super_block *sb) -{ - struct udf_inode_info *ei; - ei = kmem_cache_alloc(udf_inode_cachep, GFP_KERNEL); - if (!ei) - return NULL; - - ei->i_unique = 0; - ei->i_lenExtents = 0; - ei->i_next_alloc_block = 0; - ei->i_next_alloc_goal = 0; - ei->i_strat4096 = 0; - init_rwsem(&ei->i_data_sem); - - return &ei->vfs_inode; -} - -static void udf_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(udf_inode_cachep, UDF_I(inode)); -} - -static void udf_destroy_inode(struct inode *inode) -{ - call_rcu(&inode->i_rcu, udf_i_callback); -} - -static void init_once(void *foo) -{ - struct udf_inode_info *ei = (struct udf_inode_info *)foo; - - ei->i_ext.i_data = NULL; - inode_init_once(&ei->vfs_inode); -} - -static int init_inodecache(void) -{ - udf_inode_cachep = kmem_cache_create("udf_inode_cache", - sizeof(struct udf_inode_info), - 0, (SLAB_RECLAIM_ACCOUNT | - SLAB_MEM_SPREAD), - init_once); - if (!udf_inode_cachep) - return -ENOMEM; - return 0; -} - -static void destroy_inodecache(void) -{ - kmem_cache_destroy(udf_inode_cachep); -} - -/* Superblock operations */ -static const struct super_operations udf_sb_ops = { - .alloc_inode = udf_alloc_inode, - .destroy_inode = udf_destroy_inode, - .write_inode = udf_write_inode, - .evict_inode = udf_evict_inode, - .put_super = udf_put_super, - .sync_fs = udf_sync_fs, - .statfs = udf_statfs, - .remount_fs = udf_remount_fs, - .show_options = udf_show_options, -}; - -struct udf_options { - unsigned char novrs; - unsigned int blocksize; - unsigned int session; - unsigned int lastblock; - unsigned int anchor; - unsigned int volume; - unsigned short partition; - unsigned int fileset; - unsigned int rootdir; - unsigned int flags; - umode_t umask; - gid_t gid; - uid_t uid; - umode_t fmode; - umode_t dmode; - struct nls_table *nls_map; -}; - -static int __init init_udf_fs(void) -{ - int err; - - err = init_inodecache(); - if (err) - goto out1; - err = register_filesystem(&udf_fstype); - if (err) - goto out; - - return 0; - -out: - destroy_inodecache(); - -out1: - return err; -} - -static void __exit exit_udf_fs(void) -{ - unregister_filesystem(&udf_fstype); - destroy_inodecache(); -} - -module_init(init_udf_fs) -module_exit(exit_udf_fs) - -static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - - sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map), - GFP_KERNEL); - if (!sbi->s_partmaps) { - udf_err(sb, "Unable to allocate space for %d partition maps\n", - count); - sbi->s_partitions = 0; - return -ENOMEM; - } - - sbi->s_partitions = count; - return 0; -} - -static int udf_show_options(struct seq_file *seq, struct dentry *root) -{ - struct super_block *sb = root->d_sb; - struct udf_sb_info *sbi = UDF_SB(sb); - - if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) - seq_puts(seq, ",nostrict"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET)) - seq_printf(seq, ",bs=%lu", sb->s_blocksize); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) - seq_puts(seq, ",unhide"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) - seq_puts(seq, ",undelete"); - if (!UDF_QUERY_FLAG(sb, UDF_FLAG_USE_AD_IN_ICB)) - seq_puts(seq, ",noadinicb"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_USE_SHORT_AD)) - seq_puts(seq, ",shortad"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_FORGET)) - seq_puts(seq, ",uid=forget"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_IGNORE)) - seq_puts(seq, ",uid=ignore"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_FORGET)) - seq_puts(seq, ",gid=forget"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_IGNORE)) - seq_puts(seq, ",gid=ignore"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET)) - seq_printf(seq, ",uid=%u", sbi->s_uid); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_SET)) - seq_printf(seq, ",gid=%u", sbi->s_gid); - if (sbi->s_umask != 0) - seq_printf(seq, ",umask=%ho", sbi->s_umask); - if (sbi->s_fmode != UDF_INVALID_MODE) - seq_printf(seq, ",mode=%ho", sbi->s_fmode); - if (sbi->s_dmode != UDF_INVALID_MODE) - seq_printf(seq, ",dmode=%ho", sbi->s_dmode); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET)) - seq_printf(seq, ",session=%u", sbi->s_session); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET)) - seq_printf(seq, ",lastblock=%u", sbi->s_last_block); - if (sbi->s_anchor != 0) - seq_printf(seq, ",anchor=%u", sbi->s_anchor); - /* - * volume, partition, fileset and rootdir seem to be ignored - * currently - */ - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) - seq_puts(seq, ",utf8"); - if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP) && sbi->s_nls_map) - seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset); - - return 0; -} - -/* - * udf_parse_options - * - * PURPOSE - * Parse mount options. - * - * DESCRIPTION - * The following mount options are supported: - * - * gid= Set the default group. - * umask= Set the default umask. - * mode= Set the default file permissions. - * dmode= Set the default directory permissions. - * uid= Set the default user. - * bs= Set the block size. - * unhide Show otherwise hidden files. - * undelete Show deleted files in lists. - * adinicb Embed data in the inode (default) - * noadinicb Don't embed data in the inode - * shortad Use short ad's - * longad Use long ad's (default) - * nostrict Unset strict conformance - * iocharset= Set the NLS character set - * - * The remaining are for debugging and disaster recovery: - * - * novrs Skip volume sequence recognition - * - * The following expect a offset from 0. - * - * session= Set the CDROM session (default= last session) - * anchor= Override standard anchor location. (default= 256) - * volume= Override the VolumeDesc location. (unused) - * partition= Override the PartitionDesc location. (unused) - * lastblock= Set the last block of the filesystem/ - * - * The following expect a offset from the partition root. - * - * fileset= Override the fileset block location. (unused) - * rootdir= Override the root directory location. (unused) - * WARNING: overriding the rootdir to a non-directory may - * yield highly unpredictable results. - * - * PRE-CONDITIONS - * options Pointer to mount options string. - * uopts Pointer to mount options variable. - * - * POST-CONDITIONS - * <return> 1 Mount options parsed okay. - * <return> 0 Error parsing mount options. - * - * HISTORY - * July 1, 1997 - Andrew E. Mileski - * Written, tested, and released. - */ - -enum { - Opt_novrs, Opt_nostrict, Opt_bs, Opt_unhide, Opt_undelete, - Opt_noadinicb, Opt_adinicb, Opt_shortad, Opt_longad, - Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock, - Opt_anchor, Opt_volume, Opt_partition, Opt_fileset, - Opt_rootdir, Opt_utf8, Opt_iocharset, - Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore, - Opt_fmode, Opt_dmode -}; - -static const match_table_t tokens = { - {Opt_novrs, "novrs"}, - {Opt_nostrict, "nostrict"}, - {Opt_bs, "bs=%u"}, - {Opt_unhide, "unhide"}, - {Opt_undelete, "undelete"}, - {Opt_noadinicb, "noadinicb"}, - {Opt_adinicb, "adinicb"}, - {Opt_shortad, "shortad"}, - {Opt_longad, "longad"}, - {Opt_uforget, "uid=forget"}, - {Opt_uignore, "uid=ignore"}, - {Opt_gforget, "gid=forget"}, - {Opt_gignore, "gid=ignore"}, - {Opt_gid, "gid=%u"}, - {Opt_uid, "uid=%u"}, - {Opt_umask, "umask=%o"}, - {Opt_session, "session=%u"}, - {Opt_lastblock, "lastblock=%u"}, - {Opt_anchor, "anchor=%u"}, - {Opt_volume, "volume=%u"}, - {Opt_partition, "partition=%u"}, - {Opt_fileset, "fileset=%u"}, - {Opt_rootdir, "rootdir=%u"}, - {Opt_utf8, "utf8"}, - {Opt_iocharset, "iocharset=%s"}, - {Opt_fmode, "mode=%o"}, - {Opt_dmode, "dmode=%o"}, - {Opt_err, NULL} -}; - -static int udf_parse_options(char *options, struct udf_options *uopt, - bool remount) -{ - char *p; - int option; - - uopt->novrs = 0; - uopt->partition = 0xFFFF; - uopt->session = 0xFFFFFFFF; - uopt->lastblock = 0; - uopt->anchor = 0; - uopt->volume = 0xFFFFFFFF; - uopt->rootdir = 0xFFFFFFFF; - uopt->fileset = 0xFFFFFFFF; - uopt->nls_map = NULL; - - if (!options) - return 1; - - while ((p = strsep(&options, ",")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - if (!*p) - continue; - - token = match_token(p, tokens, args); - switch (token) { - case Opt_novrs: - uopt->novrs = 1; - break; - case Opt_bs: - if (match_int(&args[0], &option)) - return 0; - uopt->blocksize = option; - uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET); - break; - case Opt_unhide: - uopt->flags |= (1 << UDF_FLAG_UNHIDE); - break; - case Opt_undelete: - uopt->flags |= (1 << UDF_FLAG_UNDELETE); - break; - case Opt_noadinicb: - uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB); - break; - case Opt_adinicb: - uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB); - break; - case Opt_shortad: - uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD); - break; - case Opt_longad: - uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD); - break; - case Opt_gid: - if (match_int(args, &option)) - return 0; - uopt->gid = option; - uopt->flags |= (1 << UDF_FLAG_GID_SET); - break; - case Opt_uid: - if (match_int(args, &option)) - return 0; - uopt->uid = option; - uopt->flags |= (1 << UDF_FLAG_UID_SET); - break; - case Opt_umask: - if (match_octal(args, &option)) - return 0; - uopt->umask = option; - break; - case Opt_nostrict: - uopt->flags &= ~(1 << UDF_FLAG_STRICT); - break; - case Opt_session: - if (match_int(args, &option)) - return 0; - uopt->session = option; - if (!remount) - uopt->flags |= (1 << UDF_FLAG_SESSION_SET); - break; - case Opt_lastblock: - if (match_int(args, &option)) - return 0; - uopt->lastblock = option; - if (!remount) - uopt->flags |= (1 << UDF_FLAG_LASTBLOCK_SET); - break; - case Opt_anchor: - if (match_int(args, &option)) - return 0; - uopt->anchor = option; - break; - case Opt_volume: - if (match_int(args, &option)) - return 0; - uopt->volume = option; - break; - case Opt_partition: - if (match_int(args, &option)) - return 0; - uopt->partition = option; - break; - case Opt_fileset: - if (match_int(args, &option)) - return 0; - uopt->fileset = option; - break; - case Opt_rootdir: - if (match_int(args, &option)) - return 0; - uopt->rootdir = option; - break; - case Opt_utf8: - uopt->flags |= (1 << UDF_FLAG_UTF8); - break; -#ifdef CONFIG_UDF_NLS - case Opt_iocharset: - uopt->nls_map = load_nls(args[0].from); - uopt->flags |= (1 << UDF_FLAG_NLS_MAP); - break; -#endif - case Opt_uignore: - uopt->flags |= (1 << UDF_FLAG_UID_IGNORE); - break; - case Opt_uforget: - uopt->flags |= (1 << UDF_FLAG_UID_FORGET); - break; - case Opt_gignore: - uopt->flags |= (1 << UDF_FLAG_GID_IGNORE); - break; - case Opt_gforget: - uopt->flags |= (1 << UDF_FLAG_GID_FORGET); - break; - case Opt_fmode: - if (match_octal(args, &option)) - return 0; - uopt->fmode = option & 0777; - break; - case Opt_dmode: - if (match_octal(args, &option)) - return 0; - uopt->dmode = option & 0777; - break; - default: - pr_err("bad mount option \"%s\" or missing value\n", p); - return 0; - } - } - return 1; -} - -static int udf_remount_fs(struct super_block *sb, int *flags, char *options) -{ - struct udf_options uopt; - struct udf_sb_info *sbi = UDF_SB(sb); - int error = 0; - - uopt.flags = sbi->s_flags; - uopt.uid = sbi->s_uid; - uopt.gid = sbi->s_gid; - uopt.umask = sbi->s_umask; - uopt.fmode = sbi->s_fmode; - uopt.dmode = sbi->s_dmode; - - if (!udf_parse_options(options, &uopt, true)) - return -EINVAL; - - write_lock(&sbi->s_cred_lock); - sbi->s_flags = uopt.flags; - sbi->s_uid = uopt.uid; - sbi->s_gid = uopt.gid; - sbi->s_umask = uopt.umask; - sbi->s_fmode = uopt.fmode; - sbi->s_dmode = uopt.dmode; - write_unlock(&sbi->s_cred_lock); - - if (sbi->s_lvid_bh) { - int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); - if (write_rev > UDF_MAX_WRITE_VERSION) - *flags |= MS_RDONLY; - } - - if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) - goto out_unlock; - - if (*flags & MS_RDONLY) - udf_close_lvid(sb); - else - udf_open_lvid(sb); - -out_unlock: - return error; -} - -/* Check Volume Structure Descriptors (ECMA 167 2/9.1) */ -/* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ -static loff_t udf_check_vsd(struct super_block *sb) -{ - struct volStructDesc *vsd = NULL; - loff_t sector = 32768; - int sectorsize; - struct buffer_head *bh = NULL; - int nsr02 = 0; - int nsr03 = 0; - struct udf_sb_info *sbi; - - sbi = UDF_SB(sb); - if (sb->s_blocksize < sizeof(struct volStructDesc)) - sectorsize = sizeof(struct volStructDesc); - else - sectorsize = sb->s_blocksize; - - sector += (sbi->s_session << sb->s_blocksize_bits); - - udf_debug("Starting at sector %u (%ld byte sectors)\n", - (unsigned int)(sector >> sb->s_blocksize_bits), - sb->s_blocksize); - /* Process the sequence (if applicable) */ - for (; !nsr02 && !nsr03; sector += sectorsize) { - /* Read a block */ - bh = udf_tread(sb, sector >> sb->s_blocksize_bits); - if (!bh) - break; - - /* Look for ISO descriptors */ - vsd = (struct volStructDesc *)(bh->b_data + - (sector & (sb->s_blocksize - 1))); - - if (vsd->stdIdent[0] == 0) { - brelse(bh); - break; - } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, - VSD_STD_ID_LEN)) { - switch (vsd->structType) { - case 0: - udf_debug("ISO9660 Boot Record found\n"); - break; - case 1: - udf_debug("ISO9660 Primary Volume Descriptor found\n"); - break; - case 2: - udf_debug("ISO9660 Supplementary Volume Descriptor found\n"); - break; - case 3: - udf_debug("ISO9660 Volume Partition Descriptor found\n"); - break; - case 255: - udf_debug("ISO9660 Volume Descriptor Set Terminator found\n"); - break; - default: - udf_debug("ISO9660 VRS (%u) found\n", - vsd->structType); - break; - } - } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BEA01, - VSD_STD_ID_LEN)) - ; /* nothing */ - else if (!strncmp(vsd->stdIdent, VSD_STD_ID_TEA01, - VSD_STD_ID_LEN)) { - brelse(bh); - break; - } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR02, - VSD_STD_ID_LEN)) - nsr02 = sector; - else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03, - VSD_STD_ID_LEN)) - nsr03 = sector; - brelse(bh); - } - - if (nsr03) - return nsr03; - else if (nsr02) - return nsr02; - else if (sector - (sbi->s_session << sb->s_blocksize_bits) == 32768) - return -1; - else - return 0; -} - -static int udf_find_fileset(struct super_block *sb, - struct kernel_lb_addr *fileset, - struct kernel_lb_addr *root) -{ - struct buffer_head *bh = NULL; - long lastblock; - uint16_t ident; - struct udf_sb_info *sbi; - - if (fileset->logicalBlockNum != 0xFFFFFFFF || - fileset->partitionReferenceNum != 0xFFFF) { - bh = udf_read_ptagged(sb, fileset, 0, &ident); - - if (!bh) { - return 1; - } else if (ident != TAG_IDENT_FSD) { - brelse(bh); - return 1; - } - - } - - sbi = UDF_SB(sb); - if (!bh) { - /* Search backwards through the partitions */ - struct kernel_lb_addr newfileset; - -/* --> cvg: FIXME - is it reasonable? */ - return 1; - - for (newfileset.partitionReferenceNum = sbi->s_partitions - 1; - (newfileset.partitionReferenceNum != 0xFFFF && - fileset->logicalBlockNum == 0xFFFFFFFF && - fileset->partitionReferenceNum == 0xFFFF); - newfileset.partitionReferenceNum--) { - lastblock = sbi->s_partmaps - [newfileset.partitionReferenceNum] - .s_partition_len; - newfileset.logicalBlockNum = 0; - - do { - bh = udf_read_ptagged(sb, &newfileset, 0, - &ident); - if (!bh) { - newfileset.logicalBlockNum++; - continue; - } - - switch (ident) { - case TAG_IDENT_SBD: - { - struct spaceBitmapDesc *sp; - sp = (struct spaceBitmapDesc *) - bh->b_data; - newfileset.logicalBlockNum += 1 + - ((le32_to_cpu(sp->numOfBytes) + - sizeof(struct spaceBitmapDesc) - - 1) >> sb->s_blocksize_bits); - brelse(bh); - break; - } - case TAG_IDENT_FSD: - *fileset = newfileset; - break; - default: - newfileset.logicalBlockNum++; - brelse(bh); - bh = NULL; - break; - } - } while (newfileset.logicalBlockNum < lastblock && - fileset->logicalBlockNum == 0xFFFFFFFF && - fileset->partitionReferenceNum == 0xFFFF); - } - } - - if ((fileset->logicalBlockNum != 0xFFFFFFFF || - fileset->partitionReferenceNum != 0xFFFF) && bh) { - udf_debug("Fileset at block=%d, partition=%d\n", - fileset->logicalBlockNum, - fileset->partitionReferenceNum); - - sbi->s_partition = fileset->partitionReferenceNum; - udf_load_fileset(sb, bh, root); - brelse(bh); - return 0; - } - return 1; -} - -static int udf_load_pvoldesc(struct super_block *sb, sector_t block) -{ - struct primaryVolDesc *pvoldesc; - struct ustr *instr, *outstr; - struct buffer_head *bh; - uint16_t ident; - int ret = 1; - - instr = kmalloc(sizeof(struct ustr), GFP_NOFS); - if (!instr) - return 1; - - outstr = kmalloc(sizeof(struct ustr), GFP_NOFS); - if (!outstr) - goto out1; - - bh = udf_read_tagged(sb, block, block, &ident); - if (!bh) - goto out2; - - BUG_ON(ident != TAG_IDENT_PVD); - - pvoldesc = (struct primaryVolDesc *)bh->b_data; - - if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time, - pvoldesc->recordingDateAndTime)) { -#ifdef UDFFS_DEBUG - struct timestamp *ts = &pvoldesc->recordingDateAndTime; - udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n", - le16_to_cpu(ts->year), ts->month, ts->day, ts->hour, - ts->minute, le16_to_cpu(ts->typeAndTimezone)); -#endif - } - - if (!udf_build_ustr(instr, pvoldesc->volIdent, 32)) - if (udf_CS0toUTF8(outstr, instr)) { - strncpy(UDF_SB(sb)->s_volume_ident, outstr->u_name, - outstr->u_len > 31 ? 31 : outstr->u_len); - udf_debug("volIdent[] = '%s'\n", - UDF_SB(sb)->s_volume_ident); - } - - if (!udf_build_ustr(instr, pvoldesc->volSetIdent, 128)) - if (udf_CS0toUTF8(outstr, instr)) - udf_debug("volSetIdent[] = '%s'\n", outstr->u_name); - - brelse(bh); - ret = 0; -out2: - kfree(outstr); -out1: - kfree(instr); - return ret; -} - -struct inode *udf_find_metadata_inode_efe(struct super_block *sb, - u32 meta_file_loc, u32 partition_num) -{ - struct kernel_lb_addr addr; - struct inode *metadata_fe; - - addr.logicalBlockNum = meta_file_loc; - addr.partitionReferenceNum = partition_num; - - metadata_fe = udf_iget(sb, &addr); - - if (metadata_fe == NULL) - udf_warn(sb, "metadata inode efe not found\n"); - else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) { - udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n"); - iput(metadata_fe); - metadata_fe = NULL; - } - - return metadata_fe; -} - -static int udf_load_metadata_files(struct super_block *sb, int partition) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct udf_part_map *map; - struct udf_meta_data *mdata; - struct kernel_lb_addr addr; - - map = &sbi->s_partmaps[partition]; - mdata = &map->s_type_specific.s_metadata; - - /* metadata address */ - udf_debug("Metadata file location: block = %d part = %d\n", - mdata->s_meta_file_loc, map->s_partition_num); - - mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb, - mdata->s_meta_file_loc, map->s_partition_num); - - if (mdata->s_metadata_fe == NULL) { - /* mirror file entry */ - udf_debug("Mirror metadata file location: block = %d part = %d\n", - mdata->s_mirror_file_loc, map->s_partition_num); - - mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, - mdata->s_mirror_file_loc, map->s_partition_num); - - if (mdata->s_mirror_fe == NULL) { - udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n"); - goto error_exit; - } - } - - /* - * bitmap file entry - * Note: - * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102) - */ - if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) { - addr.logicalBlockNum = mdata->s_bitmap_file_loc; - addr.partitionReferenceNum = map->s_partition_num; - - udf_debug("Bitmap file location: block = %d part = %d\n", - addr.logicalBlockNum, addr.partitionReferenceNum); - - mdata->s_bitmap_fe = udf_iget(sb, &addr); - - if (mdata->s_bitmap_fe == NULL) { - if (sb->s_flags & MS_RDONLY) - udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n"); - else { - udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n"); - goto error_exit; - } - } - } - - udf_debug("udf_load_metadata_files Ok\n"); - - return 0; - -error_exit: - return 1; -} - -static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, - struct kernel_lb_addr *root) -{ - struct fileSetDesc *fset; - - fset = (struct fileSetDesc *)bh->b_data; - - *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation); - - UDF_SB(sb)->s_serial_number = le16_to_cpu(fset->descTag.tagSerialNum); - - udf_debug("Rootdir at block=%d, partition=%d\n", - root->logicalBlockNum, root->partitionReferenceNum); -} - -int udf_compute_nr_groups(struct super_block *sb, u32 partition) -{ - struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; - return DIV_ROUND_UP(map->s_partition_len + - (sizeof(struct spaceBitmapDesc) << 3), - sb->s_blocksize * 8); -} - -static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) -{ - struct udf_bitmap *bitmap; - int nr_groups; - int size; - - nr_groups = udf_compute_nr_groups(sb, index); - size = sizeof(struct udf_bitmap) + - (sizeof(struct buffer_head *) * nr_groups); - - if (size <= PAGE_SIZE) - bitmap = kzalloc(size, GFP_KERNEL); - else - bitmap = vzalloc(size); /* TODO: get rid of vzalloc */ - - if (bitmap == NULL) - return NULL; - - bitmap->s_block_bitmap = (struct buffer_head **)(bitmap + 1); - bitmap->s_nr_groups = nr_groups; - return bitmap; -} - -static int udf_fill_partdesc_info(struct super_block *sb, - struct partitionDesc *p, int p_index) -{ - struct udf_part_map *map; - struct udf_sb_info *sbi = UDF_SB(sb); - struct partitionHeaderDesc *phd; - - map = &sbi->s_partmaps[p_index]; - - map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */ - map->s_partition_root = le32_to_cpu(p->partitionStartingLocation); - - if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY)) - map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY; - if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE)) - map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE; - if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE)) - map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE; - if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE)) - map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE; - - udf_debug("Partition (%d type %x) starts at physical %d, block length %d\n", - p_index, map->s_partition_type, - map->s_partition_root, map->s_partition_len); - - if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) && - strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03)) - return 0; - - phd = (struct partitionHeaderDesc *)p->partitionContentsUse; - if (phd->unallocSpaceTable.extLength) { - struct kernel_lb_addr loc = { - .logicalBlockNum = le32_to_cpu( - phd->unallocSpaceTable.extPosition), - .partitionReferenceNum = p_index, - }; - - map->s_uspace.s_table = udf_iget(sb, &loc); - if (!map->s_uspace.s_table) { - udf_debug("cannot load unallocSpaceTable (part %d)\n", - p_index); - return 1; - } - map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE; - udf_debug("unallocSpaceTable (part %d) @ %ld\n", - p_index, map->s_uspace.s_table->i_ino); - } - - if (phd->unallocSpaceBitmap.extLength) { - struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index); - if (!bitmap) - return 1; - map->s_uspace.s_bitmap = bitmap; - bitmap->s_extLength = le32_to_cpu( - phd->unallocSpaceBitmap.extLength); - bitmap->s_extPosition = le32_to_cpu( - phd->unallocSpaceBitmap.extPosition); - map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP; - udf_debug("unallocSpaceBitmap (part %d) @ %d\n", - p_index, bitmap->s_extPosition); - } - - if (phd->partitionIntegrityTable.extLength) - udf_debug("partitionIntegrityTable (part %d)\n", p_index); - - if (phd->freedSpaceTable.extLength) { - struct kernel_lb_addr loc = { - .logicalBlockNum = le32_to_cpu( - phd->freedSpaceTable.extPosition), - .partitionReferenceNum = p_index, - }; - - map->s_fspace.s_table = udf_iget(sb, &loc); - if (!map->s_fspace.s_table) { - udf_debug("cannot load freedSpaceTable (part %d)\n", - p_index); - return 1; - } - - map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE; - udf_debug("freedSpaceTable (part %d) @ %ld\n", - p_index, map->s_fspace.s_table->i_ino); - } - - if (phd->freedSpaceBitmap.extLength) { - struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index); - if (!bitmap) - return 1; - map->s_fspace.s_bitmap = bitmap; - bitmap->s_extLength = le32_to_cpu( - phd->freedSpaceBitmap.extLength); - bitmap->s_extPosition = le32_to_cpu( - phd->freedSpaceBitmap.extPosition); - map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP; - udf_debug("freedSpaceBitmap (part %d) @ %d\n", - p_index, bitmap->s_extPosition); - } - return 0; -} - -static void udf_find_vat_block(struct super_block *sb, int p_index, - int type1_index, sector_t start_block) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct udf_part_map *map = &sbi->s_partmaps[p_index]; - sector_t vat_block; - struct kernel_lb_addr ino; - - /* - * VAT file entry is in the last recorded block. Some broken disks have - * it a few blocks before so try a bit harder... - */ - ino.partitionReferenceNum = type1_index; - for (vat_block = start_block; - vat_block >= map->s_partition_root && - vat_block >= start_block - 3 && - !sbi->s_vat_inode; vat_block--) { - ino.logicalBlockNum = vat_block - map->s_partition_root; - sbi->s_vat_inode = udf_iget(sb, &ino); - } -} - -static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct udf_part_map *map = &sbi->s_partmaps[p_index]; - struct buffer_head *bh = NULL; - struct udf_inode_info *vati; - uint32_t pos; - struct virtualAllocationTable20 *vat20; - sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; - - udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block); - if (!sbi->s_vat_inode && - sbi->s_last_block != blocks - 1) { - pr_notice("Failed to read VAT inode from the last recorded block (%lu), retrying with the last block of the device (%lu).\n", - (unsigned long)sbi->s_last_block, - (unsigned long)blocks - 1); - udf_find_vat_block(sb, p_index, type1_index, blocks - 1); - } - if (!sbi->s_vat_inode) - return 1; - - if (map->s_partition_type == UDF_VIRTUAL_MAP15) { - map->s_type_specific.s_virtual.s_start_offset = 0; - map->s_type_specific.s_virtual.s_num_entries = - (sbi->s_vat_inode->i_size - 36) >> 2; - } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { - vati = UDF_I(sbi->s_vat_inode); - if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { - pos = udf_block_map(sbi->s_vat_inode, 0); - bh = sb_bread(sb, pos); - if (!bh) - return 1; - vat20 = (struct virtualAllocationTable20 *)bh->b_data; - } else { - vat20 = (struct virtualAllocationTable20 *) - vati->i_ext.i_data; - } - - map->s_type_specific.s_virtual.s_start_offset = - le16_to_cpu(vat20->lengthHeader); - map->s_type_specific.s_virtual.s_num_entries = - (sbi->s_vat_inode->i_size - - map->s_type_specific.s_virtual. - s_start_offset) >> 2; - brelse(bh); - } - return 0; -} - -static int udf_load_partdesc(struct super_block *sb, sector_t block) -{ - struct buffer_head *bh; - struct partitionDesc *p; - struct udf_part_map *map; - struct udf_sb_info *sbi = UDF_SB(sb); - int i, type1_idx; - uint16_t partitionNumber; - uint16_t ident; - int ret = 0; - - bh = udf_read_tagged(sb, block, block, &ident); - if (!bh) - return 1; - if (ident != TAG_IDENT_PD) - goto out_bh; - - p = (struct partitionDesc *)bh->b_data; - partitionNumber = le16_to_cpu(p->partitionNumber); - - /* First scan for TYPE1, SPARABLE and METADATA partitions */ - for (i = 0; i < sbi->s_partitions; i++) { - map = &sbi->s_partmaps[i]; - udf_debug("Searching map: (%d == %d)\n", - map->s_partition_num, partitionNumber); - if (map->s_partition_num == partitionNumber && - (map->s_partition_type == UDF_TYPE1_MAP15 || - map->s_partition_type == UDF_SPARABLE_MAP15)) - break; - } - - if (i >= sbi->s_partitions) { - udf_debug("Partition (%d) not found in partition map\n", - partitionNumber); - goto out_bh; - } - - ret = udf_fill_partdesc_info(sb, p, i); - - /* - * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and - * PHYSICAL partitions are already set up - */ - type1_idx = i; - for (i = 0; i < sbi->s_partitions; i++) { - map = &sbi->s_partmaps[i]; - - if (map->s_partition_num == partitionNumber && - (map->s_partition_type == UDF_VIRTUAL_MAP15 || - map->s_partition_type == UDF_VIRTUAL_MAP20 || - map->s_partition_type == UDF_METADATA_MAP25)) - break; - } - - if (i >= sbi->s_partitions) - goto out_bh; - - ret = udf_fill_partdesc_info(sb, p, i); - if (ret) - goto out_bh; - - if (map->s_partition_type == UDF_METADATA_MAP25) { - ret = udf_load_metadata_files(sb, i); - if (ret) { - udf_err(sb, "error loading MetaData partition map %d\n", - i); - goto out_bh; - } - } else { - ret = udf_load_vat(sb, i, type1_idx); - if (ret) - goto out_bh; - /* - * Mark filesystem read-only if we have a partition with - * virtual map since we don't handle writing to it (we - * overwrite blocks instead of relocating them). - */ - sb->s_flags |= MS_RDONLY; - pr_notice("Filesystem marked read-only because writing to pseudooverwrite partition is not implemented\n"); - } -out_bh: - /* In case loading failed, we handle cleanup in udf_fill_super */ - brelse(bh); - return ret; -} - -static int udf_load_sparable_map(struct super_block *sb, - struct udf_part_map *map, - struct sparablePartitionMap *spm) -{ - uint32_t loc; - uint16_t ident; - struct sparingTable *st; - struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; - int i; - struct buffer_head *bh; - - map->s_partition_type = UDF_SPARABLE_MAP15; - sdata->s_packet_len = le16_to_cpu(spm->packetLength); - if (!is_power_of_2(sdata->s_packet_len)) { - udf_err(sb, "error loading logical volume descriptor: " - "Invalid packet length %u\n", - (unsigned)sdata->s_packet_len); - return -EIO; - } - if (spm->numSparingTables > 4) { - udf_err(sb, "error loading logical volume descriptor: " - "Too many sparing tables (%d)\n", - (int)spm->numSparingTables); - return -EIO; - } - - for (i = 0; i < spm->numSparingTables; i++) { - loc = le32_to_cpu(spm->locSparingTable[i]); - bh = udf_read_tagged(sb, loc, loc, &ident); - if (!bh) - continue; - - st = (struct sparingTable *)bh->b_data; - if (ident != 0 || - strncmp(st->sparingIdent.ident, UDF_ID_SPARING, - strlen(UDF_ID_SPARING)) || - sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > - sb->s_blocksize) { - brelse(bh); - continue; - } - - sdata->s_spar_map[i] = bh; - } - map->s_partition_func = udf_get_pblock_spar15; - return 0; -} - -static int udf_load_logicalvol(struct super_block *sb, sector_t block, - struct kernel_lb_addr *fileset) -{ - struct logicalVolDesc *lvd; - int i, offset; - uint8_t type; - struct udf_sb_info *sbi = UDF_SB(sb); - struct genericPartitionMap *gpm; - uint16_t ident; - struct buffer_head *bh; - unsigned int table_len; - int ret = 0; - - bh = udf_read_tagged(sb, block, block, &ident); - if (!bh) - return 1; - BUG_ON(ident != TAG_IDENT_LVD); - lvd = (struct logicalVolDesc *)bh->b_data; - table_len = le32_to_cpu(lvd->mapTableLength); - if (sizeof(*lvd) + table_len > sb->s_blocksize) { - udf_err(sb, "error loading logical volume descriptor: " - "Partition table too long (%u > %lu)\n", table_len, - sb->s_blocksize - sizeof(*lvd)); - goto out_bh; - } - - ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); - if (ret) - goto out_bh; - - for (i = 0, offset = 0; - i < sbi->s_partitions && offset < table_len; - i++, offset += gpm->partitionMapLength) { - struct udf_part_map *map = &sbi->s_partmaps[i]; - gpm = (struct genericPartitionMap *) - &(lvd->partitionMaps[offset]); - type = gpm->partitionMapType; - if (type == 1) { - struct genericPartitionMap1 *gpm1 = - (struct genericPartitionMap1 *)gpm; - map->s_partition_type = UDF_TYPE1_MAP15; - map->s_volumeseqnum = le16_to_cpu(gpm1->volSeqNum); - map->s_partition_num = le16_to_cpu(gpm1->partitionNum); - map->s_partition_func = NULL; - } else if (type == 2) { - struct udfPartitionMap2 *upm2 = - (struct udfPartitionMap2 *)gpm; - if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, - strlen(UDF_ID_VIRTUAL))) { - u16 suf = - le16_to_cpu(((__le16 *)upm2->partIdent. - identSuffix)[0]); - if (suf < 0x0200) { - map->s_partition_type = - UDF_VIRTUAL_MAP15; - map->s_partition_func = - udf_get_pblock_virt15; - } else { - map->s_partition_type = - UDF_VIRTUAL_MAP20; - map->s_partition_func = - udf_get_pblock_virt20; - } - } else if (!strncmp(upm2->partIdent.ident, - UDF_ID_SPARABLE, - strlen(UDF_ID_SPARABLE))) { - if (udf_load_sparable_map(sb, map, - (struct sparablePartitionMap *)gpm) < 0) - goto out_bh; - } else if (!strncmp(upm2->partIdent.ident, - UDF_ID_METADATA, - strlen(UDF_ID_METADATA))) { - struct udf_meta_data *mdata = - &map->s_type_specific.s_metadata; - struct metadataPartitionMap *mdm = - (struct metadataPartitionMap *) - &(lvd->partitionMaps[offset]); - udf_debug("Parsing Logical vol part %d type %d id=%s\n", - i, type, UDF_ID_METADATA); - - map->s_partition_type = UDF_METADATA_MAP25; - map->s_partition_func = udf_get_pblock_meta25; - - mdata->s_meta_file_loc = - le32_to_cpu(mdm->metadataFileLoc); - mdata->s_mirror_file_loc = - le32_to_cpu(mdm->metadataMirrorFileLoc); - mdata->s_bitmap_file_loc = - le32_to_cpu(mdm->metadataBitmapFileLoc); - mdata->s_alloc_unit_size = - le32_to_cpu(mdm->allocUnitSize); - mdata->s_align_unit_size = - le16_to_cpu(mdm->alignUnitSize); - if (mdm->flags & 0x01) - mdata->s_flags |= MF_DUPLICATE_MD; - - udf_debug("Metadata Ident suffix=0x%x\n", - le16_to_cpu(*(__le16 *) - mdm->partIdent.identSuffix)); - udf_debug("Metadata part num=%d\n", - le16_to_cpu(mdm->partitionNum)); - udf_debug("Metadata part alloc unit size=%d\n", - le32_to_cpu(mdm->allocUnitSize)); - udf_debug("Metadata file loc=%d\n", - le32_to_cpu(mdm->metadataFileLoc)); - udf_debug("Mirror file loc=%d\n", - le32_to_cpu(mdm->metadataMirrorFileLoc)); - udf_debug("Bitmap file loc=%d\n", - le32_to_cpu(mdm->metadataBitmapFileLoc)); - udf_debug("Flags: %d %d\n", - mdata->s_flags, mdm->flags); - } else { - udf_debug("Unknown ident: %s\n", - upm2->partIdent.ident); - continue; - } - map->s_volumeseqnum = le16_to_cpu(upm2->volSeqNum); - map->s_partition_num = le16_to_cpu(upm2->partitionNum); - } - udf_debug("Partition (%d:%d) type %d on volume %d\n", - i, map->s_partition_num, type, map->s_volumeseqnum); - } - - if (fileset) { - struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]); - - *fileset = lelb_to_cpu(la->extLocation); - udf_debug("FileSet found in LogicalVolDesc at block=%d, partition=%d\n", - fileset->logicalBlockNum, - fileset->partitionReferenceNum); - } - if (lvd->integritySeqExt.extLength) - udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); - -out_bh: - brelse(bh); - return ret; -} - -/* - * udf_load_logicalvolint - * - */ -static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) -{ - struct buffer_head *bh = NULL; - uint16_t ident; - struct udf_sb_info *sbi = UDF_SB(sb); - struct logicalVolIntegrityDesc *lvid; - - while (loc.extLength > 0 && - (bh = udf_read_tagged(sb, loc.extLocation, - loc.extLocation, &ident)) && - ident == TAG_IDENT_LVID) { - sbi->s_lvid_bh = bh; - lvid = (struct logicalVolIntegrityDesc *)bh->b_data; - - if (lvid->nextIntegrityExt.extLength) - udf_load_logicalvolint(sb, - leea_to_cpu(lvid->nextIntegrityExt)); - - if (sbi->s_lvid_bh != bh) - brelse(bh); - loc.extLength -= sb->s_blocksize; - loc.extLocation++; - } - if (sbi->s_lvid_bh != bh) - brelse(bh); -} - -/* - * udf_process_sequence - * - * PURPOSE - * Process a main/reserve volume descriptor sequence. - * - * PRE-CONDITIONS - * sb Pointer to _locked_ superblock. - * block First block of first extent of the sequence. - * lastblock Lastblock of first extent of the sequence. - * - * HISTORY - * July 1, 1997 - Andrew E. Mileski - * Written, tested, and released. - */ -static noinline int udf_process_sequence(struct super_block *sb, long block, - long lastblock, struct kernel_lb_addr *fileset) -{ - struct buffer_head *bh = NULL; - struct udf_vds_record vds[VDS_POS_LENGTH]; - struct udf_vds_record *curr; - struct generic_desc *gd; - struct volDescPtr *vdp; - int done = 0; - uint32_t vdsn; - uint16_t ident; - long next_s = 0, next_e = 0; - - memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); - - /* - * Read the main descriptor sequence and find which descriptors - * are in it. - */ - for (; (!done && block <= lastblock); block++) { - - bh = udf_read_tagged(sb, block, block, &ident); - if (!bh) { - udf_err(sb, - "Block %llu of volume descriptor sequence is corrupted or we could not read it\n", - (unsigned long long)block); - return 1; - } - - /* Process each descriptor (ISO 13346 3/8.3-8.4) */ - gd = (struct generic_desc *)bh->b_data; - vdsn = le32_to_cpu(gd->volDescSeqNum); - switch (ident) { - case TAG_IDENT_PVD: /* ISO 13346 3/10.1 */ - curr = &vds[VDS_POS_PRIMARY_VOL_DESC]; - if (vdsn >= curr->volDescSeqNum) { - curr->volDescSeqNum = vdsn; - curr->block = block; - } - break; - case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */ - curr = &vds[VDS_POS_VOL_DESC_PTR]; - if (vdsn >= curr->volDescSeqNum) { - curr->volDescSeqNum = vdsn; - curr->block = block; - - vdp = (struct volDescPtr *)bh->b_data; - next_s = le32_to_cpu( - vdp->nextVolDescSeqExt.extLocation); - next_e = le32_to_cpu( - vdp->nextVolDescSeqExt.extLength); - next_e = next_e >> sb->s_blocksize_bits; - next_e += next_s; - } - break; - case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */ - curr = &vds[VDS_POS_IMP_USE_VOL_DESC]; - if (vdsn >= curr->volDescSeqNum) { - curr->volDescSeqNum = vdsn; - curr->block = block; - } - break; - case TAG_IDENT_PD: /* ISO 13346 3/10.5 */ - curr = &vds[VDS_POS_PARTITION_DESC]; - if (!curr->block) - curr->block = block; - break; - case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */ - curr = &vds[VDS_POS_LOGICAL_VOL_DESC]; - if (vdsn >= curr->volDescSeqNum) { - curr->volDescSeqNum = vdsn; - curr->block = block; - } - break; - case TAG_IDENT_USD: /* ISO 13346 3/10.8 */ - curr = &vds[VDS_POS_UNALLOC_SPACE_DESC]; - if (vdsn >= curr->volDescSeqNum) { - curr->volDescSeqNum = vdsn; - curr->block = block; - } - break; - case TAG_IDENT_TD: /* ISO 13346 3/10.9 */ - vds[VDS_POS_TERMINATING_DESC].block = block; - if (next_e) { - block = next_s; - lastblock = next_e; - next_s = next_e = 0; - } else - done = 1; - break; - } - brelse(bh); - } - /* - * Now read interesting descriptors again and process them - * in a suitable order - */ - if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) { - udf_err(sb, "Primary Volume Descriptor not found!\n"); - return 1; - } - if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block)) - return 1; - - if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb, - vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset)) - return 1; - - if (vds[VDS_POS_PARTITION_DESC].block) { - /* - * We rescan the whole descriptor sequence to find - * partition descriptor blocks and process them. - */ - for (block = vds[VDS_POS_PARTITION_DESC].block; - block < vds[VDS_POS_TERMINATING_DESC].block; - block++) - if (udf_load_partdesc(sb, block)) - return 1; - } - - return 0; -} - -static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh, - struct kernel_lb_addr *fileset) -{ - struct anchorVolDescPtr *anchor; - long main_s, main_e, reserve_s, reserve_e; - - anchor = (struct anchorVolDescPtr *)bh->b_data; - - /* Locate the main sequence */ - main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation); - main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength); - main_e = main_e >> sb->s_blocksize_bits; - main_e += main_s; - - /* Locate the reserve sequence */ - reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation); - reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength); - reserve_e = reserve_e >> sb->s_blocksize_bits; - reserve_e += reserve_s; - - /* Process the main & reserve sequences */ - /* responsible for finding the PartitionDesc(s) */ - if (!udf_process_sequence(sb, main_s, main_e, fileset)) - return 1; - return !udf_process_sequence(sb, reserve_s, reserve_e, fileset); -} - -/* - * Check whether there is an anchor block in the given block and - * load Volume Descriptor Sequence if so. - */ -static int udf_check_anchor_block(struct super_block *sb, sector_t block, - struct kernel_lb_addr *fileset) -{ - struct buffer_head *bh; - uint16_t ident; - int ret; - - if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && - udf_fixed_to_variable(block) >= - sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) - return 0; - - bh = udf_read_tagged(sb, block, block, &ident); - if (!bh) - return 0; - if (ident != TAG_IDENT_AVDP) { - brelse(bh); - return 0; - } - ret = udf_load_sequence(sb, bh, fileset); - brelse(bh); - return ret; -} - -/* Search for an anchor volume descriptor pointer */ -static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock, - struct kernel_lb_addr *fileset) -{ - sector_t last[6]; - int i; - struct udf_sb_info *sbi = UDF_SB(sb); - int last_count = 0; - - /* First try user provided anchor */ - if (sbi->s_anchor) { - if (udf_check_anchor_block(sb, sbi->s_anchor, fileset)) - return lastblock; - } - /* - * according to spec, anchor is in either: - * block 256 - * lastblock-256 - * lastblock - * however, if the disc isn't closed, it could be 512. - */ - if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset)) - return lastblock; - /* - * The trouble is which block is the last one. Drives often misreport - * this so we try various possibilities. - */ - last[last_count++] = lastblock; - if (lastblock >= 1) - last[last_count++] = lastblock - 1; - last[last_count++] = lastblock + 1; - if (lastblock >= 2) - last[last_count++] = lastblock - 2; - if (lastblock >= 150) - last[last_count++] = lastblock - 150; - if (lastblock >= 152) - last[last_count++] = lastblock - 152; - - for (i = 0; i < last_count; i++) { - if (last[i] >= sb->s_bdev->bd_inode->i_size >> - sb->s_blocksize_bits) - continue; - if (udf_check_anchor_block(sb, last[i], fileset)) - return last[i]; - if (last[i] < 256) - continue; - if (udf_check_anchor_block(sb, last[i] - 256, fileset)) - return last[i]; - } - - /* Finally try block 512 in case media is open */ - if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset)) - return last[0]; - return 0; -} - -/* - * Find an anchor volume descriptor and load Volume Descriptor Sequence from - * area specified by it. The function expects sbi->s_lastblock to be the last - * block on the media. - * - * Return 1 if ok, 0 if not found. - * - */ -static int udf_find_anchor(struct super_block *sb, - struct kernel_lb_addr *fileset) -{ - sector_t lastblock; - struct udf_sb_info *sbi = UDF_SB(sb); - - lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); - if (lastblock) - goto out; - - /* No anchor found? Try VARCONV conversion of block numbers */ - UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); - /* Firstly, we try to not convert number of the last block */ - lastblock = udf_scan_anchors(sb, - udf_variable_to_fixed(sbi->s_last_block), - fileset); - if (lastblock) - goto out; - - /* Secondly, we try with converted number of the last block */ - lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); - if (!lastblock) { - /* VARCONV didn't help. Clear it. */ - UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); - return 0; - } -out: - sbi->s_last_block = lastblock; - return 1; -} - -/* - * Check Volume Structure Descriptor, find Anchor block and load Volume - * Descriptor Sequence - */ -static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt, - int silent, struct kernel_lb_addr *fileset) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - loff_t nsr_off; - - if (!sb_set_blocksize(sb, uopt->blocksize)) { - if (!silent) - udf_warn(sb, "Bad block size\n"); - return 0; - } - sbi->s_last_block = uopt->lastblock; - if (!uopt->novrs) { - /* Check that it is NSR02 compliant */ - nsr_off = udf_check_vsd(sb); - if (!nsr_off) { - if (!silent) - udf_warn(sb, "No VRS found\n"); - return 0; - } - if (nsr_off == -1) - udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n"); - if (!sbi->s_last_block) - sbi->s_last_block = udf_get_last_block(sb); - } else { - udf_debug("Validity check skipped because of novrs option\n"); - } - - /* Look for anchor block and load Volume Descriptor Sequence */ - sbi->s_anchor = uopt->anchor; - if (!udf_find_anchor(sb, fileset)) { - if (!silent) - udf_warn(sb, "No anchor found\n"); - return 0; - } - return 1; -} - -static void udf_open_lvid(struct super_block *sb) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct buffer_head *bh = sbi->s_lvid_bh; - struct logicalVolIntegrityDesc *lvid; - struct logicalVolIntegrityDescImpUse *lvidiu; - - if (!bh) - return; - - mutex_lock(&sbi->s_alloc_mutex); - lvid = (struct logicalVolIntegrityDesc *)bh->b_data; - lvidiu = udf_sb_lvidiu(sbi); - - lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; - lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - udf_time_to_disk_stamp(&lvid->recordingDateAndTime, - CURRENT_TIME); - lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); - - lvid->descTag.descCRC = cpu_to_le16( - crc_itu_t(0, (char *)lvid + sizeof(struct tag), - le16_to_cpu(lvid->descTag.descCRCLength))); - - lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); - mark_buffer_dirty(bh); - sbi->s_lvid_dirty = 0; - mutex_unlock(&sbi->s_alloc_mutex); -} - -static void udf_close_lvid(struct super_block *sb) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - struct buffer_head *bh = sbi->s_lvid_bh; - struct logicalVolIntegrityDesc *lvid; - struct logicalVolIntegrityDescImpUse *lvidiu; - - if (!bh) - return; - - mutex_lock(&sbi->s_alloc_mutex); - lvid = (struct logicalVolIntegrityDesc *)bh->b_data; - lvidiu = udf_sb_lvidiu(sbi); - lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; - lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; - udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); - if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev)) - lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION); - if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev)) - lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev); - if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev)) - lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev); - lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); - - lvid->descTag.descCRC = cpu_to_le16( - crc_itu_t(0, (char *)lvid + sizeof(struct tag), - le16_to_cpu(lvid->descTag.descCRCLength))); - - lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); - /* - * We set buffer uptodate unconditionally here to avoid spurious - * warnings from mark_buffer_dirty() when previous EIO has marked - * the buffer as !uptodate - */ - set_buffer_uptodate(bh); - mark_buffer_dirty(bh); - sbi->s_lvid_dirty = 0; - mutex_unlock(&sbi->s_alloc_mutex); -} - -u64 lvid_get_unique_id(struct super_block *sb) -{ - struct buffer_head *bh; - struct udf_sb_info *sbi = UDF_SB(sb); - struct logicalVolIntegrityDesc *lvid; - struct logicalVolHeaderDesc *lvhd; - u64 uniqueID; - u64 ret; - - bh = sbi->s_lvid_bh; - if (!bh) - return 0; - - lvid = (struct logicalVolIntegrityDesc *)bh->b_data; - lvhd = (struct logicalVolHeaderDesc *)lvid->logicalVolContentsUse; - - mutex_lock(&sbi->s_alloc_mutex); - ret = uniqueID = le64_to_cpu(lvhd->uniqueID); - if (!(++uniqueID & 0xFFFFFFFF)) - uniqueID += 16; - lvhd->uniqueID = cpu_to_le64(uniqueID); - mutex_unlock(&sbi->s_alloc_mutex); - mark_buffer_dirty(bh); - - return ret; -} - -static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) -{ - int i; - int nr_groups = bitmap->s_nr_groups; - int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * - nr_groups); - - for (i = 0; i < nr_groups; i++) - if (bitmap->s_block_bitmap[i]) - brelse(bitmap->s_block_bitmap[i]); - - if (size <= PAGE_SIZE) - kfree(bitmap); - else - vfree(bitmap); -} - -static void udf_free_partition(struct udf_part_map *map) -{ - int i; - struct udf_meta_data *mdata; - - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) - iput(map->s_uspace.s_table); - if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) - iput(map->s_fspace.s_table); - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) - udf_sb_free_bitmap(map->s_uspace.s_bitmap); - if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) - udf_sb_free_bitmap(map->s_fspace.s_bitmap); - if (map->s_partition_type == UDF_SPARABLE_MAP15) - for (i = 0; i < 4; i++) - brelse(map->s_type_specific.s_sparing.s_spar_map[i]); - else if (map->s_partition_type == UDF_METADATA_MAP25) { - mdata = &map->s_type_specific.s_metadata; - iput(mdata->s_metadata_fe); - mdata->s_metadata_fe = NULL; - - iput(mdata->s_mirror_fe); - mdata->s_mirror_fe = NULL; - - iput(mdata->s_bitmap_fe); - mdata->s_bitmap_fe = NULL; - } -} - -static int udf_fill_super(struct super_block *sb, void *options, int silent) -{ - int i; - int ret; - struct inode *inode = NULL; - struct udf_options uopt; - struct kernel_lb_addr rootdir, fileset; - struct udf_sb_info *sbi; - - uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); - uopt.uid = -1; - uopt.gid = -1; - uopt.umask = 0; - uopt.fmode = UDF_INVALID_MODE; - uopt.dmode = UDF_INVALID_MODE; - - sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); - if (!sbi) - return -ENOMEM; - - sb->s_fs_info = sbi; - - mutex_init(&sbi->s_alloc_mutex); - - if (!udf_parse_options((char *)options, &uopt, false)) - goto error_out; - - if (uopt.flags & (1 << UDF_FLAG_UTF8) && - uopt.flags & (1 << UDF_FLAG_NLS_MAP)) { - udf_err(sb, "utf8 cannot be combined with iocharset\n"); - goto error_out; - } -#ifdef CONFIG_UDF_NLS - if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) { - uopt.nls_map = load_nls_default(); - if (!uopt.nls_map) - uopt.flags &= ~(1 << UDF_FLAG_NLS_MAP); - else - udf_debug("Using default NLS map\n"); - } -#endif - if (!(uopt.flags & (1 << UDF_FLAG_NLS_MAP))) - uopt.flags |= (1 << UDF_FLAG_UTF8); - - fileset.logicalBlockNum = 0xFFFFFFFF; - fileset.partitionReferenceNum = 0xFFFF; - - sbi->s_flags = uopt.flags; - sbi->s_uid = uopt.uid; - sbi->s_gid = uopt.gid; - sbi->s_umask = uopt.umask; - sbi->s_fmode = uopt.fmode; - sbi->s_dmode = uopt.dmode; - sbi->s_nls_map = uopt.nls_map; - rwlock_init(&sbi->s_cred_lock); - - if (uopt.session == 0xFFFFFFFF) - sbi->s_session = udf_get_last_session(sb); - else - sbi->s_session = uopt.session; - - udf_debug("Multi-session=%d\n", sbi->s_session); - - /* Fill in the rest of the superblock */ - sb->s_op = &udf_sb_ops; - sb->s_export_op = &udf_export_ops; - - sb->s_dirt = 0; - sb->s_magic = UDF_SUPER_MAGIC; - sb->s_time_gran = 1000; - - if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) { - ret = udf_load_vrs(sb, &uopt, silent, &fileset); - } else { - uopt.blocksize = bdev_logical_block_size(sb->s_bdev); - ret = udf_load_vrs(sb, &uopt, silent, &fileset); - if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) { - if (!silent) - pr_notice("Rescanning with blocksize %d\n", - UDF_DEFAULT_BLOCKSIZE); - uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; - ret = udf_load_vrs(sb, &uopt, silent, &fileset); - } - } - if (!ret) { - udf_warn(sb, "No partition found (1)\n"); - goto error_out; - } - - udf_debug("Lastblock=%d\n", sbi->s_last_block); - - if (sbi->s_lvid_bh) { - struct logicalVolIntegrityDescImpUse *lvidiu = - udf_sb_lvidiu(sbi); - uint16_t minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev); - uint16_t minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev); - /* uint16_t maxUDFWriteRev = - le16_to_cpu(lvidiu->maxUDFWriteRev); */ - - if (minUDFReadRev > UDF_MAX_READ_VERSION) { - udf_err(sb, "minUDFReadRev=%x (max is %x)\n", - le16_to_cpu(lvidiu->minUDFReadRev), - UDF_MAX_READ_VERSION); - goto error_out; - } else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION) - sb->s_flags |= MS_RDONLY; - - sbi->s_udfrev = minUDFWriteRev; - - if (minUDFReadRev >= UDF_VERS_USE_EXTENDED_FE) - UDF_SET_FLAG(sb, UDF_FLAG_USE_EXTENDED_FE); - if (minUDFReadRev >= UDF_VERS_USE_STREAMS) - UDF_SET_FLAG(sb, UDF_FLAG_USE_STREAMS); - } - - if (!sbi->s_partitions) { - udf_warn(sb, "No partition found (2)\n"); - goto error_out; - } - - if (sbi->s_partmaps[sbi->s_partition].s_partition_flags & - UDF_PART_FLAG_READ_ONLY) { - pr_notice("Partition marked readonly; forcing readonly mount\n"); - sb->s_flags |= MS_RDONLY; - } - - if (udf_find_fileset(sb, &fileset, &rootdir)) { - udf_warn(sb, "No fileset found\n"); - goto error_out; - } - - if (!silent) { - struct timestamp ts; - udf_time_to_disk_stamp(&ts, sbi->s_record_time); - udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n", - sbi->s_volume_ident, - le16_to_cpu(ts.year), ts.month, ts.day, - ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone)); - } - if (!(sb->s_flags & MS_RDONLY)) - udf_open_lvid(sb); - - /* Assign the root inode */ - /* assign inodes by physical block number */ - /* perhaps it's not extensible enough, but for now ... */ - inode = udf_iget(sb, &rootdir); - if (!inode) { - udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n", - rootdir.logicalBlockNum, rootdir.partitionReferenceNum); - goto error_out; - } - - /* Allocate a dentry for the root inode */ - sb->s_root = d_make_root(inode); - if (!sb->s_root) { - udf_err(sb, "Couldn't allocate root dentry\n"); - goto error_out; - } - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_max_links = UDF_MAX_LINKS; - return 0; - -error_out: - if (sbi->s_vat_inode) - iput(sbi->s_vat_inode); - if (sbi->s_partitions) - for (i = 0; i < sbi->s_partitions; i++) - udf_free_partition(&sbi->s_partmaps[i]); -#ifdef CONFIG_UDF_NLS - if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) - unload_nls(sbi->s_nls_map); -#endif - if (!(sb->s_flags & MS_RDONLY)) - udf_close_lvid(sb); - brelse(sbi->s_lvid_bh); - - kfree(sbi->s_partmaps); - kfree(sbi); - sb->s_fs_info = NULL; - - return -EINVAL; -} - -void _udf_err(struct super_block *sb, const char *function, - const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - /* mark sb error */ - if (!(sb->s_flags & MS_RDONLY)) - sb->s_dirt = 1; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - pr_err("error (device %s): %s: %pV", sb->s_id, function, &vaf); - - va_end(args); -} - -void _udf_warn(struct super_block *sb, const char *function, - const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - pr_warn("warning (device %s): %s: %pV", sb->s_id, function, &vaf); - - va_end(args); -} - -static void udf_put_super(struct super_block *sb) -{ - int i; - struct udf_sb_info *sbi; - - sbi = UDF_SB(sb); - - if (sbi->s_vat_inode) - iput(sbi->s_vat_inode); - if (sbi->s_partitions) - for (i = 0; i < sbi->s_partitions; i++) - udf_free_partition(&sbi->s_partmaps[i]); -#ifdef CONFIG_UDF_NLS - if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) - unload_nls(sbi->s_nls_map); -#endif - if (!(sb->s_flags & MS_RDONLY)) - udf_close_lvid(sb); - brelse(sbi->s_lvid_bh); - kfree(sbi->s_partmaps); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; -} - -static int udf_sync_fs(struct super_block *sb, int wait) -{ - struct udf_sb_info *sbi = UDF_SB(sb); - - mutex_lock(&sbi->s_alloc_mutex); - if (sbi->s_lvid_dirty) { - /* - * Blockdevice will be synced later so we don't have to submit - * the buffer for IO - */ - mark_buffer_dirty(sbi->s_lvid_bh); - sb->s_dirt = 0; - sbi->s_lvid_dirty = 0; - } - mutex_unlock(&sbi->s_alloc_mutex); - - return 0; -} - -static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct super_block *sb = dentry->d_sb; - struct udf_sb_info *sbi = UDF_SB(sb); - struct logicalVolIntegrityDescImpUse *lvidiu; - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); - - if (sbi->s_lvid_bh != NULL) - lvidiu = udf_sb_lvidiu(sbi); - else - lvidiu = NULL; - - buf->f_type = UDF_SUPER_MAGIC; - buf->f_bsize = sb->s_blocksize; - buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len; - buf->f_bfree = udf_count_free(sb); - buf->f_bavail = buf->f_bfree; - buf->f_files = (lvidiu != NULL ? (le32_to_cpu(lvidiu->numFiles) + - le32_to_cpu(lvidiu->numDirs)) : 0) - + buf->f_bfree; - buf->f_ffree = buf->f_bfree; - buf->f_namelen = UDF_NAME_LEN - 2; - buf->f_fsid.val[0] = (u32)id; - buf->f_fsid.val[1] = (u32)(id >> 32); - - return 0; -} - -static unsigned int udf_count_free_bitmap(struct super_block *sb, - struct udf_bitmap *bitmap) -{ - struct buffer_head *bh = NULL; - unsigned int accum = 0; - int index; - int block = 0, newblock; - struct kernel_lb_addr loc; - uint32_t bytes; - uint8_t *ptr; - uint16_t ident; - struct spaceBitmapDesc *bm; - - loc.logicalBlockNum = bitmap->s_extPosition; - loc.partitionReferenceNum = UDF_SB(sb)->s_partition; - bh = udf_read_ptagged(sb, &loc, 0, &ident); - - if (!bh) { - udf_err(sb, "udf_count_free failed\n"); - goto out; - } else if (ident != TAG_IDENT_SBD) { - brelse(bh); - udf_err(sb, "udf_count_free failed\n"); - goto out; - } - - bm = (struct spaceBitmapDesc *)bh->b_data; - bytes = le32_to_cpu(bm->numOfBytes); - index = sizeof(struct spaceBitmapDesc); /* offset in first block only */ - ptr = (uint8_t *)bh->b_data; - - while (bytes > 0) { - u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index); - accum += bitmap_weight((const unsigned long *)(ptr + index), - cur_bytes * 8); - bytes -= cur_bytes; - if (bytes) { - brelse(bh); - newblock = udf_get_lb_pblock(sb, &loc, ++block); - bh = udf_tread(sb, newblock); - if (!bh) { - udf_debug("read failed\n"); - goto out; - } - index = 0; - ptr = (uint8_t *)bh->b_data; - } - } - brelse(bh); -out: - return accum; -} - -static unsigned int udf_count_free_table(struct super_block *sb, - struct inode *table) -{ - unsigned int accum = 0; - uint32_t elen; - struct kernel_lb_addr eloc; - int8_t etype; - struct extent_position epos; - - mutex_lock(&UDF_SB(sb)->s_alloc_mutex); - epos.block = UDF_I(table)->i_location; - epos.offset = sizeof(struct unallocSpaceEntry); - epos.bh = NULL; - - while ((etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) - accum += (elen >> table->i_sb->s_blocksize_bits); - - brelse(epos.bh); - mutex_unlock(&UDF_SB(sb)->s_alloc_mutex); - - return accum; -} - -static unsigned int udf_count_free(struct super_block *sb) -{ - unsigned int accum = 0; - struct udf_sb_info *sbi; - struct udf_part_map *map; - - sbi = UDF_SB(sb); - if (sbi->s_lvid_bh) { - struct logicalVolIntegrityDesc *lvid = - (struct logicalVolIntegrityDesc *) - sbi->s_lvid_bh->b_data; - if (le32_to_cpu(lvid->numOfPartitions) > sbi->s_partition) { - accum = le32_to_cpu( - lvid->freeSpaceTable[sbi->s_partition]); - if (accum == 0xFFFFFFFF) - accum = 0; - } - } - - if (accum) - return accum; - - map = &sbi->s_partmaps[sbi->s_partition]; - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { - accum += udf_count_free_bitmap(sb, - map->s_uspace.s_bitmap); - } - if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { - accum += udf_count_free_bitmap(sb, - map->s_fspace.s_bitmap); - } - if (accum) - return accum; - - if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { - accum += udf_count_free_table(sb, - map->s_uspace.s_table); - } - if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { - accum += udf_count_free_table(sb, - map->s_fspace.s_table); - } - - return accum; -} diff --git a/ANDROID_3.4.5/fs/udf/symlink.c b/ANDROID_3.4.5/fs/udf/symlink.c deleted file mode 100644 index d7c6dbe4..00000000 --- a/ANDROID_3.4.5/fs/udf/symlink.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * symlink.c - * - * PURPOSE - * Symlink handling routines for the OSTA-UDF(tm) filesystem. - * - * 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) 1998-2001 Ben Fennema - * (C) 1999 Stelias Computing Inc - * - * HISTORY - * - * 04/16/99 blf Created. - * - */ - -#include "udfdecl.h" -#include <asm/uaccess.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/stat.h> -#include <linux/pagemap.h> -#include <linux/buffer_head.h> -#include "udf_i.h" - -static void udf_pc_to_char(struct super_block *sb, unsigned char *from, - int fromlen, unsigned char *to) -{ - struct pathComponent *pc; - int elen = 0; - unsigned char *p = to; - - while (elen < fromlen) { - pc = (struct pathComponent *)(from + elen); - switch (pc->componentType) { - case 1: - /* - * Symlink points to some place which should be agreed - * upon between originator and receiver of the media. Ignore. - */ - if (pc->lengthComponentIdent > 0) - break; - /* Fall through */ - case 2: - p = to; - *p++ = '/'; - break; - case 3: - memcpy(p, "../", 3); - p += 3; - break; - case 4: - memcpy(p, "./", 2); - p += 2; - /* that would be . - just ignore */ - break; - case 5: - p += udf_get_filename(sb, pc->componentIdent, p, - pc->lengthComponentIdent); - *p++ = '/'; - break; - } - elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; - } - if (p > to + 1) - p[-1] = '\0'; - else - p[0] = '\0'; -} - -static int udf_symlink_filler(struct file *file, struct page *page) -{ - struct inode *inode = page->mapping->host; - struct buffer_head *bh = NULL; - unsigned char *symlink; - int err = -EIO; - unsigned char *p = kmap(page); - struct udf_inode_info *iinfo; - uint32_t pos; - - iinfo = UDF_I(inode); - pos = udf_block_map(inode, 0); - - down_read(&iinfo->i_data_sem); - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr; - } else { - bh = sb_bread(inode->i_sb, pos); - - if (!bh) - goto out; - - symlink = bh->b_data; - } - - udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); - brelse(bh); - - up_read(&iinfo->i_data_sem); - SetPageUptodate(page); - kunmap(page); - unlock_page(page); - return 0; - -out: - up_read(&iinfo->i_data_sem); - SetPageError(page); - kunmap(page); - unlock_page(page); - return err; -} - -/* - * symlinks can't do much... - */ -const struct address_space_operations udf_symlink_aops = { - .readpage = udf_symlink_filler, -}; diff --git a/ANDROID_3.4.5/fs/udf/truncate.c b/ANDROID_3.4.5/fs/udf/truncate.c deleted file mode 100644 index 4b98fee8..00000000 --- a/ANDROID_3.4.5/fs/udf/truncate.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * truncate.c - * - * PURPOSE - * Truncate handling routines for the OSTA-UDF(tm) filesystem. - * - * 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 Stelias Computing Inc - * - * HISTORY - * - * 02/24/99 blf Created. - * - */ - -#include "udfdecl.h" -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/buffer_head.h> - -#include "udf_i.h" -#include "udf_sb.h" - -static void extent_trunc(struct inode *inode, struct extent_position *epos, - struct kernel_lb_addr *eloc, int8_t etype, uint32_t elen, - uint32_t nelen) -{ - struct kernel_lb_addr neloc = {}; - int last_block = (elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits; - int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits; - - if (nelen) { - if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { - udf_free_blocks(inode->i_sb, inode, eloc, 0, - last_block); - etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30); - } else - neloc = *eloc; - nelen = (etype << 30) | nelen; - } - - if (elen != nelen) { - udf_write_aext(inode, epos, &neloc, nelen, 0); - if (last_block - first_block > 0) { - if (etype == (EXT_RECORDED_ALLOCATED >> 30)) - mark_inode_dirty(inode); - - if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) - udf_free_blocks(inode->i_sb, inode, eloc, - first_block, - last_block - first_block); - } - } -} - -/* - * Truncate the last extent to match i_size. This function assumes - * that preallocation extent is already truncated. - */ -void udf_truncate_tail_extent(struct inode *inode) -{ - struct extent_position epos = {}; - struct kernel_lb_addr eloc; - uint32_t elen, nelen; - uint64_t lbcount = 0; - int8_t etype = -1, netype; - int adsize; - struct udf_inode_info *iinfo = UDF_I(inode); - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || - inode->i_size == iinfo->i_lenExtents) - return; - /* Are we going to delete the file anyway? */ - if (inode->i_nlink == 0) - return; - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - BUG(); - - /* Find the last extent in the file */ - while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { - etype = netype; - lbcount += elen; - if (lbcount > inode->i_size) { - if (lbcount - inode->i_size >= inode->i_sb->s_blocksize) - udf_warn(inode->i_sb, - "Too long extent after EOF in inode %u: i_size: %lld lbcount: %lld extent %u+%u\n", - (unsigned)inode->i_ino, - (long long)inode->i_size, - (long long)lbcount, - (unsigned)eloc.logicalBlockNum, - (unsigned)elen); - nelen = elen - (lbcount - inode->i_size); - epos.offset -= adsize; - extent_trunc(inode, &epos, &eloc, etype, elen, nelen); - epos.offset += adsize; - if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) - udf_err(inode->i_sb, - "Extent after EOF in inode %u\n", - (unsigned)inode->i_ino); - break; - } - } - /* This inode entry is in-memory only and thus we don't have to mark - * the inode dirty */ - iinfo->i_lenExtents = inode->i_size; - brelse(epos.bh); -} - -void udf_discard_prealloc(struct inode *inode) -{ - struct extent_position epos = { NULL, 0, {0, 0} }; - struct kernel_lb_addr eloc; - uint32_t elen; - uint64_t lbcount = 0; - int8_t etype = -1, netype; - int adsize; - struct udf_inode_info *iinfo = UDF_I(inode); - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || - inode->i_size == iinfo->i_lenExtents) - return; - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - adsize = 0; - - epos.block = iinfo->i_location; - - /* Find the last extent in the file */ - while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { - etype = netype; - lbcount += elen; - } - if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { - epos.offset -= adsize; - lbcount -= elen; - extent_trunc(inode, &epos, &eloc, etype, elen, 0); - if (!epos.bh) { - iinfo->i_lenAlloc = - epos.offset - - udf_file_entry_alloc_offset(inode); - mark_inode_dirty(inode); - } else { - struct allocExtDesc *aed = - (struct allocExtDesc *)(epos.bh->b_data); - aed->lengthAllocDescs = - cpu_to_le32(epos.offset - - sizeof(struct allocExtDesc)); - 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, epos.offset); - else - udf_update_tag(epos.bh->b_data, - sizeof(struct allocExtDesc)); - mark_buffer_dirty_inode(epos.bh, inode); - } - } - /* This inode entry is in-memory only and thus we don't have to mark - * the inode dirty */ - iinfo->i_lenExtents = lbcount; - 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); -} - -/* - * Truncate extents of inode to inode->i_size. This function can be used only - * for making file shorter. For making file longer, udf_extend_file() has to - * be used. - */ -void udf_truncate_extents(struct inode *inode) -{ - struct extent_position epos; - struct kernel_lb_addr eloc, neloc = {}; - uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; - int8_t etype; - struct super_block *sb = inode->i_sb; - sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset; - loff_t byte_offset; - int adsize; - struct udf_inode_info *iinfo = UDF_I(inode); - - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(struct short_ad); - else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(struct long_ad); - else - BUG(); - - etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); - byte_offset = (offset << sb->s_blocksize_bits) + - (inode->i_size & (sb->s_blocksize - 1)); - if (etype == -1) { - /* We should extend the file? */ - WARN_ON(byte_offset); - return; - } - epos.offset -= adsize; - extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); - epos.offset += adsize; - if (byte_offset) - lenalloc = epos.offset; - else - lenalloc = epos.offset - adsize; - - if (!epos.bh) - lenalloc -= udf_file_entry_alloc_offset(inode); - else - lenalloc -= sizeof(struct allocExtDesc); - - while ((etype = udf_current_aext(inode, &epos, &eloc, - &elen, 0)) != -1) { - if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { - udf_write_aext(inode, &epos, &neloc, nelen, 0); - if (indirect_ext_len) { - /* We managed to free all extents in the - * indirect extent - free it too */ - BUG_ON(!epos.bh); - udf_free_blocks(sb, inode, &epos.block, - 0, indirect_ext_len); - } else if (!epos.bh) { - iinfo->i_lenAlloc = lenalloc; - mark_inode_dirty(inode); - } else - udf_update_alloc_ext_desc(inode, - &epos, lenalloc); - brelse(epos.bh); - epos.offset = sizeof(struct allocExtDesc); - epos.block = eloc; - epos.bh = udf_tread(sb, - udf_get_lb_pblock(sb, &eloc, 0)); - if (elen) - indirect_ext_len = - (elen + sb->s_blocksize - 1) >> - sb->s_blocksize_bits; - else - indirect_ext_len = 1; - } else { - extent_trunc(inode, &epos, &eloc, etype, elen, 0); - epos.offset += adsize; - } - } - - if (indirect_ext_len) { - BUG_ON(!epos.bh); - udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len); - } else if (!epos.bh) { - iinfo->i_lenAlloc = lenalloc; - mark_inode_dirty(inode); - } else - udf_update_alloc_ext_desc(inode, &epos, lenalloc); - iinfo->i_lenExtents = inode->i_size; - - brelse(epos.bh); -} diff --git a/ANDROID_3.4.5/fs/udf/udf_i.h b/ANDROID_3.4.5/fs/udf/udf_i.h deleted file mode 100644 index bb8309dc..00000000 --- a/ANDROID_3.4.5/fs/udf/udf_i.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _UDF_I_H -#define _UDF_I_H - -/* - * The i_data_sem and i_mutex serve for protection of allocation information - * of a regular files and symlinks. This includes all extents belonging to - * the file/symlink, a fact whether data are in-inode or in external data - * blocks, preallocation, goal block information... When extents are read, - * i_mutex or i_data_sem must be held (for reading is enough in case of - * i_data_sem). When extents are changed, i_data_sem must be held for writing - * and also i_mutex must be held. - * - * For directories i_mutex is used for all the necessary protection. - */ - -struct udf_inode_info { - struct timespec i_crtime; - /* Physical address of inode */ - struct 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; - __u32 i_checkpoint; - unsigned i_alloc_type : 3; - unsigned i_efe : 1; /* extendedFileEntry */ - unsigned i_use : 1; /* unallocSpaceEntry */ - unsigned i_strat4096 : 1; - unsigned reserved : 26; - union { - struct short_ad *i_sad; - struct long_ad *i_lad; - __u8 *i_data; - } i_ext; - struct rw_semaphore i_data_sem; - struct inode vfs_inode; -}; - -static inline struct udf_inode_info *UDF_I(struct inode *inode) -{ - return list_entry(inode, struct udf_inode_info, vfs_inode); -} - -#endif /* _UDF_I_H) */ diff --git a/ANDROID_3.4.5/fs/udf/udf_sb.h b/ANDROID_3.4.5/fs/udf/udf_sb.h deleted file mode 100644 index 42ad69ac..00000000 --- a/ANDROID_3.4.5/fs/udf/udf_sb.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef __LINUX_UDF_SB_H -#define __LINUX_UDF_SB_H - -#include <linux/mutex.h> -#include <linux/bitops.h> - -/* Since UDF 2.01 is ISO 13346 based... */ -#define UDF_SUPER_MAGIC 0x15013346 - -#define UDF_MAX_READ_VERSION 0x0250 -#define UDF_MAX_WRITE_VERSION 0x0201 - -#define UDF_FLAG_USE_EXTENDED_FE 0 -#define UDF_VERS_USE_EXTENDED_FE 0x0200 -#define UDF_FLAG_USE_STREAMS 1 -#define UDF_VERS_USE_STREAMS 0x0200 -#define UDF_FLAG_USE_SHORT_AD 2 -#define UDF_FLAG_USE_AD_IN_ICB 3 -#define UDF_FLAG_USE_FILE_CTIME_EA 4 -#define UDF_FLAG_STRICT 5 -#define UDF_FLAG_UNDELETE 6 -#define UDF_FLAG_UNHIDE 7 -#define UDF_FLAG_VARCONV 8 -#define UDF_FLAG_NLS_MAP 9 -#define UDF_FLAG_UTF8 10 -#define UDF_FLAG_UID_FORGET 11 /* save -1 for uid to disk */ -#define UDF_FLAG_UID_IGNORE 12 /* use sb uid instead of on disk uid */ -#define UDF_FLAG_GID_FORGET 13 -#define UDF_FLAG_GID_IGNORE 14 -#define UDF_FLAG_UID_SET 15 -#define UDF_FLAG_GID_SET 16 -#define UDF_FLAG_SESSION_SET 17 -#define UDF_FLAG_LASTBLOCK_SET 18 -#define UDF_FLAG_BLOCKSIZE_SET 19 - -#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 -#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 -#define UDF_PART_FLAG_FREED_BITMAP 0x0004 -#define UDF_PART_FLAG_FREED_TABLE 0x0008 -#define UDF_PART_FLAG_READ_ONLY 0x0010 -#define UDF_PART_FLAG_WRITE_ONCE 0x0020 -#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 - -#define UDF_INVALID_MODE ((umode_t)-1) - -#pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */ - -#define MF_DUPLICATE_MD 0x01 -#define MF_MIRROR_FE_LOADED 0x02 - -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; - int s_flags; - 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; - __u32 s_last_block; - - struct buffer_head *s_lvid_bh; - - /* Default permissions */ - umode_t s_umask; - gid_t s_gid; - uid_t s_uid; - umode_t s_fmode; - umode_t s_dmode; - /* Lock protecting consistency of above permission settings */ - rwlock_t s_cred_lock; - - /* 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 */ - unsigned long s_flags; - - /* Encoding info */ - struct nls_table *s_nls_map; - - /* VAT inode */ - struct inode *s_vat_inode; - - struct mutex s_alloc_mutex; - /* Protected by s_alloc_mutex */ - unsigned int s_lvid_dirty; -}; - -static inline struct udf_sb_info *UDF_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi); - -int udf_compute_nr_groups(struct super_block *sb, u32 partition); - -static inline int UDF_QUERY_FLAG(struct super_block *sb, int flag) -{ - return test_bit(flag, &UDF_SB(sb)->s_flags); -} - -static inline void UDF_SET_FLAG(struct super_block *sb, int flag) -{ - set_bit(flag, &UDF_SB(sb)->s_flags); -} - -static inline void UDF_CLEAR_FLAG(struct super_block *sb, int flag) -{ - clear_bit(flag, &UDF_SB(sb)->s_flags); -} - -#endif /* __LINUX_UDF_SB_H */ diff --git a/ANDROID_3.4.5/fs/udf/udfdecl.h b/ANDROID_3.4.5/fs/udf/udfdecl.h deleted file mode 100644 index ebe10314..00000000 --- a/ANDROID_3.4.5/fs/udf/udfdecl.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef __UDF_DECL_H -#define __UDF_DECL_H - -#define pr_fmt(fmt) "UDF-fs: " fmt - -#include "ecma_167.h" -#include "osta_udf.h" - -#include <linux/fs.h> -#include <linux/types.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 - -extern __printf(3, 4) void _udf_err(struct super_block *sb, - const char *function, const char *fmt, ...); -#define udf_err(sb, fmt, ...) \ - _udf_err(sb, __func__, fmt, ##__VA_ARGS__) - -extern __printf(3, 4) void _udf_warn(struct super_block *sb, - const char *function, const char *fmt, ...); -#define udf_warn(sb, fmt, ...) \ - _udf_warn(sb, __func__, fmt, ##__VA_ARGS__) - -#define udf_info(fmt, ...) \ - pr_info("INFO " fmt, ##__VA_ARGS__) - -#undef UDFFS_DEBUG - -#ifdef UDFFS_DEBUG -#define udf_debug(fmt, ...) \ - printk(KERN_DEBUG pr_fmt("%s:%d:%s: " fmt), \ - __FILE__, __LINE__, __func__, ##__VA_ARGS__) -#else -#define udf_debug(fmt, ...) \ - no_printk(fmt, ##__VA_ARGS__) -#endif - -#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) ) -#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) ) - -#define UDF_EXTENT_LENGTH_MASK 0x3FFFFFFF -#define UDF_EXTENT_FLAG_MASK 0xC0000000 - -#define UDF_NAME_PAD 4 -#define UDF_NAME_LEN 256 -#define UDF_PATH_LEN 1023 - -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; -} - -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; -} - -/* computes tag checksum */ -u8 udf_tag_checksum(const struct tag *t); - -struct dentry; -struct inode; -struct task_struct; -struct buffer_head; -struct super_block; - -extern const struct export_operations udf_export_ops; -extern const struct inode_operations udf_dir_inode_operations; -extern const struct file_operations udf_dir_operations; -extern const struct inode_operations udf_file_inode_operations; -extern const struct file_operations udf_file_operations; -extern const struct inode_operations udf_symlink_inode_operations; -extern const struct address_space_operations udf_aops; -extern const struct address_space_operations udf_adinicb_aops; -extern const struct address_space_operations udf_symlink_aops; - -struct udf_fileident_bh { - struct buffer_head *sbh; - struct buffer_head *ebh; - int soffset; - int eoffset; -}; - -struct udf_vds_record { - uint32_t block; - uint32_t volDescSeqNum; -}; - -struct generic_desc { - struct tag descTag; - __le32 volDescSeqNum; -}; - -struct ustr { - uint8_t u_cmpID; - uint8_t u_name[UDF_NAME_LEN - 2]; - uint8_t u_len; -}; - -struct extent_position { - struct buffer_head *bh; - uint32_t offset; - struct kernel_lb_addr block; -}; - -/* super.c */ - -static inline void udf_updated_lvid(struct super_block *sb) -{ - struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh; - - BUG_ON(!bh); - WARN_ON_ONCE(((struct logicalVolIntegrityDesc *) - bh->b_data)->integrityType != - cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN)); - sb->s_dirt = 1; - UDF_SB(sb)->s_lvid_dirty = 1; -} -extern u64 lvid_get_unique_id(struct super_block *sb); -struct inode *udf_find_metadata_inode_efe(struct super_block *sb, - u32 meta_file_loc, u32 partition_num); - -/* namei.c */ -extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, - struct fileIdentDesc *, struct udf_fileident_bh *, - uint8_t *, uint8_t *); - -/* file.c */ -extern long udf_ioctl(struct file *, unsigned int, unsigned long); -/* inode.c */ -extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); -extern int udf_expand_file_adinicb(struct inode *); -extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); -extern struct buffer_head *udf_bread(struct inode *, int, int, int *); -extern int udf_setsize(struct inode *, loff_t); -extern void udf_read_inode(struct inode *); -extern void udf_evict_inode(struct inode *); -extern int udf_write_inode(struct inode *, struct writeback_control *wbc); -extern long udf_block_map(struct inode *, sector_t); -extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, - struct kernel_lb_addr *, uint32_t *, sector_t *); -extern int udf_add_aext(struct inode *, struct extent_position *, - struct kernel_lb_addr *, uint32_t, int); -extern void udf_write_aext(struct inode *, struct extent_position *, - struct kernel_lb_addr *, uint32_t, int); -extern int8_t udf_delete_aext(struct inode *, struct extent_position, - struct kernel_lb_addr, uint32_t); -extern int8_t udf_next_aext(struct inode *, struct extent_position *, - struct kernel_lb_addr *, uint32_t *, int); -extern int8_t udf_current_aext(struct inode *, struct extent_position *, - struct kernel_lb_addr *, uint32_t *, int); - -/* misc.c */ -extern struct buffer_head *udf_tgetblk(struct super_block *, int); -extern struct buffer_head *udf_tread(struct super_block *, int); -extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, - uint32_t, uint8_t); -extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, - uint8_t); -extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, - uint32_t, uint16_t *); -extern struct buffer_head *udf_read_ptagged(struct super_block *, - struct kernel_lb_addr *, uint32_t, - uint16_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 *); -extern unsigned long udf_get_last_block(struct super_block *); - -/* partition.c */ -extern uint32_t udf_get_pblock(struct super_block *, uint32_t, uint16_t, - uint32_t); -extern uint32_t udf_get_pblock_virt15(struct super_block *, uint32_t, uint16_t, - uint32_t); -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 *); - -static inline uint32_t -udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, - uint32_t offset) -{ - return udf_get_pblock(sb, loc->logicalBlockNum, - loc->partitionReferenceNum, offset); -} - -/* 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 *, const struct ustr *); - -/* ialloc.c */ -extern void udf_free_inode(struct inode *); -extern struct inode *udf_new_inode(struct inode *, umode_t, int *); - -/* truncate.c */ -extern void udf_truncate_tail_extent(struct inode *); -extern void udf_discard_prealloc(struct inode *); -extern void udf_truncate_extents(struct inode *); - -/* balloc.c */ -extern void udf_free_blocks(struct super_block *, struct inode *, - struct kernel_lb_addr *, uint32_t, uint32_t); -extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, - uint32_t, uint32_t); -extern int udf_new_block(struct super_block *, struct inode *, uint16_t, - uint32_t, int *); - -/* directory.c */ -extern struct fileIdentDesc *udf_fileident_read(struct inode *, loff_t *, - struct udf_fileident_bh *, - struct fileIdentDesc *, - struct extent_position *, - struct kernel_lb_addr *, uint32_t *, - sector_t *); -extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, - int *offset); -extern struct long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); -extern struct short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); - -/* udftime.c */ -extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest, - struct timestamp src); -extern struct timestamp *udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src); - -#endif /* __UDF_DECL_H */ diff --git a/ANDROID_3.4.5/fs/udf/udfend.h b/ANDROID_3.4.5/fs/udf/udfend.h deleted file mode 100644 index 6a9f3a9c..00000000 --- a/ANDROID_3.4.5/fs/udf/udfend.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __UDF_ENDIAN_H -#define __UDF_ENDIAN_H - -#include <asm/byteorder.h> -#include <linux/string.h> - -static inline struct kernel_lb_addr lelb_to_cpu(struct lb_addr in) -{ - struct kernel_lb_addr out; - - out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum); - out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum); - - return out; -} - -static inline struct lb_addr cpu_to_lelb(struct kernel_lb_addr in) -{ - struct lb_addr out; - - out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum); - out.partitionReferenceNum = cpu_to_le16(in.partitionReferenceNum); - - return out; -} - -static inline struct short_ad lesa_to_cpu(struct short_ad in) -{ - struct short_ad out; - - out.extLength = le32_to_cpu(in.extLength); - out.extPosition = le32_to_cpu(in.extPosition); - - return out; -} - -static inline struct short_ad cpu_to_lesa(struct short_ad in) -{ - struct short_ad out; - - out.extLength = cpu_to_le32(in.extLength); - out.extPosition = cpu_to_le32(in.extPosition); - - return out; -} - -static inline struct kernel_long_ad lela_to_cpu(struct long_ad in) -{ - struct kernel_long_ad out; - - out.extLength = le32_to_cpu(in.extLength); - out.extLocation = lelb_to_cpu(in.extLocation); - - return out; -} - -static inline struct long_ad cpu_to_lela(struct kernel_long_ad in) -{ - struct long_ad out; - - out.extLength = cpu_to_le32(in.extLength); - out.extLocation = cpu_to_lelb(in.extLocation); - - return out; -} - -static inline struct kernel_extent_ad leea_to_cpu(struct extent_ad in) -{ - struct kernel_extent_ad out; - - out.extLength = le32_to_cpu(in.extLength); - out.extLocation = le32_to_cpu(in.extLocation); - - return out; -} - -#endif /* __UDF_ENDIAN_H */ diff --git a/ANDROID_3.4.5/fs/udf/udftime.c b/ANDROID_3.4.5/fs/udf/udftime.c deleted file mode 100644 index 1f11483e..00000000 --- a/ANDROID_3.4.5/fs/udf/udftime.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Eggert (eggert@twinsun.com). - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * dgb 10/02/98: ripped this from glibc source to help convert timestamps - * to unix time - * 10/04/98: added new table-based lookup after seeing how ugly - * the gnu code is - * blf 09/27/99: ripped out all the old code and inserted new table from - * John Brockmeyer (without leap second corrections) - * rewrote udf_stamp_to_time and fixed timezone accounting in - * udf_time_to_stamp. - */ - -/* - * We don't take into account leap seconds. This may be correct or incorrect. - * For more NIST information (especially dealing with leap seconds), see: - * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm - */ - -#include "udfdecl.h" - -#include <linux/types.h> -#include <linux/kernel.h> - -#define EPOCH_YEAR 1970 - -#ifndef __isleap -/* Nonzero if YEAR is a leap year (every 4 years, - except every 100th isn't, and every 400th is). */ -#define __isleap(year) \ - ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) -#endif - -/* How many days come before each month (0-12). */ -static const unsigned short int __mon_yday[2][13] = { - /* Normal years. */ - {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, - /* Leap years. */ - {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} -}; - -#define MAX_YEAR_SECONDS 69 -#define SPD 0x15180 /*3600*24 */ -#define SPY(y, l, s) (SPD * (365 * y + l) + s) - -static time_t year_seconds[MAX_YEAR_SECONDS] = { -/*1970*/ SPY(0, 0, 0), SPY(1, 0, 0), SPY(2, 0, 0), SPY(3, 1, 0), -/*1974*/ SPY(4, 1, 0), SPY(5, 1, 0), SPY(6, 1, 0), SPY(7, 2, 0), -/*1978*/ SPY(8, 2, 0), SPY(9, 2, 0), SPY(10, 2, 0), SPY(11, 3, 0), -/*1982*/ SPY(12, 3, 0), SPY(13, 3, 0), SPY(14, 3, 0), SPY(15, 4, 0), -/*1986*/ SPY(16, 4, 0), SPY(17, 4, 0), SPY(18, 4, 0), SPY(19, 5, 0), -/*1990*/ SPY(20, 5, 0), SPY(21, 5, 0), SPY(22, 5, 0), SPY(23, 6, 0), -/*1994*/ SPY(24, 6, 0), SPY(25, 6, 0), SPY(26, 6, 0), SPY(27, 7, 0), -/*1998*/ SPY(28, 7, 0), SPY(29, 7, 0), SPY(30, 7, 0), SPY(31, 8, 0), -/*2002*/ SPY(32, 8, 0), SPY(33, 8, 0), SPY(34, 8, 0), SPY(35, 9, 0), -/*2006*/ SPY(36, 9, 0), SPY(37, 9, 0), SPY(38, 9, 0), SPY(39, 10, 0), -/*2010*/ SPY(40, 10, 0), SPY(41, 10, 0), SPY(42, 10, 0), SPY(43, 11, 0), -/*2014*/ SPY(44, 11, 0), SPY(45, 11, 0), SPY(46, 11, 0), SPY(47, 12, 0), -/*2018*/ SPY(48, 12, 0), SPY(49, 12, 0), SPY(50, 12, 0), SPY(51, 13, 0), -/*2022*/ SPY(52, 13, 0), SPY(53, 13, 0), SPY(54, 13, 0), SPY(55, 14, 0), -/*2026*/ SPY(56, 14, 0), SPY(57, 14, 0), SPY(58, 14, 0), SPY(59, 15, 0), -/*2030*/ SPY(60, 15, 0), SPY(61, 15, 0), SPY(62, 15, 0), SPY(63, 16, 0), -/*2034*/ SPY(64, 16, 0), SPY(65, 16, 0), SPY(66, 16, 0), SPY(67, 17, 0), -/*2038*/ SPY(68, 17, 0) -}; - -extern struct timezone sys_tz; - -#define SECS_PER_HOUR (60 * 60) -#define SECS_PER_DAY (SECS_PER_HOUR * 24) - -struct timespec * -udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src) -{ - int yday; - 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 = typeAndTimezone << 4; - /* sign extent offset */ - offset = (offset >> 4); - if (offset == -2047) /* unspecified offset */ - offset = 0; - } else - offset = 0; - - if ((year < EPOCH_YEAR) || - (year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) { - return NULL; - } - dest->tv_sec = year_seconds[year - EPOCH_YEAR]; - dest->tv_sec -= offset * 60; - - 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; -} - -struct timestamp * -udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts) -{ - long int days, rem, y; - const unsigned short int *ip; - int16_t offset; - - offset = -sys_tz.tz_minuteswest; - - if (!dest) - return NULL; - - dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF)); - - ts.tv_sec += offset * 60; - days = ts.tv_sec / SECS_PER_DAY; - rem = ts.tv_sec % SECS_PER_DAY; - dest->hour = rem / SECS_PER_HOUR; - rem %= SECS_PER_HOUR; - dest->minute = rem / 60; - dest->second = rem % 60; - y = 1970; - -#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) -#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) - - while (days < 0 || days >= (__isleap(y) ? 366 : 365)) { - long int yg = y + days / 365 - (days % 365 < 0); - - /* Adjust DAYS and Y to match the guessed year. */ - days -= ((yg - y) * 365 - + LEAPS_THRU_END_OF(yg - 1) - - LEAPS_THRU_END_OF(y - 1)); - y = yg; - } - dest->year = cpu_to_le16(y); - ip = __mon_yday[__isleap(y)]; - for (y = 11; days < (long int)ip[y]; --y) - continue; - days -= ip[y]; - dest->month = y + 1; - dest->day = days + 1; - - dest->centiseconds = ts.tv_nsec / 10000000; - dest->hundredsOfMicroseconds = (ts.tv_nsec / 1000 - - dest->centiseconds * 10000) / 100; - dest->microseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000 - - dest->hundredsOfMicroseconds * 100); - return dest; -} - -/* EOF */ diff --git a/ANDROID_3.4.5/fs/udf/unicode.c b/ANDROID_3.4.5/fs/udf/unicode.c deleted file mode 100644 index 44b815e5..00000000 --- a/ANDROID_3.4.5/fs/udf/unicode.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * unicode.c - * - * PURPOSE - * Routines for converting between UTF-8 and OSTA Compressed Unicode. - * Also handles filename mangling - * - * DESCRIPTION - * OSTA Compressed Unicode is explained in the OSTA UDF specification. - * http://www.osta.org/ - * UTF-8 is explained in the IETF RFC XXXX. - * ftp://ftp.internic.net/rfc/rfcxxxx.txt - * - * 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" - -#include <linux/kernel.h> -#include <linux/string.h> /* for memset */ -#include <linux/nls.h> -#include <linux/crc-itu-t.h> -#include <linux/slab.h> - -#include "udf_sb.h" - -static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); - -static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) -{ - if ((!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN - 2)) - return 0; - - memset(dest, 0, sizeof(struct ustr)); - memcpy(dest->u_name, src, strlen); - dest->u_cmpID = 0x08; - dest->u_len = strlen; - - return strlen; -} - -/* - * udf_build_ustr - */ -int udf_build_ustr(struct ustr *dest, dstring *ptr, int size) -{ - int usesize; - - if (!dest || !ptr || !size) - return -1; - BUG_ON(size < 2); - - 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 = usesize; - memcpy(dest->u_name, ptr + 1, usesize); - memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize); - - return 0; -} - -/* - * udf_build_ustr_exact - */ -static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) -{ - if ((!dest) || (!ptr) || (!exactsize)) - return -1; - - memset(dest, 0, sizeof(struct ustr)); - dest->u_cmpID = ptr[0]; - dest->u_len = exactsize - 1; - memcpy(dest->u_name, ptr + 1, exactsize - 1); - - return 0; -} - -/* - * udf_ocu_to_utf8 - * - * PURPOSE - * Convert OSTA Compressed Unicode to the UTF-8 equivalent. - * - * PRE-CONDITIONS - * utf Pointer to UTF-8 output buffer. - * ocu Pointer to OSTA Compressed Unicode input buffer - * of size UDF_NAME_LEN bytes. - * both of type "struct ustr *" - * - * POST-CONDITIONS - * <return> Zero on success. - * - * HISTORY - * November 12, 1997 - Andrew E. Mileski - * Written, tested, and released. - */ -int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i) -{ - const uint8_t *ocu; - uint8_t cmp_id, ocu_len; - int i; - - ocu_len = ocu_i->u_len; - if (ocu_len == 0) { - memset(utf_o, 0, sizeof(struct ustr)); - return 0; - } - - cmp_id = ocu_i->u_cmpID; - if (cmp_id != 8 && cmp_id != 16) { - memset(utf_o, 0, sizeof(struct ustr)); - pr_err("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 */ - uint32_t c = ocu[i++]; - if (cmp_id == 16) - c = (c << 8) | ocu[i++]; - - /* Compress Unicode to UTF-8 */ - if (c < 0x80U) - utf_o->u_name[utf_o->u_len++] = (uint8_t)c; - 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++] = - (uint8_t)(0x80 | (c & 0x3f)); - } else { - utf_o->u_name[utf_o->u_len++] = - (uint8_t)(0xe0 | (c >> 12)); - utf_o->u_name[utf_o->u_len++] = - (uint8_t)(0x80 | - ((c >> 6) & 0x3f)); - utf_o->u_name[utf_o->u_len++] = - (uint8_t)(0x80 | (c & 0x3f)); - } - } - utf_o->u_cmpID = 8; - - return utf_o->u_len; -} - -/* - * - * udf_utf8_to_ocu - * - * PURPOSE - * Convert UTF-8 to the OSTA Compressed Unicode equivalent. - * - * DESCRIPTION - * This routine is only called by udf_lookup(). - * - * PRE-CONDITIONS - * ocu Pointer to OSTA Compressed Unicode output - * buffer of size UDF_NAME_LEN bytes. - * utf Pointer to UTF-8 input buffer. - * utf_len Length of UTF-8 input buffer in bytes. - * - * POST-CONDITIONS - * <return> Zero on success. - * - * HISTORY - * November 12, 1997 - Andrew E. Mileski - * Written, tested, and released. - */ -static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length) -{ - unsigned c, i, max_val, utf_char; - int utf_cnt, u_len; - - memset(ocu, 0, sizeof(dstring) * length); - ocu[0] = 8; - max_val = 0xffU; - -try_again: - u_len = 0U; - utf_char = 0U; - utf_cnt = 0U; - for (i = 0U; i < utf->u_len; i++) { - c = (uint8_t)utf->u_name[i]; - - /* Complete a multi-byte UTF-8 character */ - if (utf_cnt) { - utf_char = (utf_char << 6) | (c & 0x3fU); - if (--utf_cnt) - continue; - } else { - /* Check for a multi-byte UTF-8 character */ - if (c & 0x80U) { - /* Start a multi-byte UTF-8 character */ - if ((c & 0xe0U) == 0xc0U) { - utf_char = c & 0x1fU; - utf_cnt = 1; - } else if ((c & 0xf0U) == 0xe0U) { - utf_char = c & 0x0fU; - utf_cnt = 2; - } else if ((c & 0xf8U) == 0xf0U) { - utf_char = c & 0x07U; - utf_cnt = 3; - } else if ((c & 0xfcU) == 0xf8U) { - utf_char = c & 0x03U; - utf_cnt = 4; - } else if ((c & 0xfeU) == 0xfcU) { - utf_char = c & 0x01U; - utf_cnt = 5; - } else { - goto error_out; - } - continue; - } else { - /* Single byte UTF-8 character (most common) */ - utf_char = c; - } - } - - /* Choose no compression if necessary */ - if (utf_char > max_val) { - if (max_val == 0xffU) { - max_val = 0xffffU; - ocu[0] = (uint8_t)0x10U; - goto try_again; - } - goto error_out; - } - - if (max_val == 0xffffU) - ocu[++u_len] = (uint8_t)(utf_char >> 8); - ocu[++u_len] = (uint8_t)(utf_char & 0xffU); - } - - if (utf_cnt) { -error_out: - ocu[++u_len] = '?'; - printk(KERN_DEBUG pr_fmt("bad UTF-8 character\n")); - } - - ocu[length - 1] = (uint8_t)u_len + 1; - - return u_len + 1; -} - -static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, - const struct ustr *ocu_i) -{ - const uint8_t *ocu; - uint8_t cmp_id, ocu_len; - int i, len; - - - ocu_len = ocu_i->u_len; - if (ocu_len == 0) { - memset(utf_o, 0, sizeof(struct ustr)); - return 0; - } - - cmp_id = ocu_i->u_cmpID; - if (cmp_id != 8 && cmp_id != 16) { - memset(utf_o, 0, sizeof(struct ustr)); - pr_err("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 */ - uint32_t c = ocu[i++]; - if (cmp_id == 16) - c = (c << 8) | ocu[i++]; - - len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len], - UDF_NAME_LEN - utf_o->u_len); - /* Valid character? */ - if (len >= 0) - utf_o->u_len += len; - else - utf_o->u_name[utf_o->u_len++] = '?'; - } - utf_o->u_cmpID = 8; - - return utf_o->u_len; -} - -static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, - int length) -{ - int len; - unsigned i, max_val; - uint16_t uni_char; - int u_len; - - memset(ocu, 0, sizeof(dstring) * length); - ocu[0] = 8; - max_val = 0xffU; - -try_again: - u_len = 0U; - for (i = 0U; i < uni->u_len; i++) { - len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char); - if (!len) - continue; - /* Invalid character, deal with it */ - if (len < 0) { - len = 1; - uni_char = '?'; - } - - if (uni_char > max_val) { - max_val = 0xffffU; - ocu[0] = (uint8_t)0x10U; - goto try_again; - } - - if (max_val == 0xffffU) - ocu[++u_len] = (uint8_t)(uni_char >> 8); - ocu[++u_len] = (uint8_t)(uni_char & 0xffU); - i += len - 1; - } - - ocu[length - 1] = (uint8_t)u_len + 1; - return u_len + 1; -} - -int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, - int flen) -{ - struct ustr *filename, *unifilename; - int len = 0; - - filename = kmalloc(sizeof(struct ustr), GFP_NOFS); - if (!filename) - return 0; - - unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS); - if (!unifilename) - goto out1; - - if (udf_build_ustr_exact(unifilename, sname, flen)) - goto out2; - - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { - if (!udf_CS0toUTF8(filename, unifilename)) { - udf_debug("Failed in udf_get_filename: sname = %s\n", - sname); - goto out2; - } - } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { - if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename, - unifilename)) { - udf_debug("Failed in udf_get_filename: sname = %s\n", - sname); - goto out2; - } - } else - goto out2; - - len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, - unifilename->u_name, unifilename->u_len); -out2: - kfree(unifilename); -out1: - kfree(filename); - return len; -} - -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)) { - namelen = udf_UTF8toCS0(dname, &unifilename, UDF_NAME_LEN); - if (!namelen) - return 0; - } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { - namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, dname, - &unifilename, UDF_NAME_LEN); - if (!namelen) - return 0; - } else - return 0; - - return namelen; -} - -#define ILLEGAL_CHAR_MARK '_' -#define EXT_MARK '.' -#define CRC_MARK '#' -#define EXT_SIZE 5 - -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; - unsigned short valueCRC; - uint8_t curr; - const uint8_t hexChar[] = "0123456789ABCDEF"; - - if (udfName[0] == '.' && - (udfLen == 1 || (udfLen == 2 && udfName[1] == '.'))) { - needsCRC = 1; - newIndex = udfLen; - memcpy(newName, udfName, udfLen); - } else { - for (index = 0; index < udfLen; index++) { - curr = udfName[index]; - if (curr == '/' || curr == 0) { - needsCRC = 1; - curr = ILLEGAL_CHAR_MARK; - while (index + 1 < udfLen && - (udfName[index + 1] == '/' || - udfName[index + 1] == 0)) - index++; - } - if (curr == EXT_MARK && - (udfLen - index - 1) <= EXT_SIZE) { - if (udfLen == index + 1) - hasExt = 0; - else { - hasExt = 1; - extIndex = index; - newExtIndex = newIndex; - } - } - if (newIndex < 256) - newName[newIndex++] = curr; - else - needsCRC = 1; - } - } - if (needsCRC) { - uint8_t ext[EXT_SIZE]; - int localExtIndex = 0; - - if (hasExt) { - int maxFilenameLen; - for (index = 0; - index < EXT_SIZE && extIndex + index + 1 < udfLen; - index++) { - curr = udfName[extIndex + index + 1]; - - if (curr == '/' || curr == 0) { - needsCRC = 1; - curr = ILLEGAL_CHAR_MARK; - while (extIndex + index + 2 < udfLen && - (index + 1 < EXT_SIZE && - (udfName[extIndex + index + 2] == '/' || - udfName[extIndex + index + 2] == 0))) - index++; - } - ext[localExtIndex++] = curr; - } - maxFilenameLen = 250 - localExtIndex; - if (newIndex > maxFilenameLen) - newIndex = maxFilenameLen; - else - newIndex = newExtIndex; - } else if (newIndex > 250) - newIndex = 250; - newName[newIndex++] = CRC_MARK; - 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]; - newName[newIndex++] = hexChar[(valueCRC & 0x000f)]; - - if (hasExt) { - newName[newIndex++] = EXT_MARK; - for (index = 0; index < localExtIndex; index++) - newName[newIndex++] = ext[index]; - } - } - - return newIndex; -} |