lib/system.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Samba system utilities
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Jeremy Allison  1998-2005
00006    Copyright (C) Timur Bakeyev        2005
00007    Copyright (C) Bjoern Jacke    2006-2007
00008    
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include "includes.h"
00025 
00026 #ifdef HAVE_SYS_PRCTL_H
00027 #include <sys/prctl.h>
00028 #endif
00029 
00030 /*
00031    The idea is that this file will eventually have wrappers around all
00032    important system calls in samba. The aims are:
00033 
00034    - to enable easier porting by putting OS dependent stuff in here
00035 
00036    - to allow for hooks into other "pseudo-filesystems"
00037 
00038    - to allow easier integration of things like the japanese extensions
00039 
00040    - to support the philosophy of Samba to expose the features of
00041      the OS within the SMB model. In general whatever file/printer/variable
00042      expansions/etc make sense to the OS should be acceptable to Samba.
00043 */
00044 
00045 
00046 
00047 /*******************************************************************
00048  A wrapper for memalign
00049 ********************************************************************/
00050 
00051 void *sys_memalign( size_t align, size_t size )
00052 {
00053 #if defined(HAVE_POSIX_MEMALIGN)
00054         void *p = NULL;
00055         int ret = posix_memalign( &p, align, size );
00056         if ( ret == 0 )
00057                 return p;
00058                 
00059         return NULL;
00060 #elif defined(HAVE_MEMALIGN)
00061         return memalign( align, size );
00062 #else
00063         /* On *BSD systems memaligns doesn't exist, but memory will
00064          * be aligned on allocations of > pagesize. */
00065 #if defined(SYSCONF_SC_PAGESIZE)
00066         size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
00067 #elif defined(HAVE_GETPAGESIZE)
00068         size_t pagesize = (size_t)getpagesize();
00069 #else
00070         size_t pagesize = (size_t)-1;
00071 #endif
00072         if (pagesize == (size_t)-1) {
00073                 DEBUG(0,("memalign functionalaity not available on this platform!\n"));
00074                 return NULL;
00075         }
00076         if (size < pagesize) {
00077                 size = pagesize;
00078         }
00079         return SMB_MALLOC(size);
00080 #endif
00081 }
00082 
00083 /*******************************************************************
00084  A wrapper for usleep in case we don't have one.
00085 ********************************************************************/
00086 
00087 int sys_usleep(long usecs)
00088 {
00089 #ifndef HAVE_USLEEP
00090         struct timeval tval;
00091 #endif
00092 
00093         /*
00094          * We need this braindamage as the glibc usleep
00095          * is not SPEC1170 complient... grumble... JRA.
00096          */
00097 
00098         if(usecs < 0 || usecs > 1000000) {
00099                 errno = EINVAL;
00100                 return -1;
00101         }
00102 
00103 #if HAVE_USLEEP
00104         usleep(usecs);
00105         return 0;
00106 #else /* HAVE_USLEEP */
00107         /*
00108          * Fake it with select...
00109          */
00110         tval.tv_sec = 0;
00111         tval.tv_usec = usecs/1000;
00112         select(0,NULL,NULL,NULL,&tval);
00113         return 0;
00114 #endif /* HAVE_USLEEP */
00115 }
00116 
00117 /*******************************************************************
00118 A read wrapper that will deal with EINTR.
00119 ********************************************************************/
00120 
00121 ssize_t sys_read(int fd, void *buf, size_t count)
00122 {
00123         ssize_t ret;
00124 
00125         do {
00126                 ret = read(fd, buf, count);
00127         } while (ret == -1 && errno == EINTR);
00128         return ret;
00129 }
00130 
00131 /*******************************************************************
00132 A write wrapper that will deal with EINTR.
00133 ********************************************************************/
00134 
00135 ssize_t sys_write(int fd, const void *buf, size_t count)
00136 {
00137         ssize_t ret;
00138 
00139         do {
00140                 ret = write(fd, buf, count);
00141         } while (ret == -1 && errno == EINTR);
00142         return ret;
00143 }
00144 
00145 /*******************************************************************
00146 A pread wrapper that will deal with EINTR and 64-bit file offsets.
00147 ********************************************************************/
00148 
00149 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
00150 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
00151 {
00152         ssize_t ret;
00153 
00154         do {
00155 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
00156                 ret = pread64(fd, buf, count, off);
00157 #else
00158                 ret = pread(fd, buf, count, off);
00159 #endif
00160         } while (ret == -1 && errno == EINTR);
00161         return ret;
00162 }
00163 #endif
00164 
00165 /*******************************************************************
00166 A write wrapper that will deal with EINTR and 64-bit file offsets.
00167 ********************************************************************/
00168 
00169 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
00170 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
00171 {
00172         ssize_t ret;
00173 
00174         do {
00175 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
00176                 ret = pwrite64(fd, buf, count, off);
00177 #else
00178                 ret = pwrite(fd, buf, count, off);
00179 #endif
00180         } while (ret == -1 && errno == EINTR);
00181         return ret;
00182 }
00183 #endif
00184 
00185 /*******************************************************************
00186 A send wrapper that will deal with EINTR.
00187 ********************************************************************/
00188 
00189 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
00190 {
00191         ssize_t ret;
00192 
00193         do {
00194                 ret = send(s, msg, len, flags);
00195         } while (ret == -1 && errno == EINTR);
00196         return ret;
00197 }
00198 
00199 /*******************************************************************
00200 A sendto wrapper that will deal with EINTR.
00201 ********************************************************************/
00202 
00203 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
00204 {
00205         ssize_t ret;
00206 
00207         do {
00208                 ret = sendto(s, msg, len, flags, to, tolen);
00209         } while (ret == -1 && errno == EINTR);
00210         return ret;
00211 }
00212 
00213 /*******************************************************************
00214 A recv wrapper that will deal with EINTR.
00215 ********************************************************************/
00216 
00217 ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
00218 {
00219         ssize_t ret;
00220 
00221         do {
00222                 ret = recv(fd, buf, count, flags);
00223         } while (ret == -1 && errno == EINTR);
00224         return ret;
00225 }
00226 
00227 /*******************************************************************
00228 A recvfrom wrapper that will deal with EINTR.
00229 ********************************************************************/
00230 
00231 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
00232 {
00233         ssize_t ret;
00234 
00235         do {
00236                 ret = recvfrom(s, buf, len, flags, from, fromlen);
00237         } while (ret == -1 && errno == EINTR);
00238         return ret;
00239 }
00240 
00241 /*******************************************************************
00242 A fcntl wrapper that will deal with EINTR.
00243 ********************************************************************/
00244 
00245 int sys_fcntl_ptr(int fd, int cmd, void *arg)
00246 {
00247         int ret;
00248 
00249         do {
00250                 ret = fcntl(fd, cmd, arg);
00251         } while (ret == -1 && errno == EINTR);
00252         return ret;
00253 }
00254 
00255 /*******************************************************************
00256 A fcntl wrapper that will deal with EINTR.
00257 ********************************************************************/
00258 
00259 int sys_fcntl_long(int fd, int cmd, long arg)
00260 {
00261         int ret;
00262 
00263         do {
00264                 ret = fcntl(fd, cmd, arg);
00265         } while (ret == -1 && errno == EINTR);
00266         return ret;
00267 }
00268 
00269 /*******************************************************************
00270 A stat() wrapper that will deal with 64 bit filesizes.
00271 ********************************************************************/
00272 
00273 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
00274 {
00275         int ret;
00276 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
00277         ret = stat64(fname, sbuf);
00278 #else
00279         ret = stat(fname, sbuf);
00280 #endif
00281         /* we always want directories to appear zero size */
00282         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
00283         return ret;
00284 }
00285 
00286 /*******************************************************************
00287  An fstat() wrapper that will deal with 64 bit filesizes.
00288 ********************************************************************/
00289 
00290 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
00291 {
00292         int ret;
00293 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
00294         ret = fstat64(fd, sbuf);
00295 #else
00296         ret = fstat(fd, sbuf);
00297 #endif
00298         /* we always want directories to appear zero size */
00299         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
00300         return ret;
00301 }
00302 
00303 /*******************************************************************
00304  An lstat() wrapper that will deal with 64 bit filesizes.
00305 ********************************************************************/
00306 
00307 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
00308 {
00309         int ret;
00310 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
00311         ret = lstat64(fname, sbuf);
00312 #else
00313         ret = lstat(fname, sbuf);
00314 #endif
00315         /* we always want directories to appear zero size */
00316         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
00317         return ret;
00318 }
00319 
00320 /*******************************************************************
00321  An ftruncate() wrapper that will deal with 64 bit filesizes.
00322 ********************************************************************/
00323 
00324 int sys_ftruncate(int fd, SMB_OFF_T offset)
00325 {
00326 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
00327         return ftruncate64(fd, offset);
00328 #else
00329         return ftruncate(fd, offset);
00330 #endif
00331 }
00332 
00333 /*******************************************************************
00334  An lseek() wrapper that will deal with 64 bit filesizes.
00335 ********************************************************************/
00336 
00337 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
00338 {
00339 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
00340         return lseek64(fd, offset, whence);
00341 #else
00342         return lseek(fd, offset, whence);
00343 #endif
00344 }
00345 
00346 /*******************************************************************
00347  An fseek() wrapper that will deal with 64 bit filesizes.
00348 ********************************************************************/
00349 
00350 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
00351 {
00352 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
00353         return fseek64(fp, offset, whence);
00354 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
00355         return fseeko64(fp, offset, whence);
00356 #else
00357         return fseek(fp, offset, whence);
00358 #endif
00359 }
00360 
00361 /*******************************************************************
00362  An ftell() wrapper that will deal with 64 bit filesizes.
00363 ********************************************************************/
00364 
00365 SMB_OFF_T sys_ftell(FILE *fp)
00366 {
00367 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
00368         return (SMB_OFF_T)ftell64(fp);
00369 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
00370         return (SMB_OFF_T)ftello64(fp);
00371 #else
00372         return (SMB_OFF_T)ftell(fp);
00373 #endif
00374 }
00375 
00376 /*******************************************************************
00377  A creat() wrapper that will deal with 64 bit filesizes.
00378 ********************************************************************/
00379 
00380 int sys_creat(const char *path, mode_t mode)
00381 {
00382 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
00383         return creat64(path, mode);
00384 #else
00385         /*
00386          * If creat64 isn't defined then ensure we call a potential open64.
00387          * JRA.
00388          */
00389         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
00390 #endif
00391 }
00392 
00393 /*******************************************************************
00394  An open() wrapper that will deal with 64 bit filesizes.
00395 ********************************************************************/
00396 
00397 int sys_open(const char *path, int oflag, mode_t mode)
00398 {
00399 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
00400         return open64(path, oflag, mode);
00401 #else
00402         return open(path, oflag, mode);
00403 #endif
00404 }
00405 
00406 /*******************************************************************
00407  An fopen() wrapper that will deal with 64 bit filesizes.
00408 ********************************************************************/
00409 
00410 FILE *sys_fopen(const char *path, const char *type)
00411 {
00412 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
00413         return fopen64(path, type);
00414 #else
00415         return fopen(path, type);
00416 #endif
00417 }
00418 
00419 
00420 /*******************************************************************
00421  A flock() wrapper that will perform the kernel flock.
00422 ********************************************************************/
00423 
00424 void kernel_flock(int fd, uint32 share_mode)
00425 {
00426 #if HAVE_KERNEL_SHARE_MODES
00427         int kernel_mode = 0;
00428         if (share_mode == FILE_SHARE_WRITE) {
00429                 kernel_mode = LOCK_MAND|LOCK_WRITE;
00430         } else if (share_mode == FILE_SHARE_READ) {
00431                 kernel_mode = LOCK_MAND|LOCK_READ;
00432         } else if (share_mode == FILE_SHARE_NONE) {
00433                 kernel_mode = LOCK_MAND;
00434         }
00435         if (kernel_mode) {
00436                 flock(fd, kernel_mode);
00437         }
00438 #endif
00439         ;
00440 }
00441 
00442 
00443 
00444 /*******************************************************************
00445  An opendir wrapper that will deal with 64 bit filesizes.
00446 ********************************************************************/
00447 
00448 SMB_STRUCT_DIR *sys_opendir(const char *name)
00449 {
00450 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
00451         return opendir64(name);
00452 #else
00453         return opendir(name);
00454 #endif
00455 }
00456 
00457 /*******************************************************************
00458  A readdir wrapper that will deal with 64 bit filesizes.
00459 ********************************************************************/
00460 
00461 SMB_STRUCT_DIRENT *sys_readdir(SMB_STRUCT_DIR *dirp)
00462 {
00463 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
00464         return readdir64(dirp);
00465 #else
00466         return readdir(dirp);
00467 #endif
00468 }
00469 
00470 /*******************************************************************
00471  A seekdir wrapper that will deal with 64 bit filesizes.
00472 ********************************************************************/
00473 
00474 void sys_seekdir(SMB_STRUCT_DIR *dirp, long offset)
00475 {
00476 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
00477         seekdir64(dirp, offset);
00478 #else
00479         seekdir(dirp, offset);
00480 #endif
00481 }
00482 
00483 /*******************************************************************
00484  A telldir wrapper that will deal with 64 bit filesizes.
00485 ********************************************************************/
00486 
00487 long sys_telldir(SMB_STRUCT_DIR *dirp)
00488 {
00489 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
00490         return (long)telldir64(dirp);
00491 #else
00492         return (long)telldir(dirp);
00493 #endif
00494 }
00495 
00496 /*******************************************************************
00497  A rewinddir wrapper that will deal with 64 bit filesizes.
00498 ********************************************************************/
00499 
00500 void sys_rewinddir(SMB_STRUCT_DIR *dirp)
00501 {
00502 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
00503         rewinddir64(dirp);
00504 #else
00505         rewinddir(dirp);
00506 #endif
00507 }
00508 
00509 /*******************************************************************
00510  A close wrapper that will deal with 64 bit filesizes.
00511 ********************************************************************/
00512 
00513 int sys_closedir(SMB_STRUCT_DIR *dirp)
00514 {
00515 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
00516         return closedir64(dirp);
00517 #else
00518         return closedir(dirp);
00519 #endif
00520 }
00521 
00522 /*******************************************************************
00523  An mknod() wrapper that will deal with 64 bit filesizes.
00524 ********************************************************************/
00525 
00526 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
00527 {
00528 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
00529 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
00530         return mknod64(path, mode, dev);
00531 #else
00532         return mknod(path, mode, dev);
00533 #endif
00534 #else
00535         /* No mknod system call. */
00536         errno = ENOSYS;
00537         return -1;
00538 #endif
00539 }
00540 
00541 /*******************************************************************
00542  Wrapper for realpath.
00543 ********************************************************************/
00544 
00545 char *sys_realpath(const char *path, char *resolved_path)
00546 {
00547 #if defined(HAVE_REALPATH)
00548         return realpath(path, resolved_path);
00549 #else
00550         /* As realpath is not a system call we can't return ENOSYS. */
00551         errno = EINVAL;
00552         return NULL;
00553 #endif
00554 }
00555 
00556 /*******************************************************************
00557 The wait() calls vary between systems
00558 ********************************************************************/
00559 
00560 int sys_waitpid(pid_t pid,int *status,int options)
00561 {
00562 #ifdef HAVE_WAITPID
00563         return waitpid(pid,status,options);
00564 #else /* HAVE_WAITPID */
00565         return wait4(pid, status, options, NULL);
00566 #endif /* HAVE_WAITPID */
00567 }
00568 
00569 /*******************************************************************
00570  System wrapper for getwd
00571 ********************************************************************/
00572 
00573 char *sys_getwd(char *s)
00574 {
00575         char *wd;
00576 #ifdef HAVE_GETCWD
00577         wd = (char *)getcwd(s, sizeof (pstring));
00578 #else
00579         wd = (char *)getwd(s);
00580 #endif
00581         return wd;
00582 }
00583 
00584 /*******************************************************************
00585 system wrapper for symlink
00586 ********************************************************************/
00587 
00588 int sys_symlink(const char *oldpath, const char *newpath)
00589 {
00590 #ifndef HAVE_SYMLINK
00591         errno = ENOSYS;
00592         return -1;
00593 #else
00594         return symlink(oldpath, newpath);
00595 #endif
00596 }
00597 
00598 /*******************************************************************
00599 system wrapper for readlink
00600 ********************************************************************/
00601 
00602 int sys_readlink(const char *path, char *buf, size_t bufsiz)
00603 {
00604 #ifndef HAVE_READLINK
00605         errno = ENOSYS;
00606         return -1;
00607 #else
00608         return readlink(path, buf, bufsiz);
00609 #endif
00610 }
00611 
00612 /*******************************************************************
00613 system wrapper for link
00614 ********************************************************************/
00615 
00616 int sys_link(const char *oldpath, const char *newpath)
00617 {
00618 #ifndef HAVE_LINK
00619         errno = ENOSYS;
00620         return -1;
00621 #else
00622         return link(oldpath, newpath);
00623 #endif
00624 }
00625 
00626 /*******************************************************************
00627 chown isn't used much but OS/2 doesn't have it
00628 ********************************************************************/
00629 
00630 int sys_chown(const char *fname,uid_t uid,gid_t gid)
00631 {
00632 #ifndef HAVE_CHOWN
00633         static int done;
00634         if (!done) {
00635                 DEBUG(1,("WARNING: no chown!\n"));
00636                 done=1;
00637         }
00638         errno = ENOSYS;
00639         return -1;
00640 #else
00641         return(chown(fname,uid,gid));
00642 #endif
00643 }
00644 
00645 /*******************************************************************
00646 os/2 also doesn't have chroot
00647 ********************************************************************/
00648 int sys_chroot(const char *dname)
00649 {
00650 #ifndef HAVE_CHROOT
00651         static int done;
00652         if (!done) {
00653                 DEBUG(1,("WARNING: no chroot!\n"));
00654                 done=1;
00655         }
00656         errno = ENOSYS;
00657         return -1;
00658 #else
00659         return(chroot(dname));
00660 #endif
00661 }
00662 
00663 /**************************************************************************
00664 A wrapper for gethostbyname() that tries avoids looking up hostnames 
00665 in the root domain, which can cause dial-on-demand links to come up for no
00666 apparent reason.
00667 ****************************************************************************/
00668 
00669 struct hostent *sys_gethostbyname(const char *name)
00670 {
00671 #ifdef REDUCE_ROOT_DNS_LOOKUPS
00672         char query[256], hostname[256];
00673         char *domain;
00674 
00675         /* Does this name have any dots in it? If so, make no change */
00676 
00677         if (strchr_m(name, '.'))
00678                 return(gethostbyname(name));
00679 
00680         /* Get my hostname, which should have domain name 
00681                 attached. If not, just do the gethostname on the
00682                 original string. 
00683         */
00684 
00685         gethostname(hostname, sizeof(hostname) - 1);
00686         hostname[sizeof(hostname) - 1] = 0;
00687         if ((domain = strchr_m(hostname, '.')) == NULL)
00688                 return(gethostbyname(name));
00689 
00690         /* Attach domain name to query and do modified query.
00691                 If names too large, just do gethostname on the
00692                 original string.
00693         */
00694 
00695         if((strlen(name) + strlen(domain)) >= sizeof(query))
00696                 return(gethostbyname(name));
00697 
00698         slprintf(query, sizeof(query)-1, "%s%s", name, domain);
00699         return(gethostbyname(query));
00700 #else /* REDUCE_ROOT_DNS_LOOKUPS */
00701         return(gethostbyname(name));
00702 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
00703 }
00704 
00705 
00706 #if defined(HAVE_POSIX_CAPABILITIES)
00707 
00708 #ifdef HAVE_SYS_CAPABILITY_H
00709 
00710 #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
00711 #define _I386_STATFS_H
00712 #define _PPC_STATFS_H
00713 #define BROKEN_REDHAT_7_STATFS_WORKAROUND
00714 #endif
00715 
00716 #include <sys/capability.h>
00717 
00718 #ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
00719 #undef _I386_STATFS_H
00720 #undef _PPC_STATFS_H
00721 #undef BROKEN_REDHAT_7_STATFS_WORKAROUND
00722 #endif
00723 
00724 #endif /* HAVE_SYS_CAPABILITY_H */
00725 
00726 /**************************************************************************
00727  Try and abstract process capabilities (for systems that have them).
00728 ****************************************************************************/
00729 
00730 /* Set the POSIX capabilities needed for the given purpose into the effective
00731  * capability set of the current process. Make sure they are always removed
00732  * from the inheritable set, because there is no circumstance in which our
00733  * children should inherit our elevated privileges.
00734  */
00735 static BOOL set_process_capability(enum smbd_capability capability,
00736                                    BOOL enable)
00737 {
00738         cap_value_t cap_vals[2] = {0};
00739         int num_cap_vals = 0;
00740 
00741         cap_t cap;
00742 
00743 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
00744         /* On Linux, make sure that any capabilities we grab are sticky
00745          * across UID changes. We expect that this would allow us to keep both
00746          * the effective and permitted capability sets, but as of circa 2.6.16,
00747          * only the permitted set is kept. It is a bug (which we work around)
00748          * that the effective set is lost, but we still require the effective
00749          * set to be kept.
00750          */
00751         if (!prctl(PR_GET_KEEPCAPS)) {
00752                 prctl(PR_SET_KEEPCAPS, 1);
00753         }
00754 #endif
00755 
00756         cap = cap_get_proc();
00757         if (cap == NULL) {
00758                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
00759                         strerror(errno)));
00760                 return False;
00761         }
00762 
00763         switch (capability) {
00764                 case KERNEL_OPLOCK_CAPABILITY:
00765 #ifdef CAP_NETWORK_MGT
00766                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
00767                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
00768 #endif
00769                         break;
00770                 case DMAPI_ACCESS_CAPABILITY:
00771 #ifdef CAP_DEVICE_MGT
00772                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
00773                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
00774 #elif CAP_MKNOD
00775                         /* Linux has CAP_MKNOD for DMAPI access. */
00776                         cap_vals[num_cap_vals++] = CAP_MKNOD;
00777 #endif
00778                         break;
00779                 case LEASE_CAPABILITY:
00780 #ifdef CAP_LEASE
00781                         cap_vals[num_cap_vals++] = CAP_LEASE;
00782 #endif
00783                         break;
00784         }
00785 
00786         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
00787 
00788         if (num_cap_vals == 0) {
00789                 cap_free(cap);
00790                 return True;
00791         }
00792 
00793         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
00794                 enable ? CAP_SET : CAP_CLEAR);
00795 
00796         /* We never want to pass capabilities down to our children, so make
00797          * sure they are not inherited.
00798          */
00799         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
00800 
00801         if (cap_set_proc(cap) == -1) {
00802                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
00803                         strerror(errno)));
00804                 cap_free(cap);
00805                 return False;
00806         }
00807 
00808         cap_free(cap);
00809         return True;
00810 }
00811 
00812 #endif /* HAVE_POSIX_CAPABILITIES */
00813 
00814 /****************************************************************************
00815  Gain the oplock capability from the kernel if possible.
00816 ****************************************************************************/
00817 
00818 void set_effective_capability(enum smbd_capability capability)
00819 {
00820 #if defined(HAVE_POSIX_CAPABILITIES)
00821         set_process_capability(capability, True);
00822 #endif /* HAVE_POSIX_CAPABILITIES */
00823 }
00824 
00825 void drop_effective_capability(enum smbd_capability capability)
00826 {
00827 #if defined(HAVE_POSIX_CAPABILITIES)
00828         set_process_capability(capability, False);
00829 #endif /* HAVE_POSIX_CAPABILITIES */
00830 }
00831 
00832 /**************************************************************************
00833  Wrapper for random().
00834 ****************************************************************************/
00835 
00836 long sys_random(void)
00837 {
00838 #if defined(HAVE_RANDOM)
00839         return (long)random();
00840 #elif defined(HAVE_RAND)
00841         return (long)rand();
00842 #else
00843         DEBUG(0,("Error - no random function available !\n"));
00844         exit(1);
00845 #endif
00846 }
00847 
00848 /**************************************************************************
00849  Wrapper for srandom().
00850 ****************************************************************************/
00851 
00852 void sys_srandom(unsigned int seed)
00853 {
00854 #if defined(HAVE_SRANDOM)
00855         srandom(seed);
00856 #elif defined(HAVE_SRAND)
00857         srand(seed);
00858 #else
00859         DEBUG(0,("Error - no srandom function available !\n"));
00860         exit(1);
00861 #endif
00862 }
00863 
00864 /**************************************************************************
00865  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
00866 ****************************************************************************/
00867 
00868 int groups_max(void)
00869 {
00870 #if defined(SYSCONF_SC_NGROUPS_MAX)
00871         int ret = sysconf(_SC_NGROUPS_MAX);
00872         return (ret == -1) ? NGROUPS_MAX : ret;
00873 #else
00874         return NGROUPS_MAX;
00875 #endif
00876 }
00877 
00878 /**************************************************************************
00879  Wrapper for getgroups. Deals with broken (int) case.
00880 ****************************************************************************/
00881 
00882 int sys_getgroups(int setlen, gid_t *gidset)
00883 {
00884 #if !defined(HAVE_BROKEN_GETGROUPS)
00885         return getgroups(setlen, gidset);
00886 #else
00887 
00888         GID_T gid;
00889         GID_T *group_list;
00890         int i, ngroups;
00891 
00892         if(setlen == 0) {
00893                 return getgroups(setlen, &gid);
00894         }
00895 
00896         /*
00897          * Broken case. We need to allocate a
00898          * GID_T array of size setlen.
00899          */
00900 
00901         if(setlen < 0) {
00902                 errno = EINVAL; 
00903                 return -1;
00904         } 
00905 
00906         if (setlen == 0)
00907                 setlen = groups_max();
00908 
00909         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
00910                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
00911                 return -1;
00912         }
00913 
00914         if((ngroups = getgroups(setlen, group_list)) < 0) {
00915                 int saved_errno = errno;
00916                 SAFE_FREE(group_list);
00917                 errno = saved_errno;
00918                 return -1;
00919         }
00920 
00921         for(i = 0; i < ngroups; i++)
00922                 gidset[i] = (gid_t)group_list[i];
00923 
00924         SAFE_FREE(group_list);
00925         return ngroups;
00926 #endif /* HAVE_BROKEN_GETGROUPS */
00927 }
00928 
00929 
00930 /**************************************************************************
00931  Wrapper for setgroups. Deals with broken (int) case. Automatically used
00932  if we have broken getgroups.
00933 ****************************************************************************/
00934 
00935 int sys_setgroups(int setlen, gid_t *gidset)
00936 {
00937 #if !defined(HAVE_SETGROUPS)
00938         errno = ENOSYS;
00939         return -1;
00940 #endif /* HAVE_SETGROUPS */
00941 
00942 #if !defined(HAVE_BROKEN_GETGROUPS)
00943         return setgroups(setlen, gidset);
00944 #else
00945 
00946         GID_T *group_list;
00947         int i ; 
00948 
00949         if (setlen == 0)
00950                 return 0 ;
00951 
00952         if (setlen < 0 || setlen > groups_max()) {
00953                 errno = EINVAL; 
00954                 return -1;   
00955         }
00956 
00957         /*
00958          * Broken case. We need to allocate a
00959          * GID_T array of size setlen.
00960          */
00961 
00962         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
00963                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
00964                 return -1;    
00965         }
00966  
00967         for(i = 0; i < setlen; i++) 
00968                 group_list[i] = (GID_T) gidset[i]; 
00969 
00970         if(setgroups(setlen, group_list) != 0) {
00971                 int saved_errno = errno;
00972                 SAFE_FREE(group_list);
00973                 errno = saved_errno;
00974                 return -1;
00975         }
00976  
00977         SAFE_FREE(group_list);
00978         return 0 ;
00979 #endif /* HAVE_BROKEN_GETGROUPS */
00980 }
00981 
00982 /**************************************************************************
00983  Wrappers for setpwent(), getpwent() and endpwent()
00984 ****************************************************************************/
00985 
00986 void sys_setpwent(void)
00987 {
00988         setpwent();
00989 }
00990 
00991 struct passwd *sys_getpwent(void)
00992 {
00993         return getpwent();
00994 }
00995 
00996 void sys_endpwent(void)
00997 {
00998         endpwent();
00999 }
01000 
01001 /**************************************************************************
01002  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
01003 ****************************************************************************/
01004 
01005 #ifdef ENABLE_BUILD_FARM_HACKS
01006 
01007 /*
01008  * In the build farm we want to be able to join machines to the domain. As we
01009  * don't have root access, we need to bypass direct access to /etc/passwd
01010  * after a user has been created via samr. Fake those users.
01011  */
01012 
01013 static struct passwd *fake_pwd;
01014 static int num_fake_pwd;
01015 
01016 struct passwd *sys_getpwnam(const char *name)
01017 {
01018         int i;
01019 
01020         for (i=0; i<num_fake_pwd; i++) {
01021                 if (strcmp(fake_pwd[i].pw_name, name) == 0) {
01022                         DEBUG(10, ("Returning fake user %s\n", name));
01023                         return &fake_pwd[i];
01024                 }
01025         }
01026 
01027         return getpwnam(name);
01028 }
01029 
01030 struct passwd *sys_getpwuid(uid_t uid)
01031 {
01032         int i;
01033 
01034         for (i=0; i<num_fake_pwd; i++) {
01035                 if (fake_pwd[i].pw_uid == uid) {
01036                         DEBUG(10, ("Returning fake user %s\n",
01037                                    fake_pwd[i].pw_name));
01038                         return &fake_pwd[i];
01039                 }
01040         }
01041 
01042         return getpwuid(uid);
01043 }
01044 
01045 void faked_create_user(const char *name)
01046 {
01047         int i;
01048         uid_t uid;
01049         struct passwd new_pwd;
01050 
01051         for (i=0; i<10; i++) {
01052                 generate_random_buffer((unsigned char *)&uid,
01053                                        sizeof(uid));
01054                 if (getpwuid(uid) == NULL) {
01055                         break;
01056                 }
01057         }
01058 
01059         if (i==10) {
01060                 /* Weird. No free uid found... */
01061                 return;
01062         }
01063 
01064         new_pwd.pw_name = SMB_STRDUP(name);
01065         new_pwd.pw_passwd = SMB_STRDUP("x");
01066         new_pwd.pw_uid = uid;
01067         new_pwd.pw_gid = 100;
01068         new_pwd.pw_gecos = SMB_STRDUP("faked user");
01069         new_pwd.pw_dir = SMB_STRDUP("/nodir");
01070         new_pwd.pw_shell = SMB_STRDUP("/bin/false");
01071 
01072         ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
01073                      &num_fake_pwd);
01074 
01075         DEBUG(10, ("Added fake user %s, have %d fake users\n",
01076                    name, num_fake_pwd));
01077 }
01078 
01079 #else
01080 
01081 struct passwd *sys_getpwnam(const char *name)
01082 {
01083         return getpwnam(name);
01084 }
01085 
01086 struct passwd *sys_getpwuid(uid_t uid)
01087 {
01088         return getpwuid(uid);
01089 }
01090 
01091 #endif
01092 
01093 struct group *sys_getgrnam(const char *name)
01094 {
01095         return getgrnam(name);
01096 }
01097 
01098 struct group *sys_getgrgid(gid_t gid)
01099 {
01100         return getgrgid(gid);
01101 }
01102 
01103 #if 0 /* NOT CURRENTLY USED - JRA */
01104 /**************************************************************************
01105  The following are the UNICODE versions of *all* system interface functions
01106  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
01107  which currently are left as ascii as they are not used other than in name
01108  resolution.
01109 ****************************************************************************/
01110 
01111 /**************************************************************************
01112  Wide stat. Just narrow and call sys_xxx.
01113 ****************************************************************************/
01114 
01115 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
01116 {
01117         pstring fname;
01118         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
01119 }
01120 
01121 /**************************************************************************
01122  Wide lstat. Just narrow and call sys_xxx.
01123 ****************************************************************************/
01124 
01125 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
01126 {
01127         pstring fname;
01128         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
01129 }
01130 
01131 /**************************************************************************
01132  Wide creat. Just narrow and call sys_xxx.
01133 ****************************************************************************/
01134 
01135 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
01136 {
01137         pstring fname;
01138         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
01139 }
01140 
01141 /**************************************************************************
01142  Wide open. Just narrow and call sys_xxx.
01143 ****************************************************************************/
01144 
01145 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
01146 {
01147         pstring fname;
01148         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
01149 }
01150 
01151 /**************************************************************************
01152  Wide fopen. Just narrow and call sys_xxx.
01153 ****************************************************************************/
01154 
01155 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
01156 {
01157         pstring fname;
01158         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
01159 }
01160 
01161 /**************************************************************************
01162  Wide opendir. Just narrow and call sys_xxx.
01163 ****************************************************************************/
01164 
01165 SMB_STRUCT_DIR *wsys_opendir(const smb_ucs2_t *wfname)
01166 {
01167         pstring fname;
01168         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
01169 }
01170 
01171 /**************************************************************************
01172  Wide readdir. Return a structure pointer containing a wide filename.
01173 ****************************************************************************/
01174 
01175 SMB_STRUCT_WDIRENT *wsys_readdir(SMB_STRUCT_DIR *dirp)
01176 {
01177         static SMB_STRUCT_WDIRENT retval;
01178         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
01179 
01180         if(!dirval)
01181                 return NULL;
01182 
01183         /*
01184          * The only POSIX defined member of this struct is d_name.
01185          */
01186 
01187         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
01188 
01189         return &retval;
01190 }
01191 
01192 /**************************************************************************
01193  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
01194 ****************************************************************************/
01195 
01196 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
01197 {
01198         pstring fname;
01199         char *p = sys_getwd(fname);
01200 
01201         if(!p)
01202                 return NULL;
01203 
01204         return unix_to_unicode(s, p, sizeof(wpstring));
01205 }
01206 
01207 /**************************************************************************
01208  Wide chown. Just narrow and call sys_xxx.
01209 ****************************************************************************/
01210 
01211 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
01212 {
01213         pstring fname;
01214         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
01215 }
01216 
01217 /**************************************************************************
01218  Wide chroot. Just narrow and call sys_xxx.
01219 ****************************************************************************/
01220 
01221 int wsys_chroot(const smb_ucs2_t *wfname)
01222 {
01223         pstring fname;
01224         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
01225 }
01226 
01227 /**************************************************************************
01228  Wide getpwnam. Return a structure pointer containing wide names.
01229 ****************************************************************************/
01230 
01231 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
01232 {
01233         static SMB_STRUCT_WPASSWD retval;
01234         fstring name;
01235         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
01236 
01237         if(!pwret)
01238                 return NULL;
01239 
01240         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
01241         retval.pw_passwd = pwret->pw_passwd;
01242         retval.pw_uid = pwret->pw_uid;
01243         retval.pw_gid = pwret->pw_gid;
01244         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
01245         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
01246         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
01247 
01248         return &retval;
01249 }
01250 
01251 /**************************************************************************
01252  Wide getpwuid. Return a structure pointer containing wide names.
01253 ****************************************************************************/
01254 
01255 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
01256 {
01257         static SMB_STRUCT_WPASSWD retval;
01258         struct passwd *pwret = sys_getpwuid(uid);
01259 
01260         if(!pwret)
01261                 return NULL;
01262 
01263         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
01264         retval.pw_passwd = pwret->pw_passwd;
01265         retval.pw_uid = pwret->pw_uid;
01266         retval.pw_gid = pwret->pw_gid;
01267         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
01268         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
01269         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
01270 
01271         return &retval;
01272 }
01273 #endif /* NOT CURRENTLY USED - JRA */
01274 
01275 /**************************************************************************
01276  Extract a command into an arg list. Uses a static pstring for storage.
01277  Caller frees returned arg list (which contains pointers into the static pstring).
01278 ****************************************************************************/
01279 
01280 static char **extract_args(const char *command)
01281 {
01282         static pstring trunc_cmd;
01283         char *ptr;
01284         int argcl;
01285         char **argl = NULL;
01286         int i;
01287 
01288         pstrcpy(trunc_cmd, command);
01289 
01290         if(!(ptr = strtok(trunc_cmd, " \t"))) {
01291                 errno = EINVAL;
01292                 return NULL;
01293         }
01294 
01295         /*
01296          * Count the args.
01297          */
01298 
01299         for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
01300                 argcl++;
01301 
01302         if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
01303                 return NULL;
01304 
01305         /*
01306          * Now do the extraction.
01307          */
01308 
01309         pstrcpy(trunc_cmd, command);
01310 
01311         ptr = strtok(trunc_cmd, " \t");
01312         i = 0;
01313         argl[i++] = ptr;
01314 
01315         while((ptr = strtok(NULL, " \t")) != NULL)
01316                 argl[i++] = ptr;
01317 
01318         argl[i++] = NULL;
01319         return argl;
01320 }
01321 
01322 /**************************************************************************
01323  Wrapper for fork. Ensures that mypid is reset. Used so we can write
01324  a sys_getpid() that only does a system call *once*.
01325 ****************************************************************************/
01326 
01327 static pid_t mypid = (pid_t)-1;
01328 
01329 pid_t sys_fork(void)
01330 {
01331         pid_t forkret = fork();
01332 
01333         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
01334                 mypid = (pid_t) -1;
01335 
01336         return forkret;
01337 }
01338 
01339 /**************************************************************************
01340  Wrapper for getpid. Ensures we only do a system call *once*.
01341 ****************************************************************************/
01342 
01343 pid_t sys_getpid(void)
01344 {
01345         if (mypid == (pid_t)-1)
01346                 mypid = getpid();
01347 
01348         return mypid;
01349 }
01350 
01351 /**************************************************************************
01352  Wrapper for popen. Safer as it doesn't search a path.
01353  Modified from the glibc sources.
01354  modified by tridge to return a file descriptor. We must kick our FILE* habit
01355 ****************************************************************************/
01356 
01357 typedef struct _popen_list
01358 {
01359         int fd;
01360         pid_t child_pid;
01361         struct _popen_list *next;
01362 } popen_list;
01363 
01364 static popen_list *popen_chain;
01365 
01366 int sys_popen(const char *command)
01367 {
01368         int parent_end, child_end;
01369         int pipe_fds[2];
01370         popen_list *entry = NULL;
01371         char **argl = NULL;
01372 
01373         if (pipe(pipe_fds) < 0)
01374                 return -1;
01375 
01376         parent_end = pipe_fds[0];
01377         child_end = pipe_fds[1];
01378 
01379         if (!*command) {
01380                 errno = EINVAL;
01381                 goto err_exit;
01382         }
01383 
01384         if((entry = SMB_MALLOC_P(popen_list)) == NULL)
01385                 goto err_exit;
01386 
01387         ZERO_STRUCTP(entry);
01388 
01389         /*
01390          * Extract the command and args into a NULL terminated array.
01391          */
01392 
01393         if(!(argl = extract_args(command)))
01394                 goto err_exit;
01395 
01396         entry->child_pid = sys_fork();
01397 
01398         if (entry->child_pid == -1) {
01399                 goto err_exit;
01400         }
01401 
01402         if (entry->child_pid == 0) {
01403 
01404                 /*
01405                  * Child !
01406                  */
01407 
01408                 int child_std_end = STDOUT_FILENO;
01409                 popen_list *p;
01410 
01411                 close(parent_end);
01412                 if (child_end != child_std_end) {
01413                         dup2 (child_end, child_std_end);
01414                         close (child_end);
01415                 }
01416 
01417                 /*
01418                  * POSIX.2:  "popen() shall ensure that any streams from previous
01419                  * popen() calls that remain open in the parent process are closed
01420                  * in the new child process."
01421                  */
01422 
01423                 for (p = popen_chain; p; p = p->next)
01424                         close(p->fd);
01425 
01426                 execv(argl[0], argl);
01427                 _exit (127);
01428         }
01429 
01430         /*
01431          * Parent.
01432          */
01433 
01434         close (child_end);
01435         SAFE_FREE(argl);
01436 
01437         /* Link into popen_chain. */
01438         entry->next = popen_chain;
01439         popen_chain = entry;
01440         entry->fd = parent_end;
01441 
01442         return entry->fd;
01443 
01444 err_exit:
01445 
01446         SAFE_FREE(entry);
01447         SAFE_FREE(argl);
01448         close(pipe_fds[0]);
01449         close(pipe_fds[1]);
01450         return -1;
01451 }
01452 
01453 /**************************************************************************
01454  Wrapper for pclose. Modified from the glibc sources.
01455 ****************************************************************************/
01456 
01457 int sys_pclose(int fd)
01458 {
01459         int wstatus;
01460         popen_list **ptr = &popen_chain;
01461         popen_list *entry = NULL;
01462         pid_t wait_pid;
01463         int status = -1;
01464 
01465         /* Unlink from popen_chain. */
01466         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
01467                 if ((*ptr)->fd == fd) {
01468                         entry = *ptr;
01469                         *ptr = (*ptr)->next;
01470                         status = 0;
01471                         break;
01472                 }
01473         }
01474 
01475         if (status < 0 || close(entry->fd) < 0)
01476                 return -1;
01477 
01478         /*
01479          * As Samba is catching and eating child process
01480          * exits we don't really care about the child exit
01481          * code, a -1 with errno = ECHILD will do fine for us.
01482          */
01483 
01484         do {
01485                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
01486         } while (wait_pid == -1 && errno == EINTR);
01487 
01488         SAFE_FREE(entry);
01489 
01490         if (wait_pid == -1)
01491                 return -1;
01492         return wstatus;
01493 }
01494 
01495 /**************************************************************************
01496  Wrappers for dlopen, dlsym, dlclose.
01497 ****************************************************************************/
01498 
01499 void *sys_dlopen(const char *name, int flags)
01500 {
01501 #if defined(HAVE_DLOPEN)
01502         return dlopen(name, flags);
01503 #else
01504         return NULL;
01505 #endif
01506 }
01507 
01508 void *sys_dlsym(void *handle, const char *symbol)
01509 {
01510 #if defined(HAVE_DLSYM)
01511     return dlsym(handle, symbol);
01512 #else
01513     return NULL;
01514 #endif
01515 }
01516 
01517 int sys_dlclose (void *handle)
01518 {
01519 #if defined(HAVE_DLCLOSE)
01520         return dlclose(handle);
01521 #else
01522         return 0;
01523 #endif
01524 }
01525 
01526 const char *sys_dlerror(void)
01527 {
01528 #if defined(HAVE_DLERROR)
01529         return dlerror();
01530 #else
01531         return NULL;
01532 #endif
01533 }
01534 
01535 int sys_dup2(int oldfd, int newfd) 
01536 {
01537 #if defined(HAVE_DUP2)
01538         return dup2(oldfd, newfd);
01539 #else
01540         errno = ENOSYS;
01541         return -1;
01542 #endif
01543 }
01544 
01545 /**************************************************************************
01546  Wrapper for Admin Logs.
01547 ****************************************************************************/
01548 
01549  void sys_adminlog(int priority, const char *format_str, ...) 
01550 {
01551         va_list ap;
01552         int ret;
01553         char *msgbuf = NULL;
01554 
01555         va_start( ap, format_str );
01556         ret = vasprintf( &msgbuf, format_str, ap );
01557         va_end( ap );
01558 
01559         if (ret == -1)
01560                 return;
01561 
01562 #if defined(HAVE_SYSLOG)
01563         syslog( priority, "%s", msgbuf );
01564 #else
01565         DEBUG(0,("%s", msgbuf ));
01566 #endif
01567         SAFE_FREE(msgbuf);
01568 }
01569 
01570 /******** Solaris EA helper function prototypes ********/
01571 #ifdef HAVE_ATTROPEN
01572 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
01573 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
01574 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
01575 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
01576 static int solaris_unlinkat(int attrdirfd, const char *name);
01577 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
01578 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
01579 #endif
01580 
01581 /**************************************************************************
01582  Wrappers for extented attribute calls. Based on the Linux package with
01583  support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
01584 ****************************************************************************/
01585 
01586 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
01587 {
01588 #if defined(HAVE_GETXATTR)
01589 #ifndef XATTR_ADD_OPT
01590         return getxattr(path, name, value, size);
01591 #else
01592         int options = 0;
01593         return getxattr(path, name, value, size, 0, options);
01594 #endif
01595 #elif defined(HAVE_GETEA)
01596         return getea(path, name, value, size);
01597 #elif defined(HAVE_EXTATTR_GET_FILE)
01598         char *s;
01599         ssize_t retval;
01600         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
01601                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
01602         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
01603         /*
01604          * The BSD implementation has a nasty habit of silently truncating
01605          * the returned value to the size of the buffer, so we have to check
01606          * that the buffer is large enough to fit the returned value.
01607          */
01608         if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
01609                 if(retval > size) {
01610                         errno = ERANGE;
01611                         return -1;
01612                 }
01613                 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
01614                         return retval;
01615         }
01616 
01617         DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
01618         return -1;
01619 #elif defined(HAVE_ATTR_GET)
01620         int retval, flags = 0;
01621         int valuelength = (int)size;
01622         char *attrname = strchr(name,'.') + 1;
01623         
01624         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
01625 
01626         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
01627 
01628         return retval ? retval : valuelength;
01629 #elif defined(HAVE_ATTROPEN)
01630         ssize_t ret = -1;
01631         int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
01632         if (attrfd >= 0) {
01633                 ret = solaris_read_xattr(attrfd, value, size);
01634                 close(attrfd);
01635         }
01636         return ret;
01637 #else
01638         errno = ENOSYS;
01639         return -1;
01640 #endif
01641 }
01642 
01643 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
01644 {
01645 #if defined(HAVE_LGETXATTR)
01646         return lgetxattr(path, name, value, size);
01647 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
01648         int options = XATTR_NOFOLLOW;
01649         return getxattr(path, name, value, size, 0, options);
01650 #elif defined(HAVE_LGETEA)
01651         return lgetea(path, name, value, size);
01652 #elif defined(HAVE_EXTATTR_GET_LINK)
01653         char *s;
01654         ssize_t retval;
01655         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
01656                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
01657         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
01658 
01659         if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
01660                 if(retval > size) {
01661                         errno = ERANGE;
01662                         return -1;
01663                 }
01664                 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
01665                         return retval;
01666         }
01667         
01668         DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
01669         return -1;
01670 #elif defined(HAVE_ATTR_GET)
01671         int retval, flags = ATTR_DONTFOLLOW;
01672         int valuelength = (int)size;
01673         char *attrname = strchr(name,'.') + 1;
01674         
01675         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
01676 
01677         retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
01678 
01679         return retval ? retval : valuelength;
01680 #elif defined(HAVE_ATTROPEN)
01681         ssize_t ret = -1;
01682         int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
01683         if (attrfd >= 0) {
01684                 ret = solaris_read_xattr(attrfd, value, size);
01685                 close(attrfd);
01686         }
01687         return ret;
01688 #else
01689         errno = ENOSYS;
01690         return -1;
01691 #endif
01692 }
01693 
01694 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
01695 {
01696 #if defined(HAVE_FGETXATTR)
01697 #ifndef XATTR_ADD_OPT
01698         return fgetxattr(filedes, name, value, size);
01699 #else
01700         int options = 0;
01701         return fgetxattr(filedes, name, value, size, 0, options);
01702 #endif
01703 #elif defined(HAVE_FGETEA)
01704         return fgetea(filedes, name, value, size);
01705 #elif defined(HAVE_EXTATTR_GET_FD)
01706         char *s;
01707         ssize_t retval;
01708         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
01709                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
01710         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
01711 
01712         if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
01713                 if(retval > size) {
01714                         errno = ERANGE;
01715                         return -1;
01716                 }
01717                 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
01718                         return retval;
01719         }
01720         
01721         DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
01722         return -1;
01723 #elif defined(HAVE_ATTR_GETF)
01724         int retval, flags = 0;
01725         int valuelength = (int)size;
01726         char *attrname = strchr(name,'.') + 1;
01727         
01728         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
01729 
01730         retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
01731 
01732         return retval ? retval : valuelength;
01733 #elif defined(HAVE_ATTROPEN)
01734         ssize_t ret = -1;
01735         int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
01736         if (attrfd >= 0) {
01737                 ret = solaris_read_xattr(attrfd, value, size);
01738                 close(attrfd);
01739         }
01740         return ret;
01741 #else
01742         errno = ENOSYS;
01743         return -1;
01744 #endif
01745 }
01746 
01747 #if defined(HAVE_EXTATTR_LIST_FILE)
01748 
01749 #define EXTATTR_PREFIX(s)       (s), (sizeof((s))-1)
01750 
01751 static struct {
01752         int space;
01753         const char *name;
01754         size_t len;
01755 } 
01756 extattr[] = {
01757         { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
01758         { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
01759 };
01760 
01761 typedef union {
01762         const char *path;
01763         int filedes;
01764 } extattr_arg;
01765 
01766 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
01767 {
01768         ssize_t list_size, total_size = 0;
01769         int i, t, len;
01770         char *buf;
01771         /* Iterate through extattr(2) namespaces */
01772         for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
01773                 switch(type) {
01774 #if defined(HAVE_EXTATTR_LIST_FILE)
01775                         case 0:
01776                                 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
01777                                 break;
01778 #endif
01779 #if defined(HAVE_EXTATTR_LIST_LINK)
01780                         case 1:
01781                                 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
01782                                 break;
01783 #endif
01784 #if defined(HAVE_EXTATTR_LIST_FD)
01785                         case 2:
01786                                 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
01787                                 break;
01788 #endif
01789                         default:
01790                                 errno = ENOSYS;
01791                                 return -1;
01792                 }
01793                 /* Some error happend. Errno should be set by the previous call */
01794                 if(list_size < 0)
01795                         return -1;
01796                 /* No attributes */
01797                 if(list_size == 0)
01798                         continue;
01799                 /* XXX: Call with an empty buffer may be used to calculate
01800                    necessary buffer size. Unfortunately, we can't say, how
01801                    many attributes were returned, so here is the potential
01802                    problem with the emulation.
01803                 */
01804                 if(list == NULL) {
01805                         /* Take the worse case of one char attribute names - 
01806                            two bytes per name plus one more for sanity.
01807                         */
01808                         total_size += list_size + (list_size/2 + 1)*extattr[t].len;
01809                         continue;
01810                 }
01811                 /* Count necessary offset to fit namespace prefixes */
01812                 len = 0;
01813                 for(i = 0; i < list_size; i += list[i] + 1)
01814                         len += extattr[t].len;
01815 
01816                 total_size += list_size + len;
01817                 /* Buffer is too small to fit the results */
01818                 if(total_size > size) {
01819                         errno = ERANGE;
01820                         return -1;
01821                 }
01822                 /* Shift results back, so we can prepend prefixes */
01823                 buf = memmove(list + len, list, list_size);
01824 
01825                 for(i = 0; i < list_size; i += len + 1) {
01826                         len = buf[i];
01827                         strncpy(list, extattr[t].name, extattr[t].len + 1);
01828                         list += extattr[t].len;
01829                         strncpy(list, buf + i + 1, len);
01830                         list[len] = '\0';
01831                         list += len + 1;
01832                 }
01833                 size -= total_size;
01834         }
01835         return total_size;
01836 }
01837 
01838 #endif
01839 
01840 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
01841 static char attr_buffer[ATTR_MAX_VALUELEN];
01842 
01843 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
01844 {
01845         int retval = 0, index;
01846         attrlist_cursor_t *cursor = 0;
01847         int total_size = 0;
01848         attrlist_t * al = (attrlist_t *)attr_buffer;
01849         attrlist_ent_t *ae;
01850         size_t ent_size, left = size;
01851         char *bp = list;
01852 
01853         while (True) {
01854             if (filedes)
01855                 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
01856             else
01857                 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
01858             if (retval) break;
01859             for (index = 0; index < al->al_count; index++) {
01860                 ae = ATTR_ENTRY(attr_buffer, index);
01861                 ent_size = strlen(ae->a_name) + sizeof("user.");
01862                 if (left >= ent_size) {
01863                     strncpy(bp, "user.", sizeof("user."));
01864                     strncat(bp, ae->a_name, ent_size - sizeof("user."));
01865                     bp += ent_size;
01866                     left -= ent_size;
01867                 } else if (size) {
01868                     errno = ERANGE;
01869                     retval = -1;
01870                     break;
01871                 }
01872                 total_size += ent_size;
01873             }
01874             if (al->al_more == 0) break;
01875         }
01876         if (retval == 0) {
01877             flags |= ATTR_ROOT;
01878             cursor = 0;
01879             while (True) {
01880                 if (filedes)
01881                     retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
01882                 else
01883                     retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
01884                 if (retval) break;
01885                 for (index = 0; index < al->al_count; index++) {
01886                     ae = ATTR_ENTRY(attr_buffer, index);
01887                     ent_size = strlen(ae->a_name) + sizeof("system.");
01888                     if (left >= ent_size) {
01889                         strncpy(bp, "system.", sizeof("system."));
01890                         strncat(bp, ae->a_name, ent_size - sizeof("system."));
01891                         bp += ent_size;
01892                         left -= ent_size;
01893                     } else if (size) {
01894                         errno = ERANGE;
01895                         retval = -1;
01896                         break;
01897                     }
01898                     total_size += ent_size;
01899                 }
01900                 if (al->al_more == 0) break;
01901             }
01902         }
01903         return (ssize_t)(retval ? retval : total_size);
01904 }
01905 
01906 #endif
01907 
01908 ssize_t sys_listxattr (const char *path, char *list, size_t size)
01909 {
01910 #if defined(HAVE_LISTXATTR)
01911 #ifndef XATTR_ADD_OPT
01912         return listxattr(path, list, size);
01913 #else
01914         int options = 0;
01915         return listxattr(path, list, size, options);
01916 #endif
01917 #elif defined(HAVE_LISTEA)
01918         return listea(path, list, size);
01919 #elif defined(HAVE_EXTATTR_LIST_FILE)
01920         extattr_arg arg;
01921         arg.path = path;
01922         return bsd_attr_list(0, arg, list, size);
01923 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
01924         return irix_attr_list(path, 0, list, size, 0);
01925 #elif defined(HAVE_ATTROPEN)
01926         ssize_t ret = -1;
01927         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
01928         if (attrdirfd >= 0) {
01929                 ret = solaris_list_xattr(attrdirfd, list, size);
01930                 close(attrdirfd);
01931         }
01932         return ret;
01933 #else
01934         errno = ENOSYS;
01935         return -1;
01936 #endif
01937 }
01938 
01939 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
01940 {
01941 #if defined(HAVE_LLISTXATTR)
01942         return llistxattr(path, list, size);
01943 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
01944         int options = XATTR_NOFOLLOW;
01945         return listxattr(path, list, size, options);
01946 #elif defined(HAVE_LLISTEA)
01947         return llistea(path, list, size);
01948 #elif defined(HAVE_EXTATTR_LIST_LINK)
01949         extattr_arg arg;
01950         arg.path = path;
01951         return bsd_attr_list(1, arg, list, size);
01952 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
01953         return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
01954 #elif defined(HAVE_ATTROPEN)
01955         ssize_t ret = -1;
01956         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
01957         if (attrdirfd >= 0) {
01958                 ret = solaris_list_xattr(attrdirfd, list, size);
01959                 close(attrdirfd);
01960         }
01961         return ret;
01962 #else
01963         errno = ENOSYS;
01964         return -1;
01965 #endif
01966 }
01967 
01968 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
01969 {
01970 #if defined(HAVE_FLISTXATTR)
01971 #ifndef XATTR_ADD_OPT
01972         return flistxattr(filedes, list, size);
01973 #else
01974         int options = 0;
01975         return flistxattr(filedes, list, size, options);
01976 #endif
01977 #elif defined(HAVE_FLISTEA)
01978         return flistea(filedes, list, size);
01979 #elif defined(HAVE_EXTATTR_LIST_FD)
01980         extattr_arg arg;
01981         arg.filedes = filedes;
01982         return bsd_attr_list(2, arg, list, size);
01983 #elif defined(HAVE_ATTR_LISTF)
01984         return irix_attr_list(NULL, filedes, list, size, 0);
01985 #elif defined(HAVE_ATTROPEN)
01986         ssize_t ret = -1;
01987         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
01988         if (attrdirfd >= 0) {
01989                 ret = solaris_list_xattr(attrdirfd, list, size);
01990                 close(attrdirfd);
01991         }
01992         return ret;
01993 #else
01994         errno = ENOSYS;
01995         return -1;
01996 #endif
01997 }
01998 
01999 int sys_removexattr (const char *path, const char *name)
02000 {
02001 #if defined(HAVE_REMOVEXATTR)
02002 #ifndef XATTR_ADD_OPT
02003         return removexattr(path, name);
02004 #else
02005         int options = 0;
02006         return removexattr(path, name, options);
02007 #endif
02008 #elif defined(HAVE_REMOVEEA)
02009         return removeea(path, name);
02010 #elif defined(HAVE_EXTATTR_DELETE_FILE)
02011         char *s;
02012         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
02013                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
02014         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
02015 
02016         return extattr_delete_file(path, attrnamespace, attrname);
02017 #elif defined(HAVE_ATTR_REMOVE)
02018         int flags = 0;
02019         char *attrname = strchr(name,'.') + 1;
02020         
02021         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
02022 
02023         return attr_remove(path, attrname, flags);
02024 #elif defined(HAVE_ATTROPEN)
02025         int ret = -1;
02026         int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
02027         if (attrdirfd >= 0) {
02028                 ret = solaris_unlinkat(attrdirfd, name);
02029                 close(attrdirfd);
02030         }
02031         return ret;
02032 #else
02033         errno = ENOSYS;
02034         return -1;
02035 #endif
02036 }
02037 
02038 int sys_lremovexattr (const char *path, const char *name)
02039 {
02040 #if defined(HAVE_LREMOVEXATTR)
02041         return lremovexattr(path, name);
02042 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
02043         int options = XATTR_NOFOLLOW;
02044         return removexattr(path, name, options);
02045 #elif defined(HAVE_LREMOVEEA)
02046         return lremoveea(path, name);
02047 #elif defined(HAVE_EXTATTR_DELETE_LINK)
02048         char *s;
02049         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
02050                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
02051         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
02052 
02053         return extattr_delete_link(path, attrnamespace, attrname);
02054 #elif defined(HAVE_ATTR_REMOVE)
02055         int flags = ATTR_DONTFOLLOW;
02056         char *attrname = strchr(name,'.') + 1;
02057         
02058         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
02059 
02060         return attr_remove(path, attrname, flags);
02061 #elif defined(HAVE_ATTROPEN)
02062         int ret = -1;
02063         int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
02064         if (attrdirfd >= 0) {
02065                 ret = solaris_unlinkat(attrdirfd, name);
02066                 close(attrdirfd);
02067         }
02068         return ret;
02069 #else
02070         errno = ENOSYS;
02071         return -1;
02072 #endif
02073 }
02074 
02075 int sys_fremovexattr (int filedes, const char *name)
02076 {
02077 #if defined(HAVE_FREMOVEXATTR)
02078 #ifndef XATTR_ADD_OPT
02079         return fremovexattr(filedes, name);
02080 #else
02081         int options = 0;
02082         return fremovexattr(filedes, name, options);
02083 #endif
02084 #elif defined(HAVE_FREMOVEEA)
02085         return fremoveea(filedes, name);
02086 #elif defined(HAVE_EXTATTR_DELETE_FD)
02087         char *s;
02088         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
02089                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
02090         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
02091 
02092         return extattr_delete_fd(filedes, attrnamespace, attrname);
02093 #elif defined(HAVE_ATTR_REMOVEF)
02094         int flags = 0;
02095         char *attrname = strchr(name,'.') + 1;
02096         
02097         if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
02098 
02099         return attr_removef(filedes, attrname, flags);
02100 #elif defined(HAVE_ATTROPEN)
02101         int ret = -1;
02102         int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
02103         if (attrdirfd >= 0) {
02104                 ret = solaris_unlinkat(attrdirfd, name);
02105                 close(attrdirfd);
02106         }
02107         return ret;
02108 #else
02109         errno = ENOSYS;
02110         return -1;
02111 #endif
02112 }
02113 
02114 #if !defined(HAVE_SETXATTR)
02115 #define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
02116 #define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
02117 #endif
02118 
02119 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
02120 {
02121 #if defined(HAVE_SETXATTR)
02122 #ifndef XATTR_ADD_OPT
02123         return setxattr(path, name, value, size, flags);
02124 #else
02125         int options = 0;
02126         return setxattr(path, name, value, size, 0, options);
02127 #endif
02128 #elif defined(HAVE_SETEA)
02129         return setea(path, name, value, size, flags);
02130 #elif defined(HAVE_EXTATTR_SET_FILE)
02131         char *s;
02132         int retval = 0;
02133         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
02134                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
02135         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
02136         if (flags) {
02137                 /* Check attribute existence */
02138                 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
02139                 if (retval < 0) {
02140                         /* REPLACE attribute, that doesn't exist */
02141                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
02142                                 errno = ENOATTR;
02143                                 return -1;
02144                         }
02145                         /* Ignore other errors */
02146                 }
02147                 else {
02148                         /* CREATE attribute, that already exists */
02149                         if (flags & XATTR_CREATE) {
02150                                 errno = EEXIST;
02151                                 return -1;
02152                         }
02153                 }
02154         }
02155         retval = extattr_set_file(path, attrnamespace, attrname, value, size);
02156         return (retval < 0) ? -1 : 0;
02157 #elif defined(HAVE_ATTR_SET)
02158         int myflags = 0;
02159         char *attrname = strchr(name,'.') + 1;
02160         
02161         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
02162         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
02163         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
02164 
02165         return attr_set(path, attrname, (const char *)value, size, myflags);
02166 #elif defined(HAVE_ATTROPEN)
02167         int ret = -1;
02168         int myflags = O_RDWR;
02169         int attrfd;
02170         if (flags & XATTR_CREATE) myflags |= O_EXCL;
02171         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
02172         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
02173         if (attrfd >= 0) {
02174                 ret = solaris_write_xattr(attrfd, value, size);
02175                 close(attrfd);
02176         }
02177         return ret;
02178 #else
02179         errno = ENOSYS;
02180         return -1;
02181 #endif
02182 }
02183 
02184 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
02185 {
02186 #if defined(HAVE_LSETXATTR)
02187         return lsetxattr(path, name, value, size, flags);
02188 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
02189         int options = XATTR_NOFOLLOW;
02190         return setxattr(path, name, value, size, 0, options);
02191 #elif defined(LSETEA)
02192         return lsetea(path, name, value, size, flags);
02193 #elif defined(HAVE_EXTATTR_SET_LINK)
02194         char *s;
02195         int retval = 0;
02196         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
02197                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
02198         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
02199         if (flags) {
02200                 /* Check attribute existence */
02201                 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
02202                 if (retval < 0) {
02203                         /* REPLACE attribute, that doesn't exist */
02204                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
02205                                 errno = ENOATTR;
02206                                 return -1;
02207                         }
02208                         /* Ignore other errors */
02209                 }
02210                 else {
02211                         /* CREATE attribute, that already exists */
02212                         if (flags & XATTR_CREATE) {
02213                                 errno = EEXIST;
02214                                 return -1;
02215                         }
02216                 }
02217         }
02218 
02219         retval = extattr_set_link(path, attrnamespace, attrname, value, size);
02220         return (retval < 0) ? -1 : 0;
02221 #elif defined(HAVE_ATTR_SET)
02222         int myflags = ATTR_DONTFOLLOW;
02223         char *attrname = strchr(name,'.') + 1;
02224         
02225         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
02226         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
02227         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
02228 
02229         return attr_set(path, attrname, (const char *)value, size, myflags);
02230 #elif defined(HAVE_ATTROPEN)
02231         int ret = -1;
02232         int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
02233         int attrfd;
02234         if (flags & XATTR_CREATE) myflags |= O_EXCL;
02235         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
02236         attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
02237         if (attrfd >= 0) {
02238                 ret = solaris_write_xattr(attrfd, value, size);
02239                 close(attrfd);
02240         }
02241         return ret;
02242 #else
02243         errno = ENOSYS;
02244         return -1;
02245 #endif
02246 }
02247 
02248 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
02249 {
02250 #if defined(HAVE_FSETXATTR)
02251 #ifndef XATTR_ADD_OPT
02252         return fsetxattr(filedes, name, value, size, flags);
02253 #else
02254         int options = 0;
02255         return fsetxattr(filedes, name, value, size, 0, options);
02256 #endif
02257 #elif defined(HAVE_FSETEA)
02258         return fsetea(filedes, name, value, size, flags);
02259 #elif defined(HAVE_EXTATTR_SET_FD)
02260         char *s;
02261         int retval = 0;
02262         int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
02263                 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
02264         const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
02265         if (flags) {
02266                 /* Check attribute existence */
02267                 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
02268                 if (retval < 0) {
02269                         /* REPLACE attribute, that doesn't exist */
02270                         if (flags & XATTR_REPLACE && errno == ENOATTR) {
02271                                 errno = ENOATTR;
02272                                 return -1;
02273                         }
02274                         /* Ignore other errors */
02275                 }
02276                 else {
02277                         /* CREATE attribute, that already exists */
02278                         if (flags & XATTR_CREATE) {
02279                                 errno = EEXIST;
02280                                 return -1;
02281                         }
02282                 }
02283         }
02284         retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
02285         return (retval < 0) ? -1 : 0;
02286 #elif defined(HAVE_ATTR_SETF)
02287         int myflags = 0;
02288         char *attrname = strchr(name,'.') + 1;
02289         
02290         if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
02291         if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
02292         if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
02293 
02294         return attr_setf(filedes, attrname, (const char *)value, size, myflags);
02295 #elif defined(HAVE_ATTROPEN)
02296         int ret = -1;
02297         int myflags = O_RDWR | O_XATTR;
02298         int attrfd;
02299         if (flags & XATTR_CREATE) myflags |= O_EXCL;
02300         if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
02301         attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
02302         if (attrfd >= 0) {
02303                 ret = solaris_write_xattr(attrfd, value, size);
02304                 close(attrfd);
02305         }
02306         return ret;
02307 #else
02308         errno = ENOSYS;
02309         return -1;
02310 #endif
02311 }
02312 
02313 /**************************************************************************
02314  helper functions for Solaris' EA support
02315 ****************************************************************************/
02316 #ifdef HAVE_ATTROPEN
02317 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
02318 {
02319         struct stat sbuf;
02320 
02321         if (fstat(attrfd, &sbuf) == -1) {
02322                 errno = ENOATTR;
02323                 return -1;
02324         }
02325 
02326         /* This is to return the current size of the named extended attribute */
02327         if (size == 0) {
02328                 return sbuf.st_size;
02329         }
02330 
02331         /* check size and read xattr */
02332         if (sbuf.st_size > size) {
02333                 errno = ERANGE;
02334                 return -1;
02335         }
02336 
02337         return read(attrfd, value, sbuf.st_size);
02338 }
02339 
02340 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
02341 {
02342         ssize_t len = 0;
02343         int stop = 0;
02344         DIR *dirp;
02345         struct dirent *de;
02346         int newfd = dup(attrdirfd);
02347         /* CAUTION: The originating file descriptor should not be
02348                     used again following the call to fdopendir().
02349                     For that reason we dup() the file descriptor
02350                     here to make things more clear. */
02351         dirp = fdopendir(newfd);
02352 
02353         while ((de = readdir(dirp))) {
02354                 size_t listlen = strlen(de->d_name);
02355                 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
02356                         /* we don't want "." and ".." here: */
02357                         DEBUG(10,("skipped EA %s\n",de->d_name));
02358                         continue;
02359                 }
02360 
02361                 if (size == 0) {
02362                         /* return the current size of the list of extended attribute names*/
02363                         len += listlen + 1;
02365                         /* check size and copy entrie02364                 } else {