POSIX: lseek: support SEEK_DATA and SEEK_HOLE constants
this is queued for issue 8: https://www.austingroupbugs.net/view.php?id=415 this implementation calls the ioctl hook of the filesystem with BSD-like constants FIOSEEKDATA and FIOSEEKHOLE. if the hook doesn't know the constants, we use the stat size to return the last hole (as proposed in the draft spec). Change-Id: I5d052eed87e29b70491a7ff534e244896469d03e Reviewed-on: https://review.haiku-os.org/c/haiku/+/3385 Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
@@ -12,4 +12,7 @@
|
|||||||
#define FIONBIO 0xbe000000
|
#define FIONBIO 0xbe000000
|
||||||
#define FIONREAD 0xbe000001
|
#define FIONREAD 0xbe000001
|
||||||
|
|
||||||
|
#define FIOSEEKDATA 0xbe000002
|
||||||
|
#define FIOSEEKHOLE 0xbe000003
|
||||||
|
|
||||||
#endif /* _SYS_IOCTL_H */
|
#endif /* _SYS_IOCTL_H */
|
||||||
|
|||||||
@@ -151,6 +151,12 @@
|
|||||||
#ifndef SEEK_END
|
#ifndef SEEK_END
|
||||||
# define SEEK_END 2
|
# define SEEK_END 2
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef SEEK_DATA
|
||||||
|
# define SEEK_DATA 3
|
||||||
|
#endif
|
||||||
|
#ifndef SEEK_HOLE
|
||||||
|
# define SEEK_HOLE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -5858,6 +5859,39 @@ file_seek(struct file_descriptor* descriptor, off_t pos, int seekType)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SEEK_DATA:
|
||||||
|
case SEEK_HOLE:
|
||||||
|
{
|
||||||
|
status_t status = B_BAD_VALUE;
|
||||||
|
if (HAS_FS_CALL(vnode, ioctl)) {
|
||||||
|
offset = pos;
|
||||||
|
status = FS_CALL(vnode, ioctl, descriptor->cookie,
|
||||||
|
seekType == SEEK_DATA ? FIOSEEKDATA : FIOSEEKHOLE,
|
||||||
|
&offset, sizeof(offset));
|
||||||
|
if (status == B_OK) {
|
||||||
|
if (offset > pos)
|
||||||
|
offset -= pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status != B_BAD_VALUE && status != B_DEV_INVALID_IOCTL)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// basic implementation with stat() the node
|
||||||
|
if (!HAS_FS_CALL(vnode, read_stat) || isDevice)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
struct stat stat;
|
||||||
|
status = FS_CALL(vnode, read_stat, &stat);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
off_t end = stat.st_size;
|
||||||
|
if (pos >= end)
|
||||||
|
return ENXIO;
|
||||||
|
offset = seekType == SEEK_HOLE ? end - pos : 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user