imager.c revision 72ed12648368b3f3ea14e8102e20bf5d3a3be6d3
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * image.c --- writes out the critical parts of the filesystem as a 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * flat file. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2000 Theodore Ts'o. 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Note: this uses the POSIX IO interfaces, unlike most of the other 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * functions in this library. So sue me. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * %Begin-Header% 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This file may be redistributed under the terms of the GNU Public 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * %End-Header% 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stdio.h> 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <string.h> 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE_UNISTD_H 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <unistd.h> 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE_ERRNO_H 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <errno.h> 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <fcntl.h> 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <time.h> 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE_SYS_STAT_H 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <sys/stat.h> 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE_SYS_TYPES_H 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <sys/types.h> 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#if EXT2_FLAT_INCLUDES 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "ext2_fs.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#else 361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <linux/ext2_fs.h> 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif 381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "ext2fs.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* 421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) * This function returns 1 if the specified block is all zeros 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static int check_zero_block(char *buf, int blocksize) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *cp = buf; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int left = blocksize; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (left > 0) { 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (*cp++) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left--; 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 1; 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Write the inode table out as a single block. 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define BUF_BLOCKS 32 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned int group, left, c, d; 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *buf, *cp; 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk_t blk; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ssize_t actual; 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errcode_t retval; 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 70e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch buf = malloc(fs->blocksize * BUF_BLOCKS); 71e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (!buf) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ENOMEM; 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (group = 0; group < fs->group_desc_count; group++) { 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk = fs->group_desc[(unsigned)group].bg_inode_table; 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!blk) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return EXT2_ET_MISSING_INODE_TABLE; 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left = fs->inode_blocks_per_group; 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (left) { 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c = BUF_BLOCKS; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (c > left) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c = left; 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = io_channel_read_blk(fs->io, blk, c, buf); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (retval) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cp = buf; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (c) { 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!(flags & IMAGER_FLAG_SPARSEWRITE)) { 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) d = c; 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto skip_sparse; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* Skip zero blocks */ 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (check_zero_block(cp, fs->blocksize)) { 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c--; 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk++; 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left--; 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cp += fs->blocksize; 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lseek(fd, fs->blocksize, SEEK_CUR); 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* Find non-zero blocks */ 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (d=1; d < c; d++) { 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (check_zero_block(cp + d*fs->blocksize, fs->blocksize)) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skip_sparse: 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = write(fd, cp, fs->blocksize * d); 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != fs->blocksize * d) { 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_WRITE; 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk += d; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left -= d; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cp += fs->blocksize * d; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c -= d; 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = 0; 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errout: 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) free(buf); 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Read in the inode table and stuff it into place 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags) 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned int group, i, c, left; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *buf; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk_t blk; 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ssize_t actual; 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errcode_t retval; 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf = malloc(fs->blocksize * BUF_BLOCKS); 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!buf) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ENOMEM; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (group = 0; group < fs->group_desc_count; group++) { 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk = fs->group_desc[(unsigned)group].bg_inode_table; 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!blk) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return EXT2_ET_MISSING_INODE_TABLE; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left = fs->inode_blocks_per_group; 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (left) { 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c = BUF_BLOCKS; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (c > left) 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c = left; 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = read(fd, buf, fs->blocksize * c); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != fs->blocksize * c) { 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_READ; 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = io_channel_write_blk(fs->io, blk, c, buf); 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (retval) 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk += c; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left -= c; 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = ext2fs_flush_icache(fs); 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errout: 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) free(buf); 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Write out superblock and group descriptors 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags) 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned int i; 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *buf, *cp; 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blk_t blk; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ssize_t actual; 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errcode_t retval; 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf = malloc(fs->blocksize); 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!buf) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ENOMEM; 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Write out the superblock 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memset(buf, 0, fs->blocksize); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(buf, fs->super, SUPERBLOCK_SIZE); 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = write(fd, buf, fs->blocksize); 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != fs->blocksize) { 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_WRITE; 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Now write out the block group descriptors 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cp = (char *) fs->group_desc; 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = write(fd, cp, fs->blocksize * fs->desc_blocks); 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != fs->blocksize * fs->desc_blocks) { 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_WRITE; 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = 0; 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errout: 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) free(buf); 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Read the superblock and group descriptors and overwrite them. 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned int i; 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *buf, *cp; 2365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) blk_t blk; 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ssize_t actual, size; 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errcode_t retval; 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = fs->blocksize * (fs->group_desc_count + 1); 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf = malloc(size); 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!buf) 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ENOMEM; 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Read it all in. 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = read(fd, buf, size); 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != size) { 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_READ; 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /* 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Now copy in the superblock and group descriptors 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(fs->super, buf, SUPERBLOCK_SIZE); 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(fs->group_desc, buf + fs->blocksize, 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fs->blocksize * fs->group_desc_count); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = 0; 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errout: 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) free(buf); 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Write the block/inode bitmaps. 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *ptr; 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int c, size; 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char zero_buf[1024]; 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ssize_t actual; 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errcode_t retval; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (flags & IMAGER_FLAG_INODEMAP) { 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fs->inode_map) { 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = ext2fs_read_inode_bitmap(fs); 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (retval) 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ptr = fs->inode_map->bitmap; 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fs->block_map) { 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = ext2fs_read_block_bitmap(fs); 2958abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (retval) 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ptr = fs->block_map->bitmap; 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = write(fd, ptr, size); 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != size) { 308f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) retval = EXT2_ET_SHORT_WRITE; 309f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) goto errout; 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = size % fs->blocksize; 312f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) memset(zero_buf, 0, sizeof(zero_buf)); 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (size) { 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = fs->blocksize - size; 315f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) while (size) { 316f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) c = size; 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (c > sizeof(zero_buf)) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c = sizeof(zero_buf); 319f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) actual = write(fd, zero_buf, c); 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual == -1) { 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != c) { 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_WRITE; 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size -= c; 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = 0; 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errout: 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (retval); 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Read the block/inode bitmaps. 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char *ptr, *buf = 0; 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int c, size; 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) char zero_buf[1024]; 345f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) ssize_t actual; 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errcode_t retval; 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 348f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (flags & IMAGER_FLAG_INODEMAP) { 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fs->inode_map) { 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = ext2fs_read_inode_bitmap(fs); 351f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (retval) 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 354f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) ptr = fs->inode_map->bitmap; 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fs->block_map) { 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = ext2fs_read_block_bitmap(fs); 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (retval) 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return retval; 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ptr = fs->block_map->bitmap; 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf = malloc(size); 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!buf) 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ENOMEM; 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) actual = read(fd, buf, size); 371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (actual == -1) { 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) errno = retval; 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (actual != size) { 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retval = EXT2_ET_SHORT_WRITE; 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) goto errout; 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(ptr, buf, size); 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 381e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) retval = 0; 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)errout: 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (buf) 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) free(buf); 385e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) return (retval); 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)