This is the ubiqx binary tree and linked list library.
[Samba.git] / source / lib / system.c
blobfe8e8004d045197ec9d8468820d4dd7a83a2ad7f
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba system utilities
5 Copyright (C) Andrew Tridgell 1992-1997
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"
24 extern int DEBUGLEVEL;
27 The idea is that this file will eventually have wrappers around all
28 important system calls in samba. The aims are:
30 - to enable easier porting by putting OS dependent stuff in here
32 - to allow for hooks into other "pseudo-filesystems"
34 - to allow easier integration of things like the japanese extensions
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.
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 #ifdef NO_SELECT
48 static int pollfd(int fd)
50 int r=0;
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
60 return(r);
63 int sys_select(fd_set *fds,struct timeval *tval)
65 fd_set fds2;
66 int counter=0;
67 int found=0;
69 FD_ZERO(&fds2);
71 while (1)
73 int i;
74 for (i=0;i<255;i++) {
75 if (FD_ISSET(i,fds) && pollfd(i)>0) {
76 found++;
77 FD_SET(i,&fds2);
81 if (found) {
82 memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
83 return(found);
86 if (tval && tval->tv_sec < counter) return(0);
87 sleep(1);
88 counter++;
92 #else
93 int sys_select(fd_set *fds,struct timeval *tval)
95 struct timeval t2;
96 int selrtn;
98 do {
99 if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
100 errno = 0;
101 selrtn = select(255,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
102 } while (selrtn<0 && errno == EINTR);
104 return(selrtn);
106 #endif
109 /*******************************************************************
110 just a unlink wrapper
111 ********************************************************************/
112 int sys_unlink(char *fname)
114 return(unlink(dos_to_unix(fname,False)));
118 /*******************************************************************
119 a simple open() wrapper
120 ********************************************************************/
121 int sys_open(char *fname,int flags,int mode)
123 return(open(dos_to_unix(fname,False),flags,mode));
127 /*******************************************************************
128 a simple opendir() wrapper
129 ********************************************************************/
130 DIR *sys_opendir(char *dname)
132 return(opendir(dos_to_unix(dname,False)));
136 /*******************************************************************
137 and a stat() wrapper
138 ********************************************************************/
139 int sys_stat(char *fname,struct stat *sbuf)
141 return(stat(dos_to_unix(fname,False),sbuf));
144 /*******************************************************************
145 The wait() calls vary between systems
146 ********************************************************************/
147 int sys_waitpid(pid_t pid,int *status,int options)
149 #ifdef USE_WAITPID
150 return waitpid(pid,status,options);
151 #else /* USE_WAITPID */
152 return wait4(pid, status, options, NULL);
153 #endif /* USE_WAITPID */
156 /*******************************************************************
157 don't forget lstat()
158 ********************************************************************/
159 int sys_lstat(char *fname,struct stat *sbuf)
161 return(lstat(dos_to_unix(fname,False),sbuf));
165 /*******************************************************************
166 mkdir() gets a wrapper
167 ********************************************************************/
168 int sys_mkdir(char *dname,int mode)
170 return(mkdir(dos_to_unix(dname,False),mode));
174 /*******************************************************************
175 do does rmdir()
176 ********************************************************************/
177 int sys_rmdir(char *dname)
179 return(rmdir(dos_to_unix(dname,False)));
183 /*******************************************************************
184 I almost forgot chdir()
185 ********************************************************************/
186 int sys_chdir(char *dname)
188 return(chdir(dos_to_unix(dname,False)));
192 /*******************************************************************
193 now for utime()
194 ********************************************************************/
195 int sys_utime(char *fname,struct utimbuf *times)
197 return(utime(dos_to_unix(fname,False),times));
200 /*********************************************************
201 for rename across filesystems Patch from Warren Birnbaum
202 <warrenb@hpcvscdp.cv.hp.com>
203 **********************************************************/
205 static int copy_reg(char *source, const char *dest)
207 struct stat source_stats;
208 int ifd;
209 int full_write();
210 int safe_read();
211 int ofd;
212 char *buf;
213 int len; /* Number of bytes read into `buf'. */
215 lstat (source, &source_stats);
216 if (!S_ISREG (source_stats.st_mode))
218 return 1;
221 if (unlink (dest) && errno != ENOENT)
223 return 1;
226 if((ifd = open (source, O_RDONLY, 0)) < 0)
228 return 1;
230 if((ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 )
232 close (ifd);
233 return 1;
236 if((buf = malloc( COPYBUF_SIZE )) == NULL)
238 close (ifd);
239 close (ofd);
240 unlink (dest);
241 return 1;
244 while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0)
246 if (write_data(ofd, buf, len) < 0)
248 close (ifd);
249 close (ofd);
250 unlink (dest);
251 free(buf);
252 return 1;
255 free(buf);
256 if (len < 0)
258 close (ifd);
259 close (ofd);
260 unlink (dest);
261 return 1;
264 if (close (ifd) < 0)
266 close (ofd);
267 return 1;
269 if (close (ofd) < 0)
271 return 1;
274 /* chown turns off set[ug]id bits for non-root,
275 so do the chmod last. */
277 /* Try to copy the old file's modtime and access time. */
279 struct utimbuf tv;
281 tv.actime = source_stats.st_atime;
282 tv.modtime = source_stats.st_mtime;
283 if (utime (dest, &tv))
285 return 1;
289 /* Try to preserve ownership. For non-root it might fail, but that's ok.
290 But root probably wants to know, e.g. if NFS disallows it. */
291 if (chown (dest, source_stats.st_uid, source_stats.st_gid)
292 && (errno != EPERM))
294 return 1;
297 if (chmod (dest, source_stats.st_mode & 07777))
299 return 1;
301 unlink (source);
302 return 0;
305 /*******************************************************************
306 for rename()
307 ********************************************************************/
308 int sys_rename(char *from, char *to)
310 int rcode;
311 pstring zfrom, zto;
313 pstrcpy (zfrom, dos_to_unix (from, False));
314 pstrcpy (zto, dos_to_unix (to, False));
315 rcode = rename (zfrom, zto);
317 if (errno == EXDEV)
319 /* Rename across filesystems needed. */
320 rcode = copy_reg (zfrom, zto);
322 return rcode;
325 /*******************************************************************
326 for chmod
327 ********************************************************************/
328 int sys_chmod(char *fname,int mode)
330 return(chmod(dos_to_unix(fname,False),mode));
333 /*******************************************************************
334 for getwd
335 ********************************************************************/
336 char *sys_getwd(char *s)
338 char *wd;
339 #ifdef USE_GETCWD
340 wd = (char *) getcwd (s, sizeof (pstring));
341 #else
342 wd = (char *) getwd (s);
343 #endif
344 if (wd)
345 unix_to_dos (wd, True);
346 return wd;
349 /*******************************************************************
350 chown isn't used much but OS/2 doesn't have it
351 ********************************************************************/
352 int sys_chown(char *fname,int uid,int gid)
354 #ifdef NO_CHOWN
355 DEBUG(1,("Warning - chown(%s,%d,%d) not done\n",fname,uid,gid));
356 #else
357 return(chown(fname,uid,gid));
358 #endif
361 /*******************************************************************
362 os/2 also doesn't have chroot
363 ********************************************************************/
364 int sys_chroot(char *dname)
366 #ifdef NO_CHROOT
367 DEBUG(1,("Warning - chroot(%s) not done\n",dname));
368 #else
369 return(chroot(dname));
370 #endif
373 /**************************************************************************
374 A wrapper for gethostbyname() that tries avoids looking up hostnames
375 in the root domain, which can cause dial-on-demand links to come up for no
376 apparent reason.
377 ****************************************************************************/
378 struct hostent *sys_gethostbyname(char *name)
380 #ifdef REDUCE_ROOT_DNS_LOOKUPS
381 char query[256], hostname[256];
382 char *domain;
384 /* Does this name have any dots in it? If so, make no change */
386 if (strchr(name, '.'))
387 return(gethostbyname(name));
389 /* Get my hostname, which should have domain name
390 attached. If not, just do the gethostname on the
391 original string.
394 gethostname(hostname, sizeof(hostname) - 1);
395 hostname[sizeof(hostname) - 1] = 0;
396 if ((domain = strchr(hostname, '.')) == NULL)
397 return(gethostbyname(name));
399 /* Attach domain name to query and do modified query.
400 If names too large, just do gethostname on the
401 original string.
404 if((strlen(name) + strlen(domain)) >= sizeof(query))
405 return(gethostbyname(name));
407 sprintf(query, "%s%s", name, domain);
408 return(gethostbyname(query));
409 #else /* REDUCE_ROOT_DNS_LOOKUPS */
410 return(gethostbyname(name));
411 #endif /* REDUCE_ROOT_DNS_LOOKUPS */