diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2016-10-07 17:51:12 +0200 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2016-10-13 23:16:20 +0200 |
commit | e7f2867f4d55d5c91115f9ec6e5a31602d27a788 (patch) | |
tree | 8ff323815aa7a67499724af14ff34b902363959c | |
parent | 8ee652a86a0d1a657e7d7332807f3a192776fede (diff) | |
download | memtool-e7f2867f4d55d5c91115f9ec6e5a31602d27a788.tar.gz memtool-e7f2867f4d55d5c91115f9ec6e5a31602d27a788.tar.xz |
Improve handling of md and mw on file boundaries
Don't let md print data from offsets that are after EOF and let mw
append to a file if data is set after EOF.
The new behaviour is not entirely consistent and it only works for
regular files. Still it's better than before.
Fixes: https://bugs.debian.org/831219
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-rw-r--r-- | memtool.c | 40 |
1 files changed, 36 insertions, 4 deletions
@@ -196,12 +196,14 @@ static int memory_display(const void *addr, off_t offs, static int memfd; -static void *memmap(const char *file, off_t addr, size_t size, int readonly) +static void *memmap(const char *file, off_t addr, size_t *size, int readonly) { off_t mmap_start; size_t ofs; void *mem; long pagesize = sysconf(_SC_PAGE_SIZE); + struct stat s; + int ret; if (pagesize < 0) pagesize = 4096; @@ -212,10 +214,38 @@ static void *memmap(const char *file, off_t addr, size_t size, int readonly) return NULL; } + ret = fstat(memfd, &s); + if (ret) { + perror("fstat"); + goto out; + } + + if (S_ISREG(s.st_mode)) { + if (readonly) { + if (s.st_size <= addr) { + errno = EINVAL; + perror("File to small"); + goto out; + } + + if (s.st_size < addr + *size) + /* truncating */ + *size = s.st_size - addr; + + } else { + int ret = posix_fallocate(memfd, addr, *size); + if (ret) { + errno = ret; + perror("Failed to fallocate"); + goto out; + } + } + } + mmap_start = addr & ~((off_t)pagesize - 1); ofs = addr - mmap_start; - mem = mmap(NULL, size + ofs, PROT_READ | (readonly ? 0 : PROT_WRITE), + mem = mmap(NULL, *size + ofs, PROT_READ | (readonly ? 0 : PROT_WRITE), MAP_SHARED, memfd, mmap_start); if (mem == MAP_FAILED) { perror("mmap"); @@ -299,7 +329,7 @@ static int cmd_memory_display(int argc, char **argv) size = 0x100; } - mem = memmap(file, start, size, 1); + mem = memmap(file, start, &size, 1); if (!mem) return EXIT_FAILURE; @@ -331,6 +361,7 @@ static void usage_mw(void) static int cmd_memory_write(int argc, char *argv[]) { off_t adr; + size_t size; int width = 4; int opt; void *mem; @@ -366,7 +397,8 @@ static int cmd_memory_write(int argc, char *argv[]) adr = strtoull_suffix(argv[optind++], NULL, 0); - mem = memmap(file, adr, argc * width, 0); + size = (argc - optind) * width; + mem = memmap(file, adr, &size, 0); if (!mem) return EXIT_FAILURE; |