1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
11 #include <sys/types.h>
18 #define T1 "write data before unlink\n"
19 #define T2 "write data after unlink\n"
20 char msg[] = "yabba dabba doo, I'm coming for you, I live in a shoe, I don't know what to do.\n'Bigger, bigger,and bigger yet!' cried the Creator. 'You are not yet substantial enough for my boundless intents!' And ever greater and greater the object became, until all was lost 'neath its momentus bulk.\n";
21 char *buf, *buf_align;
26 "Usage: %s filename command-sequence\n"
27 " command-sequence items:\n"
30 " D open(O_DIRECTORY)\n"
34 " M rw mmap to EOF (must open and stat prior)\n"
37 " O open(O_CREAT|O_RDWR)\n"
38 " r[num] read [optional length]\n"
39 " R reference entire mmap-ed region\n"
43 " T[num] ftruncate [optional position, default 0]\n"
46 " w[num] write optional length\n"
47 " W write entire mmap-ed region\n"
50 " z[num] seek [optional position, default 0]\n"
51 " _ wait for signal\n";
53 static int usr1_received;
54 void usr1_handler(int unused)
60 pop_arg(int argc, char *argv[])
62 static int cur_arg = 3;
67 return argv[cur_arg++];
74 {"O_RDONLY", O_RDONLY},
75 {"O_WRONLY", O_WRONLY},
79 {"O_NOCTTY", O_NOCTTY},
81 {"O_APPEND", O_APPEND},
82 {"O_NONBLOCK", O_NONBLOCK},
83 {"O_NDELAY", O_NDELAY},
86 {"O_DIRECT", O_DIRECT},
88 {"O_LARGEFILE", O_LARGEFILE},
89 {"O_DIRECTORY", O_DIRECTORY},
90 {"O_NOFOLLOW", O_NOFOLLOW},
94 int get_flags(char *data, int *rflags)
102 cloned_flags = strdup(data);
103 if (cloned_flags == NULL) {
104 fprintf(stderr, "Insufficient memory.\n");
108 for (tmp = strtok(cloned_flags, ":"); tmp;
109 tmp = strtok(NULL, ":")) {
112 size = tmp - cloned_flags;
113 for (i = 0; flag_table[i].flag != -1; i++) {
114 if (!strcmp(tmp, flag_table[i].string)){
115 flags |= flag_table[i].flag;
116 size += strlen(flag_table[i].string);
133 #define POP_ARG() (pop_arg(argc, argv))
134 #define min(a,b) ((a)>(b)?(b):(a))
136 int main(int argc, char **argv)
138 char *fname, *commands;
141 size_t mmap_len = 0, i;
142 unsigned char *mmap_ptr = NULL, junk = 0;
143 int rc, len, fd = -1;
148 fprintf(stderr, usage, argv[0]);
152 signal(SIGUSR1, usr1_handler);
156 for (commands = argv[2]; *commands; commands++) {
159 if (usr1_received == 0)
162 signal(SIGUSR1, usr1_handler);
165 if (close(fd) == -1) {
173 if (mkdir(fname, 0755) == -1) {
175 perror("mkdir(0755)");
180 fd = open(fname, O_DIRECTORY);
183 perror("open(O_DIRECTORY)");
191 if (symlink(fname, newfile)) {
201 if (link(fname, newfile)) {
208 if (mknod(fname, S_IFREG | 0644, 0) == -1) {
210 perror("mknod(S_IFREG|0644, 0)");
215 mmap_len = st.st_size;
216 mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
218 if (mmap_ptr == MAP_FAILED) {
228 if (rename (fname, newfile)) {
235 fd = open(fname, O_CREAT|O_RDWR, 0644);
238 perror("open(O_RDWR|O_CREAT)");
243 len = get_flags(commands+1, &flags);
245 fd = open(fname, flags);
253 len = atoi(commands+1);
257 buf = realloc(buf, len + ALIGN);
260 perror("allocating buf for read\n");
264 buf_align = (char *)((long)(buf + ALIGN) &
268 rc = read(fd, buf_align, len);
275 fprintf(stderr, "short read: %u/%u\n",
281 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
285 if (stat(fname, &st) == -1) {
292 if (fstat(fd, &st) == -1) {
299 if (fchmod(fd, 0) == -1) {
306 len = atoi(commands+1);
307 if (ftruncate(fd, len) == -1) {
309 printf("ftruncate (%d,%d)\n", fd, len);
315 if (unlink(fname) == -1) {
322 if (munmap(mmap_ptr, mmap_len)) {
329 len = atoi(commands+1);
333 buf = realloc(buf, len + ALIGN);
336 perror("allocating buf for write\n");
340 buf_align = (char *)((long)(buf + ALIGN) &
342 strncpy(buf_align, msg, bufsize);
345 rc = write(fd, buf_align, len);
352 fprintf(stderr, "short write: %u/%u\n",
358 for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
359 mmap_ptr[i] += junk++;
362 if (fsync(fd) == -1) {
369 if (fdatasync(fd) == -1) {
375 len = atoi(commands+1);
376 if (lseek(fd, len, SEEK_SET) == -1) {
394 fprintf(stderr, "unknown command \"%c\"\n", *commands);
395 fprintf(stderr, usage, argv[0]);