[libvirt] [PATCH RFC 01/48] util: Introduce virFileInData
Daniel P. Berrange
berrange at redhat.com
Mon Jun 27 16:55:39 UTC 2016
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 at redhat.com>
> ---
> 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 :|
More information about the libvir-list
mailing list