changed function name of get_home_dir() to get_unixhome_dir(), to stop
[ira/wip.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba system utilities
5    Copyright (C) Andrew Tridgell 1992-1998
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 /*
27    The idea is that this file will eventually have wrappers around all
28    important system calls in samba. The aims are:
29
30    - to enable easier porting by putting OS dependent stuff in here
31
32    - to allow for hooks into other "pseudo-filesystems"
33
34    - to allow easier integration of things like the japanese extensions
35
36    - to support the philosophy of Samba to expose the features of
37      the OS within the SMB model. In general whatever file/printer/variable
38      expansions/etc make sense to the OS should be acceptable to Samba.
39 */
40
41
42 /*******************************************************************
43 this replaces the normal select() system call
44 return if some data has arrived on one of the file descriptors
45 return -1 means error
46 ********************************************************************/
47 #ifndef HAVE_SELECT
48 static int pollfd(int fd)
49 {
50   int     r=0;
51
52 #ifdef HAS_RDCHK
53   r = rdchk(fd);
54 #elif defined(TCRDCHK)
55   (void)ioctl(fd, TCRDCHK, &r);
56 #else
57   (void)ioctl(fd, FIONREAD, &r);
58 #endif
59
60   return(r);
61 }
62
63 int sys_select(int maxfd, fd_set *fds, fd_set *w_fds, struct timeval *tval)
64 {
65   fd_set fds2;
66   int counter=0;
67   int found=0;
68
69   FD_ZERO(&fds2);
70
71   while (1) 
72   {
73     int i;
74     for (i=0;i<maxfd;i++) {
75       if (FD_ISSET(i,fds) && pollfd(i)>0) {
76         found++;
77         FD_SET(i,&fds2);
78       }
79     }
80
81     if (found) {
82       memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
83       return(found);
84     }
85       
86     if (tval && tval->tv_sec < counter) return(0);
87       sleep(1);
88       counter++;
89   }
90 }
91
92 #else /* !NO_SELECT */
93 int sys_select(int maxfd, fd_set *r_fds, fd_set *w_fds, struct timeval *tval)
94 {
95 #ifdef USE_POLL
96   struct pollfd pfd[256];
97   int i;
98   int maxpoll;
99   int timeout;
100   int pollrtn;
101
102   maxpoll = 0;
103   for( i = 0; i < maxfd; i++) {
104     if(FD_ISSET(i,fds)) {
105       struct pollfd *pfdp = &pfd[maxpoll++];
106       pfdp->fd = i;
107       pfdp->events = POLLIN;
108       pfdp->revents = 0;
109     }
110   }
111
112   timeout = (tval != NULL) ? (tval->tv_sec * 1000) + (tval->tv_usec/1000) :
113                 -1;
114   errno = 0;
115   do {
116     pollrtn = poll( &pfd[0], maxpoll, timeout);
117   } while (pollrtn<0 && errno == EINTR);
118
119   FD_ZERO(fds);
120
121   for( i = 0; i < maxpoll; i++)
122     if( pfd[i].revents & POLLIN )
123       FD_SET(pfd[i].fd,fds);
124
125   return pollrtn;
126 #else /* USE_POLL */
127
128   struct timeval t2;
129   int selrtn;
130
131   do {
132     if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
133     errno = 0;
134     selrtn = select(maxfd,SELECT_CAST r_fds,SELECT_CAST w_fds,
135                     NULL,tval?&t2:NULL);
136   } while (selrtn<0 && errno == EINTR);
137
138   return(selrtn);
139 }
140 #endif /* USE_POLL */
141 #endif /* NO_SELECT */
142
143 /*******************************************************************
144 A stat() wrapper that will deal with 64 bit filesizes.
145 ********************************************************************/
146
147 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
148 {
149 #if defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
150   return stat64(fname, sbuf);
151 #else
152   return stat(fname, sbuf);
153 #endif
154 }
155
156 /*******************************************************************
157  An fstat() wrapper that will deal with 64 bit filesizes.
158 ********************************************************************/
159
160 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
161 {
162 #if defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
163   return fstat64(fd, sbuf);
164 #else
165   return fstat(fd, sbuf);
166 #endif
167 }
168
169 /*******************************************************************
170  An lstat() wrapper that will deal with 64 bit filesizes.
171 ********************************************************************/
172
173 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
174 {
175 #if defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
176   return lstat64(fname, sbuf);
177 #else
178   return lstat(fname, sbuf);
179 #endif
180 }
181
182 /*******************************************************************
183  An ftruncate() wrapper that will deal with 64 bit filesizes.
184 ********************************************************************/
185
186 int sys_ftruncate(int fd, SMB_OFF_T offset)
187 {
188 #if defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
189   return ftruncate64(fd, offset);
190 #else
191   return ftruncate(fd, offset);
192 #endif
193 }
194
195 /*******************************************************************
196  An lseek() wrapper that will deal with 64 bit filesizes.
197 ********************************************************************/
198
199 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
200 {
201 #if defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
202   return lseek64(fd, offset, whence);
203 #else
204   return lseek(fd, offset, whence);
205 #endif
206 }
207
208 /*******************************************************************
209  An fseek() wrapper that will deal with 64 bit filesizes.
210 ********************************************************************/
211
212 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
213 {
214 #if defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
215   return fseek64(fp, offset, whence);
216 #else
217   return fseek(fp, offset, whence);
218 #endif
219 }
220
221 /*******************************************************************
222  An ftell() wrapper that will deal with 64 bit filesizes.
223 ********************************************************************/
224
225 SMB_OFF_T sys_ftell(FILE *fp)
226 {
227 #if defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
228   return (SMB_OFF_T)ftell64(fp);
229 #else
230   return (SMB_OFF_T)ftell(fp);
231 #endif
232 }
233
234 /*******************************************************************
235  A creat() wrapper that will deal with 64 bit filesizes.
236 ********************************************************************/
237
238 int sys_creat(const char *path, mode_t mode)
239 {
240 #if defined(HAVE_CREAT64)
241   return creat64(path, mode);
242 #else
243   /*
244    * If creat64 isn't defined then ensure we call a potential open64.
245    * JRA.
246    */
247   return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
248 #endif
249 }
250
251 /*******************************************************************
252  An open() wrapper that will deal with 64 bit filesizes.
253 ********************************************************************/
254
255 int sys_open(const char *path, int oflag, mode_t mode)
256 {
257 #if defined(HAVE_OPEN64)
258   return open64(path, oflag, mode);
259 #else
260   return open(path, oflag, mode);
261 #endif
262 }
263
264 /*******************************************************************
265  An fopen() wrapper that will deal with 64 bit filesizes.
266 ********************************************************************/
267
268 FILE *sys_fopen(const char *path, const char *type)
269 {
270 #if defined(HAVE_FOPEN64)
271   return fopen64(path, type);
272 #else
273   return fopen(path, type);
274 #endif
275 }
276
277 /*******************************************************************
278  An mmap() wrapper that will deal with 64 bit filesizes.
279 ********************************************************************/
280
281 void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset)
282 {
283 #if defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
284   return mmap64(addr, len, prot, flags, fd, offset);
285 #else
286   return mmap(addr, len, prot, flags, fd, offset);
287 #endif
288 }
289
290 /*******************************************************************
291 The wait() calls vary between systems
292 ********************************************************************/
293
294 int sys_waitpid(pid_t pid,int *status,int options)
295 {
296 #ifdef HAVE_WAITPID
297   return waitpid(pid,status,options);
298 #else /* HAVE_WAITPID */
299   return wait4(pid, status, options, NULL);
300 #endif /* HAVE_WAITPID */
301 }
302
303 /*******************************************************************
304 system wrapper for getwd
305 ********************************************************************/
306 char *sys_getwd(char *s)
307 {
308         char *wd;
309 #ifdef HAVE_GETCWD
310         wd = (char *)getcwd(s, sizeof (pstring));
311 #else
312         wd = (char *)getwd(s);
313 #endif
314         return wd;
315 }
316
317 /*******************************************************************
318 chown isn't used much but OS/2 doesn't have it
319 ********************************************************************/
320 int sys_chown(const char *fname,uid_t uid,gid_t gid)
321 {
322 #ifndef HAVE_CHOWN
323         static int done;
324         if (!done) {
325                 DEBUG(1,("WARNING: no chown!\n"));
326                 done=1;
327         }
328 #else
329         return(chown(fname,uid,gid));
330 #endif
331 }
332
333 /*******************************************************************
334 os/2 also doesn't have chroot
335 ********************************************************************/
336 int sys_chroot(const char *dname)
337 {
338 #ifndef HAVE_CHROOT
339         static int done;
340         if (!done) {
341                 DEBUG(1,("WARNING: no chroot!\n"));
342                 done=1;
343         }
344 #else
345         return(chroot(dname));
346 #endif
347 }
348
349 /**************************************************************************
350 A wrapper for gethostbyname() that tries avoids looking up hostnames 
351 in the root domain, which can cause dial-on-demand links to come up for no
352 apparent reason.
353 ****************************************************************************/
354 struct hostent *sys_gethostbyname(const char *name)
355 {
356 #ifdef REDUCE_ROOT_DNS_LOOKUPS
357   char query[256], hostname[256];
358   char *domain;
359
360   /* Does this name have any dots in it? If so, make no change */
361
362   if (strchr(name, '.'))
363     return(gethostbyname(name));
364
365   /* Get my hostname, which should have domain name 
366      attached. If not, just do the gethostname on the
367      original string. 
368   */
369
370   gethostname(hostname, sizeof(hostname) - 1);
371   hostname[sizeof(hostname) - 1] = 0;
372   if ((domain = strchr(hostname, '.')) == NULL)
373     return(gethostbyname(name));
374
375   /* Attach domain name to query and do modified query.
376      If names too large, just do gethostname on the
377      original string.
378   */
379
380   if((strlen(name) + strlen(domain)) >= sizeof(query))
381     return(gethostbyname(name));
382
383   slprintf(query, sizeof(query)-1, "%s%s", name, domain);
384   return(gethostbyname(query));
385 #else /* REDUCE_ROOT_DNS_LOOKUPS */
386   return(gethostbyname(name));
387 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
388 }
389
390
391 /**************************************************************************
392  Try and abstract process capabilities (for systems that have them).
393 ****************************************************************************/
394
395 BOOL set_process_capability( uint32 cap_flag, BOOL enable )
396 {
397 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
398   if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
399   {
400     cap_t cap = cap_get_proc();
401
402     if (cap == NULL) {
403       DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
404             strerror(errno)));
405       return False;
406     }
407
408     if(enable)
409       cap->cap_effective |= CAP_NETWORK_MGT;
410     else
411       cap->cap_effective &= ~CAP_NETWORK_MGT;
412
413     if (cap_set_proc(cap) == -1) {
414       DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
415             strerror(errno)));
416       return False;
417     }
418
419     DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
420   }
421 #endif
422   return True;
423 }
424
425 /**************************************************************************
426  Try and abstract inherited process capabilities (for systems that have them).
427 ****************************************************************************/
428
429 BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
430 {
431 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
432   if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
433   {
434     cap_t cap = cap_get_proc();
435
436     if (cap == NULL) {
437       DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
438             strerror(errno)));
439       return False;
440     }
441
442     if(enable)
443       cap->cap_inheritable |= CAP_NETWORK_MGT;
444     else
445       cap->cap_inheritable &= ~CAP_NETWORK_MGT;
446
447     if (cap_set_proc(cap) == -1) {
448       DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", 
449             strerror(errno)));
450       return False;
451     }
452
453     DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
454   }
455 #endif
456   return True;
457 }
458
459 /**************************************************************************
460  Wrapper for random().
461 ****************************************************************************/
462
463 long sys_random(void)
464 {
465 #if defined(HAVE_RANDOM)
466   return (long)random();
467 #elif defined(HAVE_RAND)
468   return (long)rand();
469 #else
470   DEBUG(0,("Error - no random function available !\n"));
471   exit(1);
472 #endif
473 }
474
475 /**************************************************************************
476  Wrapper for srandom().
477 ****************************************************************************/
478
479 void sys_srandom(unsigned int seed)
480 {
481 #if defined(HAVE_SRANDOM)
482   srandom(seed);
483 #elif defined(HAVE_SRAND)
484   srand(seed);
485 #else
486   DEBUG(0,("Error - no srandom function available !\n"));
487   exit(1);
488 #endif
489 }
490
491 /**************************************************************************
492  Wrapper for getgroups. Deals with broken (int) case.
493 ****************************************************************************/
494
495 int sys_getgroups(int setlen, gid_t *gidset)
496 {
497 #if !defined(HAVE_BROKEN_GETGROUPS)
498   return getgroups(setlen, gidset);
499 #else
500
501   GID_T gid;
502   GID_T *group_list;
503   int i, ngroups;
504
505   if(setlen == 0) {
506     return getgroups(setlen, &gid);
507   }
508
509   /*
510    * Broken case. We need to allocate a
511    * GID_T array of size setlen.
512    */
513
514   if(setlen < 0) {
515     errno = EINVAL; 
516     return -1;
517   } 
518
519   if (setlen == 0) setlen = 1;
520
521   if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
522     DEBUG(0,("sys_getgroups: Malloc fail.\n"));
523     return -1;
524   }
525
526   if((ngroups = getgroups(setlen, group_list)) < 0) {
527     int saved_errno = errno;
528     free((char *)group_list);
529     errno = saved_errno;
530     return -1;
531   }
532
533   for(i = 0; i < ngroups; i++)
534     gidset[i] = (gid_t)group_list[i];
535
536   free((char *)group_list);
537   return ngroups;
538 #endif /* HAVE_BROKEN_GETGROUPS */
539 }
540
541 /*
542  * We only wrap pw_name and pw_passwd for now as these
543  * are the only potentially modified fields.
544  */
545
546 /**************************************************************************
547  Helper function for getpwnam/getpwuid wrappers.
548 ****************************************************************************/
549
550 struct passwd *copy_passwd_struct(struct passwd *pass)
551 {
552         static pstring pw_name;
553         static pstring pw_passwd;
554         static struct passwd pw_ret;
555
556         if (pass == NULL)
557         {
558                 return NULL;
559         }
560
561         if (pass == &pw_ret)
562         {
563                 /* catch silly error where buffer was already copied */
564                 DEBUG(0,("copy_passwd_struct: can't copy internal buffer!\n"));
565                 return NULL;
566         }
567
568         memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
569
570         if (pass->pw_name)
571         {
572                 pw_name[0] = '\0';
573                 pw_ret.pw_name = pw_name;
574                 pstrcpy(pw_ret.pw_name, pass->pw_name);
575         }
576
577         if (pass->pw_passwd)
578         {
579                 pw_passwd[0] = '\0';
580                 pw_ret.pw_passwd = pw_passwd;
581                 pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
582         }
583
584         return &pw_ret;
585 }
586
587 /**************************************************************************
588  Wrapper for getpwnam(). Always returns a static that can be modified.
589 ****************************************************************************/
590
591 struct passwd *sys_getpwnam(const char *name)
592 {
593         return copy_passwd_struct(getpwnam(name));
594 }
595
596 /**************************************************************************
597  Wrapper for getpwuid(). Always returns a static that can be modified.
598 ****************************************************************************/
599
600 struct passwd *sys_getpwuid(uid_t uid)
601 {
602         return copy_passwd_struct(getpwuid(uid));
603 }