Ticket #651: lseek-safety-test.c

File lseek-safety-test.c, 4.1 KB (added by Olly Betts, 9 years ago)

test program for lseek() to max off_t value

Line 
1#define _XOPEN_SOURCE 500
2
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <unistd.h>
7#include <errno.h>
8#include <stdio.h>
9#include <string.h>
10#include <setjmp.h>
11#include <signal.h>
12#include <sys/time.h>
13#include <sys/resource.h>
14
15static sigjmp_buf jb;
16
17static void sighandler(int signum) {
18 siglongjmp(jb, signum);
19}
20
21int main(int argc, char ** argv) {
22 if (argc != 2) {
23 fprintf(stderr, "Usage: %s TESTFILE\n", argv[0]);
24 return 1;
25 }
26
27 const char * filename = argv[1];
28
29 int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC, 0666);
30 if (fd < 0) {
31 perror("open failed");
32 return 1;
33 }
34
35 struct rlimit rlim;
36 if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) {
37 perror("rlimit");
38 } else {
39 if (rlim.rlim_cur != RLIM_INFINITY)
40 printf("RLIMIT_FSIZE cur = 0x%llx\n", (long long)rlim.rlim_cur);
41 if (rlim.rlim_max != RLIM_INFINITY)
42 printf("RLIMIT_FSIZE max = 0x%llx\n", (long long)rlim.rlim_max);
43 }
44
45#define SHIFT (sizeof(off_t) * 8 - 2)
46 volatile off_t off_t_max = (((off_t)1 << SHIFT)-1)|((off_t)1 << SHIFT);
47 off_t pos = lseek(fd, off_t_max, SEEK_SET);
48 if (pos == (off_t)-1) {
49 perror("lseek failed");
50 printf("attempted to set pos to 0x%llx\n", (long long)off_t_max);
51 printf("binary chopping to find actual max:\n");
52 int slo = 0;
53 int shi = SHIFT + 1;
54 while (shi - slo > 1) {
55 int sm = slo + (shi - slo) / 2;
56 off_t m = (off_t)1 << sm;
57 pos = lseek(fd, m, SEEK_SET);
58 if (pos == (off_t)-1) {
59 printf("lseek to 0x%llx fails, errno=%d (%s)\n", (long long)m, errno, strerror(errno));
60 shi = sm;
61 } else {
62 printf("lseek to 0x%llx works\n", (long long)m);
63 slo = sm;
64 }
65 }
66
67 off_t lo = (off_t)1 << slo;
68 off_t hi = (off_t)1 << shi;
69 while (hi - lo > 1) {
70 off_t m = lo + (hi - lo) / 2;
71 pos = lseek(fd, m, SEEK_SET);
72 if (pos == (off_t)-1) {
73 printf("lseek to 0x%llx fails, errno=%d (%s)\n", (long long)m, errno, strerror(errno));
74 hi = m;
75 } else {
76 printf("lseek to 0x%llx works\n", (long long)m);
77 lo = m;
78 }
79 }
80 off_t_max = lo;
81 printf("Max lseekable off_t = 0x%llx\n", (long long)off_t_max);
82 pos = lseek(fd, off_t_max + 1, SEEK_SET);
83 if (pos != -1)
84 printf("Odd, +1 now works\n");
85 pos = lseek(fd, off_t_max, SEEK_SET);
86 if (pos == -1)
87 printf("Odd, found limit now fails\n");
88 }
89
90 if (pos != off_t_max) {
91 fprintf(stderr, "warning: lseek to 0x%llx actually set pos to 0x%llx\n", (long long)off_t_max, (long long)pos);
92 }
93
94 if (pwrite(fd, "hello\n", 6, 2) < 0) {
95 perror("pwrite failed");
96 return 1;
97 }
98
99 pos = lseek(fd, 0, SEEK_CUR);
100 if (pos != off_t_max) {
101 fprintf(stderr, "warning: pwrite changed file pos to 0x%llx\n", (long long)pos);
102 }
103
104 char buf[10];
105 ssize_t r = pread(fd, buf, 10, 0);
106 if (r < 0) {
107 fprintf(stderr, "fd=%d\n", fd);
108 perror("pread failed");
109 return 1;
110 }
111
112 if (r != 8) {
113 int i;
114 fprintf(stderr, "pread() read %lld bytes, expected 8\ngot:", (long long)r);
115 for (i = 0; i != (int)r; ++i) {
116 fprintf(stderr, " 0x%02x", (unsigned char)buf[i]);
117 }
118 fprintf(stderr, "\n");
119 return 1;
120 }
121
122 if (memcmp(buf, "\0\0hello\n", 8) != 0) {
123 int i;
124 fprintf(stderr, "pread() didn't read the expected data back\ngot:");
125 for (i = 0; i != 8; ++i) {
126 fprintf(stderr, " 0x%02x", (unsigned char)buf[i]);
127 }
128 fprintf(stderr, "\n");
129 return 1;
130 }
131
132 if (sigsetjmp(jb, 1) == 0) {
133 signal(SIGXFSZ, sighandler);
134 r = write(fd, "", 1);
135 if (r >= 0) {
136 fprintf(stderr, "warning: write() succeeded, writing %lld bytes\n", (long long)r);
137 pos = lseek(fd, 0, SEEK_END);
138 fprintf(stderr, "lseek SEEK_END now returns 0x%llx (off_t_max was 0x%llx)\n", (long long)pos, (long long)off_t_max);
139 } else {
140 fprintf(stderr, "info: write() failed with errno=%d (%s)\n", errno, strerror(errno));
141 }
142 } else {
143 fprintf(stderr, "info: write() cause SIGXFSZ to be raised\n");
144 }
145
146 pos = lseek(fd, 0, SEEK_CUR);
147 if (pos != off_t_max) {
148 fprintf(stderr, "warning: write changed file pos to 0x%llx\n", (long long)pos);
149 }
150
151 fprintf(stderr, "Cool, that basically worked - please report the info and/or warnings given above\n");
152 return 0;
153}