#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
static char buffer[65536];
static int
parse_int(const char *text, size_t *value)
{
char *ptr;
size_t val;
val = strtoul(text, &ptr, 0);
if (*ptr != 0) {
return 0;
}
*value = val;
return 1;
}
static int
fill_area(int fd, off_t offset, size_t size)
{
size_t len;
ssize_t res;
while (size > 0) {
len = sizeof(buffer);
if (len > size) {
len = size;
}
res = pwrite(fd, buffer, len, offset);
if (res < 0) {
fprintf(stderr, "pwrite(%d, %p, %lu, %lu) failed: %d\n", fd, buffer,
size, offset, errno);
return 0;
}
if (res != len) {
fprintf(stderr,
"pwrite(%d, %p, %lu, %lu) didn't wrote all "
"data: %lu/%lu\n",
fd, buffer, size, offset, res, len);
return 0;
}
offset += len;
size -= len;
}
return 1;
}
static void
syntax(void)
{
fprintf(stderr, "Syntax: seek create <path> <offset> <size> [...]\n");
fprintf(stderr, " seek scan <path> data|hole <offset>\n");
}
static int
seek_create(const char *path, int argc, char *argv[])
{
size_t off, size;
int fd;
int ret = 1;
fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644);
if (fd < 0) {
fprintf(stderr, "Failed to create the file\n");
goto out;
}
while (argc > 0) {
if (!parse_int(argv[0], &off) || !parse_int(argv[1], &size)) {
syntax();
goto out_close;
}
if (!fill_area(fd, off, size)) {
goto out_close;
}
argv += 2;
argc -= 2;
}
ret = 0;
out_close:
close(fd);
out:
return ret;
}
static int
seek_scan(const char *path, const char *type, const char *pos)
{
size_t off, res;
int fd, whence;
int ret = 1;
if (strcmp(type, "data") == 0) {
whence = SEEK_DATA;
} else if (strcmp(type, "hole") == 0) {
whence = SEEK_HOLE;
} else {
syntax();
goto out;
}
if (!parse_int(pos, &off)) {
syntax();
goto out;
}
fd = open(path, O_RDWR);
if (fd < 0) {
fprintf(stderr, "Failed to open the file\n");
goto out;
}
res = lseek(fd, off, whence);
if (res == (off_t)-1) {
if (errno != ENXIO) {
fprintf(stderr, "seek(%d, %lu, %d) failed: %d\n", fd, off, whence,
errno);
goto out_close;
}
fprintf(stdout, "ENXIO\n");
} else {
fprintf(stdout, "%lu\n", res);
}
ret = 0;
out_close:
close(fd);
out:
return ret;
}
int
main(int argc, char *argv[])
{
int ret = 1;
memset(buffer, 0x55, sizeof(buffer));
if (argc < 3) {
syntax();
goto out;
}
if (strcmp(argv[1], "create") == 0) {
if (((argc - 3) & 1) != 0) {
syntax();
goto out;
}
ret = seek_create(argv[2], argc - 3, argv + 3);
} else if (strcmp(argv[1], "scan") == 0) {
if (argc != 5) {
syntax();
goto out;
}
ret = seek_scan(argv[2], argv[3], argv[4]);
} else {
syntax();
goto out;
}
ret = 0;
out:
return ret;
}