1 // RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s
2
3 // CHECK: READ CALLED; len={{[0-9]*}}
4 // CHECK-NEXT: READ: test
5 // CHECK-NEXT: WRITE CALLED: test
6 // CHECK-NEXT: READ CALLED; len={{[0-9]*}}
7 // CHECK-NEXT: READ: test
8 // CHECK-NEXT: WRITE CALLED: test
9 // CHECK-NEXT: CLOSE CALLED
10 // CHECK-NEXT: SEEK CALLED; off=100, whence=0
11 // CHECK-NEXT: READ CALLED; len={{[0-9]*}}
12 // CHECK-NEXT: READ: test
13 //
14 // UNSUPPORTED: linux, darwin, solaris
15
16 #include <assert.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 int cookie_var;
22
f_read(void * cookie,char * buf,int len)23 int f_read(void *cookie, char *buf, int len) {
24 assert(cookie == &cookie_var);
25 assert(len >= 6);
26 printf("READ CALLED; len=%d\n", len);
27 return strlcpy(buf, "test\n", len);
28 }
29
f_write(void * cookie,const char * buf,int len)30 int f_write(void *cookie, const char *buf, int len) {
31 assert(cookie == &cookie_var);
32 char *data = strndup(buf, len);
33 assert(data);
34 printf("WRITE CALLED: %s\n", data);
35 free(data);
36 return len;
37 }
38
f_seek(void * cookie,off_t off,int whence)39 off_t f_seek(void *cookie, off_t off, int whence) {
40 assert(cookie == &cookie_var);
41 assert(whence == SEEK_SET);
42 printf("SEEK CALLED; off=%d, whence=%d\n", (int)off, whence);
43 return off;
44 }
45
f_close(void * cookie)46 int f_close(void *cookie) {
47 assert(cookie == &cookie_var);
48 printf("CLOSE CALLED\n");
49 return 0;
50 }
51
main(void)52 int main(void) {
53 FILE *fp;
54 char buf[10];
55
56 // 1. read-only variant
57 fp = fropen(&cookie_var, f_read);
58 assert(fp);
59 // verify that fileno() does not crash or report nonsense
60 assert(fileno(fp) == -1);
61 assert(fgets(buf, sizeof(buf), fp));
62 printf("READ: %s", buf);
63 assert(!fclose(fp));
64
65 // 2. write-only variant
66 fp = fwopen(&cookie_var, f_write);
67 assert(fp);
68 assert(fileno(fp) == -1);
69 assert(fputs("test", fp) >= 0);
70 assert(!fclose(fp));
71
72 // 3. read+write+close
73 fp = funopen(&cookie_var, f_read, f_write, NULL, f_close);
74 assert(fp);
75 assert(fileno(fp) == -1);
76 assert(fgets(buf, sizeof(buf), fp));
77 printf("READ: %s", buf);
78 assert(fputs("test", fp) >= 0);
79 assert(!fclose(fp));
80
81 // 4. read+seek
82 fp = funopen(&cookie_var, f_read, NULL, f_seek, NULL);
83 assert(fp);
84 assert(fileno(fp) == -1);
85 assert(fseek(fp, 100, SEEK_SET) == 0);
86 assert(fgets(buf, sizeof(buf), fp));
87 printf("READ: %s", buf);
88 assert(!fclose(fp));
89
90 return 0;
91 }
92