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  }