/* * Read uncompressed xattr id lookup table indexes from disk into memory */ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, u64 *xattr_table_start, int *xattr_ids) { unsigned int len; struct squashfs_xattr_id_table *id_table; id_table = squashfs_read_table(sb, start, sizeof(*id_table)); if (IS_ERR(id_table)) return (__le64 *) id_table; *xattr_table_start = le64_to_cpu(id_table->xattr_table_start); *xattr_ids = le32_to_cpu(id_table->xattr_ids); kfree(id_table); /* Sanity check values */ /* there is always at least one xattr id */ if (*xattr_ids == 0) return ERR_PTR(-EINVAL); /* xattr_table should be less than start */ if (*xattr_table_start >= start) return ERR_PTR(-EINVAL); len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); TRACE("In read_xattr_index_table, length %d\n", len); return squashfs_read_table(sb, start + sizeof(*id_table), len); }
__le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, u64 *xattr_table_start, int *xattr_ids) { unsigned int len; struct squashfs_xattr_id_table *id_table; id_table = squashfs_read_table(sb, start, sizeof(*id_table)); if (IS_ERR(id_table)) return (__le64 *) id_table; *xattr_table_start = le64_to_cpu(id_table->xattr_table_start); *xattr_ids = le32_to_cpu(id_table->xattr_ids); kfree(id_table); if (*xattr_ids == 0) return ERR_PTR(-EINVAL); if (*xattr_table_start >= start) return ERR_PTR(-EINVAL); len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); TRACE("In read_xattr_index_table, length %d\n", len); return squashfs_read_table(sb, start + sizeof(*id_table), len); }
/* * Read and decompress the xattr id table and the xattr metadata. * This is cached in memory for later use by get_xattr() */ int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) { int res, bytes, i, indexes, index_bytes, ids; long long *index, start, end; struct squashfs_xattr_table id_table; TRACE("read_xattrs_from_disk\n"); if (sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK) return SQUASHFS_INVALID_BLK; /* * Read xattr id table, containing start of xattr metadata and the * number of xattrs in the file system */ res = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table), &id_table); if (res == 0) return 0; SQUASHFS_INSWAP_XATTR_TABLE(&id_table); /* * Allocate and read the index to the xattr id table metadata * blocks */ ids = id_table.xattr_ids; xattr_table_start = id_table.xattr_table_start; index_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids); indexes = SQUASHFS_XATTR_BLOCKS(ids); index = malloc(index_bytes); if (index == NULL) MEM_ERROR(); res = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table), index_bytes, index); if (res == 0) goto failed1; SQUASHFS_INSWAP_LONG_LONGS(index, indexes); /* * Allocate enough space for the uncompressed xattr id table, and * read and decompress it */ bytes = SQUASHFS_XATTR_BYTES(ids); xattr_ids = malloc(bytes); if (xattr_ids == NULL) MEM_ERROR(); for (i = 0; i < indexes; i++) { int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1); int length = read_block(fd, index[i], NULL, expected, ((unsigned char *)xattr_ids) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr id table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if (length == 0) { ERROR("Failed to read xattr id table block %d, " "from 0x%llx, length %d\n", i, index[i], length); goto failed2; } } /* * Read and decompress the xattr metadata * * Note the first xattr id table metadata block is immediately after * the last xattr metadata block, so we can use index[0] to work out * the end of the xattr metadata */ start = xattr_table_start; end = index[0]; for (i = 0; start < end; i++) { int length; xattrs = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE); if (xattrs == NULL) MEM_ERROR(); /* store mapping from location of compressed block in fs -> * location of uncompressed block in memory */ save_xattr_block(start, i * SQUASHFS_METADATA_SIZE); length = read_block(fd, start, &start, 0, ((unsigned char *)xattrs) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr block %d, length %d\n", i, length); if (length == 0) { ERROR("Failed to read xattr block %d\n", i); goto failed3; } /* * If this is not the last metadata block in the xattr metadata * then it should be SQUASHFS_METADATA_SIZE in size. * Note, we can't use expected in read_block() above for this * because we don't know if this is the last block until * after reading. */ if (start != end && length != SQUASHFS_METADATA_SIZE) { ERROR("Xattr block %d should be %d bytes in length, " "it is %d bytes\n", i, SQUASHFS_METADATA_SIZE, length); goto failed3; } } /* swap if necessary the xattr id entries */ for (i = 0; i < ids; i++) SQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]); free(index); return ids; failed3: free(xattrs); failed2: free(xattr_ids); failed1: free(index); return 0; }
/* * Read and decompress the xattr id table and the xattr metadata. * This is cached in memory for later use by get_xattr() */ int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) { int res, bytes, i, indexes, index_bytes, ids; long long *index, start, end; struct squashfs_xattr_table id_table; TRACE("read_xattrs_from_disk\n"); if(sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK) return SQUASHFS_INVALID_BLK; /* * Read xattr id table, containing start of xattr metadata and the * number of xattrs in the file system */ res = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table), &id_table); if(res == 0) return 0; SQUASHFS_INSWAP_XATTR_TABLE(&id_table); /* * Allocate and read the index to the xattr id table metadata * blocks */ ids = id_table.xattr_ids; xattr_table_start = id_table.xattr_table_start; index_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids); indexes = SQUASHFS_XATTR_BLOCKS(ids); index = malloc(index_bytes); if(index == NULL) { ERROR("Failed to allocate index array\n"); return 0; } res = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table), index_bytes, index); if(res ==0) goto failed1; SQUASHFS_INSWAP_LONG_LONGS(index, indexes); /* * Allocate enough space for the uncompressed xattr id table, and * read and decompress it */ bytes = SQUASHFS_XATTR_BYTES(ids); xattr_ids = malloc(bytes); if(xattr_ids == NULL) { ERROR("Failed to allocate xattr id table\n"); goto failed1; } for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) xattr_ids) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr id table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read xattr id table block %d, " "from 0x%llx, length %d\n", i, index[i], length); goto failed2; } } /* * Read and decompress the xattr metadata * * Note the first xattr id table metadata block is immediately after * the last xattr metadata block, so we can use index[0] to work out * the end of the xattr metadata */ start = xattr_table_start; end = index[0]; for(i = 0; start < end; i++) { int length; void *x = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE); if(x == NULL) { ERROR("Failed to realloc xattr data\n"); goto failed3; } xattrs = x; /* store mapping from location of compressed block in fs -> * location of uncompressed block in memory */ res = save_xattr_block(start, i * SQUASHFS_METADATA_SIZE); if(res == -1) goto failed3; length = read_block(fd, start, &start, ((unsigned char *) xattrs) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr block %d, length %d\n", i, length); if(length == 0) { ERROR("Failed to read xattr block %d\n", i); goto failed3; } } /* swap if necessary the xattr id entries */ for(i = 0; i < ids; i++) SQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]); free(index); return ids; failed3: free(xattrs); failed2: free(xattr_ids); failed1: free(index); return 0; }