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