summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/libsmb/clientgen.c6
-rw-r--r--source3/smbd/reply.c2
-rw-r--r--source3/smbwrapper/smbw.c30
-rw-r--r--source3/smbwrapper/smbw_dir.c2
5 files changed, 34 insertions, 7 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 56b0e3bc24..05ea1bf7c7 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -216,6 +216,7 @@ implemented */
#define ERRfilexists 80 /* File in operation already exists */
#define ERRcannotopen 110 /* Cannot open the file specified */
#define ERRunknownlevel 124
+#define ERRrename 183
#define ERRbadpipe 230 /* Named pipe invalid */
#define ERRpipebusy 231 /* All instances of pipe are busy */
#define ERRpipeclosing 232 /* named pipe close in progress */
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 2d49144695..93f7a3d222 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -1196,6 +1196,8 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t
int mid;
int blocks = (size + (block-1)) / block;
+ if (size == 0) return 0;
+
while (received < blocks) {
int size2;
@@ -1295,6 +1297,8 @@ size_t cli_write(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
int mid;
int blocks = (size + (block-1)) / block;
+ if (size == 0) return 0;
+
while (received < blocks) {
int size2;
@@ -2309,6 +2313,8 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
case ERRbadfile: return ENOENT;
case ERRbadpath: return ENOTDIR;
case ERRnoaccess: return EACCES;
+ case ERRfilexists: return EEXIST;
+ case ERRrename: return EEXIST;
}
}
if (rcls == ERRSRV) {
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 12a39589d6..6dfff54a0f 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3210,7 +3210,7 @@ int rename_internals(connection_struct *conn,
if (!count) exists = file_exist(directory,NULL);
if (!count && exists && file_exist(newname,NULL)) {
exists = True;
- error = 183;
+ error = ERRrename;
}
} else {
/*
diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c
index 6096f096a3..6b8796fb5d 100644
--- a/source3/smbwrapper/smbw.c
+++ b/source3/smbwrapper/smbw.c
@@ -647,6 +647,8 @@ 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);
@@ -666,6 +668,8 @@ ssize_t smbw_read(int fd, void *buf, size_t count)
}
file->f->offset += ret;
+
+ DEBUG(4,(" -> %d\n", ret));
smbw_busy--;
return ret;
@@ -793,8 +797,19 @@ a wrapper for access()
int smbw_access(const char *name, int mode)
{
struct stat st;
- /* how do we map this properly ?? */
- return smbw_stat(name, &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;
}
/*****************************************************
@@ -887,6 +902,8 @@ int smbw_rename(const char *oldname, const char *newname)
smbw_init();
+ DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
+
smbw_busy++;
/* work out what server they are after */
@@ -907,8 +924,13 @@ int smbw_rename(const char *oldname, const char *newname)
}
if (!cli_rename(&srv->cli, path1, path2)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
+ 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--;
diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c
index 2c1b7ef9ec..f6d648b91f 100644
--- a/source3/smbwrapper/smbw_dir.c
+++ b/source3/smbwrapper/smbw_dir.c
@@ -320,8 +320,6 @@ int smbw_getdents(unsigned int fd, struct dirent *dirp, int count)
return -1;
}
- DEBUG(4,("sizeof(*dirp)=%d\n", sizeof(*dirp)));
-
while (count>=DIRP_SIZE && (dir->offset < dir->count)) {
dirp->d_off = (dir->offset+1)*DIRP_SIZE;
dirp->d_reclen = DIRP_SIZE;