summaryrefslogtreecommitdiff
path: root/source3/smbwrapper
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbwrapper')
-rw-r--r--source3/smbwrapper/realcalls.h8
-rw-r--r--source3/smbwrapper/smbw.c69
-rw-r--r--source3/smbwrapper/smbw_dir.c1
-rw-r--r--source3/smbwrapper/wrapped.c5
4 files changed, 83 insertions, 0 deletions
diff --git a/source3/smbwrapper/realcalls.h b/source3/smbwrapper/realcalls.h
index 338e195087..65431bf53f 100644
--- a/source3/smbwrapper/realcalls.h
+++ b/source3/smbwrapper/realcalls.h
@@ -51,6 +51,14 @@
#define NO_OPEN64_ALIAS
#endif
+#ifdef HAVE__FORK
+#define real_fork() (_fork())
+#elif HAVE___FORK
+#define real_fork() (__fork())
+#elif SYS_fork
+#define real_fork() (syscall(SYS_fork,()))
+#endif
+
#ifdef HAVE__OPENDIR
#define real_opendir(fn) ((DIR *)_opendir(fn))
#elif SYS_opendir
diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c
index e5359360c3..6096f096a3 100644
--- a/source3/smbwrapper/smbw.c
+++ b/source3/smbwrapper/smbw.c
@@ -1229,3 +1229,72 @@ int smbw_dup2(int fd, int fd2)
return -1;
}
+
+/*****************************************************
+close a connection to a server
+*******************************************************/
+static void smbw_srv_close(struct smbw_server *srv)
+{
+ smbw_busy++;
+
+ cli_shutdown(&srv->cli);
+
+ free(srv->server_name);
+ free(srv->share_name);
+
+ DLIST_REMOVE(smbw_srvs, srv);
+
+ ZERO_STRUCTP(srv);
+
+ 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;
+
+ 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);
+ }
+
+ /* unblock the parent */
+ write(p[1], &c, 1);
+ close(p[1]);
+
+ /* and continue in the child */
+ return 0;
+}
diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c
index a932c102dc..2c1b7ef9ec 100644
--- a/source3/smbwrapper/smbw_dir.c
+++ b/source3/smbwrapper/smbw_dir.c
@@ -664,3 +664,4 @@ off_t smbw_telldir(DIR *dirp)
struct smbw_dir *d = (struct smbw_dir *)dirp;
return smbw_dir_lseek(d->fd,0,SEEK_CUR);
}
+
diff --git a/source3/smbwrapper/wrapped.c b/source3/smbwrapper/wrapped.c
index bda0ed1abe..10b22b35dd 100644
--- a/source3/smbwrapper/wrapped.c
+++ b/source3/smbwrapper/wrapped.c
@@ -908,3 +908,8 @@ static void dirent64_convert(struct dirent *d, struct dirent64 *d64)
return real_readdir64(dir);
}
#endif
+
+ int fork(void)
+{
+ return smbw_fork();
+}