diff options
author | Jeremy Allison <jra@samba.org> | 1998-11-25 21:17:20 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 1998-11-25 21:17:20 +0000 |
commit | bfc38ff872446e0ad365c22327c779e72a81bef9 (patch) | |
tree | b7178459d9b4ce5acc7dc636d81ac4cba745b723 /source3/lib/doscalls.c | |
parent | 59d4087160ba41aac724722dc29c4b6e4e3b69b0 (diff) | |
download | samba-bfc38ff872446e0ad365c22327c779e72a81bef9.tar.gz samba-bfc38ff872446e0ad365c22327c779e72a81bef9.tar.bz2 samba-bfc38ff872446e0ad365c22327c779e72a81bef9.zip |
Makefile.in: Added maintainer mode fixes.
aclocal.m4: Added AC_LIBTESTFUNC.
configure.in: Fixed -lsecurity -lsec problems.
client.c: dos_ fixes.
groupdb/aliasunix.c: Dead code removal.
include/includes.h: Added default PRINTCAP_NAME.
lib/genrand.c: dos_ fixes.
lib/replace.c: Added strtoul.
lib/system.c: dos_ fixes.
lib/util.c: dos_ fixes.
lib/util_sid.c: Signed/unsigned fixes.
lib/util_str.c: removed bad const.
locking/locking_slow.c: dos_ fixes.
printing/printing.c: dos_ fixes.
rpc_server/srv_samr.c: Dead code removal.
rpc_server/srv_sid.c: global_myworkgroup defined with wrong size AGAIN !
smbd/dir.c: dos_ fixes.
smbd/open.c: dos_ fixes.
smbd/oplock.c: dos_ fixes.
smbd/reply.c smbd/server.c smbd/service.c smbd/uid.c: dos_ fixes.
Jeremy.
(This used to be commit 6acb4b68f68d516e2ac3c47e500f5600d653435e)
Diffstat (limited to 'source3/lib/doscalls.c')
-rw-r--r-- | source3/lib/doscalls.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/source3/lib/doscalls.c b/source3/lib/doscalls.c new file mode 100644 index 0000000000..031effcf52 --- /dev/null +++ b/source3/lib/doscalls.c @@ -0,0 +1,471 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba system utilities + Copyright (C) Jeremy Allison 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + * Wrappers for calls that need to translate to + * DOS/Windows semantics. Note that the pathnames + * in all these functions referred to as 'DOS' names + * are actually in UNIX path format (ie. '/' instead of + * '\' directory separators etc.), but the codepage they + * are in is still the client codepage, hence the 'DOS' + * name. + */ + +extern int DEBUGLEVEL; + +/******************************************************************* + Unlink wrapper that calls dos_to_unix. +********************************************************************/ + +int dos_unlink(char *fname) +{ + return(unlink(dos_to_unix(fname,False))); +} + +/******************************************************************* + Open() wrapper that calls dos_to_unix. +********************************************************************/ + +int dos_open(char *fname,int flags,mode_t mode) +{ + return(sys_open(dos_to_unix(fname,False),flags,mode)); +} + +/******************************************************************* + Opendir() wrapper that calls dos_to_unix. +********************************************************************/ + +DIR *dos_opendir(char *dname) +{ + return(opendir(dos_to_unix(dname,False))); +} + +/******************************************************************* + Readdirname() wrapper that calls unix_to_dos. +********************************************************************/ + +char *dos_readdirname(DIR *p) +{ + char *dname = readdirname(p); + + if (!dname) + return(NULL); + + unix_to_dos(dname, True); + return(dname); +} + +/******************************************************************* + A stat() wrapper that calls dos_to_unix. +********************************************************************/ + +int dos_stat(char *fname,SMB_STRUCT_STAT *sbuf) +{ + return(sys_stat(dos_to_unix(fname,False),sbuf)); +} + +/******************************************************************* + An lstat() that calls dos_to_unix. +********************************************************************/ + +int dos_lstat(char *fname,SMB_STRUCT_STAT *sbuf) +{ + return(sys_lstat(dos_to_unix(fname,False),sbuf)); +} + +/******************************************************************* + Mkdir() that calls dos_to_unix. +********************************************************************/ + +int dos_mkdir(char *dname,mode_t mode) +{ + return(mkdir(dos_to_unix(dname,False),mode)); +} + +/******************************************************************* + Rmdir() - call dos_to_unix. +********************************************************************/ + +int dos_rmdir(char *dname) +{ + return(rmdir(dos_to_unix(dname,False))); +} + +/******************************************************************* + chdir() - call dos_to_unix. +********************************************************************/ + +int dos_chdir(char *dname) +{ + return(chdir(dos_to_unix(dname,False))); +} + +/******************************************************************* + Utime() - call dos_to_unix. +********************************************************************/ + +int dos_utime(char *fname,struct utimbuf *times) +{ + /* if the modtime is 0 or -1 then ignore the call and + return success */ + if (times->modtime == (time_t)0 || times->modtime == (time_t)-1) + return 0; + + /* if the access time is 0 or -1 then set it to the modtime */ + if (times->actime == (time_t)0 || times->actime == (time_t)-1) + times->actime = times->modtime; + + return(utime(dos_to_unix(fname,False),times)); +} + +/********************************************************* + For rename across filesystems Patch from Warren Birnbaum + <warrenb@hpcvscdp.cv.hp.com> +**********************************************************/ + +static int copy_reg(char *source, const char *dest) +{ + SMB_STRUCT_STAT source_stats; + int ifd; + int ofd; + char *buf; + int len; /* Number of bytes read into `buf'. */ + + sys_lstat (source, &source_stats); + if (!S_ISREG (source_stats.st_mode)) + return 1; + + if (unlink (dest) && errno != ENOENT) + return 1; + + if((ifd = sys_open (source, O_RDONLY, 0)) < 0) + return 1; + + if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) + { + close (ifd); + return 1; + } + + if((buf = malloc( COPYBUF_SIZE )) == NULL) + { + close (ifd); + close (ofd); + unlink (dest); + return 1; + } + + while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0) + { + if (write_data(ofd, buf, len) < 0) + { + close (ifd); + close (ofd); + unlink (dest); + free(buf); + return 1; + } + } + free(buf); + if (len < 0) + { + close (ifd); + close (ofd); + unlink (dest); + return 1; + } + + if (close (ifd) < 0) + { + close (ofd); + return 1; + } + if (close (ofd) < 0) + return 1; + + /* chown turns off set[ug]id bits for non-root, + so do the chmod last. */ + + /* Try to copy the old file's modtime and access time. */ + { + struct utimbuf tv; + + tv.actime = source_stats.st_atime; + tv.modtime = source_stats.st_mtime; + if (utime (dest, &tv)) + return 1; + } + + /* Try to preserve ownership. For non-root it might fail, but that's ok. + But root probably wants to know, e.g. if NFS disallows it. */ + if (chown (dest, source_stats.st_uid, source_stats.st_gid) + && (errno != EPERM)) + return 1; + + if (chmod (dest, source_stats.st_mode & 07777)) + return 1; + + unlink (source); + return 0; +} + +/******************************************************************* + Rename() - call dos_to_unix. +********************************************************************/ + +int dos_rename(char *from, char *to) +{ + int rcode; + pstring zfrom, zto; + + pstrcpy (zfrom, dos_to_unix (from, False)); + pstrcpy (zto, dos_to_unix (to, False)); + rcode = rename (zfrom, zto); + + if (errno == EXDEV) + { + /* Rename across filesystems needed. */ + rcode = copy_reg (zfrom, zto); + } + return rcode; +} + +/******************************************************************* + Chmod - call dos_to_unix. +********************************************************************/ + +int dos_chmod(char *fname,mode_t mode) +{ + return(chmod(dos_to_unix(fname,False),mode)); +} + +/******************************************************************* + Getwd - takes a UNIX directory name and returns the name + in dos format. +********************************************************************/ + +char *dos_getwd(char *unix_path) +{ + char *wd; + wd = sys_getwd(unix_path); + if (wd) + unix_to_dos(wd, True); + return wd; +} + +/******************************************************************* + Check if a DOS file exists. +********************************************************************/ + +BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf) +{ + return file_exist(dos_to_unix(fname, False), sbuf); +} + +/******************************************************************* + Check if a DOS directory exists. +********************************************************************/ + +BOOL dos_directory_exist(char *dname,SMB_STRUCT_STAT *st) +{ + return directory_exist(dos_to_unix(dname, False), st); +} + +/******************************************************************* + Return the modtime of a DOS pathname. +********************************************************************/ + +time_t dos_file_modtime(char *fname) +{ + return file_modtime(dos_to_unix(fname, False)); +} + +/******************************************************************* + Return the file size of a DOS pathname. +********************************************************************/ + +SMB_OFF_T dos_file_size(char *file_name) +{ + return file_size(dos_to_unix(file_name, False)); +} + +/******************************************************************* + A wrapper for dos_chdir(). +********************************************************************/ + +int dos_ChDir(char *path) +{ + int res; + static pstring LastDir=""; + + if (strcsequal(path,".")) + return(0); + + if (*path == '/' && strcsequal(LastDir,path)) + return(0); + + DEBUG(3,("dos_ChDir to %s\n",path)); + + res = dos_chdir(path); + if (!res) + pstrcpy(LastDir,path); + return(res); +} + +/* number of list structures for a caching GetWd function. */ +#define MAX_GETWDCACHE (50) + +struct +{ + SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */ + SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */ + char *dos_path; /* The pathname in DOS format. */ + BOOL valid; +} ino_list[MAX_GETWDCACHE]; + +BOOL use_getwd_cache=True; + +/**************************************************************************** + Prompte a ptr (to make it recently used) +****************************************************************************/ + +static void array_promote(char *array,int elsize,int element) +{ + char *p; + if (element == 0) + return; + + p = (char *)malloc(elsize); + + if (!p) + { + DEBUG(5,("Ahh! Can't malloc\n")); + return; + } + memcpy(p,array + element * elsize, elsize); + memmove(array + elsize,array,elsize*element); + memcpy(array,p,elsize); + free(p); +} + +/******************************************************************* + Return the absolute current directory path - given a UNIX pathname. + Note that this path is returned in DOS format, not UNIX + format. +********************************************************************/ + +char *dos_GetWd(char *path) +{ + pstring s; + static BOOL getwd_cache_init = False; + SMB_STRUCT_STAT st, st2; + int i; + + *s = 0; + + if (!use_getwd_cache) + return(dos_getwd(path)); + + /* init the cache */ + if (!getwd_cache_init) + { + getwd_cache_init = True; + for (i=0;i<MAX_GETWDCACHE;i++) + { + string_init(&ino_list[i].dos_path,""); + ino_list[i].valid = False; + } + } + + /* Get the inode of the current directory, if this doesn't work we're + in trouble :-) */ + + if (sys_stat(".",&st) == -1) + { + DEBUG(0,("Very strange, couldn't stat \".\"\n")); + return(dos_getwd(path)); + } + + + for (i=0; i<MAX_GETWDCACHE; i++) + if (ino_list[i].valid) + { + + /* If we have found an entry with a matching inode and dev number + then find the inode number for the directory in the cached string. + If this agrees with that returned by the stat for the current + directory then all is o.k. (but make sure it is a directory all + the same...) */ + + if (st.st_ino == ino_list[i].inode && + st.st_dev == ino_list[i].dev) + { + if (dos_stat(ino_list[i].dos_path,&st2) == 0) + { + if (st.st_ino == st2.st_ino && + st.st_dev == st2.st_dev && + (st2.st_mode & S_IFMT) == S_IFDIR) + { + pstrcpy (path, ino_list[i].dos_path); + + /* promote it for future use */ + array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); + return (path); + } + else + { + /* If the inode is different then something's changed, + scrub the entry and start from scratch. */ + ino_list[i].valid = False; + } + } + } + } + + + /* We don't have the information to hand so rely on traditional methods. + The very slow getcwd, which spawns a process on some systems, or the + not quite so bad getwd. */ + + if (!dos_getwd(s)) + { + DEBUG(0,("dos_GetWd: dos_getwd call failed, errno %s\n",strerror(errno))); + return (NULL); + } + + pstrcpy(path,s); + + DEBUG(5,("dos_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev)); + + /* add it to the cache */ + i = MAX_GETWDCACHE - 1; + string_set(&ino_list[i].dos_path,s); + ino_list[i].dev = st.st_dev; + ino_list[i].inode = st.st_ino; + ino_list[i].valid = True; + + /* put it at the top of the list */ + array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); + + return (path); +} |