From 869767a5cf8dc87ca5f182cd557d7fd8cd7b1419 Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Wed, 21 Mar 2018 14:36:50 +0100 Subject: [PATCH] Move general i/o code to stand-alone utility file. Get rid of internal library stuff linked to the utilities. Also rename 'count' param to 'length' clarifying handling of the parameter internally. --- lib/Makemodule.am | 2 + lib/internal.h | 8 +- lib/utils.c | 252 ----------------------------------------- lib/utils_io.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++ lib/utils_io.h | 38 +++++++ 5 files changed, 321 insertions(+), 259 deletions(-) create mode 100644 lib/utils_io.c create mode 100644 lib/utils_io.h diff --git a/lib/Makemodule.am b/lib/Makemodule.am index 56f9f377..5e200391 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -54,6 +54,8 @@ libcryptsetup_la_SOURCES = \ lib/utils_device_locking.c \ lib/utils_device_locking.h \ lib/utils_pbkdf.c \ + lib/utils_io.c \ + lib/utils_io.h \ lib/libdevmapper.c \ lib/utils_dm.h \ lib/volumekey.c \ diff --git a/lib/internal.h b/lib/internal.h index 4a61d104..d6fbae1b 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -37,6 +37,7 @@ #include "utils_dm.h" #include "utils_fips.h" #include "utils_keyring.h" +#include "utils_io.h" #include "crypto_backend.h" #include "libcryptsetup.h" @@ -132,13 +133,6 @@ uint64_t crypt_dev_partition_offset(const char *dev_path); int lookup_by_disk_id(const char *dm_uuid); int lookup_by_sysfs_uuid_field(const char *dm_uuid, size_t max_len); -ssize_t write_buffer(int fd, const void *buf, size_t count); -ssize_t read_buffer(int fd, void *buf, size_t count); -ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, void *orig_buf, size_t count); -ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, void *buf, size_t count); -ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, void *buf, size_t count, off_t offset); -ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, void *buf, size_t count, off_t offset); - size_t crypt_getpagesize(void); unsigned crypt_cpusonline(void); uint64_t crypt_getphysmemory_kb(void); diff --git a/lib/utils.c b/lib/utils.c index 65202da3..b314dcfb 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -22,13 +22,10 @@ */ #include -#include -#include #include #include #include #include -#include #include #include @@ -63,255 +60,6 @@ uint64_t crypt_getphysmemory_kb(void) return phys_memory_kb; } -ssize_t read_buffer(int fd, void *buf, size_t count) -{ - size_t read_size = 0; - ssize_t r; - - if (fd < 0 || !buf) - return -EINVAL; - - do { - r = read(fd, buf, count - read_size); - if (r == -1 && errno != EINTR) - return r; - if (r == 0) - return (ssize_t)read_size; - if (r > 0) { - read_size += (size_t)r; - buf = (uint8_t*)buf + r; - } - } while (read_size != count); - - return (ssize_t)count; -} - -ssize_t write_buffer(int fd, const void *buf, size_t count) -{ - size_t write_size = 0; - ssize_t w; - - if (fd < 0 || !buf || !count) - return -EINVAL; - - do { - w = write(fd, buf, count - write_size); - if (w < 0 && errno != EINTR) - return w; - if (w == 0) - return (ssize_t)write_size; - if (w > 0) { - write_size += (size_t) w; - buf = (const uint8_t*)buf + w; - } - } while (write_size != count); - - return (ssize_t)write_size; -} - -ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, - void *orig_buf, size_t count) -{ - void *hangover_buf = NULL, *buf = NULL; - size_t hangover, solid; - ssize_t r, ret = -1; - - if (fd == -1 || !orig_buf || !bsize || !alignment) - return -1; - - hangover = count % bsize; - solid = count - hangover; - - if ((size_t)orig_buf & (alignment - 1)) { - if (posix_memalign(&buf, alignment, count)) - return -1; - memcpy(buf, orig_buf, count); - } else - buf = orig_buf; - - if (solid) { - r = write_buffer(fd, buf, solid); - if (r < 0 || r != (ssize_t)solid) - goto out; - } - - if (hangover) { - if (posix_memalign(&hangover_buf, alignment, bsize)) - goto out; - - r = read_buffer(fd, hangover_buf, bsize); - if (r < 0 || r < (ssize_t)hangover) - goto out; - - if (r < (ssize_t)bsize) - bsize = r; - - if (lseek(fd, -(off_t)bsize, SEEK_CUR) < 0) - goto out; - - memcpy(hangover_buf, (char*)buf + solid, hangover); - - r = write_buffer(fd, hangover_buf, bsize); - if (r < 0 || r < (ssize_t)hangover) - goto out; - } - ret = count; -out: - free(hangover_buf); - if (buf != orig_buf) - free(buf); - return ret; -} - -ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, - void *orig_buf, size_t count) -{ - void *hangover_buf = NULL, *buf = NULL; - size_t hangover, solid; - ssize_t r, ret = -1; - - if (fd == -1 || !orig_buf || !bsize || !alignment) - return -1; - - hangover = count % bsize; - solid = count - hangover; - - if ((size_t)orig_buf & (alignment - 1)) { - if (posix_memalign(&buf, alignment, count)) - return -1; - } else - buf = orig_buf; - - r = read_buffer(fd, buf, solid); - if (r < 0 || r != (ssize_t)solid) - goto out; - - if (hangover) { - if (posix_memalign(&hangover_buf, alignment, bsize)) - goto out; - r = read_buffer(fd, hangover_buf, bsize); - if (r < 0 || r < (ssize_t)hangover) - goto out; - - memcpy((char *)buf + solid, hangover_buf, hangover); - } - ret = count; -out: - free(hangover_buf); - if (buf != orig_buf) { - memcpy(orig_buf, buf, count); - free(buf); - } - return ret; -} - -/* - * Combines llseek with blockwise write. write_blockwise can already deal with short writes - * but we also need a function to deal with short writes at the start. But this information - * is implicitly included in the read/write offset, which can not be set to non-aligned - * boundaries. Hence, we combine llseek with write. - */ -ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, - void *buf, size_t count, off_t offset) -{ - void *frontPadBuf = NULL; - size_t frontHang, innerCount = 0; - ssize_t r, ret = -1; - - if (fd == -1 || !buf || !bsize || !alignment) - return -1; - - if (offset < 0) - offset = lseek(fd, offset, SEEK_END); - - if (offset < 0) - return -1; - - frontHang = offset % bsize; - - if (lseek(fd, offset - frontHang, SEEK_SET) < 0) - return -1; - - if (frontHang) { - if (posix_memalign(&frontPadBuf, alignment, bsize)) - return -1; - - innerCount = bsize - frontHang; - if (innerCount > count) - innerCount = count; - - r = read_buffer(fd, frontPadBuf, bsize); - if (r < 0 || r < (ssize_t)(frontHang + innerCount)) - goto out; - - memcpy((char*)frontPadBuf + frontHang, buf, innerCount); - - if (lseek(fd, offset - frontHang, SEEK_SET) < 0) - goto out; - - r = write_buffer(fd, frontPadBuf, frontHang + innerCount); - if (r < 0 || r != (ssize_t)(frontHang + innerCount)) - goto out; - - buf = (char*)buf + innerCount; - count -= innerCount; - } - - ret = count ? write_blockwise(fd, bsize, alignment, buf, count) : 0; - if (ret >= 0) - ret += innerCount; -out: - free(frontPadBuf); - return ret; -} - -ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, - void *buf, size_t count, off_t offset) -{ - void *frontPadBuf = NULL; - size_t frontHang, innerCount = 0; - ssize_t r, ret = -1; - - if (fd == -1 || !buf || bsize <= 0) - return -1; - - if (offset < 0) - offset = lseek(fd, offset, SEEK_END); - - if (offset < 0) - return -1; - - frontHang = offset % bsize; - - if (lseek(fd, offset - frontHang, SEEK_SET) < 0) - return -1; - - if (frontHang) { - if (posix_memalign(&frontPadBuf, alignment, bsize)) - return -1; - - innerCount = bsize - frontHang; - if (innerCount > count) - innerCount = count; - - r = read_buffer(fd, frontPadBuf, bsize); - if (r < 0 || r < (ssize_t)(frontHang + innerCount)) - goto out; - - memcpy(buf, (char*)frontPadBuf + frontHang, innerCount); - - buf = (char*)buf + innerCount; - count -= innerCount; - } - - ret = read_blockwise(fd, bsize, alignment, buf, count); - if (ret >= 0) - ret += innerCount; -out: - free(frontPadBuf); - return ret; -} - /* MEMLOCK */ #define DEFAULT_PROCESS_PRIORITY -18 diff --git a/lib/utils_io.c b/lib/utils_io.c new file mode 100644 index 00000000..0f671d6c --- /dev/null +++ b/lib/utils_io.c @@ -0,0 +1,280 @@ +/* + * utils - miscellaneous I/O utilities for cryptsetup + * + * Copyright (C) 2004, Jana Saout + * Copyright (C) 2004-2007, Clemens Fruhwirth + * Copyright (C) 2009-2018, Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2018, Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "utils_io.h" + +ssize_t read_buffer(int fd, void *buf, size_t length) +{ + size_t read_size = 0; + ssize_t r; + + if (fd < 0 || !buf) + return -EINVAL; + + do { + r = read(fd, buf, length - read_size); + if (r == -1 && errno != EINTR) + return r; + if (r == 0) + return (ssize_t)read_size; + if (r > 0) { + read_size += (size_t)r; + buf = (uint8_t*)buf + r; + } + } while (read_size != length); + + return (ssize_t)length; +} + +ssize_t write_buffer(int fd, const void *buf, size_t length) +{ + size_t write_size = 0; + ssize_t w; + + if (fd < 0 || !buf || !length) + return -EINVAL; + + do { + w = write(fd, buf, length - write_size); + if (w < 0 && errno != EINTR) + return w; + if (w == 0) + return (ssize_t)write_size; + if (w > 0) { + write_size += (size_t) w; + buf = (const uint8_t*)buf + w; + } + } while (write_size != length); + + return (ssize_t)write_size; +} + +ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length) +{ + void *hangover_buf = NULL, *buf = NULL; + size_t hangover, solid; + ssize_t r, ret = -1; + + if (fd == -1 || !orig_buf || !bsize || !alignment) + return -1; + + hangover = length % bsize; + solid = length - hangover; + + if ((size_t)orig_buf & (alignment - 1)) { + if (posix_memalign(&buf, alignment, length)) + return -1; + memcpy(buf, orig_buf, length); + } else + buf = orig_buf; + + if (solid) { + r = write_buffer(fd, buf, solid); + if (r < 0 || r != (ssize_t)solid) + goto out; + } + + if (hangover) { + if (posix_memalign(&hangover_buf, alignment, bsize)) + goto out; + + r = read_buffer(fd, hangover_buf, bsize); + if (r < 0 || r < (ssize_t)hangover) + goto out; + + if (r < (ssize_t)bsize) + bsize = r; + + if (lseek(fd, -(off_t)bsize, SEEK_CUR) < 0) + goto out; + + memcpy(hangover_buf, (char*)buf + solid, hangover); + + r = write_buffer(fd, hangover_buf, bsize); + if (r < 0 || r < (ssize_t)hangover) + goto out; + } + ret = length; +out: + free(hangover_buf); + if (buf != orig_buf) + free(buf); + return ret; +} + +ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length) +{ + void *hangover_buf = NULL, *buf = NULL; + size_t hangover, solid; + ssize_t r, ret = -1; + + if (fd == -1 || !orig_buf || !bsize || !alignment) + return -1; + + hangover = length % bsize; + solid = length - hangover; + + if ((size_t)orig_buf & (alignment - 1)) { + if (posix_memalign(&buf, alignment, length)) + return -1; + } else + buf = orig_buf; + + r = read_buffer(fd, buf, solid); + if (r < 0 || r != (ssize_t)solid) + goto out; + + if (hangover) { + if (posix_memalign(&hangover_buf, alignment, bsize)) + goto out; + r = read_buffer(fd, hangover_buf, bsize); + if (r < 0 || r < (ssize_t)hangover) + goto out; + + memcpy((char *)buf + solid, hangover_buf, hangover); + } + ret = length; +out: + free(hangover_buf); + if (buf != orig_buf) { + memcpy(orig_buf, buf, length); + free(buf); + } + return ret; +} + +/* + * Combines llseek with blockwise write. write_blockwise can already deal with short writes + * but we also need a function to deal with short writes at the start. But this information + * is implicitly included in the read/write offset, which can not be set to non-aligned + * boundaries. Hence, we combine llseek with write. + */ +ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset) +{ + void *frontPadBuf = NULL; + size_t frontHang, innerCount = 0; + ssize_t r, ret = -1; + + if (fd == -1 || !buf || !bsize || !alignment) + return -1; + + if (offset < 0) + offset = lseek(fd, offset, SEEK_END); + + if (offset < 0) + return -1; + + frontHang = offset % bsize; + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + return -1; + + if (frontHang) { + if (posix_memalign(&frontPadBuf, alignment, bsize)) + return -1; + + innerCount = bsize - frontHang; + if (innerCount > length) + innerCount = length; + + r = read_buffer(fd, frontPadBuf, bsize); + if (r < 0 || r < (ssize_t)(frontHang + innerCount)) + goto out; + + memcpy((char*)frontPadBuf + frontHang, buf, innerCount); + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + goto out; + + r = write_buffer(fd, frontPadBuf, frontHang + innerCount); + if (r < 0 || r != (ssize_t)(frontHang + innerCount)) + goto out; + + buf = (char*)buf + innerCount; + length -= innerCount; + } + + ret = length ? write_blockwise(fd, bsize, alignment, buf, length) : 0; + if (ret >= 0) + ret += innerCount; +out: + free(frontPadBuf); + return ret; +} + +ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset) +{ + void *frontPadBuf = NULL; + size_t frontHang, innerCount = 0; + ssize_t r, ret = -1; + + if (fd == -1 || !buf || bsize <= 0) + return -1; + + if (offset < 0) + offset = lseek(fd, offset, SEEK_END); + + if (offset < 0) + return -1; + + frontHang = offset % bsize; + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + return -1; + + if (frontHang) { + if (posix_memalign(&frontPadBuf, alignment, bsize)) + return -1; + + innerCount = bsize - frontHang; + if (innerCount > length) + innerCount = length; + + r = read_buffer(fd, frontPadBuf, bsize); + if (r < 0 || r < (ssize_t)(frontHang + innerCount)) + goto out; + + memcpy(buf, (char*)frontPadBuf + frontHang, innerCount); + + buf = (char*)buf + innerCount; + length -= innerCount; + } + + ret = read_blockwise(fd, bsize, alignment, buf, length); + if (ret >= 0) + ret += innerCount; +out: + free(frontPadBuf); + return ret; +} diff --git a/lib/utils_io.h b/lib/utils_io.h new file mode 100644 index 00000000..9289e62e --- /dev/null +++ b/lib/utils_io.h @@ -0,0 +1,38 @@ +/* + * utils - miscellaneous I/O utilities for cryptsetup + * + * Copyright (C) 2004, Jana Saout + * Copyright (C) 2004-2007, Clemens Fruhwirth + * Copyright (C) 2009-2018, Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2018, Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_UTILS_IO_H +#define _CRYPTSETUP_UTILS_IO_H + +ssize_t read_buffer(int fd, void *buf, size_t length); +ssize_t write_buffer(int fd, const void *buf, size_t length); +ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length); +ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length); +ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset); +ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset); + +#endif