1/* 2 Unix SMB/CIFS implementation. 3 Samba system utilities 4 Copyright (C) Andrew Tridgell 1992-1998 5 Copyright (C) Jeremy Allison 1998-2005 6 Copyright (C) Timur Bakeyev 2005 7 Copyright (C) Bjoern Jacke 2006-2007 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23 sys_copyxattr modified from LGPL2.1 libattr copyright 24 Copyright (C) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. 25 Copyright (C) 2001 Andreas Gruenbacher. 26 27 Samba 3.0.28, modified for netatalk. 28 $Id: sys_ea.c,v 1.6 2009-12-04 10:26:10 franklahm Exp $ 29 30*/ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include <stdlib.h> 37#include <string.h> 38#include <sys/types.h> 39#include <errno.h> 40 41#if HAVE_ATTR_XATTR_H 42#include <attr/xattr.h> 43#elif HAVE_SYS_XATTR_H 44#include <sys/xattr.h> 45#endif 46 47#ifdef HAVE_SYS_EA_H 48#include <sys/ea.h> 49#endif 50 51#ifdef HAVE_ATTROPEN 52 53#include <dirent.h> 54#endif 55 56#ifdef HAVE_SYS_EXTATTR_H 57#include <sys/extattr.h> 58#endif 59 60#include <atalk/adouble.h> 61#include <atalk/util.h> 62#include <atalk/logger.h> 63#include <atalk/ea.h> 64 65#ifndef ENOATTR 66#define ENOATTR ENODATA 67#endif 68 69/******** Solaris EA helper function prototypes ********/ 70#ifdef HAVE_ATTROPEN 71#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP 72static int solaris_write_xattr(int attrfd, const char *value, size_t size); 73static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size); 74static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size); 75static int solaris_unlinkat(int attrdirfd, const char *name); 76static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode); 77static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode); 78#endif 79 80/************************************************************************** 81 Wrappers for extented attribute calls. Based on the Linux package with 82 support for IRIX and (Net|Free)BSD also. Expand as other systems have them. 83****************************************************************************/ 84static char attr_name[256 +5] = "user."; 85 86static const char *prefix(const char *uname) 87{ 88#if defined(HAVE_ATTROPEN) 89 return uname; 90#else 91 strlcpy(attr_name +5, uname, 256); 92 return attr_name; 93#endif 94} 95 96ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size) 97{ 98 const char *name = prefix(uname); 99 100#if defined(HAVE_GETXATTR) 101#ifndef XATTR_ADD_OPT 102 return getxattr(path, name, value, size); 103#else 104 int options = 0; 105 return getxattr(path, name, value, size, 0, options); 106#endif 107#elif defined(HAVE_GETEA) 108 return getea(path, name, value, size); 109#elif defined(HAVE_EXTATTR_GET_FILE) 110 ssize_t retval; 111 /* 112 * The BSD implementation has a nasty habit of silently truncating 113 * the returned value to the size of the buffer, so we have to check 114 * that the buffer is large enough to fit the returned value. 115 */ 116 if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) { 117 if (size == 0) 118 /* size == 0 means only return size */ 119 return retval; 120 if (retval > size) { 121 errno = ERANGE; 122 return -1; 123 } 124 if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0) 125 return retval; 126 } 127 128 LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)); 129 return -1; 130#elif defined(HAVE_ATTR_GET) 131 int retval, flags = 0; 132 int valuelength = (int)size; 133 char *attrname = strchr(name,'.') + 1; 134 135 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; 136 137 retval = attr_get(path, attrname, (char *)value, &valuelength, flags); 138 139 return retval ? retval : valuelength; 140#elif defined(HAVE_ATTROPEN) 141 ssize_t ret = -1; 142 int attrfd = solaris_attropen(path, name, O_RDONLY, 0); 143 if (attrfd >= 0) { 144 ret = solaris_read_xattr(attrfd, value, size); 145 close(attrfd); 146 } 147 return ret; 148#else 149 errno = ENOSYS; 150 return -1; 151#endif 152} 153 154ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size) 155{ 156 const char *name = prefix(uname); 157 158#if defined(HAVE_LGETXATTR) 159 return lgetxattr(path, name, value, size); 160#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT) 161 int options = XATTR_NOFOLLOW; 162 return getxattr(path, name, value, size, 0, options); 163#elif defined(HAVE_LGETEA) 164 return lgetea(path, name, value, size); 165#elif defined(HAVE_EXTATTR_GET_LINK) 166 ssize_t retval; 167 if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) { 168 if(retval > size) { 169 errno = ERANGE; 170 return -1; 171 } 172 if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0) 173 return retval; 174 } 175 176 LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)); 177 return -1; 178#elif defined(HAVE_ATTR_GET) 179 int retval, flags = ATTR_DONTFOLLOW; 180 int valuelength = (int)size; 181 char *attrname = strchr(name,'.') + 1; 182 183 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; 184 185 retval = attr_get(path, attrname, (char *)value, &valuelength, flags); 186 187 return retval ? retval : valuelength; 188#elif defined(HAVE_ATTROPEN) 189 ssize_t ret = -1; 190 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); 191 if (attrfd >= 0) { 192 ret = solaris_read_xattr(attrfd, value, size); 193 close(attrfd); 194 } 195 return ret; 196#else 197 errno = ENOSYS; 198 return -1; 199#endif 200} 201 202#if defined(HAVE_EXTATTR_LIST_FILE) 203 204#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1) 205 206static struct { 207 int space; 208 const char *name; 209 size_t len; 210} 211extattr[] = { 212 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("") }, 213 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("") }, 214}; 215 216typedef union { 217 const char *path; 218 int filedes; 219} extattr_arg; 220 221static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) 222{ 223 ssize_t list_size; 224 int i, len; 225 226 switch(type) { 227#if defined(HAVE_EXTATTR_LIST_FILE) 228 case 0: 229 list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size); 230 break; 231#endif 232#if defined(HAVE_EXTATTR_LIST_LINK) 233 case 1: 234 list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size); 235 break; 236#endif 237#if defined(HAVE_EXTATTR_LIST_FD) 238 case 2: 239 list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size); 240 break; 241#endif 242 default: 243 errno = ENOSYS; 244 return -1; 245 } 246 247 /* Some error happend. Errno should be set by the previous call */ 248 if(list_size < 0) 249 return -1; 250 251 /* No attributes */ 252 if(list_size == 0) 253 return 0; 254 255 /* XXX: Call with an empty buffer may be used to calculate 256 necessary buffer size. Unfortunately, we can't say, how 257 many attributes were returned, so here is the potential 258 problem with the emulation. 259 */ 260 if(list == NULL) 261 return list_size; 262 263 /* Buffer is too small to fit the results */ 264 if(list_size > size) { 265 errno = ERANGE; 266 return -1; 267 } 268 269 /* Convert from pascal strings to C strings */ 270 len = list[0]; 271 memmove(list, list + 1, list_size); 272 273 for(i = len; i < list_size; ) { 274 LOG(log_maxdebug, logtype_afpd, "len: %d, i: %d", len, i); 275 276 len = list[i]; 277 list[i] = '\0'; 278 i += len + 1; 279 } 280 281 return list_size; 282} 283 284#endif 285 286#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) 287static char attr_buffer[ATTR_MAX_VALUELEN]; 288 289static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags) 290{ 291 int retval = 0, index; 292 attrlist_cursor_t *cursor = 0; 293 int total_size = 0; 294 attrlist_t * al = (attrlist_t *)attr_buffer; 295 attrlist_ent_t *ae; 296 size_t ent_size, left = size; 297 char *bp = list; 298 299 while (True) { 300 if (filedes) 301 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); 302 else 303 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); 304 if (retval) break; 305 for (index = 0; index < al->al_count; index++) { 306 ae = ATTR_ENTRY(attr_buffer, index); 307 ent_size = strlen(ae->a_name) + sizeof("user."); 308 if (left >= ent_size) { 309 strncpy(bp, "user.", sizeof("user.")); 310 strncat(bp, ae->a_name, ent_size - sizeof("user.")); 311 bp += ent_size; 312 left -= ent_size; 313 } else if (size) { 314 errno = ERANGE; 315 retval = -1; 316 break; 317 } 318 total_size += ent_size; 319 } 320 if (al->al_more == 0) break; 321 } 322 if (retval == 0) { 323 flags |= ATTR_ROOT; 324 cursor = 0; 325 while (True) { 326 if (filedes) 327 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); 328 else 329 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); 330 if (retval) break; 331 for (index = 0; index < al->al_count; index++) { 332 ae = ATTR_ENTRY(attr_buffer, index); 333 ent_size = strlen(ae->a_name) + sizeof("system."); 334 if (left >= ent_size) { 335 strncpy(bp, "system.", sizeof("system.")); 336 strncat(bp, ae->a_name, ent_size - sizeof("system.")); 337 bp += ent_size; 338 left -= ent_size; 339 } else if (size) { 340 errno = ERANGE; 341 retval = -1; 342 break; 343 } 344 total_size += ent_size; 345 } 346 if (al->al_more == 0) break; 347 } 348 } 349 return (ssize_t)(retval ? retval : total_size); 350} 351 352#endif 353 354#if defined(HAVE_LISTXATTR) 355static ssize_t remove_user(ssize_t ret, char *list, size_t size) 356{ 357 size_t len; 358 char *ptr; 359 char *ptr1; 360 ssize_t ptrsize; 361 362 if (ret <= 0 || size == 0) 363 return ret; 364 ptrsize = ret; 365 ptr = ptr1 = list; 366 while (ptrsize > 0) { 367 len = strlen(ptr1) +1; 368 ptrsize -= len; 369 if (strncmp(ptr1, "user.",5)) { 370 ptr1 += len; 371 continue; 372 } 373 memmove(ptr, ptr1 +5, len -5); 374 ptr += len -5; 375 ptr1 += len; 376 } 377 return ptr -list; 378} 379#endif 380 381ssize_t sys_listxattr (const char *path, char *list, size_t size) 382{ 383#if defined(HAVE_LISTXATTR) 384 ssize_t ret; 385 386#ifndef XATTR_ADD_OPT 387 ret = listxattr(path, list, size); 388#else 389 int options = 0; 390 ret = listxattr(path, list, size, options); 391#endif 392 return remove_user(ret, list, size); 393 394#elif defined(HAVE_LISTEA) 395 return listea(path, list, size); 396#elif defined(HAVE_EXTATTR_LIST_FILE) 397 extattr_arg arg; 398 arg.path = path; 399 return bsd_attr_list(0, arg, list, size); 400#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) 401 return irix_attr_list(path, 0, list, size, 0); 402#elif defined(HAVE_ATTROPEN) 403 ssize_t ret = -1; 404 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); 405 if (attrdirfd >= 0) { 406 ret = solaris_list_xattr(attrdirfd, list, size); 407 close(attrdirfd); 408 } 409 return ret; 410#else 411 errno = ENOSYS; 412 return -1; 413#endif 414} 415 416ssize_t sys_llistxattr (const char *path, char *list, size_t size) 417{ 418#if defined(HAVE_LLISTXATTR) 419 ssize_t ret; 420 421 ret = llistxattr(path, list, size); 422 return remove_user(ret, list, size); 423#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT) 424 ssize_t ret; 425 int options = XATTR_NOFOLLOW; 426 427 ret = listxattr(path, list, size, options); 428 return remove_user(ret, list, size); 429 430#elif defined(HAVE_LLISTEA) 431 return llistea(path, list, size); 432#elif defined(HAVE_EXTATTR_LIST_LINK) 433 extattr_arg arg; 434 arg.path = path; 435 return bsd_attr_list(1, arg, list, size); 436#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) 437 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); 438#elif defined(HAVE_ATTROPEN) 439 ssize_t ret = -1; 440 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); 441 if (attrdirfd >= 0) { 442 ret = solaris_list_xattr(attrdirfd, list, size); 443 close(attrdirfd); 444 } 445 return ret; 446#else 447 errno = ENOSYS; 448 return -1; 449#endif 450} 451 452int sys_removexattr (const char *path, const char *uname) 453{ 454 const char *name = prefix(uname); 455#if defined(HAVE_REMOVEXATTR) 456#ifndef XATTR_ADD_OPT 457 return removexattr(path, name); 458#else 459 int options = 0; 460 return removexattr(path, name, options); 461#endif 462#elif defined(HAVE_REMOVEEA) 463 return removeea(path, name); 464#elif defined(HAVE_EXTATTR_DELETE_FILE) 465 return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname); 466#elif defined(HAVE_ATTR_REMOVE) 467 int flags = 0; 468 char *attrname = strchr(name,'.') + 1; 469 470 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; 471 472 return attr_remove(path, attrname, flags); 473#elif defined(HAVE_ATTROPEN) 474 int ret = -1; 475 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); 476 if (attrdirfd >= 0) { 477 ret = solaris_unlinkat(attrdirfd, name); 478 close(attrdirfd); 479 } 480 return ret; 481#else 482 errno = ENOSYS; 483 return -1; 484#endif 485} 486 487int sys_lremovexattr (const char *path, const char *uname) 488{ 489 const char *name = prefix(uname); 490#if defined(HAVE_LREMOVEXATTR) 491 return lremovexattr(path, name); 492#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT) 493 int options = XATTR_NOFOLLOW; 494 return removexattr(path, name, options); 495#elif defined(HAVE_LREMOVEEA) 496 return lremoveea(path, name); 497#elif defined(HAVE_EXTATTR_DELETE_LINK) 498 return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, uname); 499#elif defined(HAVE_ATTR_REMOVE) 500 int flags = ATTR_DONTFOLLOW; 501 char *attrname = strchr(name,'.') + 1; 502 503 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; 504 505 return attr_remove(path, attrname, flags); 506#elif defined(HAVE_ATTROPEN) 507 int ret = -1; 508 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); 509 if (attrdirfd >= 0) { 510 ret = solaris_unlinkat(attrdirfd, name); 511 close(attrdirfd); 512 } 513 return ret; 514#else 515 errno = ENOSYS; 516 return -1; 517#endif 518} 519 520int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags) 521{ 522 const char *name = prefix(uname); 523#if defined(HAVE_SETXATTR) 524#ifndef XATTR_ADD_OPT 525 return setxattr(path, name, value, size, flags); 526#else 527 int options = 0; 528 return setxattr(path, name, value, size, 0, options); 529#endif 530#elif defined(HAVE_SETEA) 531 return setea(path, name, value, size, flags); 532#elif defined(HAVE_EXTATTR_SET_FILE) 533 int retval = 0; 534 if (flags) { 535 /* Check attribute existence */ 536 retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); 537 if (retval < 0) { 538 /* REPLACE attribute, that doesn't exist */ 539 if (flags & XATTR_REPLACE && errno == ENOATTR) { 540 errno = ENOATTR; 541 return -1; 542 } 543 /* Ignore other errors */ 544 } 545 else { 546 /* CREATE attribute, that already exists */ 547 if (flags & XATTR_CREATE) { 548 errno = EEXIST; 549 return -1; 550 } 551 } 552 } 553 retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size); 554 return (retval < 0) ? -1 : 0; 555#elif defined(HAVE_ATTR_SET) 556 int myflags = 0; 557 char *attrname = strchr(name,'.') + 1; 558 559 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; 560 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; 561 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; 562 563 return attr_set(path, attrname, (const char *)value, size, myflags); 564#elif defined(HAVE_ATTROPEN) 565 int ret = -1; 566 int myflags = O_RDWR; 567 int attrfd; 568 if (flags & XATTR_CREATE) myflags |= O_EXCL; 569 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; 570 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); 571 if (attrfd >= 0) { 572 ret = solaris_write_xattr(attrfd, value, size); 573 close(attrfd); 574 } 575 return ret; 576#else 577 errno = ENOSYS; 578 return -1; 579#endif 580} 581 582int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags) 583{ 584 const char *name = prefix(uname); 585#if defined(HAVE_LSETXATTR) 586 return lsetxattr(path, name, value, size, flags); 587#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT) 588 int options = XATTR_NOFOLLOW; 589 return setxattr(path, name, value, size, 0, options); 590#elif defined(LSETEA) 591 return lsetea(path, name, value, size, flags); 592#elif defined(HAVE_EXTATTR_SET_LINK) 593 int retval = 0; 594 if (flags) { 595 /* Check attribute existence */ 596 retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); 597 if (retval < 0) { 598 /* REPLACE attribute, that doesn't exist */ 599 if (flags & XATTR_REPLACE && errno == ENOATTR) { 600 errno = ENOATTR; 601 return -1; 602 } 603 /* Ignore other errors */ 604 } 605 else { 606 /* CREATE attribute, that already exists */ 607 if (flags & XATTR_CREATE) { 608 errno = EEXIST; 609 return -1; 610 } 611 } 612 } 613 614 retval = extattr_set_link(path, EXTATTR_NAMESPACE_USER, uname, value, size); 615 return (retval < 0) ? -1 : 0; 616#elif defined(HAVE_ATTR_SET) 617 int myflags = ATTR_DONTFOLLOW; 618 char *attrname = strchr(name,'.') + 1; 619 620 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; 621 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; 622 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; 623 624 return attr_set(path, attrname, (const char *)value, size, myflags); 625#elif defined(HAVE_ATTROPEN) 626 int ret = -1; 627 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW; 628 int attrfd; 629 if (flags & XATTR_CREATE) myflags |= O_EXCL; 630 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; 631 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); 632 if (attrfd >= 0) { 633 ret = solaris_write_xattr(attrfd, value, size); 634 close(attrfd); 635 } 636 return ret; 637#else 638 errno = ENOSYS; 639 return -1; 640#endif 641} 642 643/************************************************************************** 644 helper functions for Solaris' EA support 645****************************************************************************/ 646#ifdef HAVE_ATTROPEN 647static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size) 648{ 649 struct stat sbuf; 650 651 if (fstat(attrfd, &sbuf) == -1) { 652 return -1; 653 } 654 655 /* This is to return the current size of the named extended attribute */ 656 if (size == 0) { 657 return sbuf.st_size; 658 } 659 660 /* check size and read xattr */ 661 if (sbuf.st_size > size) { 662 return -1; 663 } 664 665 return read(attrfd, value, sbuf.st_size); 666} 667 668static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size) 669{ 670 ssize_t len = 0; 671 DIR *dirp; 672 struct dirent *de; 673 int newfd = dup(attrdirfd); 674 /* CAUTION: The originating file descriptor should not be 675 used again following the call to fdopendir(). 676 For that reason we dup() the file descriptor 677 here to make things more clear. */ 678 dirp = fdopendir(newfd); 679 680 while ((de = readdir(dirp))) { 681 size_t listlen; 682 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || 683 !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw")) 684 { 685 /* we don't want "." and ".." here: */ 686 LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name); 687 continue; 688 } 689 690 listlen = strlen(de->d_name); 691 if (size == 0) { 692 /* return the current size of the list of extended attribute names*/ 693 len += listlen + 1; 694 } else { 695 /* check size and copy entry + nul into list. */ 696 if ((len + listlen + 1) > size) { 697 errno = ERANGE; 698 len = -1; 699 break; 700 } else { 701 strcpy(list + len, de->d_name); 702 len += listlen; 703 list[len] = '\0'; 704 ++len; 705 } 706 } 707 } 708 709 if (closedir(dirp) == -1) { 710 LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno)); 711 return -1; 712 } 713 return len; 714} 715 716static int solaris_unlinkat(int attrdirfd, const char *name) 717{ 718 if (unlinkat(attrdirfd, name, 0) == -1) { 719 return -1; 720 } 721 return 0; 722} 723 724static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) 725{ 726 return attropen(path, attrpath, oflag, mode); 727} 728 729static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) 730{ 731 int filedes = openat(fildes, path, oflag, mode); 732 if (filedes == -1) { 733 LOG(log_error, logtype_default, "openat(\"%s\"): %s", 734 path, strerror(errno)); 735 } 736 return filedes; 737} 738 739static int solaris_write_xattr(int attrfd, const char *value, size_t size) 740{ 741 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) { 742 return 0; 743 } else { 744 LOG(log_error, logtype_default, "solaris_write_xattr: %s", 745 strerror(errno)); 746 return -1; 747 } 748} 749 750#endif /*HAVE_ATTROPEN*/ 751 752