r6334: revert 3.0.15pre1 changes. roll back to 3.0.14.
[Samba.git] / source / lib / system.c
blob7434cbe35eea878021fa5bc3b7430b21629ebfc4
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2002
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
25 The idea is that this file will eventually have wrappers around all
26 important system calls in samba. The aims are:
28 - to enable easier porting by putting OS dependent stuff in here
30 - to allow for hooks into other "pseudo-filesystems"
32 - to allow easier integration of things like the japanese extensions
34 - to support the philosophy of Samba to expose the features of
35 the OS within the SMB model. In general whatever file/printer/variable
36 expansions/etc make sense to the OS should be acceptable to Samba.
41 /*******************************************************************
42 A wrapper for usleep in case we don't have one.
43 ********************************************************************/
45 int sys_usleep(long usecs)
47 #ifndef HAVE_USLEEP
48 struct timeval tval;
49 #endif
52 * We need this braindamage as the glibc usleep
53 * is not SPEC1170 complient... grumble... JRA.
56 if(usecs < 0 || usecs > 1000000) {
57 errno = EINVAL;
58 return -1;
61 #if HAVE_USLEEP
62 usleep(usecs);
63 return 0;
64 #else /* HAVE_USLEEP */
66 * Fake it with select...
68 tval.tv_sec = 0;
69 tval.tv_usec = usecs/1000;
70 select(0,NULL,NULL,NULL,&tval);
71 return 0;
72 #endif /* HAVE_USLEEP */
75 /*******************************************************************
76 A read wrapper that will deal with EINTR.
77 ********************************************************************/
79 ssize_t sys_read(int fd, void *buf, size_t count)
81 ssize_t ret;
83 do {
84 ret = read(fd, buf, count);
85 } while (ret == -1 && errno == EINTR);
86 return ret;
89 /*******************************************************************
90 A write wrapper that will deal with EINTR.
91 ********************************************************************/
93 ssize_t sys_write(int fd, const void *buf, size_t count)
95 ssize_t ret;
97 do {
98 ret = write(fd, buf, count);
99 } while (ret == -1 && errno == EINTR);
100 return ret;
104 /*******************************************************************
105 A pread wrapper that will deal with EINTR and 64-bit file offsets.
106 ********************************************************************/
108 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
109 ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off)
111 ssize_t ret;
113 do {
114 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
115 ret = pread64(fd, buf, count, off);
116 #else
117 ret = pread(fd, buf, count, off);
118 #endif
119 } while (ret == -1 && errno == EINTR);
120 return ret;
122 #endif
124 /*******************************************************************
125 A write wrapper that will deal with EINTR and 64-bit file offsets.
126 ********************************************************************/
128 #if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
129 ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off)
131 ssize_t ret;
133 do {
134 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
135 ret = pwrite64(fd, buf, count, off);
136 #else
137 ret = pwrite(fd, buf, count, off);
138 #endif
139 } while (ret == -1 && errno == EINTR);
140 return ret;
142 #endif
144 /*******************************************************************
145 A send wrapper that will deal with EINTR.
146 ********************************************************************/
148 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
150 ssize_t ret;
152 do {
153 ret = send(s, msg, len, flags);
154 } while (ret == -1 && errno == EINTR);
155 return ret;
158 /*******************************************************************
159 A sendto wrapper that will deal with EINTR.
160 ********************************************************************/
162 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
164 ssize_t ret;
166 do {
167 ret = sendto(s, msg, len, flags, to, tolen);
168 } while (ret == -1 && errno == EINTR);
169 return ret;
172 /*******************************************************************
173 A recvfrom wrapper that will deal with EINTR.
174 ********************************************************************/
176 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
178 ssize_t ret;
180 do {
181 ret = recvfrom(s, buf, len, flags, from, fromlen);
182 } while (ret == -1 && errno == EINTR);
183 return ret;
186 /*******************************************************************
187 A fcntl wrapper that will deal with EINTR.
188 ********************************************************************/
190 int sys_fcntl_ptr(int fd, int cmd, void *arg)
192 int ret;
194 do {
195 ret = fcntl(fd, cmd, arg);
196 } while (ret == -1 && errno == EINTR);
197 return ret;
200 /*******************************************************************
201 A fcntl wrapper that will deal with EINTR.
202 ********************************************************************/
204 int sys_fcntl_long(int fd, int cmd, long arg)
206 int ret;
208 do {
209 ret = fcntl(fd, cmd, arg);
210 } while (ret == -1 && errno == EINTR);
211 return ret;
214 /*******************************************************************
215 A stat() wrapper that will deal with 64 bit filesizes.
216 ********************************************************************/
218 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
220 int ret;
221 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
222 ret = stat64(fname, sbuf);
223 #else
224 ret = stat(fname, sbuf);
225 #endif
226 /* we always want directories to appear zero size */
227 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
228 return ret;
231 /*******************************************************************
232 An fstat() wrapper that will deal with 64 bit filesizes.
233 ********************************************************************/
235 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
237 int ret;
238 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
239 ret = fstat64(fd, sbuf);
240 #else
241 ret = fstat(fd, sbuf);
242 #endif
243 /* we always want directories to appear zero size */
244 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
245 return ret;
248 /*******************************************************************
249 An lstat() wrapper that will deal with 64 bit filesizes.
250 ********************************************************************/
252 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
254 int ret;
255 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
256 ret = lstat64(fname, sbuf);
257 #else
258 ret = lstat(fname, sbuf);
259 #endif
260 /* we always want directories to appear zero size */
261 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
262 return ret;
265 /*******************************************************************
266 An ftruncate() wrapper that will deal with 64 bit filesizes.
267 ********************************************************************/
269 int sys_ftruncate(int fd, SMB_OFF_T offset)
271 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
272 return ftruncate64(fd, offset);
273 #else
274 return ftruncate(fd, offset);
275 #endif
278 /*******************************************************************
279 An lseek() wrapper that will deal with 64 bit filesizes.
280 ********************************************************************/
282 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
284 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
285 return lseek64(fd, offset, whence);
286 #else
287 return lseek(fd, offset, whence);
288 #endif
291 /*******************************************************************
292 An fseek() wrapper that will deal with 64 bit filesizes.
293 ********************************************************************/
295 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
297 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
298 return fseek64(fp, offset, whence);
299 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
300 return fseeko64(fp, offset, whence);
301 #else
302 return fseek(fp, offset, whence);
303 #endif
306 /*******************************************************************
307 An ftell() wrapper that will deal with 64 bit filesizes.
308 ********************************************************************/
310 SMB_OFF_T sys_ftell(FILE *fp)
312 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
313 return (SMB_OFF_T)ftell64(fp);
314 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
315 return (SMB_OFF_T)ftello64(fp);
316 #else
317 return (SMB_OFF_T)ftell(fp);
318 #endif
321 /*******************************************************************
322 A creat() wrapper that will deal with 64 bit filesizes.
323 ********************************************************************/
325 int sys_creat(const char *path, mode_t mode)
327 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
328 return creat64(path, mode);
329 #else
331 * If creat64 isn't defined then ensure we call a potential open64.
332 * JRA.
334 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
335 #endif
338 /*******************************************************************
339 An open() wrapper that will deal with 64 bit filesizes.
340 ********************************************************************/
342 int sys_open(const char *path, int oflag, mode_t mode)
344 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
345 return open64(path, oflag, mode);
346 #else
347 return open(path, oflag, mode);
348 #endif
351 /*******************************************************************
352 An fopen() wrapper that will deal with 64 bit filesizes.
353 ********************************************************************/
355 FILE *sys_fopen(const char *path, const char *type)
357 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
358 return fopen64(path, type);
359 #else
360 return fopen(path, type);
361 #endif
364 /*******************************************************************
365 An opendir wrapper that will deal with 64 bit filesizes.
366 ********************************************************************/
368 DIR *sys_opendir(const char *name)
370 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
371 return opendir64(name);
372 #else
373 return opendir(name);
374 #endif
377 /*******************************************************************
378 A readdir wrapper that will deal with 64 bit filesizes.
379 ********************************************************************/
381 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
383 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
384 return readdir64(dirp);
385 #else
386 return readdir(dirp);
387 #endif
390 /*******************************************************************
391 A seekdir wrapper that will deal with 64 bit filesizes.
392 ********************************************************************/
394 void sys_seekdir(DIR *dirp, long offset)
396 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
397 seekdir64(dirp, offset);
398 #else
399 seekdir(dirp, offset);
400 #endif
403 /*******************************************************************
404 A telldir wrapper that will deal with 64 bit filesizes.
405 ********************************************************************/
407 long sys_telldir(DIR *dirp)
409 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
410 return (long)telldir64(dirp);
411 #else
412 return (long)telldir(dirp);
413 #endif
416 /*******************************************************************
417 A rewinddir wrapper that will deal with 64 bit filesizes.
418 ********************************************************************/
420 void sys_rewinddir(DIR *dirp)
422 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
423 rewinddir64(dirp);
424 #else
425 rewinddir(dirp);
426 #endif
429 /*******************************************************************
430 A close wrapper that will deal with 64 bit filesizes.
431 ********************************************************************/
433 int sys_closedir(DIR *dirp)
435 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
436 return closedir64(dirp);
437 #else
438 return closedir(dirp);
439 #endif
442 /*******************************************************************
443 An mknod() wrapper that will deal with 64 bit filesizes.
444 ********************************************************************/
446 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
448 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
449 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
450 return mknod64(path, mode, dev);
451 #else
452 return mknod(path, mode, dev);
453 #endif
454 #else
455 /* No mknod system call. */
456 errno = ENOSYS;
457 return -1;
458 #endif
461 /*******************************************************************
462 Wrapper for realpath.
463 ********************************************************************/
465 char *sys_realpath(const char *path, char *resolved_path)
467 #if defined(HAVE_REALPATH)
468 return realpath(path, resolved_path);
469 #else
470 /* As realpath is not a system call we can't return ENOSYS. */
471 errno = EINVAL;
472 return NULL;
473 #endif
476 /*******************************************************************
477 The wait() calls vary between systems
478 ********************************************************************/
480 int sys_waitpid(pid_t pid,int *status,int options)
482 #ifdef HAVE_WAITPID
483 return waitpid(pid,status,options);
484 #else /* HAVE_WAITPID */
485 return wait4(pid, status, options, NULL);
486 #endif /* HAVE_WAITPID */
489 /*******************************************************************
490 System wrapper for getwd
491 ********************************************************************/
493 char *sys_getwd(char *s)
495 char *wd;
496 #ifdef HAVE_GETCWD
497 wd = (char *)getcwd(s, sizeof (pstring));
498 #else
499 wd = (char *)getwd(s);
500 #endif
501 return wd;
504 /*******************************************************************
505 system wrapper for symlink
506 ********************************************************************/
508 int sys_symlink(const char *oldpath, const char *newpath)
510 #ifndef HAVE_SYMLINK
511 errno = ENOSYS;
512 return -1;
513 #else
514 return symlink(oldpath, newpath);
515 #endif
518 /*******************************************************************
519 system wrapper for readlink
520 ********************************************************************/
522 int sys_readlink(const char *path, char *buf, size_t bufsiz)
524 #ifndef HAVE_READLINK
525 errno = ENOSYS;
526 return -1;
527 #else
528 return readlink(path, buf, bufsiz);
529 #endif
532 /*******************************************************************
533 system wrapper for link
534 ********************************************************************/
536 int sys_link(const char *oldpath, const char *newpath)
538 #ifndef HAVE_LINK
539 errno = ENOSYS;
540 return -1;
541 #else
542 return link(oldpath, newpath);
543 #endif
546 /*******************************************************************
547 chown isn't used much but OS/2 doesn't have it
548 ********************************************************************/
550 int sys_chown(const char *fname,uid_t uid,gid_t gid)
552 #ifndef HAVE_CHOWN
553 static int done;
554 if (!done) {
555 DEBUG(1,("WARNING: no chown!\n"));
556 done=1;
558 errno = ENOSYS;
559 return -1;
560 #else
561 return(chown(fname,uid,gid));
562 #endif
565 /*******************************************************************
566 os/2 also doesn't have chroot
567 ********************************************************************/
568 int sys_chroot(const char *dname)
570 #ifndef HAVE_CHROOT
571 static int done;
572 if (!done) {
573 DEBUG(1,("WARNING: no chroot!\n"));
574 done=1;
576 errno = ENOSYS;
577 return -1;
578 #else
579 return(chroot(dname));
580 #endif
583 /**************************************************************************
584 A wrapper for gethostbyname() that tries avoids looking up hostnames
585 in the root domain, which can cause dial-on-demand links to come up for no
586 apparent reason.
587 ****************************************************************************/
589 struct hostent *sys_gethostbyname(const char *name)
591 #ifdef REDUCE_ROOT_DNS_LOOKUPS
592 char query[256], hostname[256];
593 char *domain;
595 /* Does this name have any dots in it? If so, make no change */
597 if (strchr_m(name, '.'))
598 return(gethostbyname(name));
600 /* Get my hostname, which should have domain name
601 attached. If not, just do the gethostname on the
602 original string.
605 gethostname(hostname, sizeof(hostname) - 1);
606 hostname[sizeof(hostname) - 1] = 0;
607 if ((domain = strchr_m(hostname, '.')) == NULL)
608 return(gethostbyname(name));
610 /* Attach domain name to query and do modified query.
611 If names too large, just do gethostname on the
612 original string.
615 if((strlen(name) + strlen(domain)) >= sizeof(query))
616 return(gethostbyname(name));
618 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
619 return(gethostbyname(query));
620 #else /* REDUCE_ROOT_DNS_LOOKUPS */
621 return(gethostbyname(name));
622 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
626 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
627 /**************************************************************************
628 Try and abstract process capabilities (for systems that have them).
629 ****************************************************************************/
630 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
632 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
633 cap_t cap = cap_get_proc();
635 if (cap == NULL) {
636 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
637 strerror(errno)));
638 return False;
641 if(enable)
642 cap->cap_effective |= CAP_NETWORK_MGT;
643 else
644 cap->cap_effective &= ~CAP_NETWORK_MGT;
646 if (cap_set_proc(cap) == -1) {
647 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
648 strerror(errno)));
649 cap_free(cap);
650 return False;
653 cap_free(cap);
655 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
657 return True;
660 /**************************************************************************
661 Try and abstract inherited process capabilities (for systems that have them).
662 ****************************************************************************/
664 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
666 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
667 cap_t cap = cap_get_proc();
669 if (cap == NULL) {
670 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
671 strerror(errno)));
672 return False;
675 if(enable)
676 cap->cap_inheritable |= CAP_NETWORK_MGT;
677 else
678 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
680 if (cap_set_proc(cap) == -1) {
681 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
682 strerror(errno)));
683 cap_free(cap);
684 return False;
687 cap_free(cap);
689 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
691 return True;
693 #endif
695 /****************************************************************************
696 Gain the oplock capability from the kernel if possible.
697 ****************************************************************************/
699 void oplock_set_capability(BOOL this_process, BOOL inherit)
701 #if HAVE_KERNEL_OPLOCKS_IRIX
702 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
703 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
704 #endif
707 /**************************************************************************
708 Wrapper for random().
709 ****************************************************************************/
711 long sys_random(void)
713 #if defined(HAVE_RANDOM)
714 return (long)random();
715 #elif defined(HAVE_RAND)
716 return (long)rand();
717 #else
718 DEBUG(0,("Error - no random function available !\n"));
719 exit(1);
720 #endif
723 /**************************************************************************
724 Wrapper for srandom().
725 ****************************************************************************/
727 void sys_srandom(unsigned int seed)
729 #if defined(HAVE_SRANDOM)
730 srandom(seed);
731 #elif defined(HAVE_SRAND)
732 srand(seed);
733 #else
734 DEBUG(0,("Error - no srandom function available !\n"));
735 exit(1);
736 #endif
739 /**************************************************************************
740 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
741 ****************************************************************************/
743 int groups_max(void)
745 #if defined(SYSCONF_SC_NGROUPS_MAX)
746 int ret = sysconf(_SC_NGROUPS_MAX);
747 return (ret == -1) ? NGROUPS_MAX : ret;
748 #else
749 return NGROUPS_MAX;
750 #endif
753 /**************************************************************************
754 Wrapper for getgroups. Deals with broken (int) case.
755 ****************************************************************************/
757 int sys_getgroups(int setlen, gid_t *gidset)
759 #if !defined(HAVE_BROKEN_GETGROUPS)
760 return getgroups(setlen, gidset);
761 #else
763 GID_T gid;
764 GID_T *group_list;
765 int i, ngroups;
767 if(setlen == 0) {
768 return getgroups(setlen, &gid);
772 * Broken case. We need to allocate a
773 * GID_T array of size setlen.
776 if(setlen < 0) {
777 errno = EINVAL;
778 return -1;
781 if (setlen == 0)
782 setlen = groups_max();
784 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
785 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
786 return -1;
789 if((ngroups = getgroups(setlen, group_list)) < 0) {
790 int saved_errno = errno;
791 SAFE_FREE(group_list);
792 errno = saved_errno;
793 return -1;
796 for(i = 0; i < ngroups; i++)
797 gidset[i] = (gid_t)group_list[i];
799 SAFE_FREE(group_list);
800 return ngroups;
801 #endif /* HAVE_BROKEN_GETGROUPS */
805 /**************************************************************************
806 Wrapper for setgroups. Deals with broken (int) case. Automatically used
807 if we have broken getgroups.
808 ****************************************************************************/
810 int sys_setgroups(int setlen, gid_t *gidset)
812 #if !defined(HAVE_SETGROUPS)
813 errno = ENOSYS;
814 return -1;
815 #endif /* HAVE_SETGROUPS */
817 #if !defined(HAVE_BROKEN_GETGROUPS)
818 return setgroups(setlen, gidset);
819 #else
821 GID_T *group_list;
822 int i ;
824 if (setlen == 0)
825 return 0 ;
827 if (setlen < 0 || setlen > groups_max()) {
828 errno = EINVAL;
829 return -1;
833 * Broken case. We need to allocate a
834 * GID_T array of size setlen.
837 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
838 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
839 return -1;
842 for(i = 0; i < setlen; i++)
843 group_list[i] = (GID_T) gidset[i];
845 if(setgroups(setlen, group_list) != 0) {
846 int saved_errno = errno;
847 SAFE_FREE(group_list);
848 errno = saved_errno;
849 return -1;
852 SAFE_FREE(group_list);
853 return 0 ;
854 #endif /* HAVE_BROKEN_GETGROUPS */
857 /**************************************************************************
858 Wrappers for setpwent(), getpwent() and endpwent()
859 ****************************************************************************/
861 void sys_setpwent(void)
863 setpwent();
866 struct passwd *sys_getpwent(void)
868 return getpwent();
871 void sys_endpwent(void)
873 endpwent();
876 /**************************************************************************
877 Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
878 ****************************************************************************/
880 struct passwd *sys_getpwnam(const char *name)
882 return getpwnam(name);
885 struct passwd *sys_getpwuid(uid_t uid)
887 return getpwuid(uid);
890 struct group *sys_getgrnam(const char *name)
892 return getgrnam(name);
895 struct group *sys_getgrgid(gid_t gid)
897 return getgrgid(gid);
900 #if 0 /* NOT CURRENTLY USED - JRA */
901 /**************************************************************************
902 The following are the UNICODE versions of *all* system interface functions
903 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
904 which currently are left as ascii as they are not used other than in name
905 resolution.
906 ****************************************************************************/
908 /**************************************************************************
909 Wide stat. Just narrow and call sys_xxx.
910 ****************************************************************************/
912 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
914 pstring fname;
915 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
918 /**************************************************************************
919 Wide lstat. Just narrow and call sys_xxx.
920 ****************************************************************************/
922 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
924 pstring fname;
925 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
928 /**************************************************************************
929 Wide creat. Just narrow and call sys_xxx.
930 ****************************************************************************/
932 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
934 pstring fname;
935 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
938 /**************************************************************************
939 Wide open. Just narrow and call sys_xxx.
940 ****************************************************************************/
942 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
944 pstring fname;
945 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
948 /**************************************************************************
949 Wide fopen. Just narrow and call sys_xxx.
950 ****************************************************************************/
952 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
954 pstring fname;
955 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
958 /**************************************************************************
959 Wide opendir. Just narrow and call sys_xxx.
960 ****************************************************************************/
962 DIR *wsys_opendir(const smb_ucs2_t *wfname)
964 pstring fname;
965 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
968 /**************************************************************************
969 Wide readdir. Return a structure pointer containing a wide filename.
970 ****************************************************************************/
972 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
974 static SMB_STRUCT_WDIRENT retval;
975 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
977 if(!dirval)
978 return NULL;
981 * The only POSIX defined member of this struct is d_name.
984 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
986 return &retval;
989 /**************************************************************************
990 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
991 ****************************************************************************/
993 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
995 pstring fname;
996 char *p = sys_getwd(fname);
998 if(!p)
999 return NULL;
1001 return unix_to_unicode(s, p, sizeof(wpstring));
1004 /**************************************************************************
1005 Wide chown. Just narrow and call sys_xxx.
1006 ****************************************************************************/
1008 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
1010 pstring fname;
1011 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
1014 /**************************************************************************
1015 Wide chroot. Just narrow and call sys_xxx.
1016 ****************************************************************************/
1018 int wsys_chroot(const smb_ucs2_t *wfname)
1020 pstring fname;
1021 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
1024 /**************************************************************************
1025 Wide getpwnam. Return a structure pointer containing wide names.
1026 ****************************************************************************/
1028 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1030 static SMB_STRUCT_WPASSWD retval;
1031 fstring name;
1032 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1034 if(!pwret)
1035 return NULL;
1037 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1038 retval.pw_passwd = pwret->pw_passwd;
1039 retval.pw_uid = pwret->pw_uid;
1040 retval.pw_gid = pwret->pw_gid;
1041 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1042 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1043 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1045 return &retval;
1048 /**************************************************************************
1049 Wide getpwuid. Return a structure pointer containing wide names.
1050 ****************************************************************************/
1052 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1054 static SMB_STRUCT_WPASSWD retval;
1055 struct passwd *pwret = sys_getpwuid(uid);
1057 if(!pwret)
1058 return NULL;
1060 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1061 retval.pw_passwd = pwret->pw_passwd;
1062 retval.pw_uid = pwret->pw_uid;
1063 retval.pw_gid = pwret->pw_gid;
1064 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1065 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1066 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1068 return &retval;
1070 #endif /* NOT CURRENTLY USED - JRA */
1072 /**************************************************************************
1073 Extract a command into an arg list. Uses a static pstring for storage.
1074 Caller frees returned arg list (which contains pointers into the static pstring).
1075 ****************************************************************************/
1077 static char **extract_args(const char *command)
1079 static pstring trunc_cmd;
1080 char *ptr;
1081 int argcl;
1082 char **argl = NULL;
1083 int i;
1085 pstrcpy(trunc_cmd, command);
1087 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1088 errno = EINVAL;
1089 return NULL;
1093 * Count the args.
1096 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1097 argcl++;
1099 if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL)
1100 return NULL;
1103 * Now do the extraction.
1106 pstrcpy(trunc_cmd, command);
1108 ptr = strtok(trunc_cmd, " \t");
1109 i = 0;
1110 argl[i++] = ptr;
1112 while((ptr = strtok(NULL, " \t")) != NULL)
1113 argl[i++] = ptr;
1115 argl[i++] = NULL;
1116 return argl;
1119 /**************************************************************************
1120 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1121 a sys_getpid() that only does a system call *once*.
1122 ****************************************************************************/
1124 static pid_t mypid = (pid_t)-1;
1126 pid_t sys_fork(void)
1128 pid_t forkret = fork();
1130 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1131 mypid = (pid_t) -1;
1133 return forkret;
1136 /**************************************************************************
1137 Wrapper for getpid. Ensures we only do a system call *once*.
1138 ****************************************************************************/
1140 pid_t sys_getpid(void)
1142 if (mypid == (pid_t)-1)
1143 mypid = getpid();
1145 return mypid;
1148 /**************************************************************************
1149 Wrapper for popen. Safer as it doesn't search a path.
1150 Modified from the glibc sources.
1151 modified by tridge to return a file descriptor. We must kick our FILE* habit
1152 ****************************************************************************/
1154 typedef struct _popen_list
1156 int fd;
1157 pid_t child_pid;
1158 struct _popen_list *next;
1159 } popen_list;
1161 static popen_list *popen_chain;
1163 int sys_popen(const char *command)
1165 int parent_end, child_end;
1166 int pipe_fds[2];
1167 popen_list *entry = NULL;
1168 char **argl = NULL;
1170 if (pipe(pipe_fds) < 0)
1171 return -1;
1173 parent_end = pipe_fds[0];
1174 child_end = pipe_fds[1];
1176 if (!*command) {
1177 errno = EINVAL;
1178 goto err_exit;
1181 if((entry = SMB_MALLOC_P(popen_list)) == NULL)
1182 goto err_exit;
1184 ZERO_STRUCTP(entry);
1187 * Extract the command and args into a NULL terminated array.
1190 if(!(argl = extract_args(command)))
1191 goto err_exit;
1193 entry->child_pid = sys_fork();
1195 if (entry->child_pid == -1) {
1196 goto err_exit;
1199 if (entry->child_pid == 0) {
1202 * Child !
1205 int child_std_end = STDOUT_FILENO;
1206 popen_list *p;
1208 close(parent_end);
1209 if (child_end != child_std_end) {
1210 dup2 (child_end, child_std_end);
1211 close (child_end);
1215 * POSIX.2: "popen() shall ensure that any streams from previous
1216 * popen() calls that remain open in the parent process are closed
1217 * in the new child process."
1220 for (p = popen_chain; p; p = p->next)
1221 close(p->fd);
1223 execv(argl[0], argl);
1224 _exit (127);
1228 * Parent.
1231 close (child_end);
1232 SAFE_FREE(argl);
1234 /* Link into popen_chain. */
1235 entry->next = popen_chain;
1236 popen_chain = entry;
1237 entry->fd = parent_end;
1239 return entry->fd;
1241 err_exit:
1243 SAFE_FREE(entry);
1244 SAFE_FREE(argl);
1245 close(pipe_fds[0]);
1246 close(pipe_fds[1]);
1247 return -1;
1250 /**************************************************************************
1251 Wrapper for pclose. Modified from the glibc sources.
1252 ****************************************************************************/
1254 int sys_pclose(int fd)
1256 int wstatus;
1257 popen_list **ptr = &popen_chain;
1258 popen_list *entry = NULL;
1259 pid_t wait_pid;
1260 int status = -1;
1262 /* Unlink from popen_chain. */
1263 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1264 if ((*ptr)->fd == fd) {
1265 entry = *ptr;
1266 *ptr = (*ptr)->next;
1267 status = 0;
1268 break;
1272 if (status < 0 || close(entry->fd) < 0)
1273 return -1;
1276 * As Samba is catching and eating child process
1277 * exits we don't really care about the child exit
1278 * code, a -1 with errno = ECHILD will do fine for us.
1281 do {
1282 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1283 } while (wait_pid == -1 && errno == EINTR);
1285 SAFE_FREE(entry);
1287 if (wait_pid == -1)
1288 return -1;
1289 return wstatus;
1292 /**************************************************************************
1293 Wrappers for dlopen, dlsym, dlclose.
1294 ****************************************************************************/
1296 void *sys_dlopen(const char *name, int flags)
1298 #if defined(HAVE_DLOPEN)
1299 return dlopen(name, flags);
1300 #else
1301 return NULL;
1302 #endif
1305 void *sys_dlsym(void *handle, const char *symbol)
1307 #if defined(HAVE_DLSYM)
1308 return dlsym(handle, symbol);
1309 #else
1310 return NULL;
1311 #endif
1314 int sys_dlclose (void *handle)
1316 #if defined(HAVE_DLCLOSE)
1317 return dlclose(handle);
1318 #else
1319 return 0;
1320 #endif
1323 const char *sys_dlerror(void)
1325 #if defined(HAVE_DLERROR)
1326 return dlerror();
1327 #else
1328 return NULL;
1329 #endif
1332 int sys_dup2(int oldfd, int newfd)
1334 #if defined(HAVE_DUP2)
1335 return dup2(oldfd, newfd);
1336 #else
1337 errno = ENOSYS;
1338 return -1;
1339 #endif
1342 /**************************************************************************
1343 Wrapper for Admin Logs.
1344 ****************************************************************************/
1346 void sys_adminlog(int priority, const char *format_str, ...)
1348 va_list ap;
1349 int ret;
1350 char *msgbuf = NULL;
1352 va_start( ap, format_str );
1353 ret = vasprintf( &msgbuf, format_str, ap );
1354 va_end( ap );
1356 if (ret == -1)
1357 return;
1359 #if defined(HAVE_SYSLOG)
1360 syslog( priority, "%s", msgbuf );
1361 #else
1362 DEBUG(0,("%s", msgbuf ));
1363 #endif
1364 SAFE_FREE(msgbuf);
1367 /**************************************************************************
1368 Wrappers for extented attribute calls. Based on the Linux package with
1369 support for IRIX also. Expand as other systems have them.
1370 ****************************************************************************/
1372 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
1374 #if defined(HAVE_GETXATTR)
1375 return getxattr(path, name, value, size);
1376 #elif defined(HAVE_ATTR_GET)
1377 int retval, flags = 0;
1378 int valuelength = (int)size;
1379 char *attrname = strchr(name,'.') +1;
1381 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1383 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1385 return retval ? retval : valuelength;
1386 #else
1387 errno = ENOSYS;
1388 return -1;
1389 #endif
1392 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
1394 #if defined(HAVE_LGETXATTR)
1395 return lgetxattr(path, name, value, size);
1396 #elif defined(HAVE_ATTR_GET)
1397 int retval, flags = ATTR_DONTFOLLOW;
1398 int valuelength = (int)size;
1399 char *attrname = strchr(name,'.') +1;
1401 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1403 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
1405 return retval ? retval : valuelength;
1406 #else
1407 errno = ENOSYS;
1408 return -1;
1409 #endif
1412 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
1414 #if defined(HAVE_FGETXATTR)
1415 return fgetxattr(filedes, name, value, size);
1416 #elif defined(HAVE_ATTR_GETF)
1417 int retval, flags = 0;
1418 int valuelength = (int)size;
1419 char *attrname = strchr(name,'.') +1;
1421 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1423 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
1425 return retval ? retval : valuelength;
1426 #else
1427 errno = ENOSYS;
1428 return -1;
1429 #endif
1432 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1433 static char attr_buffer[ATTR_MAX_VALUELEN];
1435 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
1437 int retval = 0, index;
1438 attrlist_cursor_t *cursor = 0;
1439 int total_size = 0;
1440 attrlist_t * al = (attrlist_t *)attr_buffer;
1441 attrlist_ent_t *ae;
1442 size_t ent_size, left = size;
1443 char *bp = list;
1445 while (True) {
1446 if (filedes)
1447 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1448 else
1449 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1450 if (retval) break;
1451 for (index = 0; index < al->al_count; index++) {
1452 ae = ATTR_ENTRY(attr_buffer, index);
1453 ent_size = strlen(ae->a_name) + sizeof("user.");
1454 if (left >= ent_size) {
1455 strncpy(bp, "user.", sizeof("user."));
1456 strncat(bp, ae->a_name, ent_size - sizeof("user."));
1457 bp += ent_size;
1458 left -= ent_size;
1459 } else if (size) {
1460 errno = ERANGE;
1461 retval = -1;
1462 break;
1464 total_size += ent_size;
1466 if (al->al_more == 0) break;
1468 if (retval == 0) {
1469 flags |= ATTR_ROOT;
1470 cursor = 0;
1471 while (True) {
1472 if (filedes)
1473 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1474 else
1475 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
1476 if (retval) break;
1477 for (index = 0; index < al->al_count; index++) {
1478 ae = ATTR_ENTRY(attr_buffer, index);
1479 ent_size = strlen(ae->a_name) + sizeof("system.");
1480 if (left >= ent_size) {
1481 strncpy(bp, "system.", sizeof("system."));
1482 strncat(bp, ae->a_name, ent_size - sizeof("system."));
1483 bp += ent_size;
1484 left -= ent_size;
1485 } else if (size) {
1486 errno = ERANGE;
1487 retval = -1;
1488 break;
1490 total_size += ent_size;
1492 if (al->al_more == 0) break;
1495 return (ssize_t)(retval ? retval : total_size);
1498 #endif
1500 ssize_t sys_listxattr (const char *path, char *list, size_t size)
1502 #if defined(HAVE_LISTXATTR)
1503 return listxattr(path, list, size);
1504 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1505 return irix_attr_list(path, 0, list, size, 0);
1506 #else
1507 errno = ENOSYS;
1508 return -1;
1509 #endif
1512 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
1514 #if defined(HAVE_LLISTXATTR)
1515 return llistxattr(path, list, size);
1516 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
1517 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
1518 #else
1519 errno = ENOSYS;
1520 return -1;
1521 #endif
1524 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
1526 #if defined(HAVE_FLISTXATTR)
1527 return flistxattr(filedes, list, size);
1528 #elif defined(HAVE_ATTR_LISTF)
1529 return irix_attr_list(NULL, filedes, list, size, 0);
1530 #else
1531 errno = ENOSYS;
1532 return -1;
1533 #endif
1536 int sys_removexattr (const char *path, const char *name)
1538 #if defined(HAVE_REMOVEXATTR)
1539 return removexattr(path, name);
1540 #elif defined(HAVE_ATTR_REMOVE)
1541 int flags = 0;
1542 char *attrname = strchr(name,'.') +1;
1544 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1546 return attr_remove(path, attrname, flags);
1547 #else
1548 errno = ENOSYS;
1549 return -1;
1550 #endif
1553 int sys_lremovexattr (const char *path, const char *name)
1555 #if defined(HAVE_LREMOVEXATTR)
1556 return lremovexattr(path, name);
1557 #elif defined(HAVE_ATTR_REMOVE)
1558 int flags = ATTR_DONTFOLLOW;
1559 char *attrname = strchr(name,'.') +1;
1561 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1563 return attr_remove(path, attrname, flags);
1564 #else
1565 errno = ENOSYS;
1566 return -1;
1567 #endif
1570 int sys_fremovexattr (int filedes, const char *name)
1572 #if defined(HAVE_FREMOVEXATTR)
1573 return fremovexattr(filedes, name);
1574 #elif defined(HAVE_ATTR_REMOVEF)
1575 int flags = 0;
1576 char *attrname = strchr(name,'.') +1;
1578 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
1580 return attr_removef(filedes, attrname, flags);
1581 #else
1582 errno = ENOSYS;
1583 return -1;
1584 #endif
1587 #if !defined(HAVE_SETXATTR)
1588 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
1589 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
1590 #endif
1592 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1594 #if defined(HAVE_SETXATTR)
1595 return setxattr(path, name, value, size, flags);
1596 #elif defined(HAVE_ATTR_SET)
1597 int myflags = 0;
1598 char *attrname = strchr(name,'.') +1;
1600 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1601 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1602 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1604 return attr_set(path, attrname, (const char *)value, size, myflags);
1605 #else
1606 errno = ENOSYS;
1607 return -1;
1608 #endif
1611 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
1613 #if defined(HAVE_LSETXATTR)
1614 return lsetxattr(path, name, value, size, flags);
1615 #elif defined(HAVE_ATTR_SET)
1616 int myflags = ATTR_DONTFOLLOW;
1617 char *attrname = strchr(name,'.') +1;
1619 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1620 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1621 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1623 return attr_set(path, attrname, (const char *)value, size, myflags);
1624 #else
1625 errno = ENOSYS;
1626 return -1;
1627 #endif
1630 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
1632 #if defined(HAVE_FSETXATTR)
1633 return fsetxattr(filedes, name, value, size, flags);
1634 #elif defined(HAVE_ATTR_SETF)
1635 int myflags = 0;
1636 char *attrname = strchr(name,'.') +1;
1638 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
1639 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
1640 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
1642 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
1643 #else
1644 errno = ENOSYS;
1645 return -1;
1646 #endif
1649 /****************************************************************************
1650 Return the major devicenumber for UNIX extensions.
1651 ****************************************************************************/
1653 uint32 unix_dev_major(SMB_DEV_T dev)
1655 #if defined(HAVE_DEVICE_MAJOR_FN)
1656 return (uint32)major(dev);
1657 #else
1658 return (uint32)(dev >> 8);
1659 #endif
1662 /****************************************************************************
1663 Return the minor devicenumber for UNIX extensions.
1664 ****************************************************************************/
1666 uint32 unix_dev_minor(SMB_DEV_T dev)
1668 #if defined(HAVE_DEVICE_MINOR_FN)
1669 return (uint32)minor(dev);
1670 #else
1671 return (uint32)(dev & 0xff);
1672 #endif