diff options
Diffstat (limited to 'source4/smbwrapper/smbw.c')
-rw-r--r-- | source4/smbwrapper/smbw.c | 1554 |
1 files changed, 0 insertions, 1554 deletions
diff --git a/source4/smbwrapper/smbw.c b/source4/smbwrapper/smbw.c deleted file mode 100644 index c62533dc2a..0000000000 --- a/source4/smbwrapper/smbw.c +++ /dev/null @@ -1,1554 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions - Copyright (C) Andrew Tridgell 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" -#include "realcalls.h" - -pstring smbw_cwd; - -static struct smbw_file *smbw_files; -static struct smbw_server *smbw_srvs; - -struct bitmap *smbw_file_bmap; - -fstring smbw_prefix = SMBW_PREFIX; - -int smbw_busy=0; - -/* needs to be here because of dumb include files on some systems */ -int creat_bits = O_WRONLY|O_CREAT|O_TRUNC; - - -/***************************************************** -initialise structures -*******************************************************/ -void smbw_init(void) -{ - extern BOOL in_client; - static int initialised; - char *p; - int eno; - pstring line; - - if (initialised) return; - initialised = 1; - - eno = errno; - - smbw_busy++; - - DEBUGLEVEL = 0; - setup_logging("smbsh", DEBUG_STDOUT); - - dbf = x_stderr; - - if ((p=smbw_getshared("LOGFILE"))) { - dbf = sys_fopen(p, "a"); - } - - smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN); - if (!smbw_file_bmap) { - exit(1); - } - - in_client = True; - - load_interfaces(); - - if ((p=smbw_getshared("SERVICESF"))) { - pstrcpy(dyn_CONFIGFILE, p); - } - - lp_load(dyn_CONFIGFILE,True,False,False); - - if (!init_names()) - exit(1); - - if ((p=smbw_getshared("DEBUG"))) { - DEBUGLEVEL = atoi(p); - } - - if ((p=smbw_getshared("RESOLVE_ORDER"))) { - lp_set_name_resolve_order(p); - } - - if ((p=smbw_getshared("PREFIX"))) { - slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p); - all_string_sub(smbw_prefix,"//", "/", 0); - DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix)); - } - - slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid()); - - p = smbw_getshared(line); - if (!p) { - sys_getwd(smbw_cwd); - } - pstrcpy(smbw_cwd, p); - DEBUG(4,("Initial cwd is %s\n", smbw_cwd)); - - smbw_busy--; - - set_maxfiles(SMBW_MAX_OPEN); - - BlockSignals(True,SIGPIPE); - - errno = eno; -} - -/***************************************************** -determine if a file descriptor is a smb one -*******************************************************/ -int smbw_fd(int fd) -{ - if (smbw_busy) return 0; - return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd); -} - -/***************************************************** -determine if a file descriptor is an internal smbw fd -*******************************************************/ -int smbw_local_fd(int fd) -{ - struct smbw_server *srv; - - smbw_init(); - - if (smbw_busy) return 0; - if (smbw_shared_fd(fd)) return 1; - - for (srv=smbw_srvs;srv;srv=srv->next) { - if (srv->cli.fd == fd) return 1; - } - - return 0; -} - -/***************************************************** -a crude inode number generator -*******************************************************/ -ino_t smbw_inode(const char *name) -{ - if (!*name) return 2; - return (ino_t)str_checksum(name); -} - -/***************************************************** -remove redundent stuff from a filename -*******************************************************/ -void clean_fname(char *name) -{ - char *p, *p2; - int l; - int modified = 1; - - if (!name) return; - - while (modified) { - modified = 0; - - DEBUG(5,("cleaning %s\n", name)); - - if ((p=strstr(name,"/./"))) { - modified = 1; - while (*p) { - p[0] = p[2]; - p++; - } - } - - if ((p=strstr(name,"//"))) { - modified = 1; - while (*p) { - p[0] = p[1]; - p++; - } - } - - if (strcmp(name,"/../")==0) { - modified = 1; - name[1] = 0; - } - - if ((p=strstr(name,"/../"))) { - modified = 1; - for (p2=(p>name?p-1:p);p2>name;p2--) { - if (p2[0] == '/') break; - } - while (*p2) { - p2[0] = p2[3]; - p2++; - } - } - - if (strcmp(name,"/..")==0) { - modified = 1; - name[1] = 0; - } - - l = strlen(name); - p = l>=3?(name+l-3):name; - if (strcmp(p,"/..")==0) { - modified = 1; - for (p2=p-1;p2>name;p2--) { - if (p2[0] == '/') break; - } - if (p2==name) { - p[0] = '/'; - p[1] = 0; - } else { - p2[0] = 0; - } - } - - l = strlen(name); - p = l>=2?(name+l-2):name; - if (strcmp(p,"/.")==0) { - if (p == name) { - p[1] = 0; - } else { - p[0] = 0; - } - } - - if (strncmp(p=name,"./",2) == 0) { - modified = 1; - do { - p[0] = p[2]; - } while (*p++); - } - - l = strlen(p=name); - if (l > 1 && p[l-1] == '/') { - modified = 1; - p[l-1] = 0; - } - } -} - - - -/***************************************************** -find a workgroup (any workgroup!) that has a master -browser on the local network -*******************************************************/ -static char *smbw_find_workgroup(void) -{ - fstring server; - char *p; - struct in_addr *ip_list = NULL; - int count = 0; - int i; - - /* first off see if an existing workgroup name exists */ - p = smbw_getshared("WORKGROUP"); - if (!p) p = lp_workgroup(); - - slprintf(server, sizeof(server), "%s#1D", p); - if (smbw_server(server, "IPC$")) return p; - - /* go looking for workgroups */ - if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) { - DEBUG(1,("No workgroups found!")); - return p; - } - - for (i=0;i<count;i++) { - static fstring name; - if (name_status_find("*", 0, 0x1d, ip_list[i], name)) { - slprintf(server, sizeof(server), "%s#1D", name); - if (smbw_server(server, "IPC$")) { - smbw_setshared("WORKGROUP", name); - SAFE_FREE(ip_list); - return name; - } - } - } - - SAFE_FREE(ip_list); - - return p; -} - -/***************************************************** -parse a smb path into its components. -server is one of - 1) the name of the SMB server - 2) WORKGROUP#1D for share listing - 3) WORKGROUP#__ for workgroup listing -share is the share on the server to query -path is the SMB path on the server -return the full path (ie. add cwd if needed) -*******************************************************/ -char *smbw_parse_path(const char *fname, char *server, char *share, char *path) -{ - static pstring s; - char *p; - int len; - fstring workgroup; - - /* add cwd if necessary */ - if (fname[0] != '/') { - slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname); - } else { - pstrcpy(s, fname); - } - clean_fname(s); - - /* see if it has the right prefix */ - len = strlen(smbw_prefix)-1; - if (strncmp(s,smbw_prefix,len) || - (s[len] != '/' && s[len] != 0)) return s; - - /* ok, its for us. Now parse out the workgroup, share etc. */ - p = s+len; - if (*p == '/') p++; - if (!next_token(&p, workgroup, "/", sizeof(fstring))) { - /* we're in /smb - give a list of workgroups */ - slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup()); - fstrcpy(share,"IPC$"); - pstrcpy(path,""); - return s; - } - - if (!next_token(&p, server, "/", sizeof(fstring))) { - /* we are in /smb/WORKGROUP */ - slprintf(server,sizeof(fstring), "%s#1D", workgroup); - fstrcpy(share,"IPC$"); - pstrcpy(path,""); - } - - if (!next_token(&p, share, "/", sizeof(fstring))) { - /* we are in /smb/WORKGROUP/SERVER */ - fstrcpy(share,"IPC$"); - pstrcpy(path,""); - } - - pstrcpy(path, p); - - all_string_sub(path, "/", "\\", 0); - - return s; -} - -/***************************************************** -determine if a path name (possibly relative) is in the -smb name space -*******************************************************/ -int smbw_path(const char *path) -{ - fstring server, share; - pstring s; - char *cwd; - int len; - - if(!path) - return 0; - - /* this is needed to prevent recursion with the BSD malloc which - opens /etc/malloc.conf on the first call */ - if (strncmp(path,"/etc/", 5) == 0) { - return 0; - } - - smbw_init(); - - len = strlen(smbw_prefix)-1; - - if (path[0] == '/' && strncmp(path,smbw_prefix,len)) { - return 0; - } - - if (smbw_busy) return 0; - - DEBUG(3,("smbw_path(%s)\n", path)); - - cwd = smbw_parse_path(path, server, share, s); - - if (strncmp(cwd,smbw_prefix,len) == 0 && - (cwd[len] == '/' || cwd[len] == 0)) { - return 1; - } - - return 0; -} - -/***************************************************** -return a unix errno from a SMB error pair -*******************************************************/ -int smbw_errno(struct cli_state *c) -{ - return cli_errno(c); -} - -/* Return a username and password given a server and share name */ - -void get_envvar_auth_data(char *server, char *share, char **workgroup, - char **username, char **password) -{ - /* Fall back to shared memory/environment variables */ - - *username = smbw_getshared("USER"); - if (!*username) *username = getenv("USER"); - if (!*username) *username = "guest"; - - *workgroup = smbw_getshared("WORKGROUP"); - if (!*workgroup) *workgroup = lp_workgroup(); - - *password = smbw_getshared("PASSWORD"); - if (!*password) *password = ""; -} - -static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data; - -/***************************************************** -set the get auth data function -******************************************************/ -void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn) -{ - get_auth_data_fn = fn; -} - -/***************************************************** -return a connection to a server (existing or new) -*******************************************************/ -struct smbw_server *smbw_server(char *server, char *share) -{ - struct smbw_server *srv=NULL; - struct cli_state c; - char *username; - char *password; - char *workgroup; - struct nmb_name called, calling; - char *p, *server_n = server; - fstring group; - pstring ipenv; - struct in_addr ip; - - zero_ip(&ip); - ZERO_STRUCT(c); - - get_auth_data_fn(server, share, &workgroup, &username, &password); - - /* try to use an existing connection */ - for (srv=smbw_srvs;srv;srv=srv->next) { - if (strcmp(server,srv->server_name)==0 && - strcmp(share,srv->share_name)==0 && - strcmp(workgroup,srv->workgroup)==0 && - strcmp(username, srv->username) == 0) - return srv; - } - - if (server[0] == 0) { - errno = EPERM; - return NULL; - } - - make_nmb_name(&calling, lp_netbios_name(), 0x0); - make_nmb_name(&called , server, 0x20); - - DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server)); - - if ((p=strchr_m(server_n,'#')) && - (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) { - struct in_addr sip; - pstring s; - - fstrcpy(group, server_n); - p = strchr_m(group,'#'); - *p = 0; - - /* cache the workgroup master lookup */ - slprintf(s,sizeof(s)-1,"MASTER_%s", group); - if (!(server_n = smbw_getshared(s))) { - if (!find_master_ip(group, &sip)) { - errno = ENOENT; - return NULL; - } - fstrcpy(group, inet_ntoa(sip)); - server_n = group; - smbw_setshared(s,server_n); - } - } - - DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); - - again: - slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n); - - zero_ip(&ip); - if ((p=smbw_getshared(ipenv))) { - ip = *(interpret_addr2(p)); - } - - /* have to open a new connection */ - if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) { - errno = ENOENT; - return NULL; - } - - if (!cli_session_request(&c, &calling, &called)) { - cli_shutdown(&c); - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } - errno = ENOENT; - return NULL; - } - - DEBUG(4,(" session request ok\n")); - - if (!cli_negprot(&c)) { - cli_shutdown(&c); - errno = ENOENT; - return NULL; - } - - if (!cli_session_setup(&c, username, - password, strlen(password), - password, strlen(password), - workgroup) && - /* try an anonymous login if it failed */ - !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) { - cli_shutdown(&c); - errno = EPERM; - return NULL; - } - - DEBUG(4,(" session setup ok\n")); - - if (!cli_send_tconX(&c, share, "?????", - password, strlen(password)+1)) { - errno = smbw_errno(&c); - cli_shutdown(&c); - return NULL; - } - - smbw_setshared(ipenv,inet_ntoa(ip)); - - DEBUG(4,(" tconx ok\n")); - - srv = (struct smbw_server *)malloc(sizeof(*srv)); - if (!srv) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(srv); - - srv->cli = c; - - srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); - - srv->server_name = strdup(server); - if (!srv->server_name) { - errno = ENOMEM; - goto failed; - } - - srv->share_name = strdup(share); - if (!srv->share_name) { - errno = ENOMEM; - goto failed; - } - - srv->workgroup = strdup(workgroup); - if (!srv->workgroup) { - errno = ENOMEM; - goto failed; - } - - srv->username = strdup(username); - if (!srv->username) { - errno = ENOMEM; - goto failed; - } - - /* some programs play with file descriptors fairly intimately. We - try to get out of the way by duping to a high fd number */ - if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) { - if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) == - srv->cli.fd+SMBW_CLI_FD) { - close(srv->cli.fd); - srv->cli.fd += SMBW_CLI_FD; - } - } - - DLIST_ADD(smbw_srvs, srv); - - return srv; - - failed: - cli_shutdown(&c); - if (!srv) return NULL; - - SAFE_FREE(srv->server_name); - SAFE_FREE(srv->share_name); - SAFE_FREE(srv); - return NULL; -} - - -/***************************************************** -map a fd to a smbw_file structure -*******************************************************/ -struct smbw_file *smbw_file(int fd) -{ - struct smbw_file *file; - - for (file=smbw_files;file;file=file->next) { - if (file->fd == fd) return file; - } - return NULL; -} - -/***************************************************** -a wrapper for open() -*******************************************************/ -int smbw_open(const char *fname, int flags, mode_t mode) -{ - fstring server, share; - pstring path; - struct smbw_server *srv=NULL; - int eno=0, fd = -1; - struct smbw_file *file=NULL; - - smbw_init(); - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (path[strlen(path)-1] == '\\') { - fd = -1; - } else { - fd = cli_open(&srv->cli, path, flags, DENY_NONE); - } - if (fd == -1) { - /* it might be a directory. Maybe we should use chkpath? */ - eno = smbw_errno(&srv->cli); - fd = smbw_dir_open(fname); - if (fd == -1) errno = eno; - smbw_busy--; - return fd; - } - - file = (struct smbw_file *)malloc(sizeof(*file)); - if (!file) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file); - - file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f))); - if (!file->f) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file->f); - - file->f->cli_fd = fd; - file->f->fname = strdup(path); - if (!file->f->fname) { - errno = ENOMEM; - goto failed; - } - file->srv = srv; - file->fd = open(SMBW_DUMMY, O_WRONLY); - if (file->fd == -1) { - errno = EMFILE; - goto failed; - } - - if (bitmap_query(smbw_file_bmap, file->fd)) { - DEBUG(0,("ERROR: fd used in smbw_open\n")); - errno = EIO; - goto failed; - } - - file->f->ref_count=1; - - bitmap_set(smbw_file_bmap, file->fd); - - DLIST_ADD(smbw_files, file); - - DEBUG(4,("opened %s\n", fname)); - - smbw_busy--; - return file->fd; - - failed: - if (fd != -1) { - cli_close(&srv->cli, fd); - } - if (file) { - if (file->f) { - SAFE_FREE(file->f->fname); - SAFE_FREE(file->f); - } - SAFE_FREE(file); - } - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for pread() -*******************************************************/ -ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs) -{ - struct smbw_file *file; - int ret; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - smbw_busy--; - return ret; -} - -/***************************************************** -a wrapper for read() -*******************************************************/ -ssize_t smbw_read(int fd, void *buf, size_t count) -{ - struct smbw_file *file; - int ret; - - DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count)); - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, - file->f->offset, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - file->f->offset += ret; - - DEBUG(4,(" -> %d\n", ret)); - - smbw_busy--; - return ret; -} - - - -/***************************************************** -a wrapper for write() -*******************************************************/ -ssize_t smbw_write(int fd, void *buf, size_t count) -{ - struct smbw_file *file; - int ret; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - file->f->offset += ret; - - smbw_busy--; - return ret; -} - -/***************************************************** -a wrapper for pwrite() -*******************************************************/ -ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs) -{ - struct smbw_file *file; - int ret; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - smbw_busy--; - return ret; -} - -/***************************************************** -a wrapper for close() -*******************************************************/ -int smbw_close(int fd) -{ - struct smbw_file *file; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - int ret = smbw_dir_close(fd); - smbw_busy--; - return ret; - } - - if (file->f->ref_count == 1 && - !cli_close(&file->srv->cli, file->f->cli_fd)) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - - bitmap_clear(smbw_file_bmap, file->fd); - close(file->fd); - - DLIST_REMOVE(smbw_files, file); - - file->f->ref_count--; - if (file->f->ref_count == 0) { - SAFE_FREE(file->f->fname); - SAFE_FREE(file->f); - } - ZERO_STRUCTP(file); - SAFE_FREE(file); - - smbw_busy--; - - return 0; -} - - -/***************************************************** -a wrapper for fcntl() -*******************************************************/ -int smbw_fcntl(int fd, int cmd, long arg) -{ - return 0; -} - - -/***************************************************** -a wrapper for access() -*******************************************************/ -int smbw_access(const char *name, int mode) -{ - struct stat st; - - DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode)); - - if (smbw_stat(name, &st)) return -1; - - if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) || - ((mode & W_OK) && !(st.st_mode & S_IWUSR)) || - ((mode & X_OK) && !(st.st_mode & S_IXUSR))) { - errno = EACCES; - return -1; - } - - return 0; -} - -/***************************************************** -a wrapper for realink() - needed for correct errno setting -*******************************************************/ -int smbw_readlink(const char *path, char *buf, size_t bufsize) -{ - struct stat st; - int ret; - - ret = smbw_stat(path, &st); - if (ret != 0) { - DEBUG(4,("readlink(%s) failed\n", path)); - return -1; - } - - /* it exists - say it isn't a link */ - DEBUG(4,("readlink(%s) not a link\n", path)); - - errno = EINVAL; - return -1; -} - - -/***************************************************** -a wrapper for unlink() -*******************************************************/ -int smbw_unlink(const char *fname) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (strncmp(srv->cli.dev, "LPT", 3) == 0) { - int job = smbw_stat_printjob(srv, path, NULL, NULL); - if (job == -1) { - goto failed; - } - if (cli_printjob_del(&srv->cli, job) != 0) { - goto failed; - } - } else if (!cli_unlink(&srv->cli, path)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for rename() -*******************************************************/ -int smbw_rename(const char *oldname, const char *newname) -{ - struct smbw_server *srv; - fstring server1, share1; - pstring path1; - fstring server2, share2; - pstring path2; - - if (!oldname || !newname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname)); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(oldname, server1, share1, path1); - smbw_parse_path(newname, server2, share2, path2); - - if (strcmp(server1, server2) || strcmp(share1, share2)) { - /* can't cross filesystems */ - errno = EXDEV; - return -1; - } - - /* get a connection to the server */ - srv = smbw_server(server1, share1); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_rename(&srv->cli, path1, path2)) { - int eno = smbw_errno(&srv->cli); - if (eno != EEXIST || - !cli_unlink(&srv->cli, path2) || - !cli_rename(&srv->cli, path1, path2)) { - errno = eno; - goto failed; - } - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for utime and utimes -*******************************************************/ -static int smbw_settime(const char *fname, time_t t) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint16 mode; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - if (!cli_setatr(&srv->cli, path, mode, t)) { - /* some servers always refuse directory changes */ - if (!(mode & aDIR)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for utime -*******************************************************/ -int smbw_utime(const char *fname, void *buf) -{ - struct utimbuf *tbuf = (struct utimbuf *)buf; - return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL)); -} - -/***************************************************** -a wrapper for utime -*******************************************************/ -int smbw_utimes(const char *fname, void *buf) -{ - struct timeval *tbuf = (struct timeval *)buf; - return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL)); -} - - -/***************************************************** -a wrapper for chown() -*******************************************************/ -int smbw_chown(const char *fname, uid_t owner, gid_t group) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint16 mode; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - /* assume success */ - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for chmod() -*******************************************************/ -int smbw_chmod(const char *fname, mode_t newmode) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint32 mode; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - mode = 0; - - if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; - if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; - if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; - if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - - if (!cli_setatr(&srv->cli, path, mode, 0)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for lseek() -*******************************************************/ -off_t smbw_lseek(int fd, off_t offset, int whence) -{ - struct smbw_file *file; - size_t size; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - off_t ret = smbw_dir_lseek(fd, offset, whence); - smbw_busy--; - return ret; - } - - switch (whence) { - case SEEK_SET: - file->f->offset = offset; - break; - case SEEK_CUR: - file->f->offset += offset; - break; - case SEEK_END: - if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, - NULL, &size, NULL, NULL, NULL, - NULL, NULL) && - !cli_getattrE(&file->srv->cli, file->f->cli_fd, - NULL, &size, NULL, NULL, NULL)) { - errno = EINVAL; - smbw_busy--; - return -1; - } - file->f->offset = size + offset; - break; - } - - smbw_busy--; - return file->f->offset; -} - - -/***************************************************** -a wrapper for dup() -*******************************************************/ -int smbw_dup(int fd) -{ - int fd2; - struct smbw_file *file, *file2; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - goto failed; - } - - fd2 = dup(file->fd); - if (fd2 == -1) { - goto failed; - } - - if (bitmap_query(smbw_file_bmap, fd2)) { - DEBUG(0,("ERROR: fd already open in dup!\n")); - errno = EIO; - goto failed; - } - - file2 = (struct smbw_file *)malloc(sizeof(*file2)); - if (!file2) { - close(fd2); - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file2); - - *file2 = *file; - file2->fd = fd2; - - file->f->ref_count++; - - bitmap_set(smbw_file_bmap, fd2); - - DLIST_ADD(smbw_files, file2); - - smbw_busy--; - return fd2; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for dup2() -*******************************************************/ -int smbw_dup2(int fd, int fd2) -{ - struct smbw_file *file, *file2; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - goto failed; - } - - if (bitmap_query(smbw_file_bmap, fd2)) { - DEBUG(0,("ERROR: fd already open in dup2!\n")); - errno = EIO; - goto failed; - } - - if (dup2(file->fd, fd2) != fd2) { - goto failed; - } - - file2 = (struct smbw_file *)malloc(sizeof(*file2)); - if (!file2) { - close(fd2); - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file2); - - *file2 = *file; - file2->fd = fd2; - - file->f->ref_count++; - - bitmap_set(smbw_file_bmap, fd2); - - DLIST_ADD(smbw_files, file2); - - smbw_busy--; - return fd2; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -close a connection to a server -*******************************************************/ -static void smbw_srv_close(struct smbw_server *srv) -{ - smbw_busy++; - - cli_shutdown(&srv->cli); - - SAFE_FREE(srv->server_name); - SAFE_FREE(srv->share_name); - - DLIST_REMOVE(smbw_srvs, srv); - - ZERO_STRUCTP(srv); - - SAFE_FREE(srv); - - smbw_busy--; -} - -/***************************************************** -when we fork we have to close all connections and files -in the child -*******************************************************/ -int smbw_fork(void) -{ - pid_t child; - int p[2]; - char c=0; - pstring line; - - struct smbw_file *file, *next_file; - struct smbw_server *srv, *next_srv; - - if (pipe(p)) return real_fork(); - - child = real_fork(); - - if (child) { - /* block the parent for a moment until the sockets are - closed */ - close(p[1]); - read(p[0], &c, 1); - close(p[0]); - return child; - } - - close(p[0]); - - /* close all files */ - for (file=smbw_files;file;file=next_file) { - next_file = file->next; - close(file->fd); - } - - /* close all server connections */ - for (srv=smbw_srvs;srv;srv=next_srv) { - next_srv = srv->next; - smbw_srv_close(srv); - } - - slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid()); - smbw_setshared(line,smbw_cwd); - - /* unblock the parent */ - write(p[1], &c, 1); - close(p[1]); - - /* and continue in the child */ - return 0; -} - -#ifndef NO_ACL_WRAPPER -/***************************************************** -say no to acls -*******************************************************/ - int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp) -{ - if (cmd == GETACL || cmd == GETACLCNT) return 0; - errno = ENOSYS; - return -1; -} -#endif - -#ifndef NO_FACL_WRAPPER -/***************************************************** -say no to acls -*******************************************************/ - int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp) -{ - if (cmd == GETACL || cmd == GETACLCNT) return 0; - errno = ENOSYS; - return -1; -} -#endif - -#ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT -#ifdef HAVE_STAT64 -/* this can't be in wrapped.c because of include conflicts */ - void stat64_convert(struct stat *st, struct stat64 *st64) -{ - st64->st_size = st->st_size; - st64->st_mode = st->st_mode; - st64->st_ino = st->st_ino; - st64->st_dev = st->st_dev; - st64->st_rdev = st->st_rdev; - st64->st_nlink = st->st_nlink; - st64->st_uid = st->st_uid; - st64->st_gid = st->st_gid; - st64->st_atime = st->st_atime; - st64->st_mtime = st->st_mtime; - st64->st_ctime = st->st_ctime; - st64->st_blksize = st->st_blksize; - st64->st_blocks = st->st_blocks; -} -#endif - -#ifdef HAVE_READDIR64 - void dirent64_convert(struct dirent *d, struct dirent64 *d64) -{ - d64->d_ino = d->d_ino; - d64->d_off = d->d_off; - d64->d_reclen = d->d_reclen; - pstrcpy(d64->d_name, d->d_name); -} -#endif -#endif - - -#ifdef HAVE___XSTAT -/* Definition of `struct stat' used in the linux kernel.. */ -struct kernel_stat { - unsigned short int st_dev; - unsigned short int __pad1; - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - unsigned long int st_atime; - unsigned long int __unused1; - unsigned long int st_mtime; - unsigned long int __unused2; - unsigned long int st_ctime; - unsigned long int __unused3; - unsigned long int __unused4; - unsigned long int __unused5; -}; - -/* - * Prototype for gcc in 'fussy' mode. - */ - void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf); - void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf) -{ -#ifdef _STAT_VER_LINUX_OLD - if (vers == _STAT_VER_LINUX_OLD) { - memcpy(st, kbuf, sizeof(*st)); - return; - } -#endif - - ZERO_STRUCTP(st); - - st->st_dev = kbuf->st_dev; - st->st_ino = kbuf->st_ino; - st->st_mode = kbuf->st_mode; - st->st_nlink = kbuf->st_nlink; - st->st_uid = kbuf->st_uid; - st->st_gid = kbuf->st_gid; - st->st_rdev = kbuf->st_rdev; - st->st_size = kbuf->st_size; - st->st_blksize = kbuf->st_blksize; - st->st_blocks = kbuf->st_blocks; - st->st_atime = kbuf->st_atime; - st->st_mtime = kbuf->st_mtime; - st->st_ctime = kbuf->st_ctime; -} -#endif |