On Wed, Jun 22, 2016 at 04:43:18PM +0200, Michal Privoznik wrote: > This function takes a FD and determines whether the current > position is in data section or in a hole. In addition to that, > it also determines how much bytes are there remaining till the > current section ends. > > Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> > --- > src/libvirt_private.syms | 1 + > src/util/virfile.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ > src/util/virfile.h | 4 +++ > 3 files changed, 75 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 501c23e..f476eae 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1513,6 +1513,7 @@ virFileGetHugepageSize; > virFileGetMountReverseSubtree; > virFileGetMountSubtree; > virFileHasSuffix; > +virFileInData; > virFileIsAbsPath; > virFileIsDir; > virFileIsExecutable; > diff --git a/src/util/virfile.c b/src/util/virfile.c > index f47bf39..05b709a 100644 > --- a/src/util/virfile.c > +++ b/src/util/virfile.c > @@ -3443,3 +3443,73 @@ int virFileIsSharedFS(const char *path) > VIR_FILE_SHFS_SMB | > VIR_FILE_SHFS_CIFS); > } > + > + > +int virFileInData(int fd, > + int *inData, > + unsigned long long *length) > +{ > + int ret = -1; > + off_t cur, data, hole; > + > + /* Get current position */ > + cur = lseek(fd, 0, SEEK_CUR); > + if (cur == (off_t) -1) { > + virReportSystemError(errno, "%s", > + _("Unable to get current position in file")); > + goto cleanup; > + } > + > + /* Now try to get data and hole offsets */ > + data = lseek(fd, cur, SEEK_DATA); > + > + /* There are four options: > + * 1) data == cur; @cur is in data > + * 2) data > cur; @cur is in a hole, next data at @data > + * 3) data < 0, errno = ENXIO; either @cur is in trailing hole, or @cur is beyond EOF. > + * 4) data < 0, errno != ENXIO; we learned nothing > + */ > + > + if (data == (off_t) -1) { > + /* cases 3 and 4 */ > + if (errno != ENXIO) { > + virReportSystemError(errno, "%s", > + _("Unable to seek to data")); > + goto cleanup; > + } > + *inData = 0; > + *length = 0; > + } else if (data > cur) { > + /* case 2 */ > + *inData = 0; > + *length = data - cur; > + } else { > + /* case 1 */ > + *inData = 1; > + > + /* We don't know where does the next hole start. Let's > + * find out. Here we get the same 4 possibilities as > + * described above.*/ > + hole = lseek(fd, data, SEEK_HOLE); > + if (hole == (off_t) -1 || hole == data) { > + /* cases 1, 3 and 4 */ > + /* Wait a second. The reason why we are here is > + * because we are in data. But at the same time we > + * are in a trailing hole? Wut!? Do the best what we > + * can do here. */ > + virReportSystemError(errno, "%s", > + _("unable to seek to hole")); > + goto cleanup; > + } else { > + /* case 2 */ > + *length = (hole - data); > + } > + } > + > + ret = 0; > + cleanup: > + /* At any rate, reposition back to where we started. */ > + if (cur != (off_t) -1) > + ignore_value(lseek(fd, cur, SEEK_SET)); Is it really safe to ignore the value here ? IIUC, callers of this function would be justified in thinking it would *not* have a side effect on file position. IOW, I think we'd probably want to treat this error as fatal too. I think it'd be desirable to have a unit test written explicitly for this function, since there's a few fun edge cases to worry about here. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list