fixing smbpasswd to link to smbd to obtain domain sid
[samba.git] / source3 / lib / doscalls.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba system utilities
5    Copyright (C) Jeremy Allison 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 /*
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'
31  * name.
32  */
33
34 extern int DEBUGLEVEL;
35
36 /*******************************************************************
37  Unlink wrapper that calls dos_to_unix.
38 ********************************************************************/
39
40 int dos_unlink(char *fname)
41 {
42   return(unlink(dos_to_unix(fname,False)));
43 }
44
45 /*******************************************************************
46  Open() wrapper that calls dos_to_unix.
47 ********************************************************************/
48
49 int dos_open(char *fname,int flags,mode_t mode)
50 {
51   return(sys_open(dos_to_unix(fname,False),flags,mode));
52 }
53
54 /*******************************************************************
55  Opendir() wrapper that calls dos_to_unix.
56 ********************************************************************/
57
58 DIR *dos_opendir(char *dname)
59 {
60   return(opendir(dos_to_unix(dname,False)));
61 }
62
63 /*******************************************************************
64  Readdirname() wrapper that calls unix_to_dos.
65 ********************************************************************/
66
67 char *dos_readdirname(DIR *p)
68 {
69   char *dname = readdirname(p);
70
71   if (!dname)
72     return(NULL);
73  
74   unix_to_dos(dname, True);
75   return(dname);
76 }
77
78 /*******************************************************************
79  A stat() wrapper that calls dos_to_unix.
80 ********************************************************************/
81
82 int dos_stat(char *fname,SMB_STRUCT_STAT *sbuf)
83 {
84   return(sys_stat(dos_to_unix(fname,False),sbuf));
85 }
86
87 /*******************************************************************
88  An lstat() that calls dos_to_unix.
89 ********************************************************************/
90
91 int dos_lstat(char *fname,SMB_STRUCT_STAT *sbuf)
92 {
93   return(sys_lstat(dos_to_unix(fname,False),sbuf));
94 }
95
96 /*******************************************************************
97  Mkdir() that calls dos_to_unix.
98 ********************************************************************/
99
100 int dos_mkdir(char *dname,mode_t mode)
101 {
102   return(mkdir(dos_to_unix(dname,False),mode));
103 }
104
105 /*******************************************************************
106  Rmdir() - call dos_to_unix.
107 ********************************************************************/
108
109 int dos_rmdir(char *dname)
110 {
111   return(rmdir(dos_to_unix(dname,False)));
112 }
113
114 /*******************************************************************
115  chdir() - call dos_to_unix.
116 ********************************************************************/
117
118 int dos_chdir(char *dname)
119 {
120   return(chdir(dos_to_unix(dname,False)));
121 }
122
123 /*******************************************************************
124  Utime() - call dos_to_unix.
125 ********************************************************************/
126
127 int dos_utime(char *fname,struct utimbuf *times)
128 {
129   /* if the modtime is 0 or -1 then ignore the call and
130      return success */
131   if (times->modtime == (time_t)0 || times->modtime == (time_t)-1)
132     return 0;
133   
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;
137    
138   return(utime(dos_to_unix(fname,False),times));
139 }
140
141 /*********************************************************
142  For rename across filesystems Patch from Warren Birnbaum 
143  <warrenb@hpcvscdp.cv.hp.com>
144 **********************************************************/
145
146 int copy_reg(char *source, const char *dest)
147 {
148   SMB_STRUCT_STAT source_stats;
149   int ifd;
150   int ofd;
151   char *buf;
152   int len;                      /* Number of bytes read into `buf'. */
153
154   sys_lstat (source, &source_stats);
155   if (!S_ISREG (source_stats.st_mode))
156     return 1;
157
158   if (unlink (dest) && errno != ENOENT)
159     return 1;
160
161   if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
162     return 1;
163
164   if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 )
165   {
166     close (ifd);
167     return 1;
168   }
169
170   if((buf = malloc( COPYBUF_SIZE )) == NULL)
171   {
172     close (ifd);  
173     close (ofd);  
174     unlink (dest);
175     return 1;
176   }
177
178   while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0)
179   {
180     if (write_data(ofd, buf, len) < 0)
181     {
182       close (ifd);
183       close (ofd);
184       unlink (dest);
185       free(buf);
186       return 1;
187     }
188   }
189   free(buf);
190   if (len < 0)
191   {
192     close (ifd);
193     close (ofd);
194     unlink (dest);
195     return 1;
196   }
197
198   if (close (ifd) < 0)
199   {
200     close (ofd);
201     return 1;
202   }
203   if (close (ofd) < 0)
204     return 1;
205
206   /* chown turns off set[ug]id bits for non-root,
207      so do the chmod last.  */
208
209   /* Try to copy the old file's modtime and access time.  */
210   {
211     struct utimbuf tv;
212
213     tv.actime = source_stats.st_atime;
214     tv.modtime = source_stats.st_mtime;
215     if (utime (dest, &tv))
216       return 1;
217   }
218
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)
222       && (errno != EPERM))
223     return 1;
224
225   if (chmod (dest, source_stats.st_mode & 07777))
226     return 1;
227
228   unlink (source);
229   return 0;
230 }
231
232 /*******************************************************************
233  Rename() - call dos_to_unix.
234 ********************************************************************/
235
236 int dos_rename(char *from, char *to)
237 {
238     pstring zfrom, zto;
239
240     pstrcpy (zfrom, dos_to_unix (from, False));
241     pstrcpy (zto, dos_to_unix (to, False));
242     return file_rename(zfrom, zto);
243 }
244
245 /*******************************************************************
246  Chmod - call dos_to_unix.
247 ********************************************************************/
248
249 int dos_chmod(char *fname,mode_t mode)
250 {
251   return(chmod(dos_to_unix(fname,False),mode));
252 }
253
254 /*******************************************************************
255  Getwd - takes a UNIX directory name and returns the name
256  in dos format.
257 ********************************************************************/
258
259 char *dos_getwd(char *unix_path)
260 {
261         char *wd;
262         wd = sys_getwd(unix_path);
263         if (wd)
264                 unix_to_dos(wd, True);
265         return wd;
266 }
267
268 /*******************************************************************
269  Check if a DOS file exists.
270 ********************************************************************/
271
272 BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
273 {
274   return file_exist(dos_to_unix(fname, False), sbuf);
275 }
276
277 /*******************************************************************
278  Check if a DOS directory exists.
279 ********************************************************************/
280
281 BOOL dos_directory_exist(char *dname,SMB_STRUCT_STAT *st)
282 {
283   return directory_exist(dos_to_unix(dname, False), st);
284 }
285
286 /*******************************************************************
287  Return the modtime of a DOS pathname.
288 ********************************************************************/
289
290 time_t dos_file_modtime(char *fname)
291 {
292   return file_modtime(dos_to_unix(fname, False));
293 }
294
295 /*******************************************************************
296  Return the file size of a DOS pathname.
297 ********************************************************************/
298
299 SMB_OFF_T dos_file_size(char *file_name)
300 {
301   return file_size(dos_to_unix(file_name, False));
302 }
303
304 /*******************************************************************
305  A wrapper for dos_chdir().
306 ********************************************************************/
307
308 int dos_ChDir(char *path)
309 {
310   int res;
311   static pstring LastDir="";
312
313   if (strcsequal(path,"."))
314     return(0);
315
316   if (*path == '/' && strcsequal(LastDir,path))
317     return(0);
318
319   DEBUG(3,("dos_ChDir to %s\n",path));
320
321   res = dos_chdir(path);
322   if (!res)
323     pstrcpy(LastDir,path);
324   return(res);
325 }
326
327 /* number of list structures for a caching GetWd function. */
328 #define MAX_GETWDCACHE (50)
329
330 struct
331 {
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. */
335   BOOL valid;
336 } ino_list[MAX_GETWDCACHE];
337
338 BOOL use_getwd_cache=True;
339
340 /****************************************************************************
341  Prompte a ptr (to make it recently used)
342 ****************************************************************************/
343
344 static void array_promote(char *array,int elsize,int element)
345 {
346   char *p;
347   if (element == 0)
348     return;
349
350   p = (char *)malloc(elsize);
351
352   if (!p)
353     {
354       DEBUG(5,("Ahh! Can't malloc\n"));
355       return;
356     }
357   memcpy(p,array + element * elsize, elsize);
358   memmove(array + elsize,array,elsize*element);
359   memcpy(array,p,elsize);
360   free(p);
361 }
362
363 /*******************************************************************
364  Return the absolute current directory path - given a UNIX pathname.
365  Note that this path is returned in DOS format, not UNIX
366  format.
367 ********************************************************************/
368
369 char *dos_GetWd(char *path)
370 {
371   pstring s;
372   static BOOL getwd_cache_init = False;
373   SMB_STRUCT_STAT st, st2;
374   int i;
375
376   *s = 0;
377
378   if (!use_getwd_cache)
379     return(dos_getwd(path));
380
381   /* init the cache */
382   if (!getwd_cache_init)
383   {
384     getwd_cache_init = True;
385     for (i=0;i<MAX_GETWDCACHE;i++)
386     {
387       string_init(&ino_list[i].dos_path,"");
388       ino_list[i].valid = False;
389     }
390   }
391
392   /*  Get the inode of the current directory, if this doesn't work we're
393       in trouble :-) */
394
395   if (sys_stat(".",&st) == -1)
396   {
397     DEBUG(0,("Very strange, couldn't stat \".\"\n"));
398     return(dos_getwd(path));
399   }
400
401
402   for (i=0; i<MAX_GETWDCACHE; i++)
403     if (ino_list[i].valid)
404     {
405
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
410           the same...) */
411
412       if (st.st_ino == ino_list[i].inode &&
413           st.st_dev == ino_list[i].dev)
414       {
415         if (dos_stat(ino_list[i].dos_path,&st2) == 0)
416         {
417           if (st.st_ino == st2.st_ino &&
418               st.st_dev == st2.st_dev &&
419               (st2.st_mode & S_IFMT) == S_IFDIR)
420           {
421             pstrcpy (path, ino_list[i].dos_path);
422
423             /* promote it for future use */
424             array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
425             return (path);
426           }
427           else
428           {
429             /*  If the inode is different then something's changed,
430                 scrub the entry and start from scratch. */
431             ino_list[i].valid = False;
432           }
433         }
434       }
435     }
436
437
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. */
441
442   if (!dos_getwd(s))
443   {
444     DEBUG(0,("dos_GetWd: dos_getwd call failed, errno %s\n",strerror(errno)));
445     return (NULL);
446   }
447
448   pstrcpy(path,s);
449
450   DEBUG(5,("dos_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
451
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;
458
459   /* put it at the top of the list */
460   array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
461
462   return (path);
463 }