1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #define _GNU_SOURCE
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <dirent.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <time.h>
43 #include <sys/xattr.h>
44
45 typedef struct FileList FileList;
46 struct FileList {
47 char *name;
48 char *path;
49 FileList *next;
50 };
51
52 static char * props[] = {
53 "user.test1",
"user.test2",
"user.test3",
"user.test4",
54 "user.test5",
"user.test6",
"user.test7",
"user.test8",
55 "user.test9",
"user.test10",
"user.test11",
"user.test12",
56 "user.test13",
"user.test14",
"user.test15",
"user.test16",
57 "user.test17",
"user.test18",
"user.test19",
"user.test20",
58 "user.test21",
"user.test22",
"user.test23",
"user.test24",
59 "user.test25",
"user.test26",
"user.test27",
"user.test28",
60 "user.test29",
"user.test30",
"user.test31",
"user.test32",
61 };
62
63 #ifndef NUM_XATTR
64 #define NUM_XATTR 16
65 #endif
66
67 #ifdef USE_FD
68
69 int get_attr(
int dirfd, FileList *elm) {
70 int fd = openat(dirfd, elm->name,
O_RDONLY);
71 if(fd == -
1) {
72 perror(
"openat");
73 return -
1;
74 }
75
76 int num =
NUM_XATTR >
4 ?
4 :
NUM_XATTR;
77
78 int ret =
0;
79 char buf[
128];
80 for(
int i=
0;i<num;i++) {
81 ssize_t s = fgetxattr(fd, props[i], buf,
128);
82 if(s <=
0) {
83 ret = -
1;
84 }
85 }
86
87 close(fd);
88
89 return 0;
90 }
91
92 #else
93
94 int get_attr(
int dirfd, FileList *elm) {
95 int num =
NUM_XATTR >
4 ?
4 :
NUM_XATTR;
96
97 int ret =
0;
98 char buf[
128];
99 for(
int i=
0;i<num;i++) {
100 ssize_t s = getxattr(elm->path, props[i], buf,
128);
101 if(s <=
0) {
102 ret = -
1;
103 }
104 }
105
106 return ret;
107 }
108
109 #endif
110
111 int main(
int argc,
char **argv) {
112 if(argc <
2) {
113 fprintf(stderr,
"Usage: %s <dir>\n", argv[
0]);
114 return EXIT_FAILURE;
115 }
116
117 printf(
"test %d xattr\n",
NUM_XATTR);
118 #ifdef USE_FD
119 printf(
"use fgetattr\n");
120 #else
121 printf(
"use getattr\n");
122 #endif
123
124 char *path = argv[
1];
125 size_t pathlen = strlen(path);
126 DIR *dir = opendir(path);
127 int fd = dirfd(dir);
128 if(!dir) {
129 fprintf(stderr,
"Cannot open directory: %s\n", path);
130 return EXIT_FAILURE;
131 }
132
133 FileList *files =
NULL;
134 FileList *last =
NULL;
135 size_t count =
0;
136
137 struct dirent *entry;
138 while((entry = readdir(dir)) !=
NULL) {
139 if(!strcmp(entry->d_name,
".") || !strcmp(entry->d_name,
"..")) {
140 continue;
141 }
142
143 FileList *file = calloc(
1,
sizeof(FileList));
144 file->name = strdup(entry->d_name);
145
146 if(path[pathlen -
1] ==
'/') {
147 asprintf(&file->path,
"%s%s", path, entry->d_name);
148 }
else {
149 asprintf(&file->path,
"%s/%s", path, entry->d_name);
150 }
151
152 if(!files) {
153 files = file;
154 }
else {
155 last->next = file;
156 }
157 last = file;
158 count++;
159 }
160
161 if(files) {
162 printf(
"test %zu files:\n\nbegin\n", count);
163
164 struct timespec begin;
165 clock_gettime(
CLOCK_REALTIME, &begin);
166
167 FileList *elm = files;
168 while(elm) {
169 if(get_attr(fd, elm)) {
170 fprintf(stderr,
"Error.\nAbort.\n");
171 break;
172 }
173
174 elm = elm->next;
175 }
176
177 struct timespec end;
178 clock_gettime(
CLOCK_REALTIME, &end);
179 printf(
"time: %ld ns\n\n", end.tv_nsec - begin.tv_nsec);
180 }
else {
181 fprintf(stderr,
"No files in %s\n", path);
182 }
183
184
185 FileList *elm = files;
186 while(elm) {
187 free(elm->name);
188 free(elm->path);
189 FileList *next = elm->next;
190 free(elm);
191 elm = next;
192 }
193 closedir(dir);
194
195 return EXIT_SUCCESS;
196 }
197