root/source3/lib/system.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_memalign
  2. sys_usleep
  3. sys_read
  4. sys_write
  5. sys_writev
  6. sys_pread
  7. sys_pwrite
  8. sys_send
  9. sys_sendto
  10. sys_recv
  11. sys_recvfrom
  12. sys_fcntl_ptr
  13. sys_fcntl_long
  14. sys_stat
  15. sys_fstat
  16. sys_lstat
  17. sys_ftruncate
  18. sys_lseek
  19. sys_fseek
  20. sys_ftell
  21. sys_creat
  22. sys_open
  23. sys_fopen
  24. kernel_flock
  25. sys_opendir
  26. sys_readdir
  27. sys_seekdir
  28. sys_telldir
  29. sys_rewinddir
  30. sys_closedir
  31. sys_mknod
  32. sys_waitpid
  33. sys_getwd
  34. set_process_capability
  35. set_effective_capability
  36. drop_effective_capability
  37. sys_random
  38. sys_srandom
  39. groups_max
  40. sys_broken_getgroups
  41. sys_broken_setgroups
  42. sys_bsd_setgroups
  43. sys_getgroups
  44. sys_setgroups
  45. sys_setpwent
  46. sys_getpwent
  47. sys_endpwent
  48. sys_getpwnam
  49. sys_getpwuid
  50. sys_getgrnam
  51. sys_getgrgid
  52. extract_args
  53. sys_popen
  54. sys_pclose
  55. sys_adminlog
  56. sys_getxattr
  57. sys_lgetxattr
  58. sys_fgetxattr
  59. bsd_attr_list
  60. irix_attr_list
  61. sys_listxattr
  62. sys_llistxattr
  63. sys_flistxattr
  64. sys_removexattr
  65. sys_lremovexattr
  66. sys_fremovexattr
  67. sys_setxattr
  68. sys_lsetxattr
  69. sys_fsetxattr
  70. solaris_read_xattr
  71. solaris_list_xattr
  72. solaris_unlinkat
  73. solaris_attropen
  74. solaris_openat
  75. solaris_write_xattr
  76. unix_dev_major
  77. unix_dev_minor
  78. sys_aio_read
  79. sys_aio_write
  80. sys_aio_return
  81. sys_aio_cancel
  82. sys_aio_error
  83. sys_aio_fsync
  84. sys_aio_suspend
  85. sys_aio_read
  86. sys_aio_write
  87. sys_aio_return
  88. sys_aio_cancel
  89. sys_aio_error
  90. sys_aio_fsync
  91. sys_aio_suspend
  92. sys_getpeereid
  93. sys_getnameinfo
  94. sys_connect

   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 3 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, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 
  25 #ifdef HAVE_SYS_PRCTL_H
  26 #include <sys/prctl.h>
  27 #endif
  28 
  29 /*
  30    The idea is that this file will eventually have wrappers around all
  31    important system calls in samba. The aims are:
  32 
  33    - to enable easier porting by putting OS dependent stuff in here
  34 
  35    - to allow for hooks into other "pseudo-filesystems"
  36 
  37    - to allow easier integration of things like the japanese extensions
  38 
  39    - to support the philosophy of Samba to expose the features of
  40      the OS within the SMB model. In general whatever file/printer/variable
  41      expansions/etc make sense to the OS should be acceptable to Samba.
  42 */
  43 
  44 
  45 
  46 /*******************************************************************
  47  A wrapper for memalign
  48 ********************************************************************/
  49 
  50 void *sys_memalign( size_t align, size_t size )
     /* [<][>][^][v][top][bottom][index][help] */
  51 {
  52 #if defined(HAVE_POSIX_MEMALIGN)
  53         void *p = NULL;
  54         int ret = posix_memalign( &p, align, size );
  55         if ( ret == 0 )
  56                 return p;
  57                 
  58         return NULL;
  59 #elif defined(HAVE_MEMALIGN)
  60         return memalign( align, size );
  61 #else
  62         /* On *BSD systems memaligns doesn't exist, but memory will
  63          * be aligned on allocations of > pagesize. */
  64 #if defined(SYSCONF_SC_PAGESIZE)
  65         size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
  66 #elif defined(HAVE_GETPAGESIZE)
  67         size_t pagesize = (size_t)getpagesize();
  68 #else
  69         size_t pagesize = (size_t)-1;
  70 #endif
  71         if (pagesize == (size_t)-1) {
  72                 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
  73                 return NULL;
  74         }
  75         if (size < pagesize) {
  76                 size = pagesize;
  77         }
  78         return SMB_MALLOC(size);
  79 #endif
  80 }
  81 
  82 /*******************************************************************
  83  A wrapper for usleep in case we don't have one.
  84 ********************************************************************/
  85 
  86 int sys_usleep(long usecs)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88 #ifndef HAVE_USLEEP
  89         struct timeval tval;
  90 #endif
  91 
  92         /*
  93          * We need this braindamage as the glibc usleep
  94          * is not SPEC1170 complient... grumble... JRA.
  95          */
  96 
  97         if(usecs < 0 || usecs > 999999) {
  98                 errno = EINVAL;
  99                 return -1;
 100         }
 101 
 102 #if HAVE_USLEEP
 103         usleep(usecs);
 104         return 0;
 105 #else /* HAVE_USLEEP */
 106         /*
 107          * Fake it with select...
 108          */
 109         tval.tv_sec = 0;
 110         tval.tv_usec = usecs/1000;
 111         select(0,NULL,NULL,NULL,&tval);
 112         return 0;
 113 #endif /* HAVE_USLEEP */
 114 }
 115 
 116 /*******************************************************************
 117 A read wrapper that will deal with EINTR.
 118 ********************************************************************/
 119 
 120 ssize_t sys_read(int fd, void *buf, size_t count)
     /* [<][>][^][v][top][bottom][index][help] */
 121 {
 122         ssize_t ret;
 123 
 124         do {
 125                 ret = read(fd, buf, count);
 126         } while (ret == -1 && errno == EINTR);
 127         return ret;
 128 }
 129 
 130 /*******************************************************************
 131 A write wrapper that will deal with EINTR.
 132 ********************************************************************/
 133 
 134 ssize_t sys_write(int fd, const void *buf, size_t count)
     /* [<][>][^][v][top][bottom][index][help] */
 135 {
 136         ssize_t ret;
 137 
 138         do {
 139                 ret = write(fd, buf, count);
 140         } while (ret == -1 && errno == EINTR);
 141         return ret;
 142 }
 143 
 144 /*******************************************************************
 145 A writev wrapper that will deal with EINTR.
 146 ********************************************************************/
 147 
 148 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150         ssize_t ret;
 151 
 152 #if 0
 153         /* Try to confuse write_data_iov a bit */
 154         if ((random() % 5) == 0) {
 155                 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
 156         }
 157         if (iov[0].iov_len > 1) {
 158                 return sys_write(fd, iov[0].iov_base,
 159                                  (random() % (iov[0].iov_len-1)) + 1);
 160         }
 161 #endif
 162 
 163         do {
 164                 ret = writev(fd, iov, iovcnt);
 165         } while (ret == -1 && errno == EINTR);
 166         return ret;
 167 }
 168 
 169 /*******************************************************************
 170 A pread wrapper that will deal with EINTR and 64-bit file offsets.
 171 ********************************************************************/
 172 
 173 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
 174 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
     /* [<][>][^][v][top][bottom][index][help] */
 175 {
 176         ssize_t ret;
 177 
 178         do {
 179 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
 180                 ret = pread64(fd, buf, count, off);
 181 #else
 182                 ret = pread(fd, buf, count, off);
 183 #endif
 184         } while (ret == -1 && errno == EINTR);
 185         return ret;
 186 }
 187 #endif
 188 
 189 /*******************************************************************
 190 A write wrapper that will deal with EINTR and 64-bit file offsets.
 191 ********************************************************************/
 192 
 193 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
 194 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
     /* [<][>][^][v][top][bottom][index][help] */
 195 {
 196         ssize_t ret;
 197 
 198         do {
 199 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
 200                 ret = pwrite64(fd, buf, count, off);
 201 #else
 202                 ret = pwrite(fd, buf, count, off);
 203 #endif
 204         } while (ret == -1 && errno == EINTR);
 205         return ret;
 206 }
 207 #endif
 208 
 209 /*******************************************************************
 210 A send wrapper that will deal with EINTR.
 211 ********************************************************************/
 212 
 213 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 214 {
 215         ssize_t ret;
 216 
 217         do {
 218                 ret = send(s, msg, len, flags);
 219         } while (ret == -1 && errno == EINTR);
 220         return ret;
 221 }
 222 
 223 /*******************************************************************
 224 A sendto wrapper that will deal with EINTR.
 225 ********************************************************************/
 226 
 227 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
     /* [<][>][^][v][top][bottom][index][help] */
 228 {
 229         ssize_t ret;
 230 
 231         do {
 232                 ret = sendto(s, msg, len, flags, to, tolen);
 233         } while (ret == -1 && errno == EINTR);
 234         return ret;
 235 }
 236 
 237 /*******************************************************************
 238 A recv wrapper that will deal with EINTR.
 239 ********************************************************************/
 240 
 241 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 242 {
 243         ssize_t ret;
 244 
 245         do {
 246                 ret = recv(fd, buf, count, flags);
 247         } while (ret == -1 && errno == EINTR);
 248         return ret;
 249 }
 250 
 251 /*******************************************************************
 252 A recvfrom wrapper that will deal with EINTR.
 253 ********************************************************************/
 254 
 255 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
     /* [<][>][^][v][top][bottom][index][help] */
 256 {
 257         ssize_t ret;
 258 
 259         do {
 260                 ret = recvfrom(s, buf, len, flags, from, fromlen);
 261         } while (ret == -1 && errno == EINTR);
 262         return ret;
 263 }
 264 
 265 /*******************************************************************
 266 A fcntl wrapper that will deal with EINTR.
 267 ********************************************************************/
 268 
 269 int sys_fcntl_ptr(int fd, int cmd, void *arg)
     /* [<][>][^][v][top][bottom][index][help] */
 270 {
 271         int ret;
 272 
 273         do {
 274                 ret = fcntl(fd, cmd, arg);
 275         } while (ret == -1 && errno == EINTR);
 276         return ret;
 277 }
 278 
 279 /*******************************************************************
 280 A fcntl wrapper that will deal with EINTR.
 281 ********************************************************************/
 282 
 283 int sys_fcntl_long(int fd, int cmd, long arg)
     /* [<][>][^][v][top][bottom][index][help] */
 284 {
 285         int ret;
 286 
 287         do {
 288                 ret = fcntl(fd, cmd, arg);
 289         } while (ret == -1 && errno == EINTR);
 290         return ret;
 291 }
 292 
 293 /*******************************************************************
 294 A stat() wrapper that will deal with 64 bit filesizes.
 295 ********************************************************************/
 296 
 297 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 298 {
 299         int ret;
 300 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
 301         ret = stat64(fname, sbuf);
 302 #else
 303         ret = stat(fname, sbuf);
 304 #endif
 305         /* we always want directories to appear zero size */
 306         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
 307         return ret;
 308 }
 309 
 310 /*******************************************************************
 311  An fstat() wrapper that will deal with 64 bit filesizes.
 312 ********************************************************************/
 313 
 314 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 315 {
 316         int ret;
 317 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
 318         ret = fstat64(fd, sbuf);
 319 #else
 320         ret = fstat(fd, sbuf);
 321 #endif
 322         /* we always want directories to appear zero size */
 323         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
 324         return ret;
 325 }
 326 
 327 /*******************************************************************
 328  An lstat() wrapper that will deal with 64 bit filesizes.
 329 ********************************************************************/
 330 
 331 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 332 {
 333         int ret;
 334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
 335         ret = lstat64(fname, sbuf);
 336 #else
 337         ret = lstat(fname, sbuf);
 338 #endif
 339         /* we always want directories to appear zero size */
 340         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
 341         return ret;
 342 }
 343 
 344 /*******************************************************************
 345  An ftruncate() wrapper that will deal with 64 bit filesizes.
 346 ********************************************************************/
 347 
 348 int sys_ftruncate(int fd, SMB_OFF_T offset)
     /* [<][>][^][v][top][bottom][index][help] */
 349 {
 350 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
 351         return ftruncate64(fd, offset);
 352 #else
 353         return ftruncate(fd, offset);
 354 #endif
 355 }
 356 
 357 /*******************************************************************
 358  An lseek() wrapper that will deal with 64 bit filesizes.
 359 ********************************************************************/
 360 
 361 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
     /* [<][>][^][v][top][bottom][index][help] */
 362 {
 363 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
 364         return lseek64(fd, offset, whence);
 365 #else
 366         return lseek(fd, offset, whence);
 367 #endif
 368 }
 369 
 370 /*******************************************************************
 371  An fseek() wrapper that will deal with 64 bit filesizes.
 372 ********************************************************************/
 373 
 374 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
     /* [<][>][^][v][top][bottom][index][help] */
 375 {
 376 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
 377         return fseek64(fp, offset, whence);
 378 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
 379         return fseeko64(fp, offset, whence);
 380 #else
 381         return fseek(fp, offset, whence);
 382 #endif
 383 }
 384 
 385 /*******************************************************************
 386  An ftell() wrapper that will deal with 64 bit filesizes.
 387 ********************************************************************/
 388 
 389 SMB_OFF_T sys_ftell(FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 390 {
 391 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
 392         return (SMB_OFF_T)ftell64(fp);
 393 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
 394         return (SMB_OFF_T)ftello64(fp);
 395 #else
 396         return (SMB_OFF_T)ftell(fp);
 397 #endif
 398 }
 399 
 400 /*******************************************************************
 401  A creat() wrapper that will deal with 64 bit filesizes.
 402 ********************************************************************/
 403 
 404 int sys_creat(const char *path, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
 405 {
 406 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
 407         return creat64(path, mode);
 408 #else
 409         /*
 410          * If creat64 isn't defined then ensure we call a potential open64.
 411          * JRA.
 412          */
 413         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
 414 #endif
 415 }
 416 
 417 /*******************************************************************
 418  An open() wrapper that will deal with 64 bit filesizes.
 419 ********************************************************************/
 420 
 421 int sys_open(const char *path, int oflag, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
 422 {
 423 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
 424         return open64(path, oflag, mode);
 425 #else
 426         return open(path, oflag, mode);
 427 #endif
 428 }
 429 
 430 /*******************************************************************
 431  An fopen() wrapper that will deal with 64 bit filesizes.
 432 ********************************************************************/
 433 
 434 FILE *sys_fopen(const char *path, const char *type)
     /* [<][>][^][v][top][bottom][index][help] */
 435 {
 436 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
 437         return fopen64(path, type);
 438 #else
 439         return fopen(path, type);
 440 #endif
 441 }
 442 
 443 
 444 /*******************************************************************
 445  A flock() wrapper that will perform the kernel flock.
 446 ********************************************************************/
 447 
 448 void kernel_flock(int fd, uint32 share_mode)
     /* [<][>][^][v][top][bottom][index][help] */
 449 {
 450 #if HAVE_KERNEL_SHARE_MODES
 451         int kernel_mode = 0;
 452         if (share_mode == FILE_SHARE_WRITE) {
 453                 kernel_mode = LOCK_MAND|LOCK_WRITE;
 454         } else if (share_mode == FILE_SHARE_READ) {
 455                 kernel_mode = LOCK_MAND|LOCK_READ;
 456         } else if (share_mode == FILE_SHARE_NONE) {
 457                 kernel_mode = LOCK_MAND;
 458         }
 459         if (kernel_mode) {
 460                 flock(fd, kernel_mode);
 461         }
 462 #endif
 463         ;
 464 }
 465 
 466 
 467 
 468 /*******************************************************************
 469  An opendir wrapper that will deal with 64 bit filesizes.
 470 ********************************************************************/
 471 
 472 SMB_STRUCT_DIR *sys_opendir(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 473 {
 474 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
 475         return opendir64(name);
 476 #else
 477         return opendir(name);
 478 #endif
 479 }
 480 
 481 /*******************************************************************
 482  A readdir wrapper that will deal with 64 bit filesizes.
 483 ********************************************************************/
 484 
 485 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 486 {
 487 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
 488         return readdir64(dirp);
 489 #else
 490         return readdir(dirp);
 491 #endif
 492 }
 493 
 494 /*******************************************************************
 495  A seekdir wrapper that will deal with 64 bit filesizes.
 496 ********************************************************************/
 497 
 498 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
     /* [<][>][^][v][top][bottom][index][help] */
 499 {
 500 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
 501         seekdir64(dirp, offset);
 502 #else
 503         seekdir(dirp, offset);
 504 #endif
 505 }
 506 
 507 /*******************************************************************
 508  A telldir wrapper that will deal with 64 bit filesizes.
 509 ********************************************************************/
 510 
 511 long sys_telldir(SMB_STRUCT_DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 512 {
 513 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
 514         return (long)telldir64(dirp);
 515 #else
 516         return (long)telldir(dirp);
 517 #endif
 518 }
 519 
 520 /*******************************************************************
 521  A rewinddir wrapper that will deal with 64 bit filesizes.
 522 ********************************************************************/
 523 
 524 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 525 {
 526 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
 527         rewinddir64(dirp);
 528 #else
 529         rewinddir(dirp);
 530 #endif
 531 }
 532 
 533 /*******************************************************************
 534  A close wrapper that will deal with 64 bit filesizes.
 535 ********************************************************************/
 536 
 537 int sys_closedir(SMB_STRUCT_DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 538 {
 539 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
 540         return closedir64(dirp);
 541 #else
 542         return closedir(dirp);
 543 #endif
 544 }
 545 
 546 /*******************************************************************
 547  An mknod() wrapper that will deal with 64 bit filesizes.
 548 ********************************************************************/
 549 
 550 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
     /* [<][>][^][v][top][bottom][index][help] */
 551 {
 552 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
 553 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
 554         return mknod64(path, mode, dev);
 555 #else
 556         return mknod(path, mode, dev);
 557 #endif
 558 #else
 559         /* No mknod system call. */
 560         errno = ENOSYS;
 561         return -1;
 562 #endif
 563 }
 564 
 565 /*******************************************************************
 566 The wait() calls vary between systems
 567 ********************************************************************/
 568 
 569 int sys_waitpid(pid_t pid,int *status,int options)
     /* [<][>][^][v][top][bottom][index][help] */
 570 {
 571 #ifdef HAVE_WAITPID
 572         return waitpid(pid,status,options);
 573 #else /* HAVE_WAITPID */
 574         return wait4(pid, status, options, NULL);
 575 #endif /* HAVE_WAITPID */
 576 }
 577 
 578 /*******************************************************************
 579  System wrapper for getwd
 580 ********************************************************************/
 581 
 582 char *sys_getwd(char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 583 {
 584         char *wd;
 585 #ifdef HAVE_GETCWD
 586         wd = (char *)getcwd(s, PATH_MAX);
 587 #else
 588         wd = (char *)getwd(s);
 589 #endif
 590         return wd;
 591 }
 592 
 593 #if defined(HAVE_POSIX_CAPABILITIES)
 594 
 595 /**************************************************************************
 596  Try and abstract process capabilities (for systems that have them).
 597 ****************************************************************************/
 598 
 599 /* Set the POSIX capabilities needed for the given purpose into the effective
 600  * capability set of the current process. Make sure they are always removed
 601  * from the inheritable set, because there is no circumstance in which our
 602  * children should inherit our elevated privileges.
 603  */
 604 static bool set_process_capability(enum smbd_capability capability,
     /* [<][>][^][v][top][bottom][index][help] */
 605                                    bool enable)
 606 {
 607         cap_value_t cap_vals[2] = {0};
 608         int num_cap_vals = 0;
 609 
 610         cap_t cap;
 611 
 612 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
 613         /* On Linux, make sure that any capabilities we grab are sticky
 614          * across UID changes. We expect that this would allow us to keep both
 615          * the effective and permitted capability sets, but as of circa 2.6.16,
 616          * only the permitted set is kept. It is a bug (which we work around)
 617          * that the effective set is lost, but we still require the effective
 618          * set to be kept.
 619          */
 620         if (!prctl(PR_GET_KEEPCAPS)) {
 621                 prctl(PR_SET_KEEPCAPS, 1);
 622         }
 623 #endif
 624 
 625         cap = cap_get_proc();
 626         if (cap == NULL) {
 627                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
 628                         strerror(errno)));
 629                 return False;
 630         }
 631 
 632         switch (capability) {
 633                 case KERNEL_OPLOCK_CAPABILITY:
 634 #ifdef CAP_NETWORK_MGT
 635                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
 636                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
 637 #endif
 638                         break;
 639                 case DMAPI_ACCESS_CAPABILITY:
 640 #ifdef CAP_DEVICE_MGT
 641                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
 642                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
 643 #elif CAP_MKNOD
 644                         /* Linux has CAP_MKNOD for DMAPI access. */
 645                         cap_vals[num_cap_vals++] = CAP_MKNOD;
 646 #endif
 647                         break;
 648                 case LEASE_CAPABILITY:
 649 #ifdef CAP_LEASE
 650                         cap_vals[num_cap_vals++] = CAP_LEASE;
 651 #endif
 652                         break;
 653         }
 654 
 655         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
 656 
 657         if (num_cap_vals == 0) {
 658                 cap_free(cap);
 659                 return True;
 660         }
 661 
 662         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
 663                 enable ? CAP_SET : CAP_CLEAR);
 664 
 665         /* We never want to pass capabilities down to our children, so make
 666          * sure they are not inherited.
 667          */
 668         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
 669 
 670         if (cap_set_proc(cap) == -1) {
 671                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
 672                         strerror(errno)));
 673                 cap_free(cap);
 674                 return False;
 675         }
 676 
 677         cap_free(cap);
 678         return True;
 679 }
 680 
 681 #endif /* HAVE_POSIX_CAPABILITIES */
 682 
 683 /****************************************************************************
 684  Gain the oplock capability from the kernel if possible.
 685 ****************************************************************************/
 686 
 687 void set_effective_capability(enum smbd_capability capability)
     /* [<][>][^][v][top][bottom][index][help] */
 688 {
 689 #if defined(HAVE_POSIX_CAPABILITIES)
 690         set_process_capability(capability, True);
 691 #endif /* HAVE_POSIX_CAPABILITIES */
 692 }
 693 
 694 void drop_effective_capability(enum smbd_capability capability)
     /* [<][>][^][v][top][bottom][index][help] */
 695 {
 696 #if defined(HAVE_POSIX_CAPABILITIES)
 697         set_process_capability(capability, False);
 698 #endif /* HAVE_POSIX_CAPABILITIES */
 699 }
 700 
 701 /**************************************************************************
 702  Wrapper for random().
 703 ****************************************************************************/
 704 
 705 long sys_random(void)
     /* [<][>][^][v][top][bottom][index][help] */
 706 {
 707 #if defined(HAVE_RANDOM)
 708         return (long)random();
 709 #elif defined(HAVE_RAND)
 710         return (long)rand();
 711 #else
 712         DEBUG(0,("Error - no random function available !\n"));
 713         exit(1);
 714 #endif
 715 }
 716 
 717 /**************************************************************************
 718  Wrapper for srandom().
 719 ****************************************************************************/
 720 
 721 void sys_srandom(unsigned int seed)
     /* [<][>][^][v][top][bottom][index][help] */
 722 {
 723 #if defined(HAVE_SRANDOM)
 724         srandom(seed);
 725 #elif defined(HAVE_SRAND)
 726         srand(seed);
 727 #else
 728         DEBUG(0,("Error - no srandom function available !\n"));
 729         exit(1);
 730 #endif
 731 }
 732 
 733 /**************************************************************************
 734  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
 735 ****************************************************************************/
 736 
 737 int groups_max(void)
     /* [<][>][^][v][top][bottom][index][help] */
 738 {
 739 #if defined(SYSCONF_SC_NGROUPS_MAX)
 740         int ret = sysconf(_SC_NGROUPS_MAX);
 741         return (ret == -1) ? NGROUPS_MAX : ret;
 742 #else
 743         return NGROUPS_MAX;
 744 #endif
 745 }
 746 
 747 /**************************************************************************
 748  Wrap setgroups and getgroups for systems that declare getgroups() as
 749  returning an array of gid_t, but actuall return an array of int.
 750 ****************************************************************************/
 751 
 752 #if defined(HAVE_BROKEN_GETGROUPS)
 753 static int sys_broken_getgroups(int setlen, gid_t *gidset)
     /* [<][>][^][v][top][bottom][index][help] */
 754 {
 755         GID_T gid;
 756         GID_T *group_list;
 757         int i, ngroups;
 758 
 759         if(setlen == 0) {
 760                 return getgroups(setlen, &gid);
 761         }
 762 
 763         /*
 764          * Broken case. We need to allocate a
 765          * GID_T array of size setlen.
 766          */
 767 
 768         if(setlen < 0) {
 769                 errno = EINVAL; 
 770                 return -1;
 771         } 
 772 
 773         if (setlen == 0)
 774                 setlen = groups_max();
 775 
 776         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
 777                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
 778                 return -1;
 779         }
 780 
 781         if((ngroups = getgroups(setlen, group_list)) < 0) {
 782                 int saved_errno = errno;
 783                 SAFE_FREE(group_list);
 784                 errno = saved_errno;
 785                 return -1;
 786         }
 787 
 788         for(i = 0; i < ngroups; i++)
 789                 gidset[i] = (gid_t)group_list[i];
 790 
 791         SAFE_FREE(group_list);
 792         return ngroups;
 793 }
 794 
 795 static int sys_broken_setgroups(int setlen, gid_t *gidset)
     /* [<][>][^][v][top][bottom][index][help] */
 796 {
 797         GID_T *group_list;
 798         int i ; 
 799 
 800         if (setlen == 0)
 801                 return 0 ;
 802 
 803         if (setlen < 0 || setlen > groups_max()) {
 804                 errno = EINVAL; 
 805                 return -1;   
 806         }
 807 
 808         /*
 809          * Broken case. We need to allocate a
 810          * GID_T array of size setlen.
 811          */
 812 
 813         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
 814                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
 815                 return -1;    
 816         }
 817  
 818         for(i = 0; i < setlen; i++) 
 819                 group_list[i] = (GID_T) gidset[i]; 
 820 
 821         if(setgroups(setlen, group_list) != 0) {
 822                 int saved_errno = errno;
 823                 SAFE_FREE(group_list);
 824                 errno = saved_errno;
 825                 return -1;
 826         }
 827  
 828         SAFE_FREE(group_list);
 829         return 0 ;
 830 }
 831 
 832 #endif /* HAVE_BROKEN_GETGROUPS */
 833 
 834 /* This is a list of systems that require the first GID passed to setgroups(2)
 835  * to be the effective GID. If your system is one of these, add it here.
 836  */
 837 #if defined (FREEBSD) || defined (DARWINOS)
 838 #define USE_BSD_SETGROUPS
 839 #endif
 840 
 841 #if defined(USE_BSD_SETGROUPS)
 842 /* Depending on the particular BSD implementation, the first GID that is
 843  * passed to setgroups(2) will either be ignored or will set the credential's
 844  * effective GID. In either case, the right thing to do is to guarantee that
 845  * gidset[0] is the effective GID.
 846  */
 847 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
     /* [<][>][^][v][top][bottom][index][help] */
 848 {
 849         gid_t *new_gidset = NULL;
 850         int max;
 851         int ret;
 852 
 853         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
 854         max = groups_max();
 855 
 856         /* No group list, just make sure we are setting the efective GID. */
 857         if (setlen == 0) {
 858                 return setgroups(1, &primary_gid);
 859         }
 860 
 861         /* If the primary gid is not the first array element, grow the array
 862          * and insert it at the front.
 863          */
 864         if (gidset[0] != primary_gid) {
 865                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
 866                 if (new_gidset == NULL) {
 867                         return -1;
 868                 }
 869 
 870                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
 871                 new_gidset[0] = primary_gid;
 872                 setlen++;
 873         }
 874 
 875         if (setlen > max) {
 876                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
 877                         setlen, max));
 878                 setlen = max;
 879         }
 880 
 881 #if defined(HAVE_BROKEN_GETGROUPS)
 882         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
 883 #else
 884         ret = setgroups(setlen, new_gidset ? new_gidset : gidset);
 885 #endif
 886 
 887         if (new_gidset) {
 888                 int errsav = errno;
 889                 SAFE_FREE(new_gidset);
 890                 errno = errsav;
 891         }
 892 
 893         return ret;
 894 }
 895 
 896 #endif /* USE_BSD_SETGROUPS */
 897 
 898 /**************************************************************************
 899  Wrapper for getgroups. Deals with broken (int) case.
 900 ****************************************************************************/
 901 
 902 int sys_getgroups(int setlen, gid_t *gidset)
     /* [<][>][^][v][top][bottom][index][help] */
 903 {
 904 #if defined(HAVE_BROKEN_GETGROUPS)
 905         return sys_broken_getgroups(setlen, gidset);
 906 #else
 907         return getgroups(setlen, gidset);
 908 #endif
 909 }
 910 
 911 /**************************************************************************
 912  Wrapper for setgroups. Deals with broken (int) case and BSD case.
 913 ****************************************************************************/
 914 
 915 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
     /* [<][>][^][v][top][bottom][index][help] */
 916 {
 917 #if !defined(HAVE_SETGROUPS)
 918         errno = ENOSYS;
 919         return -1;
 920 #endif /* HAVE_SETGROUPS */
 921 
 922 #if defined(USE_BSD_SETGROUPS)
 923         return sys_bsd_setgroups(primary_gid, setlen, gidset);
 924 #elif defined(HAVE_BROKEN_GETGROUPS)
 925         return sys_broken_setgroups(setlen, gidset);
 926 #else
 927         return setgroups(setlen, gidset);
 928 #endif
 929 }
 930 
 931 /**************************************************************************
 932  Wrappers for setpwent(), getpwent() and endpwent()
 933 ****************************************************************************/
 934 
 935 void sys_setpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 936 {
 937         setpwent();
 938 }
 939 
 940 struct passwd *sys_getpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 941 {
 942         return getpwent();
 943 }
 944 
 945 void sys_endpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 946 {
 947         endpwent();
 948 }
 949 
 950 /**************************************************************************
 951  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
 952 ****************************************************************************/
 953 
 954 
 955 struct passwd *sys_getpwnam(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 956 {
 957         return getpwnam(name);
 958 }
 959 
 960 struct passwd *sys_getpwuid(uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
 961 {
 962         return getpwuid(uid);
 963 }
 964 
 965 struct group *sys_getgrnam(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 966 {
 967         return getgrnam(name);
 968 }
 969 
 970 struct group *sys_getgrgid(gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
 971 {
 972         return getgrgid(gid);
 973 }
 974 
 975 /**************************************************************************
 976  Extract a command into an arg list.
 977 ****************************************************************************/
 978 
 979 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
     /* [<][>][^][v][top][bottom][index][help] */
 980 {
 981         char *trunc_cmd;
 982         char *saveptr;
 983         char *ptr;
 984         int argcl;
 985         char **argl = NULL;
 986         int i;
 987 
 988         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
 989                 DEBUG(0, ("talloc failed\n"));
 990                 goto nomem;
 991         }
 992 
 993         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
 994                 TALLOC_FREE(trunc_cmd);
 995                 errno = EINVAL;
 996                 return NULL;
 997         }
 998 
 999         /*
1000          * Count the args.
1001          */
1002 
1003         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1004                 argcl++;
1005 
1006         TALLOC_FREE(trunc_cmd);
1007 
1008         if (!(argl = TALLOC_ARRAY(mem_ctx, char *, argcl + 1))) {
1009                 goto nomem;
1010         }
1011 
1012         /*
1013          * Now do the extraction.
1014          */
1015 
1016         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1017                 goto nomem;
1018         }
1019 
1020         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1021         i = 0;
1022 
1023         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1024                 goto nomem;
1025         }
1026 
1027         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1028 
1029                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1030                         goto nomem;
1031                 }
1032         }
1033 
1034         argl[i++] = NULL;
1035         return argl;
1036 
1037  nomem:
1038         DEBUG(0, ("talloc failed\n"));
1039         TALLOC_FREE(trunc_cmd);
1040         TALLOC_FREE(argl);
1041         errno = ENOMEM;
1042         return NULL;
1043 }
1044 
1045 /**************************************************************************
1046  Wrapper for popen. Safer as it doesn't search a path.
1047  Modified from the glibc sources.
1048  modified by tridge to return a file descriptor. We must kick our FILE* habit
1049 ****************************************************************************/
1050 
1051 typedef struct _popen_list
1052 {
1053         int fd;
1054         pid_t child_pid;
1055         struct _popen_list *next;
1056 } popen_list;
1057 
1058 static popen_list *popen_chain;
1059 
1060 int sys_popen(const char *command)
     /* [<][>][^][v][top][bottom][index][help] */
1061 {
1062         int parent_end, child_end;
1063         int pipe_fds[2];
1064         popen_list *entry = NULL;
1065         char **argl = NULL;
1066 
1067         if (pipe(pipe_fds) < 0)
1068                 return -1;
1069 
1070         parent_end = pipe_fds[0];
1071         child_end = pipe_fds[1];
1072 
1073         if (!*command) {
1074                 errno = EINVAL;
1075                 goto err_exit;
1076         }
1077 
1078         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1079                 goto err_exit;
1080 
1081         ZERO_STRUCTP(entry);
1082 
1083         /*
1084          * Extract the command and args into a NULL terminated array.
1085          */
1086 
1087         if(!(argl = extract_args(NULL, command)))
1088                 goto err_exit;
1089 
1090         entry->child_pid = sys_fork();
1091 
1092         if (entry->child_pid == -1) {
1093                 goto err_exit;
1094         }
1095 
1096         if (entry->child_pid == 0) {
1097 
1098                 /*
1099                  * Child !
1100                  */
1101 
1102                 int child_std_end = STDOUT_FILENO;
1103                 popen_list *p;
1104 
1105                 close(parent_end);
1106                 if (child_end != child_std_end) {
1107                         dup2 (child_end, child_std_end);
1108                         close (child_end);
1109                 }
1110 
1111                 /*
1112                  * POSIX.2:  "popen() shall ensure that any streams from previous
1113                  * popen() calls that remain open in the parent process are closed
1114                  * in the new child process."
1115                  */
1116 
1117                 for (p = popen_chain; p; p = p->next)
1118                         close(p->fd);
1119 
1120                 execv(argl[0], argl);
1121                 _exit (127);
1122         }
1123 
1124         /*
1125          * Parent.
1126          */
1127 
1128         close (child_end);
1129         TALLOC_FREE(argl);
1130 
1131         /* Link into popen_chain. */
1132         entry->next = popen_chain;
1133         popen_chain = entry;
1134         entry->fd = parent_end;
1135 
1136         return entry->fd;
1137 
1138 err_exit:
1139 
1140         SAFE_FREE(entry);
1141         SAFE_FREE(argl);
1142         close(pipe_fds[0]);
1143         close(pipe_fds[1]);
1144         return -1;
1145 }
1146 
1147 /**************************************************************************
1148  Wrapper for pclose. Modified from the glibc sources.
1149 ****************************************************************************/
1150 
1151 int sys_pclose(int fd)
     /* [<][>][^][v][top][bottom][index][help] */
1152 {
1153         int wstatus;
1154         popen_list **ptr = &popen_chain;
1155         popen_list *entry = NULL;
1156         pid_t wait_pid;
1157         int status = -1;
1158 
1159         /* Unlink from popen_chain. */
1160         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1161                 if ((*ptr)->fd == fd) {
1162                         entry = *ptr;
1163                         *ptr = (*ptr)->next;
1164                         status = 0;
1165                         break;
1166                 }
1167         }
1168 
1169         if (status < 0 || close(entry->fd) < 0)
1170                 return -1;
1171 
1172         /*
1173          * As Samba is catching and eating child process
1174          * exits we don't really care about the child exit
1175          * code, a -1 with errno = ECHILD will do fine for us.
1176          */
1177 
1178         do {
1179                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1180         } while (wait_pid == -1 && errno == EINTR);
1181 
1182         SAFE_FREE(entry);
1183 
1184         if (wait_pid == -1)
1185                 return -1;
1186         return wstatus;
1187 }
1188 
1189 /**************************************************************************
1190  Wrapper for Admin Logs.
1191 ****************************************************************************/
1192 
1193  void sys_adminlog(int priority, const char *format_str, ...) 
     /* [<][>][^][v][top][bottom][index][help] */
1194 {
1195         va_list ap;
1196         int ret;
1197         char *msgbuf = NULL;
1198 
1199         va_start( ap, format_str );
1200         ret = vasprintf( &msgbuf, format_str, ap );
1201         va_end( ap );
1202 
1203         if (ret == -1)
1204                 return;
1205 
1206 #if defined(HAVE_SYSLOG)
1207         syslog( priority, "%s", msgbuf );
1208 #else
1209         DEBUG(0,("%s", msgbuf ));
1210 #endif
1211         SAFE_FREE(msgbuf);
1212 }
1213 
1214 /******** Solaris EA helper function prototypes ********/
1215 #ifdef HAVE_ATTROPEN
1216 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
1217 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
1218 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
1219 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
1220 static int solaris_unlinkat(int attrdirfd, const char *name);
1221 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
1222 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
1223 #endif
1224 
1225 /**************************************************************************
1226  Wrappers for extented attribute calls. Based on the Linux package with
1227  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
1228 ****************************************************************************/
1229 
1230 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1231 {
1232 #if defined(HAVE_GETXATTR)
1233 #ifndef XATTR_ADD_OPT
1234         return getxattr(path, name, value, size);
1235 #else
1236         int options = 0;
1237         return getxattr(path, name, value, size, 0, options);
1238 #endif
1239 #elif defined(HAVE_GETEA)
1240         return getea(path, name, value, size);
1241 #elif defined(HAVE_EXTATTR_GET_FILE)
1242         char *s;
1243         ssize_t retval;
1244         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1245                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1246         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1247         /*
1248          * The BSD implementation has a nasty habit of silently truncating
1249          * the returned value to the size of the buffer, so we have to check
1250          * that the buffer is large enough to fit the returned value.
1251          */
1252         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1253                 if(retval > size) {
1254                         errno = ERANGE;
1255                         return -1;
1256                 }
1257                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
1258                         return retval;
1259         }
1260 
1261         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
1262         return -1;
1263 #elif defined(HAVE_ATTR_GET)
1264         int retval, flags = 0;
1265         int valuelength = (int)size;
1266         char *attrname = strchr(name,'.') + 1;
1267         
1268         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1269 
1270         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1271 
1272         return retval ? retval : valuelength;
1273 #elif defined(HAVE_ATTROPEN)
1274         ssize_t ret = -1;
1275         int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
1276         if (attrfd >= 0) {
1277                 ret = solaris_read_xattr(attrfd, value, size);
1278                 close(attrfd);
1279         }
1280         return ret;
1281 #else
1282         errno = ENOSYS;
1283         return -1;
1284 #endif
1285 }
1286 
1287 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1288 {
1289 #if defined(HAVE_LGETXATTR)
1290         return lgetxattr(path, name, value, size);
1291 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
1292         int options = XATTR_NOFOLLOW;
1293         return getxattr(path, name, value, size, 0, options);
1294 #elif defined(HAVE_LGETEA)
1295         return lgetea(path, name, value, size);
1296 #elif defined(HAVE_EXTATTR_GET_LINK)
1297         char *s;
1298         ssize_t retval;
1299         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1300                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1301         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1302 
1303         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
1304                 if(retval > size) {
1305                         errno = ERANGE;
1306                         return -1;
1307                 }
1308                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
1309                         return retval;
1310         }
1311         
1312         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
1313         return -1;
1314 #elif defined(HAVE_ATTR_GET)
1315         int retval, flags = ATTR_DONTFOLLOW;
1316         int valuelength = (int)size;
1317         char *attrname = strchr(name,'.') + 1;
1318         
1319         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1320 
1321         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1322 
1323         return retval ? retval : valuelength;
1324 #elif defined(HAVE_ATTROPEN)
1325         ssize_t ret = -1;
1326         int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1327         if (attrfd >= 0) {
1328                 ret = solaris_read_xattr(attrfd, value, size);
1329                 close(attrfd);
1330         }
1331         return ret;
1332 #else
1333         errno = ENOSYS;
1334         return -1;
1335 #endif
1336 }
1337 
1338 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1339 {
1340 #if defined(HAVE_FGETXATTR)
1341 #ifndef XATTR_ADD_OPT
1342         return fgetxattr(filedes, name, value, size);
1343 #else
1344         int options = 0;
1345         return fgetxattr(filedes, name, value, size, 0, options);
1346 #endif
1347 #elif defined(HAVE_FGETEA)
1348         return fgetea(filedes, name, value, size);
1349 #elif defined(HAVE_EXTATTR_GET_FD)
1350         char *s;
1351         ssize_t retval;
1352         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1353                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1354         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1355 
1356         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
1357                 if(retval > size) {
1358                         errno = ERANGE;
1359                         return -1;
1360                 }
1361                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
1362                         return retval;
1363         }
1364         
1365         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
1366         return -1;
1367 #elif defined(HAVE_ATTR_GETF)
1368         int retval, flags = 0;
1369         int valuelength = (int)size;
1370         char *attrname = strchr(name,'.') + 1;
1371         
1372         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1373 
1374         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1375 
1376         return retval ? retval : valuelength;
1377 #elif defined(HAVE_ATTROPEN)
1378         ssize_t ret = -1;
1379         int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
1380         if (attrfd >= 0) {
1381                 ret = solaris_read_xattr(attrfd, value, size);
1382                 close(attrfd);
1383         }
1384         return ret;
1385 #else
1386         errno = ENOSYS;
1387         return -1;
1388 #endif
1389 }
1390 
1391 #if defined(HAVE_EXTATTR_LIST_FILE)
1392 
1393 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
1394 
1395 static struct {
1396         int space;
1397         const char *name;
1398         size_t len;
1399 } 
1400 extattr[] = {
1401         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
1402         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
1403 };
1404 
1405 typedef union {
1406         const char *path;
1407         int filedes;
1408 } extattr_arg;
1409 
1410 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1411 {
1412         ssize_t list_size, total_size = 0;
1413         int i, t, len;
1414         char *buf;
1415         /* Iterate through extattr(2) namespaces */
1416         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
1417                 switch(type) {
1418 #if defined(HAVE_EXTATTR_LIST_FILE)
1419                         case 0:
1420                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
1421                                 break;
1422 #endif
1423 #if defined(HAVE_EXTATTR_LIST_LINK)
1424                         case 1:
1425                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
1426                                 break;
1427 #endif
1428 #if defined(HAVE_EXTATTR_LIST_FD)
1429                         case 2:
1430                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
1431                                 break;
1432 #endif
1433                         default:
1434                                 errno = ENOSYS;
1435                                 return -1;
1436                 }
1437                 /* Some error happend. Errno should be set by the previous call */
1438                 if(list_size < 0)
1439                         return -1;
1440                 /* No attributes */
1441                 if(list_size == 0)
1442                         continue;
1443                 /* XXX: Call with an empty buffer may be used to calculate
1444                    necessary buffer size. Unfortunately, we can't say, how
1445                    many attributes were returned, so here is the potential
1446                    problem with the emulation.
1447                 */
1448                 if(list == NULL) {
1449                         /* Take the worse case of one char attribute names - 
1450                            two bytes per name plus one more for sanity.
1451                         */
1452                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
1453                         continue;
1454                 }
1455                 /* Count necessary offset to fit namespace prefixes */
1456                 len = 0;
1457                 for(i = 0; i < list_size; i += list[i] + 1)
1458                         len += extattr[t].len;
1459 
1460                 total_size += list_size + len;
1461                 /* Buffer is too small to fit the results */
1462                 if(total_size > size) {
1463                         errno = ERANGE;
1464                         return -1;
1465                 }
1466                 /* Shift results back, so we can prepend prefixes */
1467                 buf = memmove(list + len, list, list_size);
1468 
1469                 for(i = 0; i < list_size; i += len + 1) {
1470                         len = buf[i];
1471                         strncpy(list, extattr[t].name, extattr[t].len + 1);
1472                         list += extattr[t].len;
1473                         strncpy(list, buf + i + 1, len);
1474                         list[len] = '\0';
1475                         list += len + 1;
1476                 }
1477                 size -= total_size;
1478         }
1479         return total_size;
1480 }
1481 
1482 #endif
1483 
1484 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1485 static char attr_buffer[ATTR_MAX_VALUELEN];
1486 
1487 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
1488 {
1489         int retval = 0, index;
1490         attrlist_cursor_t *cursor = 0;
1491         int total_size = 0;
1492         attrlist_t * al = (attrlist_t *)attr_buffer;
1493         attrlist_ent_t *ae;
1494         size_t ent_size, left = size;
1495         char *bp = list;
1496 
1497         while (True) {
1498             if (filedes)
1499                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1500             else
1501                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1502             if (retval) break;
1503             for (index = 0; index < al->al_count; index++) {
1504                 ae = ATTR_ENTRY(attr_buffer, index);
1505                 ent_size = strlen(ae->a_name) + sizeof("user.");
1506                 if (left >= ent_size) {
1507                     strncpy(bp, "user.", sizeof("user."));
1508                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
1509                     bp += ent_size;
1510                     left -= ent_size;
1511                 } else if (size) {
1512                     errno = ERANGE;
1513                     retval = -1;
1514                     break;
1515                 }
1516                 total_size += ent_size;
1517             }
1518             if (al->al_more == 0) break;
1519         }
1520         if (retval == 0) {
1521             flags |= ATTR_ROOT;
1522             cursor = 0;
1523             while (True) {
1524                 if (filedes)
1525                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1526                 else
1527                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1528                 if (retval) break;
1529                 for (index = 0; index < al->al_count; index++) {
1530                     ae = ATTR_ENTRY(attr_buffer, index);
1531                     ent_size = strlen(ae->a_name) + sizeof("system.");
1532                     if (left >= ent_size) {
1533                         strncpy(bp, "system.", sizeof("system."));
1534                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
1535                         bp += ent_size;
1536                         left -= ent_size;
1537                     } else if (size) {
1538                         errno = ERANGE;
1539                         retval = -1;
1540                         break;
1541                     }
1542                     total_size += ent_size;
1543                 }
1544                 if (al->al_more == 0) break;
1545             }
1546         }
1547         return (ssize_t)(retval ? retval : total_size);
1548 }
1549 
1550 #endif
1551 
1552 ssize_t sys_listxattr (const char *path, char *list, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1553 {
1554 #if defined(HAVE_LISTXATTR)
1555 #ifndef XATTR_ADD_OPT
1556         return listxattr(path, list, size);
1557 #else
1558         int options = 0;
1559         return listxattr(path, list, size, options);
1560 #endif
1561 #elif defined(HAVE_LISTEA)
1562         return listea(path, list, size);
1563 #elif defined(HAVE_EXTATTR_LIST_FILE)
1564         extattr_arg arg;
1565         arg.path = path;
1566         return bsd_attr_list(0, arg, list, size);
1567 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1568         return irix_attr_list(path, 0, list, size, 0);
1569 #elif defined(HAVE_ATTROPEN)
1570         ssize_t ret = -1;
1571         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1572         if (attrdirfd >= 0) {
1573                 ret = solaris_list_xattr(attrdirfd, list, size);
1574                 close(attrdirfd);
1575         }
1576         return ret;
1577 #else
1578         errno = ENOSYS;
1579         return -1;
1580 #endif
1581 }
1582 
1583 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1584 {
1585 #if defined(HAVE_LLISTXATTR)
1586         return llistxattr(path, list, size);
1587 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
1588         int options = XATTR_NOFOLLOW;
1589         return listxattr(path, list, size, options);
1590 #elif defined(HAVE_LLISTEA)
1591         return llistea(path, list, size);
1592 #elif defined(HAVE_EXTATTR_LIST_LINK)
1593         extattr_arg arg;
1594         arg.path = path;
1595         return bsd_attr_list(1, arg, list, size);
1596 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1597         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1598 #elif defined(HAVE_ATTROPEN)
1599         ssize_t ret = -1;
1600         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1601         if (attrdirfd >= 0) {
1602                 ret = solaris_list_xattr(attrdirfd, list, size);
1603                 close(attrdirfd);
1604         }
1605         return ret;
1606 #else
1607         errno = ENOSYS;
1608         return -1;
1609 #endif
1610 }
1611 
1612 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1613 {
1614 #if defined(HAVE_FLISTXATTR)
1615 #ifndef XATTR_ADD_OPT
1616         return flistxattr(filedes, list, size);
1617 #else
1618         int options = 0;
1619         return flistxattr(filedes, list, size, options);
1620 #endif
1621 #elif defined(HAVE_FLISTEA)
1622         return flistea(filedes, list, size);
1623 #elif defined(HAVE_EXTATTR_LIST_FD)
1624         extattr_arg arg;
1625         arg.filedes = filedes;
1626         return bsd_attr_list(2, arg, list, size);
1627 #elif defined(HAVE_ATTR_LISTF)
1628         return irix_attr_list(NULL, filedes, list, size, 0);
1629 #elif defined(HAVE_ATTROPEN)
1630         ssize_t ret = -1;
1631         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1632         if (attrdirfd >= 0) {
1633                 ret = solaris_list_xattr(attrdirfd, list, size);
1634                 close(attrdirfd);
1635         }
1636         return ret;
1637 #else
1638         errno = ENOSYS;
1639         return -1;
1640 #endif
1641 }
1642 
1643 int sys_removexattr (const char *path, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1644 {
1645 #if defined(HAVE_REMOVEXATTR)
1646 #ifndef XATTR_ADD_OPT
1647         return removexattr(path, name);
1648 #else
1649         int options = 0;
1650         return removexattr(path, name, options);
1651 #endif
1652 #elif defined(HAVE_REMOVEEA)
1653         return removeea(path, name);
1654 #elif defined(HAVE_EXTATTR_DELETE_FILE)
1655         char *s;
1656         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1657                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1658         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1659 
1660         return extattr_delete_file(path, attrnamespace, attrname);
1661 #elif defined(HAVE_ATTR_REMOVE)
1662         int flags = 0;
1663         char *attrname = strchr(name,'.') + 1;
1664         
1665         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1666 
1667         return attr_remove(path, attrname, flags);
1668 #elif defined(HAVE_ATTROPEN)
1669         int ret = -1;
1670         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
1671         if (attrdirfd >= 0) {
1672                 ret = solaris_unlinkat(attrdirfd, name);
1673                 close(attrdirfd);
1674         }
1675         return ret;
1676 #else
1677         errno = ENOSYS;
1678         return -1;
1679 #endif
1680 }
1681 
1682 int sys_lremovexattr (const char *path, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1683 {
1684 #if defined(HAVE_LREMOVEXATTR)
1685         return lremovexattr(path, name);
1686 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
1687         int options = XATTR_NOFOLLOW;
1688         return removexattr(path, name, options);
1689 #elif defined(HAVE_LREMOVEEA)
1690         return lremoveea(path, name);
1691 #elif defined(HAVE_EXTATTR_DELETE_LINK)
1692         char *s;
1693         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1694                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1695         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1696 
1697         return extattr_delete_link(path, attrnamespace, attrname);
1698 #elif defined(HAVE_ATTR_REMOVE)
1699         int flags = ATTR_DONTFOLLOW;
1700         char *attrname = strchr(name,'.') + 1;
1701         
1702         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1703 
1704         return attr_remove(path, attrname, flags);
1705 #elif defined(HAVE_ATTROPEN)
1706         int ret = -1;
1707         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
1708         if (attrdirfd >= 0) {
1709                 ret = solaris_unlinkat(attrdirfd, name);
1710                 close(attrdirfd);
1711         }
1712         return ret;
1713 #else
1714         errno = ENOSYS;
1715         return -1;
1716 #endif
1717 }
1718 
1719 int sys_fremovexattr (int filedes, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1720 {
1721 #if defined(HAVE_FREMOVEXATTR)
1722 #ifndef XATTR_ADD_OPT
1723         return fremovexattr(filedes, name);
1724 #else
1725         int options = 0;
1726         return fremovexattr(filedes, name, options);
1727 #endif
1728 #elif defined(HAVE_FREMOVEEA)
1729         return fremoveea(filedes, name);
1730 #elif defined(HAVE_EXTATTR_DELETE_FD)
1731         char *s;
1732         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1733                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1734         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1735 
1736         return extattr_delete_fd(filedes, attrnamespace, attrname);
1737 #elif defined(HAVE_ATTR_REMOVEF)
1738         int flags = 0;
1739         char *attrname = strchr(name,'.') + 1;
1740         
1741         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1742 
1743         return attr_removef(filedes, attrname, flags);
1744 #elif defined(HAVE_ATTROPEN)
1745         int ret = -1;
1746         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
1747         if (attrdirfd >= 0) {
1748                 ret = solaris_unlinkat(attrdirfd, name);
1749                 close(attrdirfd);
1750         }
1751         return ret;
1752 #else
1753         errno = ENOSYS;
1754         return -1;
1755 #endif
1756 }
1757 
1758 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
1759 {
1760 #if defined(HAVE_SETXATTR)
1761 #ifndef XATTR_ADD_OPT
1762         return setxattr(path, name, value, size, flags);
1763 #else
1764         int options = 0;
1765         return setxattr(path, name, value, size, 0, options);
1766 #endif
1767 #elif defined(HAVE_SETEA)
1768         return setea(path, name, value, size, flags);
1769 #elif defined(HAVE_EXTATTR_SET_FILE)
1770         char *s;
1771         int retval = 0;
1772         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1773                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1774         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1775         if (flags) {
1776                 /* Check attribute existence */
1777                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
1778                 if (retval < 0) {
1779                         /* REPLACE attribute, that doesn't exist */
1780                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1781                                 errno = ENOATTR;
1782                                 return -1;
1783                         }
1784                         /* Ignore other errors */
1785                 }
1786                 else {
1787                         /* CREATE attribute, that already exists */
1788                         if (flags & XATTR_CREATE) {
1789                                 errno = EEXIST;
1790                                 return -1;
1791                         }
1792                 }
1793         }
1794         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
1795         return (retval < 0) ? -1 : 0;
1796 #elif defined(HAVE_ATTR_SET)
1797         int myflags = 0;
1798         char *attrname = strchr(name,'.') + 1;
1799         
1800         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1801         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1802         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1803 
1804         return attr_set(path, attrname, (const char *)value, size, myflags);
1805 #elif defined(HAVE_ATTROPEN)
1806         int ret = -1;
1807         int myflags = O_RDWR;
1808         int attrfd;
1809         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1810         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1811         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1812         if (attrfd >= 0) {
1813                 ret = solaris_write_xattr(attrfd, value, size);
1814                 close(attrfd);
1815         }
1816         return ret;
1817 #else
1818         errno = ENOSYS;
1819         return -1;
1820 #endif
1821 }
1822 
1823 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
1824 {
1825 #if defined(HAVE_LSETXATTR)
1826         return lsetxattr(path, name, value, size, flags);
1827 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
1828         int options = XATTR_NOFOLLOW;
1829         return setxattr(path, name, value, size, 0, options);
1830 #elif defined(LSETEA)
1831         return lsetea(path, name, value, size, flags);
1832 #elif defined(HAVE_EXTATTR_SET_LINK)
1833         char *s;
1834         int retval = 0;
1835         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1836                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1837         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1838         if (flags) {
1839                 /* Check attribute existence */
1840                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
1841                 if (retval < 0) {
1842                         /* REPLACE attribute, that doesn't exist */
1843                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1844                                 errno = ENOATTR;
1845                                 return -1;
1846                         }
1847                         /* Ignore other errors */
1848                 }
1849                 else {
1850                         /* CREATE attribute, that already exists */
1851                         if (flags & XATTR_CREATE) {
1852                                 errno = EEXIST;
1853                                 return -1;
1854                         }
1855                 }
1856         }
1857 
1858         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
1859         return (retval < 0) ? -1 : 0;
1860 #elif defined(HAVE_ATTR_SET)
1861         int myflags = ATTR_DONTFOLLOW;
1862         char *attrname = strchr(name,'.') + 1;
1863         
1864         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1865         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1866         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1867 
1868         return attr_set(path, attrname, (const char *)value, size, myflags);
1869 #elif defined(HAVE_ATTROPEN)
1870         int ret = -1;
1871         int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
1872         int attrfd;
1873         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1874         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1875         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1876         if (attrfd >= 0) {
1877                 ret = solaris_write_xattr(attrfd, value, size);
1878                 close(attrfd);
1879         }
1880         return ret;
1881 #else
1882         errno = ENOSYS;
1883         return -1;
1884 #endif
1885 }
1886 
1887 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
1888 {
1889 #if defined(HAVE_FSETXATTR)
1890 #ifndef XATTR_ADD_OPT
1891         return fsetxattr(filedes, name, value, size, flags);
1892 #else
1893         int options = 0;
1894         return fsetxattr(filedes, name, value, size, 0, options);
1895 #endif
1896 #elif defined(HAVE_FSETEA)
1897         return fsetea(filedes, name, value, size, flags);
1898 #elif defined(HAVE_EXTATTR_SET_FD)
1899         char *s;
1900         int retval = 0;
1901         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
1902                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
1903         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
1904         if (flags) {
1905                 /* Check attribute existence */
1906                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
1907                 if (retval < 0) {
1908                         /* REPLACE attribute, that doesn't exist */
1909                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
1910                                 errno = ENOATTR;
1911                                 return -1;
1912                         }
1913                         /* Ignore other errors */
1914                 }
1915                 else {
1916                         /* CREATE attribute, that already exists */
1917                         if (flags & XATTR_CREATE) {
1918                                 errno = EEXIST;
1919                                 return -1;
1920                         }
1921                 }
1922         }
1923         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
1924         return (retval < 0) ? -1 : 0;
1925 #elif defined(HAVE_ATTR_SETF)
1926         int myflags = 0;
1927         char *attrname = strchr(name,'.') + 1;
1928         
1929         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1930         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1931         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1932 
1933         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1934 #elif defined(HAVE_ATTROPEN)
1935         int ret = -1;
1936         int myflags = O_RDWR | O_XATTR;
1937         int attrfd;
1938         if (flags & XATTR_CREATE) myflags |= O_EXCL;
1939         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
1940         attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
1941         if (attrfd >= 0) {
1942                 ret = solaris_write_xattr(attrfd, value, size);
1943                 close(attrfd);
1944         }
1945         return ret;
1946 #else
1947         errno = ENOSYS;
1948         return -1;
1949 #endif
1950 }
1951 
1952 /**************************************************************************
1953  helper functions for Solaris' EA support
1954 ****************************************************************************/
1955 #ifdef HAVE_ATTROPEN
1956 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1957 {
1958         struct stat sbuf;
1959 
1960         if (fstat(attrfd, &sbuf) == -1) {
1961                 errno = ENOATTR;
1962                 return -1;
1963         }
1964 
1965         /* This is to return the current size of the named extended attribute */
1966         if (size == 0) {
1967                 return sbuf.st_size;
1968         }
1969 
1970         /* check size and read xattr */
1971         if (sbuf.st_size > size) {
1972                 errno = ERANGE;
1973                 return -1;
1974         }
1975 
1976         return read(attrfd, value, sbuf.st_size);
1977 }
1978 
1979 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1980 {
1981         ssize_t len = 0;
1982         DIR *dirp;
1983         struct dirent *de;
1984         int newfd = dup(attrdirfd);
1985         /* CAUTION: The originating file descriptor should not be
1986                     used again following the call to fdopendir().
1987                     For that reason we dup() the file descriptor
1988                     here to make things more clear. */
1989         dirp = fdopendir(newfd);
1990 
1991         while ((de = readdir(dirp))) {
1992                 size_t listlen = strlen(de->d_name);
1993                 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
1994                         /* we don't want "." and ".." here: */
1995                         DEBUG(10,("skipped EA %s\n",de->d_name));
1996                         continue;
1997                 }
1998 
1999                 if (size == 0) {
2000                         /* return the current size of the list of extended attribute names*/
2001                         len += listlen + 1;
2002                 } else {
2003                         /* check size and copy entrieѕ + nul into list. */
2004                         if ((len + listlen + 1) > size) {
2005                                 errno = ERANGE;
2006                                 len = -1;
2007                                 break;
2008                         } else {
2009                                 safe_strcpy(list + len, de->d_name, listlen);
2010                                 len += listlen;
2011                                 list[len] = '\0';
2012                                 ++len;
2013                         }
2014                 }
2015         }
2016 
2017         if (closedir(dirp) == -1) {
2018                 DEBUG(0,("closedir dirp failed: %s\n",strerror(errno)));
2019                 return -1;
2020         }
2021         return len;
2022 }
2023 
2024 static int solaris_unlinkat(int attrdirfd, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2025 {
2026         if (unlinkat(attrdirfd, name, 0) == -1) {
2027                 if (errno == ENOENT) {
2028                         errno = ENOATTR;
2029                 }
2030                 return -1;
2031         }
2032         return 0;
2033 }
2034 
2035 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
2036 {
2037         int filedes = attropen(path, attrpath, oflag, mode);
2038         if (filedes == -1) {
2039                 DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
2040                 if (errno == EINVAL) {
2041                         errno = ENOTSUP;
2042                 } else {
2043                         errno = ENOATTR;
2044                 }
2045         }
2046         return filedes;
2047 }
2048 
2049 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
2050 {
2051         int filedes = openat(fildes, path, oflag, mode);
2052         if (filedes == -1) {
2053                 DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
2054                 if (errno == EINVAL) {
2055                         errno = ENOTSUP;
2056                 } else {
2057                         errno = ENOATTR;
2058                 }
2059         }
2060         return filedes;
2061 }
2062 
2063 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
2064 {
2065         if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
2066                 return 0;
2067         } else {
2068                 DEBUG(10,("solaris_write_xattr FAILED!\n"));
2069                 return -1;
2070         }
2071 }
2072 #endif /*HAVE_ATTROPEN*/
2073 
2074 
2075 /****************************************************************************
2076  Return the major devicenumber for UNIX extensions.
2077 ****************************************************************************/
2078                                                                                                                 
2079 uint32 unix_dev_major(SMB_DEV_T dev)
     /* [<][>][^][v][top][bottom][index][help] */
2080 {
2081 #if defined(HAVE_DEVICE_MAJOR_FN)
2082         return (uint32)major(dev);
2083 #else
2084         return (uint32)(dev >> 8);
2085 #endif
2086 }
2087                                                                                                                 
2088 /****************************************************************************
2089  Return the minor devicenumber for UNIX extensions.
2090 ****************************************************************************/
2091                                                                                                                 
2092 uint32 unix_dev_minor(SMB_DEV_T dev)
     /* [<][>][^][v][top][bottom][index][help] */
2093 {
2094 #if defined(HAVE_DEVICE_MINOR_FN)
2095         return (uint32)minor(dev);
2096 #else
2097         return (uint32)(dev & 0xff);
2098 #endif
2099 }
2100 
2101 #if defined(WITH_AIO)
2102 
2103 /*******************************************************************
2104  An aio_read wrapper that will deal with 64-bit sizes.
2105 ********************************************************************/
2106                                                                                                                                            
2107 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2108 {
2109 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
2110         return aio_read64(aiocb);
2111 #elif defined(HAVE_AIO_READ)
2112         return aio_read(aiocb);
2113 #else
2114         errno = ENOSYS;
2115         return -1;
2116 #endif
2117 }
2118 
2119 /*******************************************************************
2120  An aio_write wrapper that will deal with 64-bit sizes.
2121 ********************************************************************/
2122                                                                                                                                            
2123 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2124 {
2125 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
2126         return aio_write64(aiocb);
2127 #elif defined(HAVE_AIO_WRITE)
2128         return aio_write(aiocb);
2129 #else
2130         errno = ENOSYS;
2131         return -1;
2132 #endif
2133 }
2134 
2135 /*******************************************************************
2136  An aio_return wrapper that will deal with 64-bit sizes.
2137 ********************************************************************/
2138                                                                                                                                            
2139 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2140 {
2141 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
2142         return aio_return64(aiocb);
2143 #elif defined(HAVE_AIO_RETURN)
2144         return aio_return(aiocb);
2145 #else
2146         errno = ENOSYS;
2147         return -1;
2148 #endif
2149 }
2150 
2151 /*******************************************************************
2152  An aio_cancel wrapper that will deal with 64-bit sizes.
2153 ********************************************************************/
2154 
2155 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2156 {
2157 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
2158         return aio_cancel64(fd, aiocb);
2159 #elif defined(HAVE_AIO_CANCEL)
2160         return aio_cancel(fd, aiocb);
2161 #else
2162         errno = ENOSYS;
2163         return -1;
2164 #endif
2165 }
2166 
2167 /*******************************************************************
2168  An aio_error wrapper that will deal with 64-bit sizes.
2169 ********************************************************************/
2170 
2171 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2172 {
2173 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
2174         return aio_error64(aiocb);
2175 #elif defined(HAVE_AIO_ERROR)
2176         return aio_error(aiocb);
2177 #else
2178         errno = ENOSYS;
2179         return -1;
2180 #endif
2181 }
2182 
2183 /*******************************************************************
2184  An aio_fsync wrapper that will deal with 64-bit sizes.
2185 ********************************************************************/
2186 
2187 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2188 {
2189 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
2190         return aio_fsync64(op, aiocb);
2191 #elif defined(HAVE_AIO_FSYNC)
2192         return aio_fsync(op, aiocb);
2193 #else
2194         errno = ENOSYS;
2195         return -1;
2196 #endif
2197 }
2198 
2199 /*******************************************************************
2200  An aio_fsync wrapper that will deal with 64-bit sizes.
2201 ********************************************************************/
2202 
2203 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
     /* [<][>][^][v][top][bottom][index][help] */
2204 {
2205 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
2206         return aio_suspend64(cblist, n, timeout);
2207 #elif defined(HAVE_AIO_FSYNC)
2208         return aio_suspend(cblist, n, timeout);
2209 #else
2210         errno = ENOSYS;
2211         return -1;
2212 #endif
2213 }
2214 #else /* !WITH_AIO */
2215 
2216 int sys_aio_read(SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2217 {
2218         errno = ENOSYS;
2219         return -1;
2220 }
2221 
2222 int sys_aio_write(SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2223 {
2224         errno = ENOSYS;
2225         return -1;
2226 }
2227 
2228 ssize_t sys_aio_return(SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2229 {
2230         errno = ENOSYS;
2231         return -1;
2232 }
2233 
2234 int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2235 {
2236         errno = ENOSYS;
2237         return -1;
2238 }
2239 
2240 int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2241 {
2242         errno = ENOSYS;
2243         return -1;
2244 }
2245 
2246 int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb)
     /* [<][>][^][v][top][bottom][index][help] */
2247 {
2248         errno = ENOSYS;
2249         return -1;
2250 }
2251 
2252 int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout)
     /* [<][>][^][v][top][bottom][index][help] */
2253 {
2254         errno = ENOSYS;
2255         return -1;
2256 }
2257 #endif /* WITH_AIO */
2258 
2259 int sys_getpeereid( int s, uid_t *uid)
     /* [<][>][^][v][top][bottom][index][help] */
2260 {
2261 #if defined(HAVE_PEERCRED)
2262         struct ucred cred;
2263         socklen_t cred_len = sizeof(struct ucred);
2264         int ret;
2265 
2266         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
2267         if (ret != 0) {
2268                 return -1;
2269         }
2270 
2271         if (cred_len != sizeof(struct ucred)) {
2272                 errno = EINVAL;
2273                 return -1;
2274         }
2275 
2276         *uid = cred.uid;
2277         return 0;
2278 #else
2279         errno = ENOSYS;
2280         return -1;
2281 #endif
2282 }
2283 
2284 int sys_getnameinfo(const struct sockaddr *psa,
     /* [<][>][^][v][top][bottom][index][help] */
2285                         socklen_t salen,
2286                         char *host,
2287                         size_t hostlen,
2288                         char *service,
2289                         size_t servlen,
2290                         int flags)
2291 {
2292         /*
2293          * For Solaris we must make sure salen is the
2294          * correct length for the incoming sa_family.
2295          */
2296 
2297         if (salen == sizeof(struct sockaddr_storage)) {
2298                 salen = sizeof(struct sockaddr_in);
2299 #if defined(HAVE_IPV6)
2300                 if (psa->sa_family == AF_INET6) {
2301                         salen = sizeof(struct sockaddr_in6);
2302                 }
2303 #endif
2304         }
2305         return getnameinfo(psa, salen, host, hostlen, service, servlen, flags);
2306 }
2307 
2308 int sys_connect(int fd, const struct sockaddr * addr)
     /* [<][>][^][v][top][bottom][index][help] */
2309 {
2310         socklen_t salen = -1;
2311 
2312         if (addr->sa_family == AF_INET) {
2313             salen = sizeof(struct sockaddr_in);
2314         } else if (addr->sa_family == AF_UNIX) {
2315             salen = sizeof(struct sockaddr_un);
2316         }
2317 #if defined(HAVE_IPV6)
2318         else if (addr->sa_family == AF_INET6) {
2319             salen = sizeof(struct sockaddr_in6);
2320         }
2321 #endif
2322 
2323         return connect(fd, addr, salen);
2324 }

/* [<][>][^][v][top][bottom][index][help] */