UNIXworkcode

1 /* 2 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 3 * Version 2, December 2004 4 * 5 * Copyright (C) 2016 Olaf Wintermann <olaf.wintermann@gmail.com> 6 * 7 * Everyone is permitted to copy and distribute verbatim or modified 8 * copies of this license document, and changing it is allowed as long 9 * as the name is changed. 10 * 11 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 12 * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 13 * 14 * 0. You just DO WHAT THE FUCK YOU WANT TO. 15 */ 16 17 /* create a test directory with this script: 18 19 #!/bin/sh 20 echo create $1 files 21 for i in `seq 1 $1`; 22 do 23 file=file$i 24 echo create $file 25 echo "hello" > $file 26 for j in `seq 1 32`; 27 do 28 setfattr -n user.test$j -v content$j $file 29 done 30 done 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 // cleanup 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