First cut at unicode sys_xx functions. Now to start moving upwards.....
[kai/samba.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,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 *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 fds,NULL,NULL,tval?&t2:NULL);
135   } while (selrtn<0 && errno == EINTR);
136
137   return(selrtn);
138 }
139 #endif /* USE_POLL */
140 #endif /* NO_SELECT */
141
142 /*******************************************************************
143  A wrapper for usleep in case we don't have one.
144 ********************************************************************/
145
146 int sys_usleep(long usecs)
147 {
148 #ifndef HAVE_USLEEP
149   struct timeval tval;
150 #endif
151
152   /*
153    * We need this braindamage as the glibc usleep
154    * is not SPEC1170 complient... grumble... JRA.
155    */
156
157   if(usecs < 0 || usecs > 1000000) {
158     errno = EINVAL;
159     return -1;
160   }
161
162 #if HAVE_USLEEP
163   usleep(usecs);
164   return 0;
165 #else /* HAVE_USLEEP */
166   /*
167    * Fake it with select...
168    */
169   tval.tv_sec = 0;
170   tval.tv_usec = usecs/1000;
171   select(0,NULL,NULL,NULL,&tval);
172   return 0;
173 #endif /* HAVE_USLEEP */
174 }
175
176 /*******************************************************************
177 A stat() wrapper that will deal with 64 bit filesizes.
178 ********************************************************************/
179
180 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
181 {
182         int ret;
183 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
184         ret = stat64(fname, sbuf);
185 #else
186         ret = stat(fname, sbuf);
187 #endif
188         /* we always want directories to appear zero size */
189         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
190         return ret;
191 }
192
193 /*******************************************************************
194  An fstat() wrapper that will deal with 64 bit filesizes.
195 ********************************************************************/
196
197 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
198 {
199         int ret;
200 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
201         ret = fstat64(fd, sbuf);
202 #else
203         ret = fstat(fd, sbuf);
204 #endif
205         /* we always want directories to appear zero size */
206         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
207         return ret;
208 }
209
210 /*******************************************************************
211  An lstat() wrapper that will deal with 64 bit filesizes.
212 ********************************************************************/
213
214 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
215 {
216         int ret;
217 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
218         ret = lstat64(fname, sbuf);
219 #else
220         ret = lstat(fname, sbuf);
221 #endif
222         /* we always want directories to appear zero size */
223         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
224         return ret;
225 }
226
227 /*******************************************************************
228  An ftruncate() wrapper that will deal with 64 bit filesizes.
229 ********************************************************************/
230
231 int sys_ftruncate(int fd, SMB_OFF_T offset)
232 {
233 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
234   return ftruncate64(fd, offset);
235 #else
236   return ftruncate(fd, offset);
237 #endif
238 }
239
240 /*******************************************************************
241  An lseek() wrapper that will deal with 64 bit filesizes.
242 ********************************************************************/
243
244 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
245 {
246 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
247   return lseek64(fd, offset, whence);
248 #else
249   return lseek(fd, offset, whence);
250 #endif
251 }
252
253 /*******************************************************************
254  An fseek() wrapper that will deal with 64 bit filesizes.
255 ********************************************************************/
256
257 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
258 {
259 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
260   return fseek64(fp, offset, whence);
261 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
262   return fseeko64(fp, offset, whence);
263 #else
264   return fseek(fp, offset, whence);
265 #endif
266 }
267
268 /*******************************************************************
269  An ftell() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
271
272 SMB_OFF_T sys_ftell(FILE *fp)
273 {
274 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
275   return (SMB_OFF_T)ftell64(fp);
276 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
277   return (SMB_OFF_T)ftello64(fp);
278 #else
279   return (SMB_OFF_T)ftell(fp);
280 #endif
281 }
282
283 /*******************************************************************
284  A creat() wrapper that will deal with 64 bit filesizes.
285 ********************************************************************/
286
287 int sys_creat(const char *path, mode_t mode)
288 {
289 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
290   return creat64(path, mode);
291 #else
292   /*
293    * If creat64 isn't defined then ensure we call a potential open64.
294    * JRA.
295    */
296   return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
297 #endif
298 }
299
300 /*******************************************************************
301  An open() wrapper that will deal with 64 bit filesizes.
302 ********************************************************************/
303
304 int sys_open(const char *path, int oflag, mode_t mode)
305 {
306 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
307   return open64(path, oflag, mode);
308 #else
309   return open(path, oflag, mode);
310 #endif
311 }
312
313 /*******************************************************************
314  An fopen() wrapper that will deal with 64 bit filesizes.
315 ********************************************************************/
316
317 FILE *sys_fopen(const char *path, const char *type)
318 {
319 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
320   return fopen64(path, type);
321 #else
322   return fopen(path, type);
323 #endif
324 }
325
326 #if defined(HAVE_MMAP)
327
328 /*******************************************************************
329  An mmap() wrapper that will deal with 64 bit filesizes.
330 ********************************************************************/
331
332 void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset)
333 {
334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
335   return mmap64(addr, len, prot, flags, fd, offset);
336 #else
337   return mmap(addr, len, prot, flags, fd, offset);
338 #endif
339 }
340
341 #endif /* HAVE_MMAP */
342
343 /*******************************************************************
344  A readdir wrapper that will deal with 64 bit filesizes.
345 ********************************************************************/
346
347 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
348 {
349 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
350   return readdir64(dirp);
351 #else
352   return readdir(dirp);
353 #endif
354 }
355
356 /*******************************************************************
357 The wait() calls vary between systems
358 ********************************************************************/
359
360 int sys_waitpid(pid_t pid,int *status,int options)
361 {
362 #ifdef HAVE_WAITPID
363   return waitpid(pid,status,options);
364 #else /* HAVE_WAITPID */
365   return wait4(pid, status, options, NULL);
366 #endif /* HAVE_WAITPID */
367 }
368
369 /*******************************************************************
370 system wrapper for getwd
371 ********************************************************************/
372 char *sys_getwd(char *s)
373 {
374     char *wd;
375 #ifdef HAVE_GETCWD
376     wd = (char *)getcwd(s, sizeof (pstring));
377 #else
378     wd = (char *)getwd(s);
379 #endif
380     return wd;
381 }
382
383 /*******************************************************************
384 chown isn't used much but OS/2 doesn't have it
385 ********************************************************************/
386
387 int sys_chown(const char *fname,uid_t uid,gid_t gid)
388 {
389 #ifndef HAVE_CHOWN
390         static int done;
391         if (!done) {
392                 DEBUG(1,("WARNING: no chown!\n"));
393                 done=1;
394         }
395 #else
396         return(chown(fname,uid,gid));
397 #endif
398 }
399
400 /*******************************************************************
401 os/2 also doesn't have chroot
402 ********************************************************************/
403 int sys_chroot(const char *dname)
404 {
405 #ifndef HAVE_CHROOT
406         static int done;
407         if (!done) {
408                 DEBUG(1,("WARNING: no chroot!\n"));
409                 done=1;
410         }
411 #else
412         return(chroot(dname));
413 #endif
414 }
415
416 /**************************************************************************
417 A wrapper for gethostbyname() that tries avoids looking up hostnames 
418 in the root domain, which can cause dial-on-demand links to come up for no
419 apparent reason.
420 ****************************************************************************/
421 struct hostent *sys_gethostbyname(const char *name)
422 {
423 #ifdef REDUCE_ROOT_DNS_LOOKUPS
424   char query[256], hostname[256];
425   char *domain;
426
427   /* Does this name have any dots in it? If so, make no change */
428
429   if (strchr(name, '.'))
430     return(gethostbyname(name));
431
432   /* Get my hostname, which should have domain name 
433      attached. If not, just do the gethostname on the
434      original string. 
435   */
436
437   gethostname(hostname, sizeof(hostname) - 1);
438   hostname[sizeof(hostname) - 1] = 0;
439   if ((domain = strchr(hostname, '.')) == NULL)
440     return(gethostbyname(name));
441
442   /* Attach domain name to query and do modified query.
443      If names too large, just do gethostname on the
444      original string.
445   */
446
447   if((strlen(name) + strlen(domain)) >= sizeof(query))
448     return(gethostbyname(name));
449
450   slprintf(query, sizeof(query)-1, "%s%s", name, domain);
451   return(gethostbyname(query));
452 #else /* REDUCE_ROOT_DNS_LOOKUPS */
453   return(gethostbyname(name));
454 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
455 }
456
457
458 /**************************************************************************
459  Try and abstract process capabilities (for systems that have them).
460 ****************************************************************************/
461
462 BOOL set_process_capability( uint32 cap_flag, BOOL enable )
463 {
464 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
465   if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
466   {
467     cap_t cap = cap_get_proc();
468
469     if (cap == NULL) {
470       DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
471             strerror(errno)));
472       return False;
473     }
474
475     if(enable)
476       cap->cap_effective |= CAP_NETWORK_MGT;
477     else
478       cap->cap_effective &= ~CAP_NETWORK_MGT;
479
480     if (cap_set_proc(cap) == -1) {
481       DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
482             strerror(errno)));
483       cap_free(cap);
484       return False;
485     }
486
487     cap_free(cap);
488
489     DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
490   }
491 #endif
492   return True;
493 }
494
495 /**************************************************************************
496  Try and abstract inherited process capabilities (for systems that have them).
497 ****************************************************************************/
498
499 BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
500 {
501 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
502   if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
503   {
504     cap_t cap = cap_get_proc();
505
506     if (cap == NULL) {
507       DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
508             strerror(errno)));
509       return False;
510     }
511
512     if(enable)
513       cap->cap_inheritable |= CAP_NETWORK_MGT;
514     else
515       cap->cap_inheritable &= ~CAP_NETWORK_MGT;
516
517     if (cap_set_proc(cap) == -1) {
518       DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", 
519             strerror(errno)));
520       cap_free(cap);
521       return False;
522     }
523
524     cap_free(cap);
525
526     DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
527   }
528 #endif
529   return True;
530 }
531
532 /**************************************************************************
533  Wrapper for random().
534 ****************************************************************************/
535
536 long sys_random(void)
537 {
538 #if defined(HAVE_RANDOM)
539   return (long)random();
540 #elif defined(HAVE_RAND)
541   return (long)rand();
542 #else
543   DEBUG(0,("Error - no random function available !\n"));
544   exit(1);
545 #endif
546 }
547
548 /**************************************************************************
549  Wrapper for srandom().
550 ****************************************************************************/
551
552 void sys_srandom(unsigned int seed)
553 {
554 #if defined(HAVE_SRANDOM)
555   srandom(seed);
556 #elif defined(HAVE_SRAND)
557   srand(seed);
558 #else
559   DEBUG(0,("Error - no srandom function available !\n"));
560   exit(1);
561 #endif
562 }
563
564 /**************************************************************************
565  Wrapper for getgroups. Deals with broken (int) case.
566 ****************************************************************************/
567
568 int sys_getgroups(int setlen, gid_t *gidset)
569 {
570 #if !defined(HAVE_BROKEN_GETGROUPS)
571   return getgroups(setlen, gidset);
572 #else
573
574   GID_T gid;
575   GID_T *group_list;
576   int i, ngroups;
577
578   if(setlen == 0) {
579     return getgroups(setlen, &gid);
580   }
581
582   /*
583    * Broken case. We need to allocate a
584    * GID_T array of size setlen.
585    */
586
587   if(setlen < 0) {
588     errno = EINVAL; 
589     return -1;
590   } 
591
592   if (setlen == 0)
593     setlen = 1;
594
595   if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
596     DEBUG(0,("sys_getgroups: Malloc fail.\n"));
597     return -1;
598   }
599
600   if((ngroups = getgroups(setlen, group_list)) < 0) {
601     int saved_errno = errno;
602     free((char *)group_list);
603     errno = saved_errno;
604     return -1;
605   }
606
607   for(i = 0; i < ngroups; i++)
608     gidset[i] = (gid_t)group_list[i];
609
610   free((char *)group_list);
611   return ngroups;
612 #endif /* HAVE_BROKEN_GETGROUPS */
613 }
614
615 #ifdef HAVE_SETGROUPS
616
617 /**************************************************************************
618  Wrapper for setgroups. Deals with broken (int) case. Automatically used
619  if we have broken getgroups.
620 ****************************************************************************/
621
622 int sys_setgroups(int setlen, gid_t *gidset)
623 {
624 #if !defined(HAVE_BROKEN_GETGROUPS)
625   return setgroups(setlen, gidset);
626 #else
627
628   GID_T *group_list;
629   int i ; 
630
631   if (setlen == 0)
632     return 0 ;
633
634 #ifdef NGROUPS_MAX
635   if (setlen > NGROUPS_MAX) {
636     errno = EINVAL; 
637     return -1;   
638   }
639 #endif
640
641   /*
642    * Broken case. We need to allocate a
643    * GID_T array of size setlen.
644    */
645
646   if (setlen == 0)
647     setlen = 1;
648
649   if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
650     DEBUG(0,("sys_setgroups: Malloc fail.\n"));
651     return -1;    
652   }
653  
654   for(i = 0; i < setlen; i++) 
655     group_list[i] = (GID_T) gidset[i]; 
656
657   if(setgroups(setlen, group_list) != 0) {
658     int saved_errno = errno;
659     free((char *)group_list);
660     errno = saved_errno;
661     return -1;
662   }
663  
664   free((char *)group_list);
665   return 0 ;
666 #endif /* HAVE_BROKEN_GETGROUPS */
667 }
668
669 #endif /* HAVE_SETGROUPS */
670
671 /*
672  * We only wrap pw_name and pw_passwd for now as these
673  * are the only potentially modified fields.
674  */
675
676 /**************************************************************************
677  Helper function for getpwnam/getpwuid wrappers.
678 ****************************************************************************/
679
680 static struct passwd *setup_pwret(struct passwd *pass)
681 {
682         static pstring pw_name;
683         static pstring pw_passwd;
684         static struct passwd pw_ret;
685
686         if (pass == NULL)
687         {
688                 return NULL;
689         }
690
691         memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
692
693         if (pass->pw_name)
694         {
695                 pw_ret.pw_name = pw_name;
696                 pstrcpy(pw_ret.pw_name, pass->pw_name);
697         }
698
699         if (pass->pw_passwd)
700         {
701                 pw_ret.pw_passwd = pw_passwd;
702                 pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
703         }
704
705         return &pw_ret;
706 }
707
708 /**************************************************************************
709  Wrapper for getpwnam(). Always returns a static that can be modified.
710 ****************************************************************************/
711
712 struct passwd *sys_getpwnam(const char *name)
713 {
714         return setup_pwret(getpwnam(name));
715 }
716
717 /**************************************************************************
718  Wrapper for getpwuid(). Always returns a static that can be modified.
719 ****************************************************************************/
720
721 struct passwd *sys_getpwuid(uid_t uid)
722 {
723         return setup_pwret(getpwuid(uid));
724 }
725
726 /**************************************************************************
727  The following are the UNICODE versions of *all* system interface functions
728  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
729  which currently are left as ascii as they are not used other than in name
730  resolution.
731 ****************************************************************************/
732
733 /**************************************************************************
734  Wide stat. Just narrow and call sys_xxx.
735 ****************************************************************************/
736
737 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
738 {
739         pstring fname;
740         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
741 }
742
743 /**************************************************************************
744  Wide lstat. Just narrow and call sys_xxx.
745 ****************************************************************************/
746
747 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
748 {
749         pstring fname;
750         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
751 }
752
753 /**************************************************************************
754  Wide creat. Just narrow and call sys_xxx.
755 ****************************************************************************/
756
757 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
758 {
759         pstring fname;
760         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
761 }
762
763 /**************************************************************************
764  Wide open. Just narrow and call sys_xxx.
765 ****************************************************************************/
766
767 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
768 {
769         pstring fname;
770         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
771 }
772
773 /**************************************************************************
774  Wide fopen. Just narrow and call sys_xxx.
775 ****************************************************************************/
776
777 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
778 {
779         pstring fname;
780         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
781 }
782
783 /**************************************************************************
784  Wide opendir. Just narrow and call sys_xxx.
785 ****************************************************************************/
786
787 DIR *wsys_opendir(const smb_ucs2_t *wfname)
788 {
789         pstring fname;
790         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
791 }
792
793 /**************************************************************************
794  Wide readdir. Return a structure pointer containing a wide filename.
795 ****************************************************************************/
796
797 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
798 {
799         static SMB_STRUCT_WDIRENT retval;
800         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
801
802         if(!dirval)
803                 return NULL;
804
805         retval.d_ino = (SMB_INO_T)dirval->d_ino;
806         retval.d_off = (SMB_OFF_T)dirval->d_off;
807         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
808         retval.d_reclen = wstrlen(retval.d_name);
809
810         return &retval;
811 }
812
813 /**************************************************************************
814  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
815 ****************************************************************************/
816
817 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
818 {
819         pstring fname;
820         char *p = sys_getwd(fname);
821
822         if(!p)
823                 return NULL;
824
825         return unix_to_unicode(s, p, sizeof(wpstring));
826 }
827
828 /**************************************************************************
829  Wide chown. Just narrow and call sys_xxx.
830 ****************************************************************************/
831
832 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
833 {
834         pstring fname;
835         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
836 }
837
838 /**************************************************************************
839  Wide chroot. Just narrow and call sys_xxx.
840 ****************************************************************************/
841
842 int wsys_chroot(const smb_ucs2_t *wfname)
843 {
844         pstring fname;
845         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
846 }
847
848 /**************************************************************************
849  Wide getpwnam. Return a structure pointer containing wide names.
850 ****************************************************************************/
851
852 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
853 {
854         static SMB_STRUCT_WPASSWD retval;
855         fstring name;
856         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
857
858         if(!pwret)
859                 return NULL;
860
861         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
862         retval.pw_passwd = pwret->pw_passwd;
863         retval.pw_uid = pwret->pw_uid;
864         retval.pw_gid = pwret->pw_gid;
865         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
866         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
867         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
868
869         return &retval;
870 }
871
872 /**************************************************************************
873  Wide getpwuid. Return a structure pointer containing wide names.
874 ****************************************************************************/
875
876 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
877 {
878         static SMB_STRUCT_WPASSWD retval;
879         struct passwd *pwret = sys_getpwuid(uid);
880
881         if(!pwret)
882                 return NULL;
883
884         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
885         retval.pw_passwd = pwret->pw_passwd;
886         retval.pw_uid = pwret->pw_uid;
887         retval.pw_gid = pwret->pw_gid;
888         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
889         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
890         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
891
892         return &retval;
893 }