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
;
54 if (initialised
) return;
62 setup_logging("smbsh",True
);
66 if ((p
=smbw_getshared("LOGFILE"))) {
67 dbf
= sys_fopen(p
, "a");
70 smbw_file_bmap
= bitmap_allocate(SMBW_MAX_OPEN
);
71 if (!smbw_file_bmap
) {
79 if ((p
=smbw_getshared("SERVICESF"))) {
80 pstrcpy(servicesf
, p
);
83 lp_load(servicesf
,True
,False
,False
);
87 get_myname(global_myname
);
89 if ((p
=smbw_getshared("DEBUG"))) {
93 if ((p
=smbw_getshared("RESOLVE_ORDER"))) {
94 lp_set_name_resolve_order(p
);
97 if ((p
=smbw_getshared("PREFIX"))) {
98 slprintf(smbw_prefix
,sizeof(fstring
)-1, "/%s/", p
);
99 all_string_sub(smbw_prefix
,"//", "/", 0);
100 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix
));
103 slprintf(line
,sizeof(line
)-1,"PWD_%d", (int)getpid());
105 p
= smbw_getshared(line
);
109 pstrcpy(smbw_cwd
, p
);
110 DEBUG(4,("Initial cwd is %s\n", smbw_cwd
));
114 set_maxfiles(SMBW_MAX_OPEN
);
116 BlockSignals(True
,SIGPIPE
);
121 /*****************************************************
122 determine if a file descriptor is a smb one
123 *******************************************************/
126 if (smbw_busy
) return 0;
127 return smbw_file_bmap
&& bitmap_query(smbw_file_bmap
, fd
);
130 /*****************************************************
131 determine if a file descriptor is an internal smbw fd
132 *******************************************************/
133 int smbw_local_fd(int fd
)
135 struct smbw_server
*srv
;
139 if (smbw_busy
) return 0;
140 if (smbw_shared_fd(fd
)) return 1;
142 for (srv
=smbw_srvs
;srv
;srv
=srv
->next
) {
143 if (srv
->cli
.fd
== fd
) return 1;
149 /*****************************************************
150 a crude inode number generator
151 *******************************************************/
152 ino_t
smbw_inode(const char *name
)
154 if (!*name
) return 2;
155 return (ino_t
)str_checksum(name
);
158 /*****************************************************
159 remove redundent stuff from a filename
160 *******************************************************/
161 void clean_fname(char *name
)
172 DEBUG(5,("cleaning %s\n", name
));
174 if ((p
=strstr(name
,"/./"))) {
182 if ((p
=strstr(name
,"//"))) {
190 if (strcmp(name
,"/../")==0) {
195 if ((p
=strstr(name
,"/../"))) {
197 for (p2
=(p
>name
?p
-1:p
);p2
>name
;p2
--) {
198 if (p2
[0] == '/') break;
206 if (strcmp(name
,"/..")==0) {
212 p
= l
>=3?(name
+l
-3):name
;
213 if (strcmp(p
,"/..")==0) {
215 for (p2
=p
-1;p2
>name
;p2
--) {
216 if (p2
[0] == '/') break;
227 p
= l
>=2?(name
+l
-2):name
;
228 if (strcmp(p
,"/.")==0) {
236 if (strncmp(p
=name
,"./",2) == 0) {
244 if (l
> 1 && p
[l
-1] == '/') {
253 /*****************************************************
254 find a workgroup (any workgroup!) that has a master
255 browser on the local network
256 *******************************************************/
257 static char *smbw_find_workgroup(void)
261 struct in_addr
*ip_list
= NULL
;
265 /* first off see if an existing workgroup name exists */
266 p
= smbw_getshared("WORKGROUP");
267 if (!p
) p
= lp_workgroup();
269 slprintf(server
, sizeof(server
), "%s#1D", p
);
270 if (smbw_server(server
, "IPC$")) return p
;
272 /* go looking for workgroups */
273 if (!name_resolve_bcast(MSBROWSE
, 1, &ip_list
, &count
)) {
274 DEBUG(1,("No workgroups found!"));
278 for (i
=0;i
<count
;i
++) {
280 if (name_status_find(0x1d, ip_list
[i
], name
)) {
281 slprintf(server
, sizeof(server
), "%s#1D", name
);
282 if (smbw_server(server
, "IPC$")) {
283 smbw_setshared("WORKGROUP", name
);
295 /*****************************************************
296 parse a smb path into its components.
298 1) the name of the SMB server
299 2) WORKGROUP#1D for share listing
300 3) WORKGROUP#__ for workgroup listing
301 share is the share on the server to query
302 path is the SMB path on the server
303 return the full path (ie. add cwd if needed)
304 *******************************************************/
305 char *smbw_parse_path(const char *fname
, char *server
, char *share
, char *path
)
312 /* add cwd if necessary */
313 if (fname
[0] != '/') {
314 slprintf(s
, sizeof(s
), "%s/%s", smbw_cwd
, fname
);
320 /* see if it has the right prefix */
321 len
= strlen(smbw_prefix
)-1;
322 if (strncmp(s
,smbw_prefix
,len
) ||
323 (s
[len
] != '/' && s
[len
] != 0)) return s
;
325 /* ok, its for us. Now parse out the workgroup, share etc. */
328 if (!next_token(&p
, workgroup
, "/", sizeof(fstring
))) {
329 /* we're in /smb - give a list of workgroups */
330 slprintf(server
,sizeof(fstring
), "%s#01", smbw_find_workgroup());
331 fstrcpy(share
,"IPC$");
336 if (!next_token(&p
, server
, "/", sizeof(fstring
))) {
337 /* we are in /smb/WORKGROUP */
338 slprintf(server
,sizeof(fstring
), "%s#1D", workgroup
);
339 fstrcpy(share
,"IPC$");
343 if (!next_token(&p
, share
, "/", sizeof(fstring
))) {
344 /* we are in /smb/WORKGROUP/SERVER */
345 fstrcpy(share
,"IPC$");
351 all_string_sub(path
, "/", "\\", 0);
356 /*****************************************************
357 determine if a path name (possibly relative) is in the
359 *******************************************************/
360 int smbw_path(const char *path
)
362 fstring server
, share
;
370 /* this is needed to prevent recursion with the BSD malloc which
371 opens /etc/malloc.conf on the first call */
372 if (strncmp(path
,"/etc/", 5) == 0) {
378 len
= strlen(smbw_prefix
)-1;
380 if (path
[0] == '/' && strncmp(path
,smbw_prefix
,len
)) {
384 if (smbw_busy
) return 0;
386 DEBUG(3,("smbw_path(%s)\n", path
));
388 cwd
= smbw_parse_path(path
, server
, share
, s
);
390 if (strncmp(cwd
,smbw_prefix
,len
) == 0 &&
391 (cwd
[len
] == '/' || cwd
[len
] == 0)) {
398 /*****************************************************
399 return a unix errno from a SMB error pair
400 *******************************************************/
401 int smbw_errno(struct cli_state
*c
)
407 ret
= cli_error(c
, &eclass
, &ecode
, NULL
);
410 DEBUG(3,("smbw_error %d %d (0x%x) -> %d\n",
411 (int)eclass
, (int)ecode
, (int)ecode
, ret
));
416 /* Return a username and password given a server and share name */
418 void get_envvar_auth_data(char *server
, char *share
, char **workgroup
,
419 char **username
, char **password
)
421 /* Fall back to shared memory/environment variables */
423 *username
= smbw_getshared("USER");
424 if (!*username
) *username
= getenv("USER");
425 if (!*username
) *username
= "guest";
427 *workgroup
= smbw_getshared("WORKGROUP");
428 if (!*workgroup
) *workgroup
= lp_workgroup();
430 *password
= smbw_getshared("PASSWORD");
431 if (!*password
) *password
= "";
434 static smbw_get_auth_data_fn get_auth_data_fn
= get_envvar_auth_data
;
436 /*****************************************************
437 set the get auth data function
438 ******************************************************/
439 void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn
)
441 get_auth_data_fn
= fn
;
444 /*****************************************************
445 return a connection to a server (existing or new)
446 *******************************************************/
447 struct smbw_server
*smbw_server(char *server
, char *share
)
449 struct smbw_server
*srv
=NULL
;
454 struct nmb_name called
, calling
;
455 char *p
, *server_n
= server
;
459 extern struct in_addr ipzero
;
464 get_auth_data_fn(server
, share
, &workgroup
, &username
, &password
);
466 /* try to use an existing connection */
467 for (srv
=smbw_srvs
;srv
;srv
=srv
->next
) {
468 if (strcmp(server
,srv
->server_name
)==0 &&
469 strcmp(share
,srv
->share_name
)==0 &&
470 strcmp(workgroup
,srv
->workgroup
)==0 &&
471 strcmp(username
, srv
->username
) == 0)
475 if (server
[0] == 0) {
480 make_nmb_name(&calling
, global_myname
, 0x0);
481 make_nmb_name(&called
, server
, 0x20);
483 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n
, server
));
485 if ((p
=strchr_m(server_n
,'#')) &&
486 (strcmp(p
+1,"1D")==0 || strcmp(p
+1,"01")==0)) {
490 fstrcpy(group
, server_n
);
491 p
= strchr_m(group
,'#');
494 /* cache the workgroup master lookup */
495 slprintf(s
,sizeof(s
)-1,"MASTER_%s", group
);
496 if (!(server_n
= smbw_getshared(s
))) {
497 if (!find_master_ip(group
, &sip
)) {
501 fstrcpy(group
, inet_ntoa(sip
));
503 smbw_setshared(s
,server_n
);
507 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n
, server
));
510 slprintf(ipenv
,sizeof(ipenv
)-1,"HOST_%s", server_n
);
513 if ((p
=smbw_getshared(ipenv
))) {
514 ip
= *(interpret_addr2(p
));
517 /* have to open a new connection */
518 if (!cli_initialise(&c
) || !cli_connect(&c
, server_n
, &ip
)) {
523 if (!cli_session_request(&c
, &calling
, &called
)) {
525 if (strcmp(called
.name
, "*SMBSERVER")) {
526 make_nmb_name(&called
, "*SMBSERVER", 0x20);
533 DEBUG(4,(" session request ok\n"));
535 if (!cli_negprot(&c
)) {
541 if (!cli_session_setup(&c
, username
,
542 password
, strlen(password
),
543 password
, strlen(password
),
545 /* try an anonymous login if it failed */
546 !cli_session_setup(&c
, "", "", 1,"", 0, workgroup
)) {
552 DEBUG(4,(" session setup ok\n"));
554 if (!cli_send_tconX(&c
, share
, "?????",
555 password
, strlen(password
)+1)) {
556 errno
= smbw_errno(&c
);
561 smbw_setshared(ipenv
,inet_ntoa(ip
));
563 DEBUG(4,(" tconx ok\n"));
565 srv
= (struct smbw_server
*)malloc(sizeof(*srv
));
575 srv
->dev
= (dev_t
)(str_checksum(server
) ^ str_checksum(share
));
577 srv
->server_name
= strdup(server
);
578 if (!srv
->server_name
) {
583 srv
->share_name
= strdup(share
);
584 if (!srv
->share_name
) {
589 srv
->workgroup
= strdup(workgroup
);
590 if (!srv
->workgroup
) {
595 srv
->username
= strdup(username
);
596 if (!srv
->username
) {
601 /* some programs play with file descriptors fairly intimately. We
602 try to get out of the way by duping to a high fd number */
603 if (fcntl(SMBW_CLI_FD
+ srv
->cli
.fd
, F_GETFD
) && errno
== EBADF
) {
604 if (dup2(srv
->cli
.fd
,SMBW_CLI_FD
+srv
->cli
.fd
) ==
605 srv
->cli
.fd
+SMBW_CLI_FD
) {
607 srv
->cli
.fd
+= SMBW_CLI_FD
;
611 DLIST_ADD(smbw_srvs
, srv
);
617 if (!srv
) return NULL
;
619 if (srv
->server_name
) free(srv
->server_name
);
620 if (srv
->share_name
) free(srv
->share_name
);
626 /*****************************************************
627 map a fd to a smbw_file structure
628 *******************************************************/
629 struct smbw_file
*smbw_file(int fd
)
631 struct smbw_file
*file
;
633 for (file
=smbw_files
;file
;file
=file
->next
) {
634 if (file
->fd
== fd
) return file
;
639 /*****************************************************
641 *******************************************************/
642 int smbw_open(const char *fname
, int flags
, mode_t mode
)
644 fstring server
, share
;
646 struct smbw_server
*srv
=NULL
;
648 struct smbw_file
*file
=NULL
;
659 /* work out what server they are after */
660 smbw_parse_path(fname
, server
, share
, path
);
662 /* get a connection to the server */
663 srv
= smbw_server(server
, share
);
665 /* smbw_server sets errno */
669 if (path
[strlen(path
)-1] == '\\') {
672 fd
= cli_open(&srv
->cli
, path
, flags
, DENY_NONE
);
675 /* it might be a directory. Maybe we should use chkpath? */
676 eno
= smbw_errno(&srv
->cli
);
677 fd
= smbw_dir_open(fname
);
678 if (fd
== -1) errno
= eno
;
683 file
= (struct smbw_file
*)malloc(sizeof(*file
));
691 file
->f
= (struct smbw_filedes
*)malloc(sizeof(*(file
->f
)));
697 ZERO_STRUCTP(file
->f
);
699 file
->f
->cli_fd
= fd
;
700 file
->f
->fname
= strdup(path
);
701 if (!file
->f
->fname
) {
706 file
->fd
= open(SMBW_DUMMY
, O_WRONLY
);
707 if (file
->fd
== -1) {
712 if (bitmap_query(smbw_file_bmap
, file
->fd
)) {
713 DEBUG(0,("ERROR: fd used in smbw_open\n"));
718 file
->f
->ref_count
=1;
720 bitmap_set(smbw_file_bmap
, file
->fd
);
722 DLIST_ADD(smbw_files
, file
);
724 DEBUG(4,("opened %s\n", fname
));
731 cli_close(&srv
->cli
, fd
);
735 if (file
->f
->fname
) {
736 free(file
->f
->fname
);
747 /*****************************************************
748 a wrapper for pread()
749 *******************************************************/
750 ssize_t
smbw_pread(int fd
, void *buf
, size_t count
, off_t ofs
)
752 struct smbw_file
*file
;
757 file
= smbw_file(fd
);
764 ret
= cli_read(&file
->srv
->cli
, file
->f
->cli_fd
, buf
, ofs
, count
);
767 errno
= smbw_errno(&file
->srv
->cli
);
776 /*****************************************************
778 *******************************************************/
779 ssize_t
smbw_read(int fd
, void *buf
, size_t count
)
781 struct smbw_file
*file
;
784 DEBUG(4,("smbw_read(%d, %d)\n", fd
, (int)count
));
788 file
= smbw_file(fd
);
795 ret
= cli_read(&file
->srv
->cli
, file
->f
->cli_fd
, buf
,
796 file
->f
->offset
, count
);
799 errno
= smbw_errno(&file
->srv
->cli
);
804 file
->f
->offset
+= ret
;
806 DEBUG(4,(" -> %d\n", ret
));
814 /*****************************************************
815 a wrapper for write()
816 *******************************************************/
817 ssize_t
smbw_write(int fd
, void *buf
, size_t count
)
819 struct smbw_file
*file
;
824 file
= smbw_file(fd
);
831 ret
= cli_write(&file
->srv
->cli
, file
->f
->cli_fd
, 0, buf
, file
->f
->offset
, count
);
834 errno
= smbw_errno(&file
->srv
->cli
);
839 file
->f
->offset
+= ret
;
845 /*****************************************************
846 a wrapper for pwrite()
847 *******************************************************/
848 ssize_t
smbw_pwrite(int fd
, void *buf
, size_t count
, off_t ofs
)
850 struct smbw_file
*file
;
855 file
= smbw_file(fd
);
862 ret
= cli_write(&file
->srv
->cli
, file
->f
->cli_fd
, 0, buf
, ofs
, count
);
865 errno
= smbw_errno(&file
->srv
->cli
);
874 /*****************************************************
875 a wrapper for close()
876 *******************************************************/
877 int smbw_close(int fd
)
879 struct smbw_file
*file
;
883 file
= smbw_file(fd
);
885 int ret
= smbw_dir_close(fd
);
890 if (file
->f
->ref_count
== 1 &&
891 !cli_close(&file
->srv
->cli
, file
->f
->cli_fd
)) {
892 errno
= smbw_errno(&file
->srv
->cli
);
898 bitmap_clear(smbw_file_bmap
, file
->fd
);
901 DLIST_REMOVE(smbw_files
, file
);
903 file
->f
->ref_count
--;
904 if (file
->f
->ref_count
== 0) {
905 free(file
->f
->fname
);
917 /*****************************************************
918 a wrapper for fcntl()
919 *******************************************************/
920 int smbw_fcntl(int fd
, int cmd
, long arg
)
926 /*****************************************************
927 a wrapper for access()
928 *******************************************************/
929 int smbw_access(const char *name
, int mode
)
933 DEBUG(4,("smbw_access(%s, 0x%x)\n", name
, mode
));
935 if (smbw_stat(name
, &st
)) return -1;
937 if (((mode
& R_OK
) && !(st
.st_mode
& S_IRUSR
)) ||
938 ((mode
& W_OK
) && !(st
.st_mode
& S_IWUSR
)) ||
939 ((mode
& X_OK
) && !(st
.st_mode
& S_IXUSR
))) {
947 /*****************************************************
948 a wrapper for realink() - needed for correct errno setting
949 *******************************************************/
950 int smbw_readlink(const char *path
, char *buf
, size_t bufsize
)
955 ret
= smbw_stat(path
, &st
);
957 DEBUG(4,("readlink(%s) failed\n", path
));
961 /* it exists - say it isn't a link */
962 DEBUG(4,("readlink(%s) not a link\n", path
));
969 /*****************************************************
970 a wrapper for unlink()
971 *******************************************************/
972 int smbw_unlink(const char *fname
)
974 struct smbw_server
*srv
;
975 fstring server
, share
;
987 /* work out what server they are after */
988 smbw_parse_path(fname
, server
, share
, path
);
990 /* get a connection to the server */
991 srv
= smbw_server(server
, share
);
993 /* smbw_server sets errno */
997 if (strncmp(srv
->cli
.dev
, "LPT", 3) == 0) {
998 int job
= smbw_stat_printjob(srv
, path
, NULL
, NULL
);
1002 if (cli_printjob_del(&srv
->cli
, job
) != 0) {
1005 } else if (!cli_unlink(&srv
->cli
, path
)) {
1006 errno
= smbw_errno(&srv
->cli
);
1019 /*****************************************************
1020 a wrapper for rename()
1021 *******************************************************/
1022 int smbw_rename(const char *oldname
, const char *newname
)
1024 struct smbw_server
*srv
;
1025 fstring server1
, share1
;
1027 fstring server2
, share2
;
1030 if (!oldname
|| !newname
) {
1037 DEBUG(4,("smbw_rename(%s,%s)\n", oldname
, newname
));
1041 /* work out what server they are after */
1042 smbw_parse_path(oldname
, server1
, share1
, path1
);
1043 smbw_parse_path(newname
, server2
, share2
, path2
);
1045 if (strcmp(server1
, server2
) || strcmp(share1
, share2
)) {
1046 /* can't cross filesystems */
1051 /* get a connection to the server */
1052 srv
= smbw_server(server1
, share1
);
1054 /* smbw_server sets errno */
1058 if (!cli_rename(&srv
->cli
, path1
, path2
)) {
1059 int eno
= smbw_errno(&srv
->cli
);
1060 if (eno
!= EEXIST
||
1061 !cli_unlink(&srv
->cli
, path2
) ||
1062 !cli_rename(&srv
->cli
, path1
, path2
)) {
1077 /*****************************************************
1078 a wrapper for utime and utimes
1079 *******************************************************/
1080 static int smbw_settime(const char *fname
, time_t t
)
1082 struct smbw_server
*srv
;
1083 fstring server
, share
;
1096 /* work out what server they are after */
1097 smbw_parse_path(fname
, server
, share
, path
);
1099 /* get a connection to the server */
1100 srv
= smbw_server(server
, share
);
1102 /* smbw_server sets errno */
1106 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1107 errno
= smbw_errno(&srv
->cli
);
1111 if (!cli_setatr(&srv
->cli
, path
, mode
, t
)) {
1112 /* some servers always refuse directory changes */
1113 if (!(mode
& aDIR
)) {
1114 errno
= smbw_errno(&srv
->cli
);
1127 /*****************************************************
1129 *******************************************************/
1130 int smbw_utime(const char *fname
, void *buf
)
1132 struct utimbuf
*tbuf
= (struct utimbuf
*)buf
;
1133 return smbw_settime(fname
, tbuf
?tbuf
->modtime
:time(NULL
));
1136 /*****************************************************
1138 *******************************************************/
1139 int smbw_utimes(const char *fname
, void *buf
)
1141 struct timeval
*tbuf
= (struct timeval
*)buf
;
1142 return smbw_settime(fname
, tbuf
?tbuf
->tv_sec
:time(NULL
));
1146 /*****************************************************
1147 a wrapper for chown()
1148 *******************************************************/
1149 int smbw_chown(const char *fname
, uid_t owner
, gid_t group
)
1151 struct smbw_server
*srv
;
1152 fstring server
, share
;
1165 /* work out what server they are after */
1166 smbw_parse_path(fname
, server
, share
, path
);
1168 /* get a connection to the server */
1169 srv
= smbw_server(server
, share
);
1171 /* smbw_server sets errno */
1175 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1176 errno
= smbw_errno(&srv
->cli
);
1180 /* assume success */
1190 /*****************************************************
1191 a wrapper for chmod()
1192 *******************************************************/
1193 int smbw_chmod(const char *fname
, mode_t newmode
)
1195 struct smbw_server
*srv
;
1196 fstring server
, share
;
1209 /* work out what server they are after */
1210 smbw_parse_path(fname
, server
, share
, path
);
1212 /* get a connection to the server */
1213 srv
= smbw_server(server
, share
);
1215 /* smbw_server sets errno */
1221 if (!(newmode
& (S_IWUSR
| S_IWGRP
| S_IWOTH
))) mode
|= aRONLY
;
1222 if ((newmode
& S_IXUSR
) && lp_map_archive(-1)) mode
|= aARCH
;
1223 if ((newmode
& S_IXGRP
) && lp_map_system(-1)) mode
|= aSYSTEM
;
1224 if ((newmode
& S_IXOTH
) && lp_map_hidden(-1)) mode
|= aHIDDEN
;
1226 if (!cli_setatr(&srv
->cli
, path
, mode
, 0)) {
1227 errno
= smbw_errno(&srv
->cli
);
1239 /*****************************************************
1240 a wrapper for lseek()
1241 *******************************************************/
1242 off_t
smbw_lseek(int fd
, off_t offset
, int whence
)
1244 struct smbw_file
*file
;
1249 file
= smbw_file(fd
);
1251 off_t ret
= smbw_dir_lseek(fd
, offset
, whence
);
1258 file
->f
->offset
= offset
;
1261 file
->f
->offset
+= offset
;
1264 if (!cli_qfileinfo(&file
->srv
->cli
, file
->f
->cli_fd
,
1265 NULL
, &size
, NULL
, NULL
, NULL
,
1267 !cli_getattrE(&file
->srv
->cli
, file
->f
->cli_fd
,
1268 NULL
, &size
, NULL
, NULL
, NULL
)) {
1273 file
->f
->offset
= size
+ offset
;
1278 return file
->f
->offset
;
1282 /*****************************************************
1284 *******************************************************/
1285 int smbw_dup(int fd
)
1288 struct smbw_file
*file
, *file2
;
1292 file
= smbw_file(fd
);
1298 fd2
= dup(file
->fd
);
1303 if (bitmap_query(smbw_file_bmap
, fd2
)) {
1304 DEBUG(0,("ERROR: fd already open in dup!\n"));
1309 file2
= (struct smbw_file
*)malloc(sizeof(*file2
));
1316 ZERO_STRUCTP(file2
);
1321 file
->f
->ref_count
++;
1323 bitmap_set(smbw_file_bmap
, fd2
);
1325 DLIST_ADD(smbw_files
, file2
);
1336 /*****************************************************
1337 a wrapper for dup2()
1338 *******************************************************/
1339 int smbw_dup2(int fd
, int fd2
)
1341 struct smbw_file
*file
, *file2
;
1345 file
= smbw_file(fd
);
1351 if (bitmap_query(smbw_file_bmap
, fd2
)) {
1352 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1357 if (dup2(file
->fd
, fd2
) != fd2
) {
1361 file2
= (struct smbw_file
*)malloc(sizeof(*file2
));
1368 ZERO_STRUCTP(file2
);
1373 file
->f
->ref_count
++;
1375 bitmap_set(smbw_file_bmap
, fd2
);
1377 DLIST_ADD(smbw_files
, file2
);
1388 /*****************************************************
1389 close a connection to a server
1390 *******************************************************/
1391 static void smbw_srv_close(struct smbw_server
*srv
)
1395 cli_shutdown(&srv
->cli
);
1397 free(srv
->server_name
);
1398 free(srv
->share_name
);
1400 DLIST_REMOVE(smbw_srvs
, srv
);
1409 /*****************************************************
1410 when we fork we have to close all connections and files
1412 *******************************************************/
1420 struct smbw_file
*file
, *next_file
;
1421 struct smbw_server
*srv
, *next_srv
;
1423 if (pipe(p
)) return real_fork();
1425 child
= real_fork();
1428 /* block the parent for a moment until the sockets are
1438 /* close all files */
1439 for (file
=smbw_files
;file
;file
=next_file
) {
1440 next_file
= file
->next
;
1444 /* close all server connections */
1445 for (srv
=smbw_srvs
;srv
;srv
=next_srv
) {
1446 next_srv
= srv
->next
;
1447 smbw_srv_close(srv
);
1450 slprintf(line
,sizeof(line
)-1,"PWD_%d", (int)getpid());
1451 smbw_setshared(line
,smbw_cwd
);
1453 /* unblock the parent */
1457 /* and continue in the child */
1461 #ifndef NO_ACL_WRAPPER
1462 /*****************************************************
1464 *******************************************************/
1465 int smbw_acl(const char *pathp
, int cmd
, int nentries
, aclent_t
*aclbufp
)
1467 if (cmd
== GETACL
|| cmd
== GETACLCNT
) return 0;
1473 #ifndef NO_FACL_WRAPPER
1474 /*****************************************************
1476 *******************************************************/
1477 int smbw_facl(int fd
, int cmd
, int nentries
, aclent_t
*aclbufp
)
1479 if (cmd
== GETACL
|| cmd
== GETACLCNT
) return 0;
1485 #ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
1487 /* this can't be in wrapped.c because of include conflicts */
1488 void stat64_convert(struct stat
*st
, struct stat64
*st64
)
1490 st64
->st_size
= st
->st_size
;
1491 st64
->st_mode
= st
->st_mode
;
1492 st64
->st_ino
= st
->st_ino
;
1493 st64
->st_dev
= st
->st_dev
;
1494 st64
->st_rdev
= st
->st_rdev
;
1495 st64
->st_nlink
= st
->st_nlink
;
1496 st64
->st_uid
= st
->st_uid
;
1497 st64
->st_gid
= st
->st_gid
;
1498 st64
->st_atime
= st
->st_atime
;
1499 st64
->st_mtime
= st
->st_mtime
;
1500 st64
->st_ctime
= st
->st_ctime
;
1501 st64
->st_blksize
= st
->st_blksize
;
1502 st64
->st_blocks
= st
->st_blocks
;
1506 #ifdef HAVE_READDIR64
1507 void dirent64_convert(struct dirent
*d
, struct dirent64
*d64
)
1509 d64
->d_ino
= d
->d_ino
;
1510 d64
->d_off
= d
->d_off
;
1511 d64
->d_reclen
= d
->d_reclen
;
1512 pstrcpy(d64
->d_name
, d
->d_name
);
1519 /* Definition of `struct stat' used in the linux kernel.. */
1520 struct kernel_stat
{
1521 unsigned short int st_dev
;
1522 unsigned short int __pad1
;
1523 unsigned long int st_ino
;
1524 unsigned short int st_mode
;
1525 unsigned short int st_nlink
;
1526 unsigned short int st_uid
;
1527 unsigned short int st_gid
;
1528 unsigned short int st_rdev
;
1529 unsigned short int __pad2
;
1530 unsigned long int st_size
;
1531 unsigned long int st_blksize
;
1532 unsigned long int st_blocks
;
1533 unsigned long int st_atime
;
1534 unsigned long int __unused1
;
1535 unsigned long int st_mtime
;
1536 unsigned long int __unused2
;
1537 unsigned long int st_ctime
;
1538 unsigned long int __unused3
;
1539 unsigned long int __unused4
;
1540 unsigned long int __unused5
;
1544 * Prototype for gcc in 'fussy' mode.
1546 void xstat_convert(int vers
, struct stat
*st
, struct kernel_stat
*kbuf
);
1547 void xstat_convert(int vers
, struct stat
*st
, struct kernel_stat
*kbuf
)
1549 #ifdef _STAT_VER_LINUX_OLD
1550 if (vers
== _STAT_VER_LINUX_OLD
) {
1551 memcpy(st
, kbuf
, sizeof(*st
));
1558 st
->st_dev
= kbuf
->st_dev
;
1559 st
->st_ino
= kbuf
->st_ino
;
1560 st
->st_mode
= kbuf
->st_mode
;
1561 st
->st_nlink
= kbuf
->st_nlink
;
1562 st
->st_uid
= kbuf
->st_uid
;
1563 st
->st_gid
= kbuf
->st_gid
;
1564 st
->st_rdev
= kbuf
->st_rdev
;
1565 st
->st_size
= kbuf
->st_size
;
1566 st
->st_blksize
= kbuf
->st_blksize
;
1567 st
->st_blocks
= kbuf
->st_blocks
;
1568 st
->st_atime
= kbuf
->st_atime
;
1569 st
->st_mtime
= kbuf
->st_mtime
;
1570 st
->st_ctime
= kbuf
->st_ctime
;