diff options
| author | Ron Yorston <rmy@pobox.com> | 2020-05-20 15:52:42 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2020-05-20 15:52:42 +0100 |
| commit | 184aa4b5d07d5f3fcc15dd4bb0d4636fba734de3 (patch) | |
| tree | e34649217179b033cbc2838df5302b74346caaad | |
| parent | 1d2a15e040b272155d3e40b597292a56de540e7d (diff) | |
| download | busybox-w32-184aa4b5d07d5f3fcc15dd4bb0d4636fba734de3.tar.gz busybox-w32-184aa4b5d07d5f3fcc15dd4bb0d4636fba734de3.tar.bz2 busybox-w32-184aa4b5d07d5f3fcc15dd4bb0d4636fba734de3.zip | |
dd: fix handling of 'conv=notrunc seek=N'
Commit e6680912a (dd: create a sparse file when seek=N is used)
broke the use of 'conv=notrunc seek=N' to modify existing files.
Rename seek_sparse() to make_sparse() and:
- add an argument to specify the start of the sparse region;
- call make_sparse() before ftruncate();
- call make_sparse() only if:
* we can determine the size of the file;
* the file is not open in append mode;
* the file is being extended.
This should fix GitHub issue #186.
| -rw-r--r-- | coreutils/dd.c | 25 | ||||
| -rw-r--r-- | include/mingw.h | 2 | ||||
| -rw-r--r-- | win32/mingw.c | 6 |
3 files changed, 26 insertions, 7 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c index fc8b1dbb2..042355e24 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
| @@ -466,6 +466,27 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 466 | 466 | ||
| 467 | xmove_fd(xopen(outfile, oflag), ofd); | 467 | xmove_fd(xopen(outfile, oflag), ofd); |
| 468 | 468 | ||
| 469 | #if ENABLE_PLATFORM_MINGW32 | ||
| 470 | { | ||
| 471 | off_t len = (off_t)seek * ((G.flags & FLAG_SEEK_BYTES) ? 1 : obs); | ||
| 472 | struct stat st; | ||
| 473 | int ret = fstat(ofd, &st); | ||
| 474 | |||
| 475 | if (ret == 0 && !(G.flags & FLAG_APPEND) && len > st.st_size) | ||
| 476 | make_sparse(ofd, st.st_size, len); | ||
| 477 | |||
| 478 | if (seek && !(G.flags & FLAG_NOTRUNC)) { | ||
| 479 | if (ftruncate(ofd, len) < 0) { | ||
| 480 | if (ret < 0 | ||
| 481 | || S_ISREG(st.st_mode) | ||
| 482 | || S_ISDIR(st.st_mode) | ||
| 483 | ) { | ||
| 484 | goto die_outfile; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | } | ||
| 488 | } | ||
| 489 | #else | ||
| 469 | if (seek && !(G.flags & FLAG_NOTRUNC)) { | 490 | if (seek && !(G.flags & FLAG_NOTRUNC)) { |
| 470 | size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; | 491 | size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; |
| 471 | if (ftruncate(ofd, seek * blocksz) < 0) { | 492 | if (ftruncate(ofd, seek * blocksz) < 0) { |
| @@ -479,6 +500,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 479 | } | 500 | } |
| 480 | } | 501 | } |
| 481 | } | 502 | } |
| 503 | #endif | ||
| 482 | } else { | 504 | } else { |
| 483 | outfile = bb_msg_standard_output; | 505 | outfile = bb_msg_standard_output; |
| 484 | } | 506 | } |
| @@ -502,9 +524,6 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 502 | } | 524 | } |
| 503 | if (seek) { | 525 | if (seek) { |
| 504 | size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; | 526 | size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; |
| 505 | #if ENABLE_PLATFORM_MINGW32 | ||
| 506 | seek_sparse(ofd, seek * blocksz); | ||
| 507 | #endif | ||
| 508 | if (lseek(ofd, seek * blocksz, SEEK_CUR) < 0) | 527 | if (lseek(ofd, seek * blocksz, SEEK_CUR) < 0) |
| 509 | goto die_outfile; | 528 | goto die_outfile; |
| 510 | } | 529 | } |
diff --git a/include/mingw.h b/include/mingw.h index 0fead43c9..39d716521 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
| @@ -537,5 +537,5 @@ int chdir_system_drive(void); | |||
| 537 | char *xabsolute_path(char *path); | 537 | char *xabsolute_path(char *path); |
| 538 | char *get_drive_cwd(const char *path, char *buffer, int size); | 538 | char *get_drive_cwd(const char *path, char *buffer, int size); |
| 539 | void fix_path_case(char *path); | 539 | void fix_path_case(char *path); |
| 540 | void seek_sparse(int fd, size_t size); | 540 | void make_sparse(int fd, off_t start, off_t end); |
| 541 | int skip_ansi_emulation(int reset); | 541 | int skip_ansi_emulation(int reset); |
diff --git a/win32/mingw.c b/win32/mingw.c index 7f8fecdc3..5c4c39b9d 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
| @@ -1751,7 +1751,7 @@ void fix_path_case(char *path) | |||
| 1751 | } | 1751 | } |
| 1752 | } | 1752 | } |
| 1753 | 1753 | ||
| 1754 | void seek_sparse(int fd, size_t size) | 1754 | void make_sparse(int fd, off_t start, off_t end) |
| 1755 | { | 1755 | { |
| 1756 | DWORD dwTemp; | 1756 | DWORD dwTemp; |
| 1757 | HANDLE fh; | 1757 | HANDLE fh; |
| @@ -1762,8 +1762,8 @@ void seek_sparse(int fd, size_t size) | |||
| 1762 | 1762 | ||
| 1763 | DeviceIoControl(fh, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL); | 1763 | DeviceIoControl(fh, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL); |
| 1764 | 1764 | ||
| 1765 | fzdi.FileOffset.QuadPart = 0; | 1765 | fzdi.FileOffset.QuadPart = start; |
| 1766 | fzdi.BeyondFinalZero.QuadPart = size; | 1766 | fzdi.BeyondFinalZero.QuadPart = end; |
| 1767 | DeviceIoControl(fh, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi), | 1767 | DeviceIoControl(fh, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi), |
| 1768 | NULL, 0, &dwTemp, NULL); | 1768 | NULL, 0, &dwTemp, NULL); |
| 1769 | } | 1769 | } |
