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 stat() wrapper that calls dos_to_unix.
80 ********************************************************************/
82 int dos_stat(char *fname,SMB_STRUCT_STAT *sbuf)
84 return(sys_stat(dos_to_unix(fname,False),sbuf));
87 /*******************************************************************
88 An lstat() that calls dos_to_unix.
89 ********************************************************************/
91 int dos_lstat(char *fname,SMB_STRUCT_STAT *sbuf)
93 return(sys_lstat(dos_to_unix(fname,False),sbuf));
96 /*******************************************************************
97 Mkdir() that calls dos_to_unix.
98 ********************************************************************/
100 int dos_mkdir(char *dname,mode_t mode)
102 return(mkdir(dos_to_unix(dname,False),mode));
105 /*******************************************************************
106 Rmdir() - call dos_to_unix.
107 ********************************************************************/
109 int dos_rmdir(char *dname)
111 return(rmdir(dos_to_unix(dname,False)));
114 /*******************************************************************
115 chdir() - call dos_to_unix.
116 ********************************************************************/
118 int dos_chdir(char *dname)
120 return(chdir(dos_to_unix(dname,False)));
123 /*******************************************************************
124 Utime() - call dos_to_unix.
125 ********************************************************************/
127 int dos_utime(char *fname,struct utimbuf *times)
129 /* if the modtime is 0 or -1 then ignore the call and
131 if (times->modtime == (time_t)0 || times->modtime == (time_t)-1)
134 /* if the access time is 0 or -1 then set it to the modtime */
135 if (times->actime == (time_t)0 || times->actime == (time_t)-1)
136 times->actime = times->modtime;
138 return(utime(dos_to_unix(fname,False),times));
141 /*********************************************************
142 For rename across filesystems Patch from Warren Birnbaum
143 <warrenb@hpcvscdp.cv.hp.com>
144 **********************************************************/
146 int copy_reg(char *source, const char *dest)
148 SMB_STRUCT_STAT source_stats;
152 int len; /* Number of bytes read into `buf'. */
154 sys_lstat (source, &source_stats);
155 if (!S_ISREG (source_stats.st_mode))
158 if (unlink (dest) && errno != ENOENT)
161 if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
164 if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 )
170 if((buf = malloc( COPYBUF_SIZE )) == NULL)
178 while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0)
180 if (write_data(ofd, buf, len) < 0)
206 /* chown turns off set[ug]id bits for non-root,
207 so do the chmod last. */
209 /* Try to copy the old file's modtime and access time. */
213 tv.actime = source_stats.st_atime;
214 tv.modtime = source_stats.st_mtime;
215 if (utime (dest, &tv))
219 /* Try to preserve ownership. For non-root it might fail, but that's ok.
220 But root probably wants to know, e.g. if NFS disallows it. */
221 if (chown (dest, source_stats.st_uid, source_stats.st_gid)
225 if (chmod (dest, source_stats.st_mode & 07777))
232 /*******************************************************************
233 Rename() - call dos_to_unix.
234 ********************************************************************/
236 int dos_rename(char *from, char *to)
240 pstrcpy (zfrom, dos_to_unix (from, False));
241 pstrcpy (zto, dos_to_unix (to, False));
242 return file_rename(zfrom, zto);
245 /*******************************************************************
246 Chmod - call dos_to_unix.
247 ********************************************************************/
249 int dos_chmod(char *fname,mode_t mode)
251 return(chmod(dos_to_unix(fname,False),mode));
254 /*******************************************************************
255 Getwd - takes a UNIX directory name and returns the name
257 ********************************************************************/
259 char *dos_getwd(char *unix_path)
262 wd = sys_getwd(unix_path);
264 unix_to_dos(wd, True);
268 /*******************************************************************
269 Check if a DOS file exists.
270 ********************************************************************/
272 BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
274 return file_exist(dos_to_unix(fname, False), sbuf);
277 /*******************************************************************
278 Check if a DOS directory exists.
279 ********************************************************************/
281 BOOL dos_directory_exist(char *dname,SMB_STRUCT_STAT *st)
283 return directory_exist(dos_to_unix(dname, False), st);
286 /*******************************************************************
287 Return the modtime of a DOS pathname.
288 ********************************************************************/
290 time_t dos_file_modtime(char *fname)
292 return file_modtime(dos_to_unix(fname, False));
295 /*******************************************************************
296 Return the file size of a DOS pathname.
297 ********************************************************************/
299 SMB_OFF_T dos_file_size(char *file_name)
301 return file_size(dos_to_unix(file_name, False));
304 /*******************************************************************
305 A wrapper for dos_chdir().
306 ********************************************************************/
308 int dos_ChDir(char *path)
311 static pstring LastDir="";
313 if (strcsequal(path,"."))
316 if (*path == '/' && strcsequal(LastDir,path))
319 DEBUG(3,("dos_ChDir to %s\n",path));
321 res = dos_chdir(path);
323 pstrcpy(LastDir,path);
327 /* number of list structures for a caching GetWd function. */
328 #define MAX_GETWDCACHE (50)
332 SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
333 SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
334 char *dos_path; /* The pathname in DOS format. */
336 } ino_list[MAX_GETWDCACHE];
338 BOOL use_getwd_cache=True;
340 /****************************************************************************
341 Prompte a ptr (to make it recently used)
342 ****************************************************************************/
344 static void array_promote(char *array,int elsize,int element)
350 p = (char *)malloc(elsize);
354 DEBUG(5,("Ahh! Can't malloc\n"));
357 memcpy(p,array + element * elsize, elsize);
358 memmove(array + elsize,array,elsize*element);
359 memcpy(array,p,elsize);
363 /*******************************************************************
364 Return the absolute current directory path - given a UNIX pathname.
365 Note that this path is returned in DOS format, not UNIX
367 ********************************************************************/
369 char *dos_GetWd(char *path)
372 static BOOL getwd_cache_init = False;
373 SMB_STRUCT_STAT st, st2;
378 if (!use_getwd_cache)
379 return(dos_getwd(path));
382 if (!getwd_cache_init)
384 getwd_cache_init = True;
385 for (i=0;i<MAX_GETWDCACHE;i++)
387 string_init(&ino_list[i].dos_path,"");
388 ino_list[i].valid = False;
392 /* Get the inode of the current directory, if this doesn't work we're
395 if (sys_stat(".",&st) == -1)
397 DEBUG(0,("Very strange, couldn't stat \".\"\n"));
398 return(dos_getwd(path));
402 for (i=0; i<MAX_GETWDCACHE; i++)
403 if (ino_list[i].valid)
406 /* If we have found an entry with a matching inode and dev number
407 then find the inode number for the directory in the cached string.
408 If this agrees with that returned by the stat for the current
409 directory then all is o.k. (but make sure it is a directory all
412 if (st.st_ino == ino_list[i].inode &&
413 st.st_dev == ino_list[i].dev)
415 if (dos_stat(ino_list[i].dos_path,&st2) == 0)
417 if (st.st_ino == st2.st_ino &&
418 st.st_dev == st2.st_dev &&
419 (st2.st_mode & S_IFMT) == S_IFDIR)
421 pstrcpy (path, ino_list[i].dos_path);
423 /* promote it for future use */
424 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
429 /* If the inode is different then something's changed,
430 scrub the entry and start from scratch. */
431 ino_list[i].valid = False;
438 /* We don't have the information to hand so rely on traditional methods.
439 The very slow getcwd, which spawns a process on some systems, or the
440 not quite so bad getwd. */
444 DEBUG(0,("dos_GetWd: dos_getwd call failed, errno %s\n",strerror(errno)));
450 DEBUG(5,("dos_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
452 /* add it to the cache */
453 i = MAX_GETWDCACHE - 1;
454 string_set(&ino_list[i].dos_path,s);
455 ino_list[i].dev = st.st_dev;
456 ino_list[i].inode = st.st_ino;
457 ino_list[i].valid = True;
459 /* put it at the top of the list */
460 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);