/***************************************************** 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; }
/***************************************************** 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 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 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 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 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; }
/***************************************************** 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; }
/***************************************************** 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 stat() *******************************************************/ int smbw_stat(const char *fname, struct stat *st) { struct smbw_server *srv; fstring server, share; pstring path; time_t m_time=0, a_time=0, c_time=0; size_t size=0; uint16 mode=0; SMB_INO_T ino = 0; ZERO_STRUCTP(st); if (!fname) { errno = EINVAL; return -1; } DEBUG(4,("stat(%s)\n", fname)); 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; } DEBUG(4,("smbw_stat\n")); if (strncmp(srv->cli.dev,"IPC",3) == 0) { mode = aDIR | aRONLY; } else if (strncmp(srv->cli.dev,"LPT",3) == 0) { if (strcmp(path,"\\") == 0) { mode = aDIR | aRONLY; } else { mode = aRONLY; smbw_stat_printjob(srv, path, &size, &m_time); c_time = a_time = m_time; } } else { if (!smbw_getatr(srv, path, &mode, &size, &c_time, &a_time, &m_time, &ino)) { errno = smbw_errno(&srv->cli); goto failed; } } st->st_ino = ino; smbw_setup_stat(st, path, size, mode); st->st_atime = a_time; st->st_ctime = c_time; st->st_mtime = m_time; st->st_dev = srv->dev; smbw_busy--; return 0; failed: smbw_busy--; return -1; }