2 Unix SMB/Netbios implementation.
5 Copyright (C) Jeremy Allison 1992-1998
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.
25 * Wrappers for calls that need to translate to
26 * DOS/Windows semantics. Note that the pathnames
27 * in all these functions referred to as 'DOS' names
28 * are actually in UNIX path format (ie. '/' instead of
29 * '\' directory separators etc.), but the codepage they
30 * are in is still the client codepage, hence the 'DOS'
34 extern int DEBUGLEVEL;
36 /*******************************************************************
37 Unlink wrapper that calls dos_to_unix.
38 ********************************************************************/
40 int dos_unlink(char *fname)
42 return(unlink(dos_to_unix(fname,False)));
45 /*******************************************************************
46 Open() wrapper that calls dos_to_unix.
47 ********************************************************************/
49 int dos_open(char *fname,int flags,mode_t mode)
51 return(sys_open(dos_to_unix(fname,False),flags,mode));
54 /*******************************************************************
55 Opendir() wrapper that calls dos_to_unix.
56 ********************************************************************/
58 DIR *dos_opendir(char *dname)
60 return(opendir(dos_to_unix(dname,False)));
63 /*******************************************************************
64 Readdirname() wrapper that calls unix_to_dos.
65 ********************************************************************/
67 char *dos_readdirname(DIR *p)
69 char *dname = readdirname(p);
74 unix_to_dos(dname, True);
78 /*******************************************************************
79 A chown() wrapper that calls dos_to_unix.
80 ********************************************************************/
82 int dos_chown(char *fname, uid_t uid, gid_t gid)
84 return(sys_chown(dos_to_unix(fname,False),uid,gid));
87 /*******************************************************************
88 A stat() wrapper that calls dos_to_unix.
89 ********************************************************************/
91 int dos_stat(char *fname,SMB_STRUCT_STAT *sbuf)
93 return(sys_stat(dos_to_unix(fname,False),sbuf));
96 /*******************************************************************
97 An lstat() that calls dos_to_unix.
98 ********************************************************************/
100 int dos_lstat(char *fname,SMB_STRUCT_STAT *sbuf)
102 return(sys_lstat(dos_to_unix(fname,False),sbuf));
105 /*******************************************************************
106 Mkdir() that calls dos_to_unix.
107 Cope with UNIXes that don't allow high order mode bits on mkdir.
108 Patch from gcarter@lanier.com.
109 ********************************************************************/
111 int dos_mkdir(char *dname,mode_t mode)
113 int ret = mkdir(dos_to_unix(dname,False),mode);
115 return(dos_chmod(dname,mode));
120 /*******************************************************************
121 Rmdir() - call dos_to_unix.
122 ********************************************************************/
124 int dos_rmdir(char *dname)
126 return(rmdir(dos_to_unix(dname,False)));
129 /*******************************************************************
130 chdir() - call dos_to_unix.
131 ********************************************************************/
133 int dos_chdir(char *dname)
135 return(chdir(dos_to_unix(dname,False)));
138 /*******************************************************************
139 Utime() - call dos_to_unix.
140 ********************************************************************/
142 int dos_utime(char *fname,struct utimbuf *times)
144 /* if the modtime is 0 or -1 then ignore the call and
146 if (times->modtime == (time_t)0 || times->modtime == (time_t)-1)
149 /* if the access time is 0 or -1 then set it to the modtime */
150 if (times->actime == (time_t)0 || times->actime == (time_t)-1)
151 times->actime = times->modtime;
153 return(utime(dos_to_unix(fname,False),times));
156 /*********************************************************
157 For rename across filesystems Patch from Warren Birnbaum
158 <warrenb@hpcvscdp.cv.hp.com>
159 **********************************************************/
161 static int copy_reg(char *source, const char *dest)
163 SMB_STRUCT_STAT source_stats;
167 int len; /* Number of bytes read into `buf'. */
169 sys_lstat (source, &source_stats);
170 if (!S_ISREG (source_stats.st_mode))
173 if (unlink (dest) && errno != ENOENT)
176 if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
179 if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 )
185 if((buf = malloc( COPYBUF_SIZE )) == NULL)
193 while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0)
195 if (write_data(ofd, buf, len) < 0)
221 /* chown turns off set[ug]id bits for non-root,
222 so do the chmod last. */
224 /* Try to copy the old file's modtime and access time. */
228 tv.actime = source_stats.st_atime;
229 tv.modtime = source_stats.st_mtime;
230 if (utime (dest, &tv))
234 /* Try to preserve ownership. For non-root it might fail, but that's ok.
235 But root probably wants to know, e.g. if NFS disallows it. */
236 if (chown (dest, source_stats.st_uid, source_stats.st_gid)
240 if (chmod (dest, source_stats.st_mode & 07777))
247 /*******************************************************************
248 Rename() - call dos_to_unix.
249 ********************************************************************/
251 int dos_rename(char *from, char *to)
256 pstrcpy (zfrom, dos_to_unix (from, False));
257 pstrcpy (zto, dos_to_unix (to, False));
258 rcode = rename (zfrom, zto);
262 /* Rename across filesystems needed. */
263 rcode = copy_reg (zfrom, zto);
268 /*******************************************************************
269 Chmod - call dos_to_unix.
270 ********************************************************************/
272 int dos_chmod(char *fname,mode_t mode)
274 return(chmod(dos_to_unix(fname,False),mode));
277 /*******************************************************************
278 Getwd - takes a UNIX directory name and returns the name
280 ********************************************************************/
282 char *dos_getwd(char *unix_path)
285 wd = sys_getwd(unix_path);
287 unix_to_dos(wd, True);
291 /*******************************************************************
292 Check if a DOS file exists.
293 ********************************************************************/
295 BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
297 return file_exist(dos_to_unix(fname, False), sbuf);
300 /*******************************************************************
301 Check if a DOS directory exists.
302 ********************************************************************/
304 BOOL dos_directory_exist(char *dname,SMB_STRUCT_STAT *st)
306 return directory_exist(dos_to_unix(dname, False), st);
309 /*******************************************************************
310 Return the modtime of a DOS pathname.
311 ********************************************************************/
313 time_t dos_file_modtime(char *fname)
315 return file_modtime(dos_to_unix(fname, False));
318 /*******************************************************************
319 Return the file size of a DOS pathname.
320 ********************************************************************/
322 SMB_OFF_T dos_file_size(char *file_name)
324 return get_file_size(dos_to_unix(file_name, False));
327 /*******************************************************************
328 A wrapper for dos_chdir().
329 ********************************************************************/
331 int dos_ChDir(char *path)
334 static pstring LastDir="";
336 if (strcsequal(path,"."))
339 if (*path == '/' && strcsequal(LastDir,path))
342 DEBUG(3,("dos_ChDir to %s\n",path));
344 res = dos_chdir(path);
346 pstrcpy(LastDir,path);
350 /* number of list structures for a caching GetWd function. */
351 #define MAX_GETWDCACHE (50)
355 SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
356 SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
357 char *dos_path; /* The pathname in DOS format. */
359 } ino_list[MAX_GETWDCACHE];
361 BOOL use_getwd_cache=True;
363 /****************************************************************************
364 Prompte a ptr (to make it recently used)
365 ****************************************************************************/
367 static void array_promote(char *array,int elsize,int element)
373 p = (char *)malloc(elsize);
377 DEBUG(5,("Ahh! Can't malloc\n"));
380 memcpy(p,array + element * elsize, elsize);
381 memmove(array + elsize,array,elsize*element);
382 memcpy(array,p,elsize);
386 /*******************************************************************
387 Return the absolute current directory path - given a UNIX pathname.
388 Note that this path is returned in DOS format, not UNIX
390 ********************************************************************/
392 char *dos_GetWd(char *path)
395 static BOOL getwd_cache_init = False;
396 SMB_STRUCT_STAT st, st2;
401 if (!use_getwd_cache)
402 return(dos_getwd(path));
405 if (!getwd_cache_init)
407 getwd_cache_init = True;
408 for (i=0;i<MAX_GETWDCACHE;i++)
410 string_init(&ino_list[i].dos_path,"");
411 ino_list[i].valid = False;
415 /* Get the inode of the current directory, if this doesn't work we're
418 if (sys_stat(".",&st) == -1)
420 DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path));
421 return(dos_getwd(path));
425 for (i=0; i<MAX_GETWDCACHE; i++)
426 if (ino_list[i].valid)
429 /* If we have found an entry with a matching inode and dev number
430 then find the inode number for the directory in the cached string.
431 If this agrees with that returned by the stat for the current
432 directory then all is o.k. (but make sure it is a directory all
435 if (st.st_ino == ino_list[i].inode &&
436 st.st_dev == ino_list[i].dev)
438 if (dos_stat(ino_list[i].dos_path,&st2) == 0)
440 if (st.st_ino == st2.st_ino &&
441 st.st_dev == st2.st_dev &&
442 (st2.st_mode & S_IFMT) == S_IFDIR)
444 pstrcpy (path, ino_list[i].dos_path);
446 /* promote it for future use */
447 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
452 /* If the inode is different then something's changed,
453 scrub the entry and start from scratch. */
454 ino_list[i].valid = False;
461 /* We don't have the information to hand so rely on traditional methods.
462 The very slow getcwd, which spawns a process on some systems, or the
463 not quite so bad getwd. */
467 DEBUG(0,("dos_GetWd: dos_getwd call failed, errno %s\n",strerror(errno)));
473 DEBUG(5,("dos_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
475 /* add it to the cache */
476 i = MAX_GETWDCACHE - 1;
477 string_set(&ino_list[i].dos_path,s);
478 ino_list[i].dev = st.st_dev;
479 ino_list[i].inode = st.st_ino;
480 ino_list[i].valid = True;
482 /* put it at the top of the list */
483 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);