This source file includes following definitions.
- perror_exit
- fts_dealloc
- remove_tree
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include <config.h>
18
19 #include <fts_.h>
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28
29 #define BASE "t-fts.tmp"
30 static char base[] = BASE;
31 static char const base_d[] = BASE "/d";
32 static char *const argv[2] = { base, 0 };
33
34 static void
35 perror_exit (char const *message, int status)
36 {
37 perror (message);
38 exit (status);
39 }
40
41
42 static void
43 fts_dealloc (void)
44 {
45 static char dir[] = "./";
46 static char *const curr_dir[2] = { dir, 0 };
47 FTS *ftsp = fts_open (curr_dir, FTS_NOSTAT | FTS_PHYSICAL | FTS_CWDFD, 0);
48 if (ftsp)
49 {
50 if (fts_close (ftsp) != 0)
51 perror_exit ("fts_close", 9);
52 }
53 else
54 perror_exit (base, 10);
55 }
56
57
58 static void
59 remove_tree (void)
60 {
61 FTSENT *e;
62 FTS *ftsp = fts_open (argv, FTS_NOSTAT | FTS_PHYSICAL | FTS_CWDFD, 0);
63 if (ftsp)
64 {
65 while ((e = fts_read (ftsp)))
66 {
67 int status = 0;
68 switch (e->fts_info)
69 {
70 case FTS_DP:
71 status = unlinkat (ftsp->fts_cwd_fd, e->fts_accpath,
72 AT_REMOVEDIR);
73 break;
74
75 case FTS_F: case FTS_NSOK:
76 status = unlinkat (ftsp->fts_cwd_fd, e->fts_accpath, 0);
77 break;
78 }
79 if (status != 0)
80 perror_exit (e->fts_path, 1);
81 }
82 if (fts_close (ftsp) != 0)
83 perror_exit ("fts_close", 2);
84 }
85 else if (errno != ENOENT)
86 perror_exit (base, 3);
87 }
88
89 int
90 main (void)
91 {
92 FTS *ftsp;
93 FTSENT *e;
94 char buf[sizeof BASE + 100];
95 int i;
96 enum { needles = 4 };
97 int needles_seen = 0;
98 struct stat st;
99
100 remove_tree ();
101
102
103
104
105
106
107
108 if (mkdir (BASE, 0777) != 0)
109 perror_exit (base, 4);
110 if (mkdir (base_d, 0777) != 0)
111 perror_exit (base_d, 5);
112 for (i = 1; i <= 65536; i++)
113 {
114 sprintf (buf, "%s/d/%i", base, i);
115 if (mkdir (buf, 0777) != 0)
116 {
117 if (errno == EMFILE || errno == EMLINK)
118 break;
119 if (i <= needles)
120 perror_exit (buf, 77);
121 break;
122 }
123 if (needles < i && stat (base_d, &st) == 0 && st.st_nlink != i + 2)
124 break;
125 }
126
127
128 for (i = 1; i <= needles; i++)
129 {
130 int fd;
131 sprintf (buf, "%s/d/%d/needle", base, i);
132 fd = open (buf, O_WRONLY | O_CREAT, 0666);
133 if (fd < 0 || close (fd) != 0)
134 perror_exit (buf, 77);
135 }
136
137
138 ftsp = fts_open (argv, FTS_SEEDOT | FTS_NOSTAT | FTS_PHYSICAL | FTS_CWDFD, 0);
139 if (!ftsp)
140 perror_exit (base, 6);
141 while ((e = fts_read (ftsp)))
142 needles_seen += strcmp (e->fts_name, "needle") == 0;
143 int fts_read_errno = errno;
144 fflush (stdout);
145 if (fts_read_errno)
146 {
147 errno = fts_read_errno;
148 perror_exit ("fts_read", 7);
149 }
150 if (fts_close (ftsp) != 0)
151 perror_exit (base, 8);
152
153
154 if (needles_seen != needles)
155 {
156 fprintf (stderr, "%d needles found (should be %d)\n",
157 needles_seen, needles);
158 return 1;
159 }
160
161 remove_tree ();
162 if (stat (base, &st) == 0)
163 {
164 fprintf (stderr, "fts could not remove directory\n");
165 return 1;
166 }
167
168 fts_dealloc ();
169
170 return 0;
171 }