dav/libxattr.c

changeset 813
06cf17795b86
parent 765
305ce525ad4a
child 814
0ce45bdc48bc
equal deleted inserted replaced
812:5fe4453fc025 813:06cf17795b86
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 }
148 free(attrname); 184 free(attrname);
149 return NULL; 185 return NULL;
150 } 186 }
151 } 187 }
152 } 188 }
189 buf[vlen] = 0;
153 190
154 free(attrname); 191 free(attrname);
155 buf[vlen] = 0;
156 *len = vlen; 192 *len = vlen;
157 return buf; 193 return buf;
158 } 194 }
159 195
160 int xattr_set(const char *path, const char *name, const void *value, size_t len) { 196 int xattr_set(const char *path, const char *name, const void *value, size_t len) {
184 220
185 char *name = buf; 221 char *name = buf;
186 for(int i=0;i<length;i++) { 222 for(int i=0;i<length;i++) {
187 if(buf[i] == '\0') { 223 if(buf[i] == '\0') {
188 char *attrname = strdup(name); 224 char *attrname = strdup(name);
189 ARRAY_ADD(array, arraypos, arraylen, attrname); 225 if(strarray_add(&array, &arraypos, &arraylen, attrname)) {
226 strarray_free(array, arraypos);
227 *nelm = -1;
228 return NULL;
229 }
190 name = buf + i + 1; 230 name = buf + i + 1;
191 } 231 }
192 } 232 }
193 233
194 if(arraypos == 0) { 234 if(arraypos == 0) {
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 }
238 *len = -1; 288 *len = -1;
239 return NULL; 289 return NULL;
240 } 290 }
241 291
242 char *buf = malloc(attrlen + 1); 292 char *buf = malloc(attrlen + 1);
293 if(!buf) {
294 *len = -1;
295 return NULL;
296 }
243 ssize_t vlen = getxattr(path, attr, buf, attrlen, 0, 0); 297 ssize_t vlen = getxattr(path, attr, buf, attrlen, 0, 0);
244 if(vlen < 0) { 298 if(vlen < 0) {
245 *len = -1; 299 *len = -1;
246 free(buf); 300 free(buf);
247 return NULL; 301 return NULL;
248 } 302 }
249 303 buf[vlen] = 0;
250 buf[attrlen] = 0; 304
251 *len = vlen; 305 *len = vlen;
252 return buf; 306 return buf;
253 } 307 }
254 308
255 int xattr_set(const char *path, const char *name, const void *value, size_t len) { 309 int xattr_set(const char *path, const char *name, const void *value, size_t len) {
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;
328 return NULL; 392 return NULL;
329 } 393 }
330 394
331 size_t bufsize = (size_t)s.st_size; 395 size_t bufsize = (size_t)s.st_size;
332 char *buf = malloc(bufsize + 1); 396 char *buf = malloc(bufsize + 1);
333 buf[bufsize] = 0; 397 if(!buf) {
398 close(attrfile);
399 return NULL;
400 }
334 401
335 char *b = buf; 402 char *b = buf;
336 size_t cur = 0; 403 size_t cur = 0;
337 while(cur < bufsize) { 404 while(cur < bufsize) {
338 ssize_t r = read(attrfile, buf + cur, bufsize - cur); 405 ssize_t r = read(attrfile, buf + cur, bufsize - cur);
346 if(cur != bufsize) { 413 if(cur != bufsize) {
347 free(buf); 414 free(buf);
348 return NULL; 415 return NULL;
349 } 416 }
350 417
418 buf[cur] = 0;
351 *len = (ssize_t)bufsize; 419 *len = (ssize_t)bufsize;
352 return buf; 420 return buf;
353 } 421 }
354 422
355 int xattr_set(const char *path, const char *name, const void *value, size_t len) { 423 int xattr_set(const char *path, const char *name, const void *value, size_t len) {
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);
427 } 508 }
428 return NULL; 509 return NULL;
429 } 510 }
430 511
431 char *list = malloc(lslen); 512 char *list = malloc(lslen);
513 if(!list) {
514 return NULL;
515 }
432 ssize_t len = extattr_list_file(path, EXTATTR_NAMESPACE_USER, list, lslen); 516 ssize_t len = extattr_list_file(path, EXTATTR_NAMESPACE_USER, list, lslen);
433 if(len == -1) { 517 if(len == -1) {
434 free(list); 518 free(list);
435 return NULL; 519 return NULL;
436 } 520 }

mercurial