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;
33 fstring smbw_prefix = SMBW_PREFIX;
37 /* needs to be here because of dumb include files on some systems */
38 int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;
41 /*****************************************************
43 *******************************************************/
46 extern BOOL in_client;
47 static int initialised;
52 if (initialised) return;
60 setup_logging("smbsh",True);
64 if ((p=smbw_getshared("LOGFILE"))) {
65 dbf = sys_fopen(p, "a");
68 smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
69 if (!smbw_file_bmap) {
77 if ((p=smbw_getshared("SERVICESF"))) {
78 pstrcpy(dyn_CONFIGFILE, p);
81 lp_load(dyn_CONFIGFILE,True,False,False);
83 get_myname(global_myname);
85 if ((p=smbw_getshared("DEBUG"))) {
89 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
90 lp_set_name_resolve_order(p);
93 if ((p=smbw_getshared("PREFIX"))) {
94 slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);
95 all_string_sub(smbw_prefix,"//", "/", 0);
96 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));
99 slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
101 p = smbw_getshared(line);
105 pstrcpy(smbw_cwd, p);
106 DEBUG(4,("Initial cwd is %s\n", smbw_cwd));
110 set_maxfiles(SMBW_MAX_OPEN);
112 BlockSignals(True,SIGPIPE);
117 /*****************************************************
118 determine if a file descriptor is a smb one
119 *******************************************************/
122 if (smbw_busy) return 0;
123 return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);
126 /*****************************************************
127 determine if a file descriptor is an internal smbw fd
128 *******************************************************/
129 int smbw_local_fd(int fd)
131 struct smbw_server *srv;
135 if (smbw_busy) return 0;
136 if (smbw_shared_fd(fd)) return 1;
138 for (srv=smbw_srvs;srv;srv=srv->next) {
139 if (srv->cli.fd == fd) return 1;
145 /*****************************************************
146 a crude inode number generator
147 *******************************************************/
148 ino_t smbw_inode(const char *name)
150 if (!*name) return 2;
151 return (ino_t)str_checksum(name);
154 /*****************************************************
155 remove redundent stuff from a filename
156 *******************************************************/
157 void clean_fname(char *name)
168 DEBUG(5,("cleaning %s\n", name));
170 if ((p=strstr(name,"/./"))) {
178 if ((p=strstr(name,"//"))) {
186 if (strcmp(name,"/../")==0) {
191 if ((p=strstr(name,"/../"))) {
193 for (p2=(p>name?p-1:p);p2>name;p2--) {
194 if (p2[0] == '/') break;
202 if (strcmp(name,"/..")==0) {
208 p = l>=3?(name+l-3):name;
209 if (strcmp(p,"/..")==0) {
211 for (p2=p-1;p2>name;p2--) {
212 if (p2[0] == '/') break;
223 p = l>=2?(name+l-2):name;
224 if (strcmp(p,"/.")==0) {
232 if (strncmp(p=name,"./",2) == 0) {
240 if (l > 1 && p[l-1] == '/') {
249 /*****************************************************
250 find a workgroup (any workgroup!) that has a master
251 browser on the local network
252 *******************************************************/
253 static char *smbw_find_workgroup(void)
257 struct in_addr *ip_list = NULL;
261 /* first off see if an existing workgroup name exists */
262 p = smbw_getshared("WORKGROUP");
263 if (!p) p = lp_workgroup();
265 slprintf(server, sizeof(server), "%s#1D", p);
266 if (smbw_server(server, "IPC$")) return p;
268 /* go looking for workgroups */
269 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
270 DEBUG(1,("No workgroups found!"));
274 for (i=0;i<count;i++) {
276 if (name_status_find(0x1d, ip_list[i], name)) {
277 slprintf(server, sizeof(server), "%s#1D", name);
278 if (smbw_server(server, "IPC$")) {
279 smbw_setshared("WORKGROUP", name);
291 /*****************************************************
292 parse a smb path into its components.
294 1) the name of the SMB server
295 2) WORKGROUP#1D for share listing
296 3) WORKGROUP#__ for workgroup listing
297 share is the share on the server to query
298 path is the SMB path on the server
299 return the full path (ie. add cwd if needed)
300 *******************************************************/
301 char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
308 /* add cwd if necessary */
309 if (fname[0] != '/') {
310 slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname);
316 /* see if it has the right prefix */
317 len = strlen(smbw_prefix)-1;
318 if (strncmp(s,smbw_prefix,len) ||
319 (s[len] != '/' && s[len] != 0)) return s;
321 /* ok, its for us. Now parse out the workgroup, share etc. */
324 if (!next_token(&p, workgroup, "/", sizeof(fstring))) {
325 /* we're in /smb - give a list of workgroups */
326 slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup());
327 fstrcpy(share,"IPC$");
332 if (!next_token(&p, server, "/", sizeof(fstring))) {
333 /* we are in /smb/WORKGROUP */
334 slprintf(server,sizeof(fstring), "%s#1D", workgroup);
335 fstrcpy(share,"IPC$");
339 if (!next_token(&p, share, "/", sizeof(fstring))) {
340 /* we are in /smb/WORKGROUP/SERVER */
341 fstrcpy(share,"IPC$");
347 all_string_sub(path, "/", "\\", 0);
352 /*****************************************************
353 determine if a path name (possibly relative) is in the
355 *******************************************************/
356 int smbw_path(const char *path)
358 fstring server, share;
366 /* this is needed to prevent recursion with the BSD malloc which
367 opens /etc/malloc.conf on the first call */
368 if (strncmp(path,"/etc/", 5) == 0) {
374 len = strlen(smbw_prefix)-1;
376 if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {
380 if (smbw_busy) return 0;
382 DEBUG(3,("smbw_path(%s)\n", path));
384 cwd = smbw_parse_path(path, server, share, s);
386 if (strncmp(cwd,smbw_prefix,len) == 0 &&
387 (cwd[len] == '/' || cwd[len] == 0)) {
394 /*****************************************************
395 return a unix errno from a SMB error pair
396 *******************************************************/
397 int smbw_errno(struct cli_state *c)
402 /* Return a username and password given a server and share name */
404 void get_envvar_auth_data(char *server, char *share, char **workgroup,
405 char **username, char **password)
407 /* Fall back to shared memory/environment variables */
409 *username = smbw_getshared("USER");
410 if (!*username) *username = getenv("USER");
411 if (!*username) *username = "guest";
413 *workgroup = smbw_getshared("WORKGROUP");
414 if (!*workgroup) *workgroup = lp_workgroup();
416 *password = smbw_getshared("PASSWORD");
417 if (!*password) *password = "";
420 static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;
422 /*****************************************************
423 set the get auth data function
424 ******************************************************/
425 void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn)
427 get_auth_data_fn = fn;
430 /*****************************************************
431 return a connection to a server (existing or new)
432 *******************************************************/
433 struct smbw_server *smbw_server(char *server, char *share)
435 struct smbw_server *srv=NULL;
440 struct nmb_name called, calling;
441 char *p, *server_n = server;
445 extern struct in_addr ipzero;
450 get_auth_data_fn(server, share, &workgroup, &username, &password);
452 /* try to use an existing connection */
453 for (srv=smbw_srvs;srv;srv=srv->next) {
454 if (strcmp(server,srv->server_name)==0 &&
455 strcmp(share,srv->share_name)==0 &&
456 strcmp(workgroup,srv->workgroup)==0 &&
457 strcmp(username, srv->username) == 0)
461 if (server[0] == 0) {
466 make_nmb_name(&calling, global_myname, 0x0);
467 make_nmb_name(&called , server, 0x20);
469 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));
471 if ((p=strchr_m(server_n,'#')) &&
472 (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
476 fstrcpy(group, server_n);
477 p = strchr_m(group,'#');
480 /* cache the workgroup master lookup */
481 slprintf(s,sizeof(s)-1,"MASTER_%s", group);
482 if (!(server_n = smbw_getshared(s))) {
483 if (!find_master_ip(group, &sip)) {
487 fstrcpy(group, inet_ntoa(sip));
489 smbw_setshared(s,server_n);
493 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
496 slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
499 if ((p=smbw_getshared(ipenv))) {
500 ip = *(interpret_addr2(p));
503 /* have to open a new connection */
504 if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
509 if (!cli_session_request(&c, &calling, &called)) {
511 if (strcmp(called.name, "*SMBSERVER")) {
512 make_nmb_name(&called , "*SMBSERVER", 0x20);
519 DEBUG(4,(" session request ok\n"));
521 if (!cli_negprot(&c)) {
527 if (!cli_session_setup(&c, username,
528 password, strlen(password),
529 password, strlen(password),
531 /* try an anonymous login if it failed */
532 !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
538 DEBUG(4,(" session setup ok\n"));
540 if (!cli_send_tconX(&c, share, "?????",
541 password, strlen(password)+1)) {
542 errno = smbw_errno(&c);
547 smbw_setshared(ipenv,inet_ntoa(ip));
549 DEBUG(4,(" tconx ok\n"));
551 srv = (struct smbw_server *)malloc(sizeof(*srv));
561 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
563 srv->server_name = strdup(server);
564 if (!srv->server_name) {
569 srv->share_name = strdup(share);
570 if (!srv->share_name) {
575 srv->workgroup = strdup(workgroup);
576 if (!srv->workgroup) {
581 srv->username = strdup(username);
582 if (!srv->username) {
587 /* some programs play with file descriptors fairly intimately. We
588 try to get out of the way by duping to a high fd number */
589 if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
590 if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
591 srv->cli.fd+SMBW_CLI_FD) {
593 srv->cli.fd += SMBW_CLI_FD;
597 DLIST_ADD(smbw_srvs, srv);
603 if (!srv) return NULL;
605 SAFE_FREE(srv->server_name);
606 SAFE_FREE(srv->share_name);
612 /*****************************************************
613 map a fd to a smbw_file structure
614 *******************************************************/
615 struct smbw_file *smbw_file(int fd)
617 struct smbw_file *file;
619 for (file=smbw_files;file;file=file->next) {
620 if (file->fd == fd) return file;
625 /*****************************************************
627 *******************************************************/
628 int smbw_open(const char *fname, int flags, mode_t mode)
630 fstring server, share;
632 struct smbw_server *srv=NULL;
634 struct smbw_file *file=NULL;
645 /* work out what server they are after */
646 smbw_parse_path(fname, server, share, path);
648 /* get a connection to the server */
649 srv = smbw_server(server, share);
651 /* smbw_server sets errno */
655 if (path[strlen(path)-1] == '\\') {
658 fd = cli_open(&srv->cli, path, flags, DENY_NONE);
661 /* it might be a directory. Maybe we should use chkpath? */
662 eno = smbw_errno(&srv->cli);
663 fd = smbw_dir_open(fname);
664 if (fd == -1) errno = eno;
669 file = (struct smbw_file *)malloc(sizeof(*file));
677 file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
683 ZERO_STRUCTP(file->f);
685 file->f->cli_fd = fd;
686 file->f->fname = strdup(path);
687 if (!file->f->fname) {
692 file->fd = open(SMBW_DUMMY, O_WRONLY);
693 if (file->fd == -1) {
698 if (bitmap_query(smbw_file_bmap, file->fd)) {
699 DEBUG(0,("ERROR: fd used in smbw_open\n"));
704 file->f->ref_count=1;
706 bitmap_set(smbw_file_bmap, file->fd);
708 DLIST_ADD(smbw_files, file);
710 DEBUG(4,("opened %s\n", fname));
717 cli_close(&srv->cli, fd);
721 SAFE_FREE(file->f->fname);
731 /*****************************************************
732 a wrapper for pread()
733 *******************************************************/
734 ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs)
736 struct smbw_file *file;
741 file = smbw_file(fd);
748 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count);
751 errno = smbw_errno(&file->srv->cli);
760 /*****************************************************
762 *******************************************************/
763 ssize_t smbw_read(int fd, void *buf, size_t count)
765 struct smbw_file *file;
768 DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));
772 file = smbw_file(fd);
779 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf,
780 file->f->offset, count);
783 errno = smbw_errno(&file->srv->cli);
788 file->f->offset += ret;
790 DEBUG(4,(" -> %d\n", ret));
798 /*****************************************************
799 a wrapper for write()
800 *******************************************************/
801 ssize_t smbw_write(int fd, void *buf, size_t count)
803 struct smbw_file *file;
808 file = smbw_file(fd);
815 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count);
818 errno = smbw_errno(&file->srv->cli);
823 file->f->offset += ret;
829 /*****************************************************
830 a wrapper for pwrite()
831 *******************************************************/
832 ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
834 struct smbw_file *file;
839 file = smbw_file(fd);
846 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);
849 errno = smbw_errno(&file->srv->cli);
858 /*****************************************************
859 a wrapper for close()
860 *******************************************************/
861 int smbw_close(int fd)
863 struct smbw_file *file;
867 file = smbw_file(fd);
869 int ret = smbw_dir_close(fd);
874 if (file->f->ref_count == 1 &&
875 !cli_close(&file->srv->cli, file->f->cli_fd)) {
876 errno = smbw_errno(&file->srv->cli);
882 bitmap_clear(smbw_file_bmap, file->fd);
885 DLIST_REMOVE(smbw_files, file);
887 file->f->ref_count--;
888 if (file->f->ref_count == 0) {
889 SAFE_FREE(file->f->fname);
901 /*****************************************************
902 a wrapper for fcntl()
903 *******************************************************/
904 int smbw_fcntl(int fd, int cmd, long arg)
910 /*****************************************************
911 a wrapper for access()
912 *******************************************************/
913 int smbw_access(const char *name, int mode)
917 DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode));
919 if (smbw_stat(name, &st)) return -1;
921 if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) ||
922 ((mode & W_OK) && !(st.st_mode & S_IWUSR)) ||
923 ((mode & X_OK) && !(st.st_mode & S_IXUSR))) {
931 /*****************************************************
932 a wrapper for realink() - needed for correct errno setting
933 *******************************************************/
934 int smbw_readlink(const char *path, char *buf, size_t bufsize)
939 ret = smbw_stat(path, &st);
941 DEBUG(4,("readlink(%s) failed\n", path));
945 /* it exists - say it isn't a link */
946 DEBUG(4,("readlink(%s) not a link\n", path));
953 /*****************************************************
954 a wrapper for unlink()
955 *******************************************************/
956 int smbw_unlink(const char *fname)
958 struct smbw_server *srv;
959 fstring server, share;
971 /* work out what server they are after */
972 smbw_parse_path(fname, server, share, path);
974 /* get a connection to the server */
975 srv = smbw_server(server, share);
977 /* smbw_server sets errno */
981 if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
982 int job = smbw_stat_printjob(srv, path, NULL, NULL);
986 if (cli_printjob_del(&srv->cli, job) != 0) {
989 } else if (!cli_unlink(&srv->cli, path)) {
990 errno = smbw_errno(&srv->cli);
1003 /*****************************************************
1004 a wrapper for rename()
1005 *******************************************************/
1006 int smbw_rename(const char *oldname, const char *newname)
1008 struct smbw_server *srv;
1009 fstring server1, share1;
1011 fstring server2, share2;
1014 if (!oldname || !newname) {
1021 DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
1025 /* work out what server they are after */
1026 smbw_parse_path(oldname, server1, share1, path1);
1027 smbw_parse_path(newname, server2, share2, path2);
1029 if (strcmp(server1, server2) || strcmp(share1, share2)) {
1030 /* can't cross filesystems */
1035 /* get a connection to the server */
1036 srv = smbw_server(server1, share1);
1038 /* smbw_server sets errno */
1042 if (!cli_rename(&srv->cli, path1, path2)) {
1043 int eno = smbw_errno(&srv->cli);
1044 if (eno != EEXIST ||
1045 !cli_unlink(&srv->cli, path2) ||
1046 !cli_rename(&srv->cli, path1, path2)) {
1061 /*****************************************************
1062 a wrapper for utime and utimes
1063 *******************************************************/
1064 static int smbw_settime(const char *fname, time_t t)
1066 struct smbw_server *srv;
1067 fstring server, share;
1080 /* work out what server they are after */
1081 smbw_parse_path(fname, server, share, path);
1083 /* get a connection to the server */
1084 srv = smbw_server(server, share);
1086 /* smbw_server sets errno */
1090 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1091 errno = smbw_errno(&srv->cli);
1095 if (!cli_setatr(&srv->cli, path, mode, t)) {
1096 /* some servers always refuse directory changes */
1097 if (!(mode & aDIR)) {
1098 errno = smbw_errno(&srv->cli);
1111 /*****************************************************
1113 *******************************************************/
1114 int smbw_utime(const char *fname, void *buf)
1116 struct utimbuf *tbuf = (struct utimbuf *)buf;
1117 return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL));
1120 /*****************************************************
1122 *******************************************************/
1123 int smbw_utimes(const char *fname, void *buf)
1125 struct timeval *tbuf = (struct timeval *)buf;
1126 return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL));
1130 /*****************************************************
1131 a wrapper for chown()
1132 *******************************************************/
1133 int smbw_chown(const char *fname, uid_t owner, gid_t group)
1135 struct smbw_server *srv;
1136 fstring server, share;
1149 /* work out what server they are after */
1150 smbw_parse_path(fname, server, share, path);
1152 /* get a connection to the server */
1153 srv = smbw_server(server, share);
1155 /* smbw_server sets errno */
1159 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1160 errno = smbw_errno(&srv->cli);
1164 /* assume success */
1174 /*****************************************************
1175 a wrapper for chmod()
1176 *******************************************************/
1177 int smbw_chmod(const char *fname, mode_t newmode)
1179 struct smbw_server *srv;
1180 fstring server, share;
1193 /* work out what server they are after */
1194 smbw_parse_path(fname, server, share, path);
1196 /* get a connection to the server */
1197 srv = smbw_server(server, share);
1199 /* smbw_server sets errno */
1205 if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
1206 if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
1207 if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
1208 if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
1210 if (!cli_setatr(&srv->cli, path, mode, 0)) {
1211 errno = smbw_errno(&srv->cli);
1223 /*****************************************************
1224 a wrapper for lseek()
1225 *******************************************************/
1226 off_t smbw_lseek(int fd, off_t offset, int whence)
1228 struct smbw_file *file;
1233 file = smbw_file(fd);
1235 off_t ret = smbw_dir_lseek(fd, offset, whence);
1242 file->f->offset = offset;
1245 file->f->offset += offset;
1248 if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
1249 NULL, &size, NULL, NULL, NULL,
1251 !cli_getattrE(&file->srv->cli, file->f->cli_fd,
1252 NULL, &size, NULL, NULL, NULL)) {
1257 file->f->offset = size + offset;
1262 return file->f->offset;
1266 /*****************************************************
1268 *******************************************************/
1269 int smbw_dup(int fd)
1272 struct smbw_file *file, *file2;
1276 file = smbw_file(fd);
1282 fd2 = dup(file->fd);
1287 if (bitmap_query(smbw_file_bmap, fd2)) {
1288 DEBUG(0,("ERROR: fd already open in dup!\n"));
1293 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1300 ZERO_STRUCTP(file2);
1305 file->f->ref_count++;
1307 bitmap_set(smbw_file_bmap, fd2);
1309 DLIST_ADD(smbw_files, file2);
1320 /*****************************************************
1321 a wrapper for dup2()
1322 *******************************************************/
1323 int smbw_dup2(int fd, int fd2)
1325 struct smbw_file *file, *file2;
1329 file = smbw_file(fd);
1335 if (bitmap_query(smbw_file_bmap, fd2)) {
1336 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1341 if (dup2(file->fd, fd2) != fd2) {
1345 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1352 ZERO_STRUCTP(file2);
1357 file->f->ref_count++;
1359 bitmap_set(smbw_file_bmap, fd2);
1361 DLIST_ADD(smbw_files, file2);
1372 /*****************************************************
1373 close a connection to a server
1374 *******************************************************/
1375 static void smbw_srv_close(struct smbw_server *srv)
1379 cli_shutdown(&srv->cli);
1381 SAFE_FREE(srv->server_name);
1382 SAFE_FREE(srv->share_name);
1384 DLIST_REMOVE(smbw_srvs, srv);
1393 /*****************************************************
1394 when we fork we have to close all connections and files
1396 *******************************************************/
1404 struct smbw_file *file, *next_file;
1405 struct smbw_server *srv, *next_srv;
1407 if (pipe(p)) return real_fork();
1409 child = real_fork();
1412 /* block the parent for a moment until the sockets are
1422 /* close all files */
1423 for (file=smbw_files;file;file=next_file) {
1424 next_file = file->next;
1428 /* close all server connections */
1429 for (srv=smbw_srvs;srv;srv=next_srv) {
1430 next_srv = srv->next;
1431 smbw_srv_close(srv);
1434 slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
1435 smbw_setshared(line,smbw_cwd);
1437 /* unblock the parent */
1441 /* and continue in the child */
1445 #ifndef NO_ACL_WRAPPER
1446 /*****************************************************
1448 *******************************************************/
1449 int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp)
1451 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1457 #ifndef NO_FACL_WRAPPER
1458 /*****************************************************
1460 *******************************************************/
1461 int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp)
1463 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1469 #ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
1471 /* this can't be in wrapped.c because of include conflicts */
1472 void stat64_convert(struct stat *st, struct stat64 *st64)
1474 st64->st_size = st->st_size;
1475 st64->st_mode = st->st_mode;
1476 st64->st_ino = st->st_ino;
1477 st64->st_dev = st->st_dev;
1478 st64->st_rdev = st->st_rdev;
1479 st64->st_nlink = st->st_nlink;
1480 st64->st_uid = st->st_uid;
1481 st64->st_gid = st->st_gid;
1482 st64->st_atime = st->st_atime;
1483 st64->st_mtime = st->st_mtime;
1484 st64->st_ctime = st->st_ctime;
1485 st64->st_blksize = st->st_blksize;
1486 st64->st_blocks = st->st_blocks;
1490 #ifdef HAVE_READDIR64
1491 void dirent64_convert(struct dirent *d, struct dirent64 *d64)
1493 d64->d_ino = d->d_ino;
1494 d64->d_off = d->d_off;
1495 d64->d_reclen = d->d_reclen;
1496 pstrcpy(d64->d_name, d->d_name);
1503 /* Definition of `struct stat' used in the linux kernel.. */
1504 struct kernel_stat {
1505 unsigned short int st_dev;
1506 unsigned short int __pad1;
1507 unsigned long int st_ino;
1508 unsigned short int st_mode;
1509 unsigned short int st_nlink;
1510 unsigned short int st_uid;
1511 unsigned short int st_gid;
1512 unsigned short int st_rdev;
1513 unsigned short int __pad2;
1514 unsigned long int st_size;
1515 unsigned long int st_blksize;
1516 unsigned long int st_blocks;
1517 unsigned long int st_atime;
1518 unsigned long int __unused1;
1519 unsigned long int st_mtime;
1520 unsigned long int __unused2;
1521 unsigned long int st_ctime;
1522 unsigned long int __unused3;
1523 unsigned long int __unused4;
1524 unsigned long int __unused5;
1528 * Prototype for gcc in 'fussy' mode.
1530 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf);
1531 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf)
1533 #ifdef _STAT_VER_LINUX_OLD
1534 if (vers == _STAT_VER_LINUX_OLD) {
1535 memcpy(st, kbuf, sizeof(*st));
1542 st->st_dev = kbuf->st_dev;
1543 st->st_ino = kbuf->st_ino;
1544 st->st_mode = kbuf->st_mode;
1545 st->st_nlink = kbuf->st_nlink;
1546 st->st_uid = kbuf->st_uid;
1547 st->st_gid = kbuf->st_gid;
1548 st->st_rdev = kbuf->st_rdev;
1549 st->st_size = kbuf->st_size;
1550 st->st_blksize = kbuf->st_blksize;
1551 st->st_blocks = kbuf->st_blocks;
1552 st->st_atime = kbuf->st_atime;
1553 st->st_mtime = kbuf->st_mtime;
1554 st->st_ctime = kbuf->st_ctime;