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   /*
18    * tool for copying extended attributes on FreeBSD
19    */
20  
21  #include <sys/types.h>
22  #include <sys/extattr.h>
23  
24  #include <stdio.h>
25  #include <stdlib.h>
26  #include <unistd.h>
27  #include <fcntl.h>
28  
29  int main(int argc, char **argv) {
30      if(argc < 3) {
31          fprintf(stderr, "usage: %s <srcfile> <destfile>\n", argv[0]);
32          return -1;
33      }
34      
35      int src = open(argv[1], O_RDONLY);
36      if(src == -1) {
37          fprintf(stderr, "Cannot open %s: ", argv[1]);
38          perror(NULL);
39          return -1;
40      }
41      
42      int dst = open(argv[2], O_WRONLY);
43      if(dst == -1) {
44          fprintf(stderr, "Cannot open %s: ", argv[2]);
45          perror(NULL);
46          return -1;
47      }
48      
49      // get length of attributes list
50      ssize_t lslen = extattr_list_fd(src, EXTATTR_NAMESPACE_USER, NULL, 0);
51      if(lslen < 0) {
52          perror("extattr_list_fd");
53          return -1;
54      }
55      if(lslen == 0) {
56          return 0;
57      }
58      
59      // get attributes list
60      char *list = malloc(lslen + 1);
61      lslen = extattr_list_fd(src, EXTATTR_NAMESPACE_USER, list, lslen);
62      if(lslen < 0) {
63          perror("extattr_list_fd");
64          return -1;
65      }
66      
67      for(int i=0;i<lslen;i++) {
68          char namelen = list[i];
69          char *name = list + i + 1;
70          
71          char nextlen = list[i + namelen + 1]; // save length of next name
72          list[i + namelen + 1] = '\0'; // terminate string temporary
73          
74          // get xattr from src and add it to dst
75          printf("%s\n", name);
76          ssize_t len = extattr_get_fd(src, EXTATTR_NAMESPACE_USER, name, NULL, 0);
77          if(len > 0) {
78              char *value = malloc(len);
79              len = extattr_get_fd(src, EXTATTR_NAMESPACE_USER, name, value, len);
80              if(len > 0) {
81                  if(extattr_set_fd(dst, EXTATTR_NAMESPACE_USER, name, value, len) == -1) {
82                      perror("extattr_set_fd");
83                  }
84              } else {
85                  perror("extattr_get_fd");
86              }
87              free(value);
88          } else {
89              perror("extattr_get_fd");
90          }
91          
92          list[i + namelen + 1] = nextlen; // restore length
93          i += namelen;
94      }
95      
96      return 0;
97  }