#define _GNU_SOURCE #include #include #include #include #include #include #include #include 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 [...]\n"); fprintf(stderr, " seek scan data|hole \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; }