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 lp_load(servicesf,True,False,False);
84 get_myname(global_myname);
86 if ((p=smbw_getshared("DEBUG"))) {
90 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
91 lp_set_name_resolve_order(p);
94 if ((p=smbw_getshared("PREFIX"))) {
95 slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);
96 all_string_sub(smbw_prefix,"//", "/", 0);
97 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));
100 slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
102 p = smbw_getshared(line);
106 pstrcpy(smbw_cwd, p);
107 DEBUG(4,("Initial cwd is %s\n", smbw_cwd));
111 set_maxfiles(SMBW_MAX_OPEN);
113 BlockSignals(True,SIGPIPE);
118 /*****************************************************
119 determine if a file descriptor is a smb one
120 *******************************************************/
123 if (smbw_busy) return 0;
124 return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);
127 /*****************************************************
128 determine if a file descriptor is an internal smbw fd
129 *******************************************************/
130 int smbw_local_fd(int fd)
132 struct smbw_server *srv;
136 if (smbw_busy) return 0;
137 if (smbw_shared_fd(fd)) return 1;
139 for (srv=smbw_srvs;srv;srv=srv->next) {
140 if (srv->cli.fd == fd) return 1;
146 /*****************************************************
147 a crude inode number generator
148 *******************************************************/
149 ino_t smbw_inode(const char *name)
151 if (!*name) return 2;
152 return (ino_t)str_checksum(name);
155 /*****************************************************
156 remove redundent stuff from a filename
157 *******************************************************/
158 void clean_fname(char *name)
169 DEBUG(5,("cleaning %s\n", name));
171 if ((p=strstr(name,"/./"))) {
179 if ((p=strstr(name,"//"))) {
187 if (strcmp(name,"/../")==0) {
192 if ((p=strstr(name,"/../"))) {
194 for (p2=(p>name?p-1:p);p2>name;p2--) {
195 if (p2[0] == '/') break;
203 if (strcmp(name,"/..")==0) {
209 p = l>=3?(name+l-3):name;
210 if (strcmp(p,"/..")==0) {
212 for (p2=p-1;p2>name;p2--) {
213 if (p2[0] == '/') break;
224 p = l>=2?(name+l-2):name;
225 if (strcmp(p,"/.")==0) {
233 if (strncmp(p=name,"./",2) == 0) {
241 if (l > 1 && p[l-1] == '/') {
250 /*****************************************************
251 find a workgroup (any workgroup!) that has a master
252 browser on the local network
253 *******************************************************/
254 static char *smbw_find_workgroup(void)
258 struct in_addr *ip_list = NULL;
262 /* first off see if an existing workgroup name exists */
263 p = smbw_getshared("WORKGROUP");
264 if (!p) p = lp_workgroup();
266 slprintf(server, sizeof(server), "%s#1D", p);
267 if (smbw_server(server, "IPC$")) return p;
269 /* go looking for workgroups */
270 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
271 DEBUG(1,("No workgroups found!"));
276 free((char *)ip_list);
278 DEBUG(0,("Need to do node status code"));
282 /*****************************************************
283 parse a smb path into its components.
285 1) the name of the SMB server
286 2) WORKGROUP#1D for share listing
287 3) WORKGROUP#__ for workgroup listing
288 share is the share on the server to query
289 path is the SMB path on the server
290 return the full path (ie. add cwd if needed)
291 *******************************************************/
292 char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
299 /* add cwd if necessary */
300 if (fname[0] != '/') {
301 slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname);
307 /* see if it has the right prefix */
308 len = strlen(smbw_prefix)-1;
309 if (strncmp(s,smbw_prefix,len) ||
310 (s[len] != '/' && s[len] != 0)) return s;
312 /* ok, its for us. Now parse out the workgroup, share etc. */
315 if (!next_token(&p, workgroup, "/", sizeof(fstring))) {
316 /* we're in /smb - give a list of workgroups */
317 slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup());
318 fstrcpy(share,"IPC$");
323 if (!next_token(&p, server, "/", sizeof(fstring))) {
324 /* we are in /smb/WORKGROUP */
325 slprintf(server,sizeof(fstring), "%s#1D", workgroup);
326 fstrcpy(share,"IPC$");
330 if (!next_token(&p, share, "/", sizeof(fstring))) {
331 /* we are in /smb/WORKGROUP/SERVER */
332 fstrcpy(share,"IPC$");
338 all_string_sub(path, "/", "\\", 0);
343 /*****************************************************
344 determine if a path name (possibly relative) is in the
346 *******************************************************/
347 int smbw_path(const char *path)
349 fstring server, share;
357 /* this is needed to prevent recursion with the BSD malloc which
358 opens /etc/malloc.conf on the first call */
359 if (strncmp(path,"/etc/", 5) == 0) {
365 len = strlen(smbw_prefix)-1;
367 if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {
371 if (smbw_busy) return 0;
373 DEBUG(3,("smbw_path(%s)\n", path));
375 cwd = smbw_parse_path(path, server, share, s);
377 if (strncmp(cwd,smbw_prefix,len) == 0 &&
378 (cwd[len] == '/' || cwd[len] == 0)) {
385 /*****************************************************
386 return a unix errno from a SMB error pair
387 *******************************************************/
388 int smbw_errno(struct cli_state *c)
394 ret = cli_error(c, &eclass, &ecode, NULL);
397 DEBUG(3,("smbw_error %d %d (0x%x) -> %d\n",
398 (int)eclass, (int)ecode, (int)ecode, ret));
403 /* Return a username and password given a server and share name */
405 void get_envvar_auth_data(char *server, char *share, char **workgroup,
406 char **username, char **password)
408 /* Fall back to shared memory/environment variables */
410 *username = smbw_getshared("USER");
411 if (!*username) *username = getenv("USER");
412 if (!*username) *username = "guest";
414 *workgroup = smbw_getshared("WORKGROUP");
415 if (!*workgroup) *workgroup = lp_workgroup();
417 *password = smbw_getshared("PASSWORD");
418 if (!*password) *password = "";
421 static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;
423 /*****************************************************
424 set the get auth data function
425 ******************************************************/
426 void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn)
428 get_auth_data_fn = fn;
431 /*****************************************************
432 return a connection to a server (existing or new)
433 *******************************************************/
434 struct smbw_server *smbw_server(char *server, char *share)
436 struct smbw_server *srv=NULL;
441 struct nmb_name called, calling;
442 char *p, *server_n = server;
446 extern struct in_addr ipzero;
451 get_auth_data_fn(server, share, &workgroup, &username, &password);
453 /* try to use an existing connection */
454 for (srv=smbw_srvs;srv;srv=srv->next) {
455 if (strcmp(server,srv->server_name)==0 &&
456 strcmp(share,srv->share_name)==0 &&
457 strcmp(workgroup,srv->workgroup)==0 &&
458 strcmp(username, srv->username) == 0)
462 if (server[0] == 0) {
467 make_nmb_name(&calling, global_myname, 0x0);
468 make_nmb_name(&called , server, 0x20);
470 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));
472 if ((p=strchr(server_n,'#')) &&
473 (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
477 fstrcpy(group, server_n);
478 p = strchr(group,'#');
481 /* cache the workgroup master lookup */
482 slprintf(s,sizeof(s)-1,"MASTER_%s", group);
483 if (!(server_n = smbw_getshared(s))) {
484 if (!find_master_ip(group, &sip)) {
488 fstrcpy(group, inet_ntoa(sip));
490 smbw_setshared(s,server_n);
494 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
497 slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
500 if ((p=smbw_getshared(ipenv))) {
501 ip = *(interpret_addr2(p));
504 /* have to open a new connection */
505 if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
510 if (!cli_session_request(&c, &calling, &called)) {
512 if (strcmp(called.name, "*SMBSERVER")) {
513 make_nmb_name(&called , "*SMBSERVER", 0x20);
520 DEBUG(4,(" session request ok\n"));
522 if (!cli_negprot(&c)) {
528 if (!cli_session_setup(&c, username,
529 password, strlen(password),
530 password, strlen(password),
532 /* try an anonymous login if it failed */
533 !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
539 DEBUG(4,(" session setup ok\n"));
541 if (!cli_send_tconX(&c, share, "?????",
542 password, strlen(password)+1)) {
543 errno = smbw_errno(&c);
548 smbw_setshared(ipenv,inet_ntoa(ip));
550 DEBUG(4,(" tconx ok\n"));
552 srv = (struct smbw_server *)malloc(sizeof(*srv));
562 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
564 srv->server_name = strdup(server);
565 if (!srv->server_name) {
570 srv->share_name = strdup(share);
571 if (!srv->share_name) {
576 srv->workgroup = strdup(workgroup);
577 if (!srv->workgroup) {
582 srv->username = strdup(username);
583 if (!srv->username) {
588 /* some programs play with file descriptors fairly intimately. We
589 try to get out of the way by duping to a high fd number */
590 if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
591 if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
592 srv->cli.fd+SMBW_CLI_FD) {
594 srv->cli.fd += SMBW_CLI_FD;
598 DLIST_ADD(smbw_srvs, srv);
604 if (!srv) return NULL;
606 if (srv->server_name) free(srv->server_name);
607 if (srv->share_name) free(srv->share_name);
613 /*****************************************************
614 map a fd to a smbw_file structure
615 *******************************************************/
616 struct smbw_file *smbw_file(int fd)
618 struct smbw_file *file;
620 for (file=smbw_files;file;file=file->next) {
621 if (file->fd == fd) return file;
626 /*****************************************************
628 *******************************************************/
629 int smbw_open(const char *fname, int flags, mode_t mode)
631 fstring server, share;
633 struct smbw_server *srv=NULL;
635 struct smbw_file *file=NULL;
646 /* work out what server they are after */
647 smbw_parse_path(fname, server, share, path);
649 /* get a connection to the server */
650 srv = smbw_server(server, share);
652 /* smbw_server sets errno */
656 if (path[strlen(path)-1] == '\\') {
659 fd = cli_open(&srv->cli, path, flags, DENY_NONE);
662 /* it might be a directory. Maybe we should use chkpath? */
663 eno = smbw_errno(&srv->cli);
664 fd = smbw_dir_open(fname);
665 if (fd == -1) errno = eno;
670 file = (struct smbw_file *)malloc(sizeof(*file));
678 file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
684 ZERO_STRUCTP(file->f);
686 file->f->cli_fd = fd;
687 file->f->fname = strdup(path);
688 if (!file->f->fname) {
693 file->fd = open(SMBW_DUMMY, O_WRONLY);
694 if (file->fd == -1) {
699 if (bitmap_query(smbw_file_bmap, file->fd)) {
700 DEBUG(0,("ERROR: fd used in smbw_open\n"));
705 file->f->ref_count=1;
707 bitmap_set(smbw_file_bmap, file->fd);
709 DLIST_ADD(smbw_files, file);
711 DEBUG(4,("opened %s\n", fname));
718 cli_close(&srv->cli, fd);
722 if (file->f->fname) {
723 free(file->f->fname);
734 /*****************************************************
735 a wrapper for pread()
736 *******************************************************/
737 ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs)
739 struct smbw_file *file;
744 file = smbw_file(fd);
751 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count);
754 errno = smbw_errno(&file->srv->cli);
763 /*****************************************************
765 *******************************************************/
766 ssize_t smbw_read(int fd, void *buf, size_t count)
768 struct smbw_file *file;
771 DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));
775 file = smbw_file(fd);
782 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf,
783 file->f->offset, count);
786 errno = smbw_errno(&file->srv->cli);
791 file->f->offset += ret;
793 DEBUG(4,(" -> %d\n", ret));
801 /*****************************************************
802 a wrapper for write()
803 *******************************************************/
804 ssize_t smbw_write(int fd, void *buf, size_t count)
806 struct smbw_file *file;
811 file = smbw_file(fd);
818 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count);
821 errno = smbw_errno(&file->srv->cli);
826 file->f->offset += ret;
832 /*****************************************************
833 a wrapper for pwrite()
834 *******************************************************/
835 ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
837 struct smbw_file *file;
842 file = smbw_file(fd);
849 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);
852 errno = smbw_errno(&file->srv->cli);
861 /*****************************************************
862 a wrapper for close()
863 *******************************************************/
864 int smbw_close(int fd)
866 struct smbw_file *file;
870 file = smbw_file(fd);
872 int ret = smbw_dir_close(fd);
877 if (file->f->ref_count == 1 &&
878 !cli_close(&file->srv->cli, file->f->cli_fd)) {
879 errno = smbw_errno(&file->srv->cli);
885 bitmap_clear(smbw_file_bmap, file->fd);
888 DLIST_REMOVE(smbw_files, file);
890 file->f->ref_count--;
891 if (file->f->ref_count == 0) {
892 free(file->f->fname);
904 /*****************************************************
905 a wrapper for fcntl()
906 *******************************************************/
907 int smbw_fcntl(int fd, int cmd, long arg)
913 /*****************************************************
914 a wrapper for access()
915 *******************************************************/
916 int smbw_access(const char *name, int mode)
920 DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode));
922 if (smbw_stat(name, &st)) return -1;
924 if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) ||
925 ((mode & W_OK) && !(st.st_mode & S_IWUSR)) ||
926 ((mode & X_OK) && !(st.st_mode & S_IXUSR))) {
934 /*****************************************************
935 a wrapper for realink() - needed for correct errno setting
936 *******************************************************/
937 int smbw_readlink(const char *path, char *buf, size_t bufsize)
942 ret = smbw_stat(path, &st);
944 DEBUG(4,("readlink(%s) failed\n", path));
948 /* it exists - say it isn't a link */
949 DEBUG(4,("readlink(%s) not a link\n", path));
956 /*****************************************************
957 a wrapper for unlink()
958 *******************************************************/
959 int smbw_unlink(const char *fname)
961 struct smbw_server *srv;
962 fstring server, share;
974 /* work out what server they are after */
975 smbw_parse_path(fname, server, share, path);
977 /* get a connection to the server */
978 srv = smbw_server(server, share);
980 /* smbw_server sets errno */
984 if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
985 int job = smbw_stat_printjob(srv, path, NULL, NULL);
989 if (cli_printjob_del(&srv->cli, job) != 0) {
992 } else if (!cli_unlink(&srv->cli, path)) {
993 errno = smbw_errno(&srv->cli);
1006 /*****************************************************
1007 a wrapper for rename()
1008 *******************************************************/
1009 int smbw_rename(const char *oldname, const char *newname)
1011 struct smbw_server *srv;
1012 fstring server1, share1;
1014 fstring server2, share2;
1017 if (!oldname || !newname) {
1024 DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
1028 /* work out what server they are after */
1029 smbw_parse_path(oldname, server1, share1, path1);
1030 smbw_parse_path(newname, server2, share2, path2);
1032 if (strcmp(server1, server2) || strcmp(share1, share2)) {
1033 /* can't cross filesystems */
1038 /* get a connection to the server */
1039 srv = smbw_server(server1, share1);
1041 /* smbw_server sets errno */
1045 if (!cli_rename(&srv->cli, path1, path2)) {
1046 int eno = smbw_errno(&srv->cli);
1047 if (eno != EEXIST ||
1048 !cli_unlink(&srv->cli, path2) ||
1049 !cli_rename(&srv->cli, path1, path2)) {
1064 /*****************************************************
1065 a wrapper for utime and utimes
1066 *******************************************************/
1067 static int smbw_settime(const char *fname, time_t t)
1069 struct smbw_server *srv;
1070 fstring server, share;
1083 /* work out what server they are after */
1084 smbw_parse_path(fname, server, share, path);
1086 /* get a connection to the server */
1087 srv = smbw_server(server, share);
1089 /* smbw_server sets errno */
1093 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1094 errno = smbw_errno(&srv->cli);
1098 if (!cli_setatr(&srv->cli, path, mode, t)) {
1099 /* some servers always refuse directory changes */
1100 if (!(mode & aDIR)) {
1101 errno = smbw_errno(&srv->cli);
1114 /*****************************************************
1116 *******************************************************/
1117 int smbw_utime(const char *fname, void *buf)
1119 struct utimbuf *tbuf = (struct utimbuf *)buf;
1120 return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL));
1123 /*****************************************************
1125 *******************************************************/
1126 int smbw_utimes(const char *fname, void *buf)
1128 struct timeval *tbuf = (struct timeval *)buf;
1129 return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL));
1133 /*****************************************************
1134 a wrapper for chown()
1135 *******************************************************/
1136 int smbw_chown(const char *fname, uid_t owner, gid_t group)
1138 struct smbw_server *srv;
1139 fstring server, share;
1152 /* work out what server they are after */
1153 smbw_parse_path(fname, server, share, path);
1155 /* get a connection to the server */
1156 srv = smbw_server(server, share);
1158 /* smbw_server sets errno */
1162 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1163 errno = smbw_errno(&srv->cli);
1167 /* assume success */
1177 /*****************************************************
1178 a wrapper for chmod()
1179 *******************************************************/
1180 int smbw_chmod(const char *fname, mode_t newmode)
1182 struct smbw_server *srv;
1183 fstring server, share;
1196 /* work out what server they are after */
1197 smbw_parse_path(fname, server, share, path);
1199 /* get a connection to the server */
1200 srv = smbw_server(server, share);
1202 /* smbw_server sets errno */
1208 if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
1209 if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
1210 if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
1211 if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
1213 if (!cli_setatr(&srv->cli, path, mode, 0)) {
1214 errno = smbw_errno(&srv->cli);
1226 /*****************************************************
1227 a wrapper for lseek()
1228 *******************************************************/
1229 off_t smbw_lseek(int fd, off_t offset, int whence)
1231 struct smbw_file *file;
1236 file = smbw_file(fd);
1238 off_t ret = smbw_dir_lseek(fd, offset, whence);
1245 file->f->offset = offset;
1248 file->f->offset += offset;
1251 if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
1252 NULL, &size, NULL, NULL, NULL,
1254 !cli_getattrE(&file->srv->cli, file->f->cli_fd,
1255 NULL, &size, NULL, NULL, NULL)) {
1260 file->f->offset = size + offset;
1265 return file->f->offset;
1269 /*****************************************************
1271 *******************************************************/
1272 int smbw_dup(int fd)
1275 struct smbw_file *file, *file2;
1279 file = smbw_file(fd);
1285 fd2 = dup(file->fd);
1290 if (bitmap_query(smbw_file_bmap, fd2)) {
1291 DEBUG(0,("ERROR: fd already open in dup!\n"));
1296 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1303 ZERO_STRUCTP(file2);
1308 file->f->ref_count++;
1310 bitmap_set(smbw_file_bmap, fd2);
1312 DLIST_ADD(smbw_files, file2);
1323 /*****************************************************
1324 a wrapper for dup2()
1325 *******************************************************/
1326 int smbw_dup2(int fd, int fd2)
1328 struct smbw_file *file, *file2;
1332 file = smbw_file(fd);
1338 if (bitmap_query(smbw_file_bmap, fd2)) {
1339 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1344 if (dup2(file->fd, fd2) != fd2) {
1348 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1355 ZERO_STRUCTP(file2);
1360 file->f->ref_count++;
1362 bitmap_set(smbw_file_bmap, fd2);
1364 DLIST_ADD(smbw_files, file2);
1375 /*****************************************************
1376 close a connection to a server
1377 *******************************************************/
1378 static void smbw_srv_close(struct smbw_server *srv)
1382 cli_shutdown(&srv->cli);
1384 free(srv->server_name);
1385 free(srv->share_name);
1387 DLIST_REMOVE(smbw_srvs, srv);
1396 /*****************************************************
1397 when we fork we have to close all connections and files
1399 *******************************************************/
1407 struct smbw_file *file, *next_file;
1408 struct smbw_server *srv, *next_srv;
1410 if (pipe(p)) return real_fork();
1412 child = real_fork();
1415 /* block the parent for a moment until the sockets are
1425 /* close all files */
1426 for (file=smbw_files;file;file=next_file) {
1427 next_file = file->next;
1431 /* close all server connections */
1432 for (srv=smbw_srvs;srv;srv=next_srv) {
1433 next_srv = srv->next;
1434 smbw_srv_close(srv);
1437 slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
1438 smbw_setshared(line,smbw_cwd);
1440 /* unblock the parent */
1444 /* and continue in the child */
1448 #ifndef NO_ACL_WRAPPER
1449 /*****************************************************
1451 *******************************************************/
1452 int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp)
1454 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1460 #ifndef NO_FACL_WRAPPER
1461 /*****************************************************
1463 *******************************************************/
1464 int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp)
1466 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1472 #ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
1474 /* this can't be in wrapped.c because of include conflicts */
1475 void stat64_convert(struct stat *st, struct stat64 *st64)
1477 st64->st_size = st->st_size;
1478 st64->st_mode = st->st_mode;
1479 st64->st_ino = st->st_ino;
1480 st64->st_dev = st->st_dev;
1481 st64->st_rdev = st->st_rdev;
1482 st64->st_nlink = st->st_nlink;
1483 st64->st_uid = st->st_uid;
1484 st64->st_gid = st->st_gid;
1485 st64->st_atime = st->st_atime;
1486 st64->st_mtime = st->st_mtime;
1487 st64->st_ctime = st->st_ctime;
1488 st64->st_blksize = st->st_blksize;
1489 st64->st_blocks = st->st_blocks;
1493 #ifdef HAVE_READDIR64
1494 void dirent64_convert(struct dirent *d, struct dirent64 *d64)
1496 d64->d_ino = d->d_ino;
1497 d64->d_off = d->d_off;
1498 d64->d_reclen = d->d_reclen;
1499 pstrcpy(d64->d_name, d->d_name);
1506 /* Definition of `struct stat' used in the linux kernel.. */
1507 struct kernel_stat {
1508 unsigned short int st_dev;
1509 unsigned short int __pad1;
1510 unsigned long int st_ino;
1511 unsigned short int st_mode;
1512 unsigned short int st_nlink;
1513 unsigned short int st_uid;
1514 unsigned short int st_gid;
1515 unsigned short int st_rdev;
1516 unsigned short int __pad2;
1517 unsigned long int st_size;
1518 unsigned long int st_blksize;
1519 unsigned long int st_blocks;
1520 unsigned long int st_atime;
1521 unsigned long int __unused1;
1522 unsigned long int st_mtime;
1523 unsigned long int __unused2;
1524 unsigned long int st_ctime;
1525 unsigned long int __unused3;
1526 unsigned long int __unused4;
1527 unsigned long int __unused5;
1531 * Prototype for gcc in 'fussy' mode.
1533 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf);
1534 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf)
1536 #ifdef _STAT_VER_LINUX_OLD
1537 if (vers == _STAT_VER_LINUX_OLD) {
1538 memcpy(st, kbuf, sizeof(*st));
1545 st->st_dev = kbuf->st_dev;
1546 st->st_ino = kbuf->st_ino;
1547 st->st_mode = kbuf->st_mode;
1548 st->st_nlink = kbuf->st_nlink;
1549 st->st_uid = kbuf->st_uid;
1550 st->st_gid = kbuf->st_gid;
1551 st->st_rdev = kbuf->st_rdev;
1552 st->st_size = kbuf->st_size;
1553 st->st_blksize = kbuf->st_blksize;
1554 st->st_blocks = kbuf->st_blocks;
1555 st->st_atime = kbuf->st_atime;
1556 st->st_mtime = kbuf->st_mtime;
1557 st->st_ctime = kbuf->st_ctime;