2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "realcalls.h"
27 static struct smbw_file *smbw_files;
28 static struct smbw_server *smbw_srvs;
30 struct bitmap *smbw_file_bmap;
31 extern pstring global_myname;
32 extern int DEBUGLEVEL;
34 fstring smbw_prefix = SMBW_PREFIX;
38 /* needs to be here because of dumb include files on some systems */
39 int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;
42 /*****************************************************
44 *******************************************************/
47 extern BOOL in_client;
48 static int initialised;
49 static pstring servicesf = CONFIGFILE;
55 if (initialised) return;
63 setup_logging("smbsh",True);
67 if ((p=smbw_getshared("LOGFILE"))) {
68 dbf = sys_fopen(p, "a");
71 smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
72 if (!smbw_file_bmap) {
82 if ((p=smbw_getshared("SERVICESF"))) {
83 pstrcpy(servicesf, p);
86 lp_load(servicesf,True,False,False);
88 get_myname(global_myname);
90 if ((p=smbw_getshared("DEBUG"))) {
94 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
95 lp_set_name_resolve_order(p);
98 if ((p=smbw_getshared("PREFIX"))) {
99 slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);
100 all_string_sub(smbw_prefix,"//", "/", 0);
101 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));
104 slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
106 p = smbw_getshared(line);
110 pstrcpy(smbw_cwd, p);
111 DEBUG(4,("Initial cwd is %s\n", smbw_cwd));
115 set_maxfiles(SMBW_MAX_OPEN);
117 BlockSignals(True,SIGPIPE);
122 /*****************************************************
123 determine if a file descriptor is a smb one
124 *******************************************************/
127 if (smbw_busy) return 0;
128 return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);
131 /*****************************************************
132 determine if a file descriptor is an internal smbw fd
133 *******************************************************/
134 int smbw_local_fd(int fd)
136 struct smbw_server *srv;
140 if (smbw_busy) return 0;
141 if (smbw_shared_fd(fd)) return 1;
143 for (srv=smbw_srvs;srv;srv=srv->next) {
144 if (srv->cli.fd == fd) return 1;
150 /*****************************************************
151 a crude inode number generator
152 *******************************************************/
153 ino_t smbw_inode(const char *name)
155 if (!*name) return 2;
156 return (ino_t)str_checksum(name);
159 /*****************************************************
160 remove redundent stuff from a filename
161 *******************************************************/
162 void clean_fname(char *name)
173 DEBUG(5,("cleaning %s\n", name));
175 if ((p=strstr(name,"/./"))) {
183 if ((p=strstr(name,"//"))) {
191 if (strcmp(name,"/../")==0) {
196 if ((p=strstr(name,"/../"))) {
198 for (p2=(p>name?p-1:p);p2>name;p2--) {
199 if (p2[0] == '/') break;
207 if (strcmp(name,"/..")==0) {
213 p = l>=3?(name+l-3):name;
214 if (strcmp(p,"/..")==0) {
216 for (p2=p-1;p2>name;p2--) {
217 if (p2[0] == '/') break;
228 p = l>=2?(name+l-2):name;
229 if (strcmp(p,"/.")==0) {
237 if (strncmp(p=name,"./",2) == 0) {
245 if (l > 1 && p[l-1] == '/') {
254 /*****************************************************
255 find a workgroup (any workgroup!) that has a master
256 browser on the local network
257 *******************************************************/
258 static char *smbw_find_workgroup(void)
262 struct in_addr *ip_list = NULL;
266 /* first off see if an existing workgroup name exists */
267 p = smbw_getshared("WORKGROUP");
268 if (!p) p = lp_workgroup();
270 slprintf(server, sizeof(server), "%s#1D", p);
271 if (smbw_server(server, "IPC$")) return p;
273 /* go looking for workgroups */
274 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
275 DEBUG(1,("No workgroups found!"));
279 for (i=0;i<count;i++) {
281 if (name_status_find(0x1d, ip_list[i], name)) {
282 slprintf(server, sizeof(server), "%s#1D", name);
283 if (smbw_server(server, "IPC$")) {
284 smbw_setshared("WORKGROUP", name);
296 /*****************************************************
297 parse a smb path into its components.
299 1) the name of the SMB server
300 2) WORKGROUP#1D for share listing
301 3) WORKGROUP#__ for workgroup listing
302 share is the share on the server to query
303 path is the SMB path on the server
304 return the full path (ie. add cwd if needed)
305 *******************************************************/
306 char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
313 /* add cwd if necessary */
314 if (fname[0] != '/') {
315 slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname);
321 /* see if it has the right prefix */
322 len = strlen(smbw_prefix)-1;
323 if (strncmp(s,smbw_prefix,len) ||
324 (s[len] != '/' && s[len] != 0)) return s;
326 /* ok, its for us. Now parse out the workgroup, share etc. */
329 if (!next_token(&p, workgroup, "/", sizeof(fstring))) {
330 /* we're in /smb - give a list of workgroups */
331 slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup());
332 fstrcpy(share,"IPC$");
337 if (!next_token(&p, server, "/", sizeof(fstring))) {
338 /* we are in /smb/WORKGROUP */
339 slprintf(server,sizeof(fstring), "%s#1D", workgroup);
340 fstrcpy(share,"IPC$");
344 if (!next_token(&p, share, "/", sizeof(fstring))) {
345 /* we are in /smb/WORKGROUP/SERVER */
346 fstrcpy(share,"IPC$");
352 all_string_sub(path, "/", "\\", 0);
357 /*****************************************************
358 determine if a path name (possibly relative) is in the
360 *******************************************************/
361 int smbw_path(const char *path)
363 fstring server, share;
371 /* this is needed to prevent recursion with the BSD malloc which
372 opens /etc/malloc.conf on the first call */
373 if (strncmp(path,"/etc/", 5) == 0) {
379 len = strlen(smbw_prefix)-1;
381 if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {
385 if (smbw_busy) return 0;
387 DEBUG(3,("smbw_path(%s)\n", path));
389 cwd = smbw_parse_path(path, server, share, s);
391 if (strncmp(cwd,smbw_prefix,len) == 0 &&
392 (cwd[len] == '/' || cwd[len] == 0)) {
399 /*****************************************************
400 return a unix errno from a SMB error pair
401 *******************************************************/
402 int smbw_errno(struct cli_state *c)
408 ret = cli_error(c, &eclass, &ecode, NULL);
411 DEBUG(3,("smbw_error %d %d (0x%x) -> %d\n",
412 (int)eclass, (int)ecode, (int)ecode, ret));
417 /* Return a username and password given a server and share name */
419 void get_envvar_auth_data(char *server, char *share, char **workgroup,
420 char **username, char **password)
422 /* Fall back to shared memory/environment variables */
424 *username = smbw_getshared("USER");
425 if (!*username) *username = getenv("USER");
426 if (!*username) *username = "guest";
428 *workgroup = smbw_getshared("WORKGROUP");
429 if (!*workgroup) *workgroup = lp_workgroup();
431 *password = smbw_getshared("PASSWORD");
432 if (!*password) *password = "";
435 static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;
437 /*****************************************************
438 set the get auth data function
439 ******************************************************/
440 void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn)
442 get_auth_data_fn = fn;
445 /*****************************************************
446 return a connection to a server (existing or new)
447 *******************************************************/
448 struct smbw_server *smbw_server(char *server, char *share)
450 struct smbw_server *srv=NULL;
455 struct nmb_name called, calling;
456 char *p, *server_n = server;
460 extern struct in_addr ipzero;
465 get_auth_data_fn(server, share, &workgroup, &username, &password);
467 /* try to use an existing connection */
468 for (srv=smbw_srvs;srv;srv=srv->next) {
469 if (strcmp(server,srv->server_name)==0 &&
470 strcmp(share,srv->share_name)==0 &&
471 strcmp(workgroup,srv->workgroup)==0 &&
472 strcmp(username, srv->username) == 0)
476 if (server[0] == 0) {
481 make_nmb_name(&calling, global_myname, 0x0);
482 make_nmb_name(&called , server, 0x20);
484 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));
486 if ((p=strchr(server_n,'#')) &&
487 (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
491 fstrcpy(group, server_n);
492 p = strchr(group,'#');
495 /* cache the workgroup master lookup */
496 slprintf(s,sizeof(s)-1,"MASTER_%s", group);
497 if (!(server_n = smbw_getshared(s))) {
498 if (!find_master_ip(group, &sip)) {
502 fstrcpy(group, inet_ntoa(sip));
504 smbw_setshared(s,server_n);
508 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
511 slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
514 if ((p=smbw_getshared(ipenv))) {
515 ip = *(interpret_addr2(p));
518 /* have to open a new connection */
519 if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
524 if (!cli_session_request(&c, &calling, &called)) {
526 if (strcmp(called.name, "*SMBSERVER")) {
527 make_nmb_name(&called , "*SMBSERVER", 0x20);
534 DEBUG(4,(" session request ok\n"));
536 if (!cli_negprot(&c)) {
542 if (!cli_session_setup(&c, username,
543 password, strlen(password),
544 password, strlen(password),
546 /* try an anonymous login if it failed */
547 !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
553 DEBUG(4,(" session setup ok\n"));
555 if (!cli_send_tconX(&c, share, "?????",
556 password, strlen(password)+1)) {
557 errno = smbw_errno(&c);
562 smbw_setshared(ipenv,inet_ntoa(ip));
564 DEBUG(4,(" tconx ok\n"));
566 srv = (struct smbw_server *)malloc(sizeof(*srv));
576 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
578 srv->server_name = strdup(server);
579 if (!srv->server_name) {
584 srv->share_name = strdup(share);
585 if (!srv->share_name) {
590 srv->workgroup = strdup(workgroup);
591 if (!srv->workgroup) {
596 srv->username = strdup(username);
597 if (!srv->username) {
602 /* some programs play with file descriptors fairly intimately. We
603 try to get out of the way by duping to a high fd number */
604 if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
605 if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
606 srv->cli.fd+SMBW_CLI_FD) {
608 srv->cli.fd += SMBW_CLI_FD;
612 DLIST_ADD(smbw_srvs, srv);
618 if (!srv) return NULL;
620 if (srv->server_name) free(srv->server_name);
621 if (srv->share_name) free(srv->share_name);
627 /*****************************************************
628 map a fd to a smbw_file structure
629 *******************************************************/
630 struct smbw_file *smbw_file(int fd)
632 struct smbw_file *file;
634 for (file=smbw_files;file;file=file->next) {
635 if (file->fd == fd) return file;
640 /*****************************************************
642 *******************************************************/
643 int smbw_open(const char *fname, int flags, mode_t mode)
645 fstring server, share;
647 struct smbw_server *srv=NULL;
649 struct smbw_file *file=NULL;
660 /* work out what server they are after */
661 smbw_parse_path(fname, server, share, path);
663 /* get a connection to the server */
664 srv = smbw_server(server, share);
666 /* smbw_server sets errno */
670 if (path[strlen(path)-1] == '\\') {
673 fd = cli_open(&srv->cli, path, flags, DENY_NONE);
676 /* it might be a directory. Maybe we should use chkpath? */
677 eno = smbw_errno(&srv->cli);
678 fd = smbw_dir_open(fname);
679 if (fd == -1) errno = eno;
684 file = (struct smbw_file *)malloc(sizeof(*file));
692 file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
698 ZERO_STRUCTP(file->f);
700 file->f->cli_fd = fd;
701 file->f->fname = strdup(path);
702 if (!file->f->fname) {
707 file->fd = open(SMBW_DUMMY, O_WRONLY);
708 if (file->fd == -1) {
713 if (bitmap_query(smbw_file_bmap, file->fd)) {
714 DEBUG(0,("ERROR: fd used in smbw_open\n"));
719 file->f->ref_count=1;
721 bitmap_set(smbw_file_bmap, file->fd);
723 DLIST_ADD(smbw_files, file);
725 DEBUG(4,("opened %s\n", fname));
732 cli_close(&srv->cli, fd);
736 if (file->f->fname) {
737 free(file->f->fname);
748 /*****************************************************
749 a wrapper for pread()
750 *******************************************************/
751 ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs)
753 struct smbw_file *file;
758 file = smbw_file(fd);
765 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count);
768 errno = smbw_errno(&file->srv->cli);
777 /*****************************************************
779 *******************************************************/
780 ssize_t smbw_read(int fd, void *buf, size_t count)
782 struct smbw_file *file;
785 DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));
789 file = smbw_file(fd);
796 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf,
797 file->f->offset, count);
800 errno = smbw_errno(&file->srv->cli);
805 file->f->offset += ret;
807 DEBUG(4,(" -> %d\n", ret));
815 /*****************************************************
816 a wrapper for write()
817 *******************************************************/
818 ssize_t smbw_write(int fd, void *buf, size_t count)
820 struct smbw_file *file;
825 file = smbw_file(fd);
832 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count);
835 errno = smbw_errno(&file->srv->cli);
840 file->f->offset += ret;
846 /*****************************************************
847 a wrapper for pwrite()
848 *******************************************************/
849 ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
851 struct smbw_file *file;
856 file = smbw_file(fd);
863 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);
866 errno = smbw_errno(&file->srv->cli);
875 /*****************************************************
876 a wrapper for close()
877 *******************************************************/
878 int smbw_close(int fd)
880 struct smbw_file *file;
884 file = smbw_file(fd);
886 int ret = smbw_dir_close(fd);
891 if (file->f->ref_count == 1 &&
892 !cli_close(&file->srv->cli, file->f->cli_fd)) {
893 errno = smbw_errno(&file->srv->cli);
899 bitmap_clear(smbw_file_bmap, file->fd);
902 DLIST_REMOVE(smbw_files, file);
904 file->f->ref_count--;
905 if (file->f->ref_count == 0) {
906 free(file->f->fname);
918 /*****************************************************
919 a wrapper for fcntl()
920 *******************************************************/
921 int smbw_fcntl(int fd, int cmd, long arg)
927 /*****************************************************
928 a wrapper for access()
929 *******************************************************/
930 int smbw_access(const char *name, int mode)
934 DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode));
936 if (smbw_stat(name, &st)) return -1;
938 if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) ||
939 ((mode & W_OK) && !(st.st_mode & S_IWUSR)) ||
940 ((mode & X_OK) && !(st.st_mode & S_IXUSR))) {
948 /*****************************************************
949 a wrapper for realink() - needed for correct errno setting
950 *******************************************************/
951 int smbw_readlink(const char *path, char *buf, size_t bufsize)
956 ret = smbw_stat(path, &st);
958 DEBUG(4,("readlink(%s) failed\n", path));
962 /* it exists - say it isn't a link */
963 DEBUG(4,("readlink(%s) not a link\n", path));
970 /*****************************************************
971 a wrapper for unlink()
972 *******************************************************/
973 int smbw_unlink(const char *fname)
975 struct smbw_server *srv;
976 fstring server, share;
988 /* work out what server they are after */
989 smbw_parse_path(fname, server, share, path);
991 /* get a connection to the server */
992 srv = smbw_server(server, share);
994 /* smbw_server sets errno */
998 if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
999 int job = smbw_stat_printjob(srv, path, NULL, NULL);
1003 if (cli_printjob_del(&srv->cli, job) != 0) {
1006 } else if (!cli_unlink(&srv->cli, path)) {
1007 errno = smbw_errno(&srv->cli);
1020 /*****************************************************
1021 a wrapper for rename()
1022 *******************************************************/
1023 int smbw_rename(const char *oldname, const char *newname)
1025 struct smbw_server *srv;
1026 fstring server1, share1;
1028 fstring server2, share2;
1031 if (!oldname || !newname) {
1038 DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
1042 /* work out what server they are after */
1043 smbw_parse_path(oldname, server1, share1, path1);
1044 smbw_parse_path(newname, server2, share2, path2);
1046 if (strcmp(server1, server2) || strcmp(share1, share2)) {
1047 /* can't cross filesystems */
1052 /* get a connection to the server */
1053 srv = smbw_server(server1, share1);
1055 /* smbw_server sets errno */
1059 if (!cli_rename(&srv->cli, path1, path2)) {
1060 int eno = smbw_errno(&srv->cli);
1061 if (eno != EEXIST ||
1062 !cli_unlink(&srv->cli, path2) ||
1063 !cli_rename(&srv->cli, path1, path2)) {
1078 /*****************************************************
1079 a wrapper for utime and utimes
1080 *******************************************************/
1081 static int smbw_settime(const char *fname, time_t t)
1083 struct smbw_server *srv;
1084 fstring server, share;
1097 /* work out what server they are after */
1098 smbw_parse_path(fname, server, share, path);
1100 /* get a connection to the server */
1101 srv = smbw_server(server, share);
1103 /* smbw_server sets errno */
1107 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1108 errno = smbw_errno(&srv->cli);
1112 if (!cli_setatr(&srv->cli, path, mode, t)) {
1113 /* some servers always refuse directory changes */
1114 if (!(mode & aDIR)) {
1115 errno = smbw_errno(&srv->cli);
1128 /*****************************************************
1130 *******************************************************/
1131 int smbw_utime(const char *fname, void *buf)
1133 struct utimbuf *tbuf = (struct utimbuf *)buf;
1134 return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL));
1137 /*****************************************************
1139 *******************************************************/
1140 int smbw_utimes(const char *fname, void *buf)
1142 struct timeval *tbuf = (struct timeval *)buf;
1143 return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL));
1147 /*****************************************************
1148 a wrapper for chown()
1149 *******************************************************/
1150 int smbw_chown(const char *fname, uid_t owner, gid_t group)
1152 struct smbw_server *srv;
1153 fstring server, share;
1166 /* work out what server they are after */
1167 smbw_parse_path(fname, server, share, path);
1169 /* get a connection to the server */
1170 srv = smbw_server(server, share);
1172 /* smbw_server sets errno */
1176 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1177 errno = smbw_errno(&srv->cli);
1181 /* assume success */
1191 /*****************************************************
1192 a wrapper for chmod()
1193 *******************************************************/
1194 int smbw_chmod(const char *fname, mode_t newmode)
1196 struct smbw_server *srv;
1197 fstring server, share;
1210 /* work out what server they are after */
1211 smbw_parse_path(fname, server, share, path);
1213 /* get a connection to the server */
1214 srv = smbw_server(server, share);
1216 /* smbw_server sets errno */
1222 if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
1223 if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
1224 if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
1225 if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
1227 if (!cli_setatr(&srv->cli, path, mode, 0)) {
1228 errno = smbw_errno(&srv->cli);
1240 /*****************************************************
1241 a wrapper for lseek()
1242 *******************************************************/
1243 off_t smbw_lseek(int fd, off_t offset, int whence)
1245 struct smbw_file *file;
1250 file = smbw_file(fd);
1252 off_t ret = smbw_dir_lseek(fd, offset, whence);
1259 file->f->offset = offset;
1262 file->f->offset += offset;
1265 if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
1266 NULL, &size, NULL, NULL, NULL,
1268 !cli_getattrE(&file->srv->cli, file->f->cli_fd,
1269 NULL, &size, NULL, NULL, NULL)) {
1274 file->f->offset = size + offset;
1279 return file->f->offset;
1283 /*****************************************************
1285 *******************************************************/
1286 int smbw_dup(int fd)
1289 struct smbw_file *file, *file2;
1293 file = smbw_file(fd);
1299 fd2 = dup(file->fd);
1304 if (bitmap_query(smbw_file_bmap, fd2)) {
1305 DEBUG(0,("ERROR: fd already open in dup!\n"));
1310 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1317 ZERO_STRUCTP(file2);
1322 file->f->ref_count++;
1324 bitmap_set(smbw_file_bmap, fd2);
1326 DLIST_ADD(smbw_files, file2);
1337 /*****************************************************
1338 a wrapper for dup2()
1339 *******************************************************/
1340 int smbw_dup2(int fd, int fd2)
1342 struct smbw_file *file, *file2;
1346 file = smbw_file(fd);
1352 if (bitmap_query(smbw_file_bmap, fd2)) {
1353 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1358 if (dup2(file->fd, fd2) != fd2) {
1362 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1369 ZERO_STRUCTP(file2);
1374 file->f->ref_count++;
1376 bitmap_set(smbw_file_bmap, fd2);
1378 DLIST_ADD(smbw_files, file2);
1389 /*****************************************************
1390 close a connection to a server
1391 *******************************************************/
1392 static void smbw_srv_close(struct smbw_server *srv)
1396 cli_shutdown(&srv->cli);
1398 free(srv->server_name);
1399 free(srv->share_name);
1401 DLIST_REMOVE(smbw_srvs, srv);
1410 /*****************************************************
1411 when we fork we have to close all connections and files
1413 *******************************************************/
1421 struct smbw_file *file, *next_file;
1422 struct smbw_server *srv, *next_srv;
1424 if (pipe(p)) return real_fork();
1426 child = real_fork();
1429 /* block the parent for a moment until the sockets are
1439 /* close all files */
1440 for (file=smbw_files;file;file=next_file) {
1441 next_file = file->next;
1445 /* close all server connections */
1446 for (srv=smbw_srvs;srv;srv=next_srv) {
1447 next_srv = srv->next;
1448 smbw_srv_close(srv);
1451 slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
1452 smbw_setshared(line,smbw_cwd);
1454 /* unblock the parent */
1458 /* and continue in the child */
1462 #ifndef NO_ACL_WRAPPER
1463 /*****************************************************
1465 *******************************************************/
1466 int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp)
1468 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1474 #ifndef NO_FACL_WRAPPER
1475 /*****************************************************
1477 *******************************************************/
1478 int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp)
1480 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1486 #ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
1488 /* this can't be in wrapped.c because of include conflicts */
1489 void stat64_convert(struct stat *st, struct stat64 *st64)
1491 st64->st_size = st->st_size;
1492 st64->st_mode = st->st_mode;
1493 st64->st_ino = st->st_ino;
1494 st64->st_dev = st->st_dev;
1495 st64->st_rdev = st->st_rdev;
1496 st64->st_nlink = st->st_nlink;
1497 st64->st_uid = st->st_uid;
1498 st64->st_gid = st->st_gid;
1499 st64->st_atime = st->st_atime;
1500 st64->st_mtime = st->st_mtime;
1501 st64->st_ctime = st->st_ctime;
1502 st64->st_blksize = st->st_blksize;
1503 st64->st_blocks = st->st_blocks;
1507 #ifdef HAVE_READDIR64
1508 void dirent64_convert(struct dirent *d, struct dirent64 *d64)
1510 d64->d_ino = d->d_ino;
1511 d64->d_off = d->d_off;
1512 d64->d_reclen = d->d_reclen;
1513 pstrcpy(d64->d_name, d->d_name);
1520 /* Definition of `struct stat' used in the linux kernel.. */
1521 struct kernel_stat {
1522 unsigned short int st_dev;
1523 unsigned short int __pad1;
1524 unsigned long int st_ino;
1525 unsigned short int st_mode;
1526 unsigned short int st_nlink;
1527 unsigned short int st_uid;
1528 unsigned short int st_gid;
1529 unsigned short int st_rdev;
1530 unsigned short int __pad2;
1531 unsigned long int st_size;
1532 unsigned long int st_blksize;
1533 unsigned long int st_blocks;
1534 unsigned long int st_atime;
1535 unsigned long int __unused1;
1536 unsigned long int st_mtime;
1537 unsigned long int __unused2;
1538 unsigned long int st_ctime;
1539 unsigned long int __unused3;
1540 unsigned long int __unused4;
1541 unsigned long int __unused5;
1545 * Prototype for gcc in 'fussy' mode.
1547 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf);
1548 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf)
1550 #ifdef _STAT_VER_LINUX_OLD
1551 if (vers == _STAT_VER_LINUX_OLD) {
1552 memcpy(st, kbuf, sizeof(*st));
1559 st->st_dev = kbuf->st_dev;
1560 st->st_ino = kbuf->st_ino;
1561 st->st_mode = kbuf->st_mode;
1562 st->st_nlink = kbuf->st_nlink;
1563 st->st_uid = kbuf->st_uid;
1564 st->st_gid = kbuf->st_gid;
1565 st->st_rdev = kbuf->st_rdev;
1566 st->st_size = kbuf->st_size;
1567 st->st_blksize = kbuf->st_blksize;
1568 st->st_blocks = kbuf->st_blocks;
1569 st->st_atime = kbuf->st_atime;
1570 st->st_mtime = kbuf->st_mtime;
1571 st->st_ctime = kbuf->st_ctime;