1 /* |
1 /* |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 * Copyright 2019 Olaf Wintermann |
3 * |
3 * |
4 * Copyright 2018 Olaf Wintermann. All rights reserved. |
4 * Permission is hereby granted, free of charge, to any person obtaining a |
|
5 * copy of this software and associated documentation files (the "Software"), |
|
6 * to deal in the Software without restriction, including without limitation |
|
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
8 * and/or sell copies of the Software, and to permit persons to whom the |
|
9 * Software is furnished to do so, subject to the following conditions: |
|
10 * |
|
11 * The above copyright notice and this permission notice shall be included in |
|
12 * all copies or substantial portions of the Software. |
5 * |
13 * |
6 * Redistribution and use in source and binary forms, with or without |
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
7 * modification, are permitted provided that the following conditions are met: |
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
8 * |
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
9 * 1. Redistributions of source code must retain the above copyright |
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
10 * notice, this list of conditions and the following disclaimer. |
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
11 * |
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
12 * 2. Redistributions in binary form must reproduce the above copyright |
20 * DEALINGS IN THE SOFTWARE. |
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
21 */ |
28 |
22 |
29 #define _GNU_SOURCE |
23 #define _GNU_SOURCE |
30 |
24 |
31 #include <stdio.h> |
25 #include <stdio.h> |
40 |
34 |
41 #define LIST_BUF_LEN 1024 |
35 #define LIST_BUF_LEN 1024 |
42 #define LIST_ARRAY_LEN 8 |
36 #define LIST_ARRAY_LEN 8 |
43 #define ATTR_BUF_LEN 1024 |
37 #define ATTR_BUF_LEN 1024 |
44 |
38 |
45 #define ARRAY_ADD(array, pos, len, obj) if(pos >= len) { \ |
39 |
46 len *= 2; /* TODO: missing error handling for realloc() */ \ |
40 static int strarray_add(char ***array_ptr, size_t *pos, size_t *len, char *str) { |
47 array = realloc(array, len * sizeof(char*)); \ |
41 char **array = *array_ptr; |
48 } \ |
42 size_t array_pos = *pos; |
49 array[pos] = obj; \ |
43 size_t array_len = *len; |
50 pos++; |
44 if(array_pos >= array_len) { |
51 |
45 size_t newlen = array_len * 2; |
|
46 char **new_array = NULL; //realloc(array, newlen * sizeof(char*)); |
|
47 if(!new_array) { |
|
48 return 1; |
|
49 } |
|
50 *len = array_len; |
|
51 array = new_array; |
|
52 *array_ptr = new_array; |
|
53 } |
|
54 |
|
55 array[array_pos] = str; |
|
56 *pos = array_pos + 1; |
|
57 |
|
58 return 0; |
|
59 } |
|
60 |
|
61 static void strarray_free(char **array, size_t nelm) { |
|
62 for(size_t i=0;i<nelm;i++) { |
|
63 free(array[i]); |
|
64 } |
|
65 free(array); |
|
66 } |
52 |
67 |
53 #ifdef __linux__ |
68 #ifdef __linux__ |
54 #define XATTR_SUPPORTED |
69 #define XATTR_SUPPORTED |
55 #include <sys/xattr.h> |
70 #include <sys/xattr.h> |
56 |
71 |
61 |
76 |
62 char *begin = buf; |
77 char *begin = buf; |
63 char *name = NULL; |
78 char *name = NULL; |
64 for(int i=0;i<length;i++) { |
79 for(int i=0;i<length;i++) { |
65 if(!name && buf[i] == '.') { |
80 if(!name && buf[i] == '.') { |
66 int nslen = (buf+i-begin); |
|
67 //printf("%.*s\n", nslen, begin); |
|
68 name = buf + i + 1; |
81 name = buf + i + 1; |
69 } |
82 } |
70 if(buf[i] == '\0') { |
83 if(buf[i] == '\0') { |
71 char *attrname = strdup(name); |
84 char *attrname = strdup(name); |
72 ARRAY_ADD(array, arraypos, arraylen, attrname); |
85 if(strarray_add(&array, &arraypos, &arraylen, attrname)) { |
|
86 strarray_free(array, arraypos); |
|
87 *nelm = -1; |
|
88 return NULL; |
|
89 } |
73 begin = buf + i + 1; |
90 begin = buf + i + 1; |
74 name = 0; |
91 name = 0; |
75 } |
92 } |
76 } |
93 } |
77 |
94 |
84 return array; |
101 return array; |
85 } |
102 } |
86 |
103 |
87 char ** xattr_list(const char *path, ssize_t *nelm) { |
104 char ** xattr_list(const char *path, ssize_t *nelm) { |
88 char *list = malloc(LIST_BUF_LEN); |
105 char *list = malloc(LIST_BUF_LEN); |
|
106 if(!list) { |
|
107 *nelm = -1; |
|
108 return NULL; |
|
109 } |
89 ssize_t len = listxattr(path, list, LIST_BUF_LEN); |
110 ssize_t len = listxattr(path, list, LIST_BUF_LEN); |
90 if(len == -1) { |
111 if(len == -1) { |
91 switch(errno) { |
112 switch(errno) { |
92 case ERANGE: { |
113 case ERANGE: { |
93 // buffer too, get size of attribute list |
114 // buffer too, get size of attribute list |
94 ssize_t newlen = listxattr(path, NULL, 0); |
115 ssize_t newlen = listxattr(path, NULL, 0); |
95 if(newlen > 0) { |
116 if(newlen > 0) { |
96 // second try |
117 // second try |
97 list = realloc(list, newlen); |
118 char *new_list = realloc(list, newlen); |
|
119 if(!new_list) { |
|
120 free(list); |
|
121 *nelm = -1; |
|
122 return NULL; |
|
123 } |
|
124 list = new_list; |
98 len = listxattr(path, list, newlen); |
125 len = listxattr(path, list, newlen); |
99 if(len != -1) { |
126 if(len != -1) { |
100 // this time it worked |
127 // this time it worked |
101 break; |
128 break; |
102 } |
129 } |
126 |
153 |
127 char * xattr_get(const char *path, const char *attr, ssize_t *len) { |
154 char * xattr_get(const char *path, const char *attr, ssize_t *len) { |
128 char *attrname = name2nsname(attr); |
155 char *attrname = name2nsname(attr); |
129 |
156 |
130 char *buf = malloc(ATTR_BUF_LEN); |
157 char *buf = malloc(ATTR_BUF_LEN); |
131 ssize_t vlen = getxattr(path, attrname, buf, ATTR_BUF_LEN); |
158 if(!buf) { |
|
159 *len = -1; |
|
160 return NULL; |
|
161 } |
|
162 ssize_t vlen = getxattr(path, attrname, buf, ATTR_BUF_LEN - 1); |
132 if(vlen < 0) { |
163 if(vlen < 0) { |
133 switch(errno) { |
164 switch(errno) { |
134 case ERANGE: { |
165 case ERANGE: { |
135 ssize_t attrlen = getxattr(path, attrname, NULL, 0); |
166 ssize_t attrlen = getxattr(path, attrname, NULL, 0); |
136 if(attrlen > 0) { |
167 if(attrlen > 0) { |
137 free(buf); |
168 free(buf); |
138 buf = malloc(attrlen + 1); |
169 buf = malloc(attrlen + 1); |
|
170 if(!buf) { |
|
171 *len = -1; |
|
172 free(attrname); |
|
173 return NULL; |
|
174 } |
139 vlen = getxattr(path, attrname, buf, attrlen); |
175 vlen = getxattr(path, attrname, buf, attrlen); |
140 if(vlen > 0) { |
176 if(vlen > 0) { |
141 break; |
177 break; |
142 } |
178 } |
143 } |
179 } |
200 return array; |
240 return array; |
201 } |
241 } |
202 |
242 |
203 char ** xattr_list(const char *path, ssize_t *nelm) { |
243 char ** xattr_list(const char *path, ssize_t *nelm) { |
204 char *list = malloc(LIST_BUF_LEN); |
244 char *list = malloc(LIST_BUF_LEN); |
|
245 if(!list) { |
|
246 *nelm = -1; |
|
247 return NULL; |
|
248 } |
205 ssize_t len = listxattr(path, list, LIST_BUF_LEN, 0); |
249 ssize_t len = listxattr(path, list, LIST_BUF_LEN, 0); |
206 if(len == -1) { |
250 if(len == -1) { |
207 switch(errno) { |
251 switch(errno) { |
208 case ERANGE: { |
252 case ERANGE: { |
209 // buffer too, get size of attribute list |
253 // buffer too, get size of attribute list |
210 ssize_t newlen = listxattr(path, NULL, 0, 0); |
254 ssize_t newlen = listxattr(path, NULL, 0, 0); |
211 if(newlen > 0) { |
255 if(newlen > 0) { |
212 // second try |
256 // second try |
213 list = realloc(list, newlen); |
257 char *new_list = realloc(list, newlen); |
|
258 if(!new_list) { |
|
259 free(list); |
|
260 *nelm = -1; |
|
261 return NULL; |
|
262 } |
|
263 list = new_list; |
214 len = listxattr(path, list, newlen, 0); |
264 len = listxattr(path, list, newlen, 0); |
215 if(len != -1) { |
265 if(len != -1) { |
216 // this time it worked |
266 // this time it worked |
217 break; |
267 break; |
218 } |
268 } |
297 } |
351 } |
298 |
352 |
299 size_t arraylen = LIST_ARRAY_LEN; |
353 size_t arraylen = LIST_ARRAY_LEN; |
300 size_t arraypos = 0; |
354 size_t arraypos = 0; |
301 char **array = malloc(LIST_ARRAY_LEN * sizeof(char*)); |
355 char **array = malloc(LIST_ARRAY_LEN * sizeof(char*)); |
|
356 if(!array) { |
|
357 closedir(dir); |
|
358 *nelm = -1; |
|
359 return NULL; |
|
360 } |
302 |
361 |
303 struct dirent *ent; |
362 struct dirent *ent; |
304 while((ent = readdir(dir)) != NULL) { |
363 while((ent = readdir(dir)) != NULL) { |
305 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "SUNWattr_ro") || !strcmp(ent->d_name, "SUNWattr_rw")) { |
364 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "SUNWattr_ro") || !strcmp(ent->d_name, "SUNWattr_rw")) { |
306 continue; |
365 continue; |
307 } |
366 } |
308 char *name = strdup(ent->d_name); |
367 char *name = strdup(ent->d_name); |
309 ARRAY_ADD(array, arraypos, arraylen, name); |
368 if(strarray_add(&array, &arraypos, &arraylen, name)) { |
|
369 strarray_free(array, arraypos); |
|
370 *nelm = -1; |
|
371 closedir(dir); |
|
372 return NULL; |
|
373 } |
310 } |
374 } |
311 closedir(dir); |
375 closedir(dir); |
312 |
376 |
313 *nelm = arraypos; |
377 *nelm = arraypos; |
314 return array; |
378 return array; |
396 |
464 |
397 static char ** parse_xattrlist(char *buf, ssize_t length, ssize_t *nelm) { |
465 static char ** parse_xattrlist(char *buf, ssize_t length, ssize_t *nelm) { |
398 size_t arraylen = LIST_ARRAY_LEN; |
466 size_t arraylen = LIST_ARRAY_LEN; |
399 size_t arraypos = 0; |
467 size_t arraypos = 0; |
400 char **array = malloc(LIST_ARRAY_LEN * sizeof(char*)); |
468 char **array = malloc(LIST_ARRAY_LEN * sizeof(char*)); |
|
469 if(!array) { |
|
470 *nelm = -1; |
|
471 return NULL; |
|
472 } |
401 |
473 |
402 for(int i=0;i<length;i++) { |
474 for(int i=0;i<length;i++) { |
403 char namelen = buf[i]; |
475 int namelen = buf[i]; |
404 char *name = buf + i + 1; |
476 char *name = buf + i + 1; |
405 char *attrname = malloc(namelen + 1); |
477 char *attrname = malloc(namelen + 1); |
|
478 if(!attrname) { |
|
479 strarray_free(array, arraypos); |
|
480 *nelm = -1; |
|
481 return NULL; |
|
482 } |
406 memcpy(attrname, name, namelen); |
483 memcpy(attrname, name, namelen); |
407 attrname[namelen] = 0; |
484 attrname[namelen] = 0; |
408 ARRAY_ADD(array, arraypos, arraylen, attrname); |
485 if(strarray_add(&array, &arraypos, &arraylen, attrname)) { |
|
486 strarray_free(array, arraypos); |
|
487 *nelm = -1; |
|
488 return NULL; |
|
489 } |
409 i += namelen; |
490 i += namelen; |
410 } |
491 } |
411 |
492 |
412 if(arraypos == 0) { |
493 if(arraypos == 0) { |
413 free(array); |
494 free(array); |