diff options
author | Karel Zak | 2015-04-13 13:40:25 +0200 |
---|---|---|
committer | Karel Zak | 2015-04-13 13:40:25 +0200 |
commit | 3457d90e3014b0ec25341c39629583b5655aa97f (patch) | |
tree | 52aa9989467d29645b8aa095cc07de29ab2f65f6 /libfdisk/src/utils.c | |
parent | sfdisk: improve -N warnings (diff) | |
download | kernel-qcow2-util-linux-3457d90e3014b0ec25341c39629583b5655aa97f.tar.gz kernel-qcow2-util-linux-3457d90e3014b0ec25341c39629583b5655aa97f.tar.xz kernel-qcow2-util-linux-3457d90e3014b0ec25341c39629583b5655aa97f.zip |
libfdisk: support bootbits protection from (p)MBR
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/utils.c')
-rw-r--r-- | libfdisk/src/utils.c | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/libfdisk/src/utils.c b/libfdisk/src/utils.c index 482a3062d..cc470d99b 100644 --- a/libfdisk/src/utils.c +++ b/libfdisk/src/utils.c @@ -10,14 +10,49 @@ * @short_description: misc fdisk functions */ +static int read_from_device(struct fdisk_context *cxt, + unsigned char *buf, + uintmax_t start, size_t size) +{ + ssize_t r; + + assert(cxt); + + DBG(CXT, ul_debugobj(cxt, "reading: offset=%ju, size=%zu", + start, size)); + + r = lseek(cxt->dev_fd, start, SEEK_SET); + if (r == -1) + { + DBG(CXT, ul_debugobj(cxt, "failed to seek to offset %ju: %m", start)); + return -errno; + } + + r = read(cxt->dev_fd, buf, size); + if (r < 0 || r != size) { + if (!errno) + errno = EINVAL; /* probably too small file/device */ + DBG(CXT, ul_debugobj(cxt, "failed to read %zu from offset %ju: %m", + size, start)); + return -errno; + } + + return 0; +} + + /* * Zeros in-memory first sector buffer */ -int fdisk_init_firstsector_buffer(struct fdisk_context *cxt) +int fdisk_init_firstsector_buffer(struct fdisk_context *cxt, + unsigned int protect_off, + unsigned int protect_size) { if (!cxt) return -EINVAL; + assert(protect_off + protect_size <= cxt->sector_size); + if (!cxt->firstsector || cxt->firstsector_bufsz != cxt->sector_size) { /* Let's allocate a new buffer if no allocated yet, or the * current buffer has incorrect size */ @@ -36,43 +71,37 @@ int fdisk_init_firstsector_buffer(struct fdisk_context *cxt) DBG(CXT, ul_debugobj(cxt, "zeroize in-memory first sector buffer")); memset(cxt->firstsector, 0, cxt->firstsector_bufsz); + + if (protect_size) { + /* + * It would be possible to reuse data from cxt->firstsector + * (call memset() for non-protected area only) and avoid one + * read() from the device, but it seems like a too fragile + * solution as we have no clue about stuff in the buffer -- + * maybe it was already modified. Let's re-read from the device + * to be sure. -- kzak 13-Apr-2015 + */ + DBG(CXT, ul_debugobj(cxt, "first sector protection enabled -- re-reading")); + read_from_device(cxt, cxt->firstsector, protect_off, protect_size); + } return 0; } int fdisk_read_firstsector(struct fdisk_context *cxt) { - ssize_t r; int rc; assert(cxt); assert(cxt->sector_size); - rc = fdisk_init_firstsector_buffer(cxt); + rc = fdisk_init_firstsector_buffer(cxt, 0, 0); if (rc) return rc; assert(cxt->sector_size == cxt->firstsector_bufsz); - DBG(CXT, ul_debugobj(cxt, "reading first sector " - "buffer [sector_size=%lu]", cxt->sector_size)); - - r = lseek(cxt->dev_fd, 0, SEEK_SET); - if (r == -1) - { - DBG(CXT, ul_debugobj(cxt, "failed to seek to first sector %m")); - return -errno; - } - - r = read(cxt->dev_fd, cxt->firstsector, cxt->sector_size); - if (r != cxt->sector_size) { - if (!errno) - errno = EINVAL; /* probably too small file/device */ - DBG(CXT, ul_debugobj(cxt, "failed to read first sector %m")); - return -errno; - } - - return 0; + return read_from_device(cxt, cxt->firstsector, 0, cxt->sector_size); } /** |