On Thu, Jun 3, 2021 at 1:00 PM Eric Biggers <ebiggers@xxxxxxxxxx> wrote: > > From: Eric Biggers <ebiggers@xxxxxxxxxx> > > These helper functions will be used by the implementation of the > --out-merkle-tree option for 'fsverity digest' and 'fsverity sign'. > > Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx> > --- > programs/utils.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ > programs/utils.h | 3 +++ > 2 files changed, 62 insertions(+) > > diff --git a/programs/utils.c b/programs/utils.c > index ce19b57..116eb95 100644 > --- a/programs/utils.c > +++ b/programs/utils.c > @@ -13,10 +13,14 @@ > > #include <errno.h> > #include <fcntl.h> > +#include <inttypes.h> > #include <limits.h> > #include <stdarg.h> > #include <sys/stat.h> > #include <unistd.h> > +#ifdef _WIN32 > +# include <windows.h> > +#endif > > /* ========== Memory allocation ========== */ > > @@ -126,6 +130,26 @@ bool get_file_size(struct filedes *file, u64 *size_ret) > return true; > } > > +bool preallocate_file(struct filedes *file, u64 size) > +{ > + int res; > + > + if (size == 0) > + return true; > +#ifdef _WIN32 > + /* Not exactly the same as posix_fallocate(), but good enough... */ > + res = _chsize_s(file->fd, size); > +#else > + res = posix_fallocate(file->fd, 0, size); > +#endif > + if (res != 0) { > + error_msg_errno("preallocating %" PRIu64 "-byte file '%s'", > + size, file->name); > + return false; > + } > + return true; > +} > + > bool full_read(struct filedes *file, void *buf, size_t count) > { > while (count) { > @@ -160,6 +184,41 @@ bool full_write(struct filedes *file, const void *buf, size_t count) > return true; > } > > +static int raw_pwrite(int fd, const void *buf, int count, u64 offset) > +{ > +#ifdef _WIN32 > + HANDLE h = (HANDLE)_get_osfhandle(fd); > + OVERLAPPED pos = { .Offset = offset, .OffsetHigh = offset >> 32 }; > + DWORD written = 0; > + > + /* Not exactly the same as pwrite(), but good enough... */ > + if (!WriteFile(h, buf, count, &written, &pos)) { > + errno = EIO; > + return -1; > + } > + return written; > +#else > + return pwrite(fd, buf, count, offset); > +#endif > +} > + > +bool full_pwrite(struct filedes *file, const void *buf, size_t count, > + u64 offset) > +{ > + while (count) { > + int n = raw_pwrite(file->fd, buf, min(count, INT_MAX), offset); > + > + if (n < 0) { > + error_msg_errno("writing to '%s'", file->name); > + return false; > + } > + buf += n; I think this pointer arithmetic is not portable? Consider changing the type of buf to "const char*". > + count -= n; > + offset += n; > + } > + return true; > +} > + > bool filedes_close(struct filedes *file) > { > int res; > diff --git a/programs/utils.h b/programs/utils.h > index ab5005f..9a5c97a 100644 > --- a/programs/utils.h > +++ b/programs/utils.h > @@ -40,8 +40,11 @@ struct filedes { > > bool open_file(struct filedes *file, const char *filename, int flags, int mode); > bool get_file_size(struct filedes *file, u64 *size_ret); > +bool preallocate_file(struct filedes *file, u64 size); > bool full_read(struct filedes *file, void *buf, size_t count); > bool full_write(struct filedes *file, const void *buf, size_t count); > +bool full_pwrite(struct filedes *file, const void *buf, size_t count, > + u64 offset); > bool filedes_close(struct filedes *file); > int read_callback(void *file, void *buf, size_t count); > > -- > 2.31.1 >