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: darwin, target={{.*(linux|solaris).*}}
15
16#include <assert.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21int cookie_var;
22
23int f_read(void *cookie, char *buf, int len) {
24 assert(cookie == &cookie_var);
25 assert(len >= 6);
26 printf(format: "READ CALLED; len=%d\n", len);
27 return strlcpy(dest: buf, src: "test\n", n: len);
28}
29
30int f_write(void *cookie, const char *buf, int len) {
31 assert(cookie == &cookie_var);
32 char *data = strndup(string: buf, n: len);
33 assert(data);
34 printf(format: "WRITE CALLED: %s\n", data);
35 free(ptr: data);
36 return len;
37}
38
39off_t f_seek(void *cookie, off_t off, int whence) {
40 assert(cookie == &cookie_var);
41 assert(whence == SEEK_SET);
42 printf(format: "SEEK CALLED; off=%d, whence=%d\n", (int)off, whence);
43 return off;
44}
45
46int f_close(void *cookie) {
47 assert(cookie == &cookie_var);
48 printf(format: "CLOSE CALLED\n");
49 return 0;
50}
51
52int 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(format: "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(format: "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(format: "READ: %s", buf);
88 assert(!fclose(fp));
89
90 return 0;
91}
92

source code of compiler-rt/test/sanitizer_common/TestCases/Posix/funopen.cpp