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