2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "realcalls.h"
26 static struct smbw_file
*smbw_files
;
27 static struct smbw_server
*smbw_srvs
;
29 struct bitmap
*smbw_file_bmap
;
31 fstring smbw_prefix
= SMBW_PREFIX
;
35 /* needs to be here because of dumb include files on some systems */
36 int creat_bits
= O_WRONLY
|O_CREAT
|O_TRUNC
;
39 /*****************************************************
41 *******************************************************/
44 extern BOOL in_client
;
45 static int initialised
;
50 if (initialised
) return;
58 setup_logging("smbsh",True
);
62 if ((p
=smbw_getshared("LOGFILE"))) {
63 dbf
= sys_fopen(p
, "a");
66 smbw_file_bmap
= bitmap_allocate(SMBW_MAX_OPEN
);
67 if (!smbw_file_bmap
) {
75 if ((p
=smbw_getshared("SERVICESF"))) {
76 pstrcpy(dyn_CONFIGFILE
, p
);
79 lp_load(dyn_CONFIGFILE
,True
,False
,False
);
84 if ((p
=smbw_getshared("DEBUG"))) {
88 if ((p
=smbw_getshared("RESOLVE_ORDER"))) {
89 lp_set_name_resolve_order(p
);
92 if ((p
=smbw_getshared("PREFIX"))) {
93 slprintf(smbw_prefix
,sizeof(fstring
)-1, "/%s/", p
);
94 all_string_sub(smbw_prefix
,"//", "/", 0);
95 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix
));
98 slprintf(line
,sizeof(line
)-1,"PWD_%d", (int)getpid());
100 p
= smbw_getshared(line
);
104 pstrcpy(smbw_cwd
, p
);
105 DEBUG(4,("Initial cwd is %s\n", smbw_cwd
));
109 set_maxfiles(SMBW_MAX_OPEN
);
111 BlockSignals(True
,SIGPIPE
);
116 /*****************************************************
117 determine if a file descriptor is a smb one
118 *******************************************************/
121 if (smbw_busy
) return 0;
122 return smbw_file_bmap
&& bitmap_query(smbw_file_bmap
, fd
);
125 /*****************************************************
126 determine if a file descriptor is an internal smbw fd
127 *******************************************************/
128 int smbw_local_fd(int fd
)
130 struct smbw_server
*srv
;
134 if (smbw_busy
) return 0;
135 if (smbw_shared_fd(fd
)) return 1;
137 for (srv
=smbw_srvs
;srv
;srv
=srv
->next
) {
138 if (srv
->cli
.fd
== fd
) return 1;
144 /*****************************************************
145 a crude inode number generator
146 *******************************************************/
147 ino_t
smbw_inode(const char *name
)
149 if (!*name
) return 2;
150 return (ino_t
)str_checksum(name
);
153 /*****************************************************
154 remove redundent stuff from a filename
155 *******************************************************/
156 void clean_fname(char *name
)
167 DEBUG(5,("cleaning %s\n", name
));
169 if ((p
=strstr(name
,"/./"))) {
177 if ((p
=strstr(name
,"//"))) {
185 if (strcmp(name
,"/../")==0) {
190 if ((p
=strstr(name
,"/../"))) {
192 for (p2
=(p
>name
?p
-1:p
);p2
>name
;p2
--) {
193 if (p2
[0] == '/') break;
201 if (strcmp(name
,"/..")==0) {
207 p
= l
>=3?(name
+l
-3):name
;
208 if (strcmp(p
,"/..")==0) {
210 for (p2
=p
-1;p2
>name
;p2
--) {
211 if (p2
[0] == '/') break;
222 p
= l
>=2?(name
+l
-2):name
;
223 if (strcmp(p
,"/.")==0) {
231 if (strncmp(p
=name
,"./",2) == 0) {
239 if (l
> 1 && p
[l
-1] == '/') {
248 /*****************************************************
249 find a workgroup (any workgroup!) that has a master
250 browser on the local network
251 *******************************************************/
252 static char *smbw_find_workgroup(void)
256 struct in_addr
*ip_list
= NULL
;
260 /* first off see if an existing workgroup name exists */
261 p
= smbw_getshared("WORKGROUP");
262 if (!p
) p
= lp_workgroup();
264 slprintf(server
, sizeof(server
), "%s#1D", p
);
265 if (smbw_server(server
, "IPC$")) return p
;
267 /* go looking for workgroups */
268 if (!name_resolve_bcast(MSBROWSE
, 1, &ip_list
, &count
)) {
269 DEBUG(1,("No workgroups found!"));
273 for (i
=0;i
<count
;i
++) {
275 if (name_status_find("*", 0, 0x1d, ip_list
[i
], name
)) {
276 slprintf(server
, sizeof(server
), "%s#1D", name
);
277 if (smbw_server(server
, "IPC$")) {
278 smbw_setshared("WORKGROUP", name
);
290 /*****************************************************
291 parse a smb path into its components.
293 1) the name of the SMB server
294 2) WORKGROUP#1D for share listing
295 3) WORKGROUP#__ for workgroup listing
296 share is the share on the server to query
297 path is the SMB path on the server
298 return the full path (ie. add cwd if needed)
299 *******************************************************/
300 char *smbw_parse_path(const char *fname
, char *server
, char *share
, char *path
)
307 /* add cwd if necessary */
308 if (fname
[0] != '/') {
309 slprintf(s
, sizeof(s
), "%s/%s", smbw_cwd
, fname
);
315 /* see if it has the right prefix */
316 len
= strlen(smbw_prefix
)-1;
317 if (strncmp(s
,smbw_prefix
,len
) ||
318 (s
[len
] != '/' && s
[len
] != 0)) return s
;
320 /* ok, its for us. Now parse out the workgroup, share etc. */
323 if (!next_token(&p
, workgroup
, "/", sizeof(fstring
))) {
324 /* we're in /smb - give a list of workgroups */
325 slprintf(server
,sizeof(fstring
), "%s#01", smbw_find_workgroup());
326 fstrcpy(share
,"IPC$");
331 if (!next_token(&p
, server
, "/", sizeof(fstring
))) {
332 /* we are in /smb/WORKGROUP */
333 slprintf(server
,sizeof(fstring
), "%s#1D", workgroup
);
334 fstrcpy(share
,"IPC$");
338 if (!next_token(&p
, share
, "/", sizeof(fstring
))) {
339 /* we are in /smb/WORKGROUP/SERVER */
340 fstrcpy(share
,"IPC$");
346 all_string_sub(path
, "/", "\\", 0);
351 /*****************************************************
352 determine if a path name (possibly relative) is in the
354 *******************************************************/
355 int smbw_path(const char *path
)
357 fstring server
, share
;
365 /* this is needed to prevent recursion with the BSD malloc which
366 opens /etc/malloc.conf on the first call */
367 if (strncmp(path
,"/etc/", 5) == 0) {
373 len
= strlen(smbw_prefix
)-1;
375 if (path
[0] == '/' && strncmp(path
,smbw_prefix
,len
)) {
379 if (smbw_busy
) return 0;
381 DEBUG(3,("smbw_path(%s)\n", path
));
383 cwd
= smbw_parse_path(path
, server
, share
, s
);
385 if (strncmp(cwd
,smbw_prefix
,len
) == 0 &&
386 (cwd
[len
] == '/' || cwd
[len
] == 0)) {
393 /*****************************************************
394 return a unix errno from a SMB error pair
395 *******************************************************/
396 int smbw_errno(struct cli_state
*c
)
401 /* Return a username and password given a server and share name */
403 void get_envvar_auth_data(char *server
, char *share
, char **workgroup
,
404 char **username
, char **password
)
406 /* Fall back to shared memory/environment variables */
408 *username
= smbw_getshared("USER");
409 if (!*username
) *username
= getenv("USER");
410 if (!*username
) *username
= "guest";
412 *workgroup
= smbw_getshared("WORKGROUP");
413 if (!*workgroup
) *workgroup
= lp_workgroup();
415 *password
= smbw_getshared("PASSWORD");
416 if (!*password
) *password
= "";
419 static smbw_get_auth_data_fn get_auth_data_fn
= get_envvar_auth_data
;
421 /*****************************************************
422 set the get auth data function
423 ******************************************************/
424 void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn
)
426 get_auth_data_fn
= fn
;
429 /*****************************************************
430 return a connection to a server (existing or new)
431 *******************************************************/
432 struct smbw_server
*smbw_server(char *server
, char *share
)
434 struct smbw_server
*srv
=NULL
;
439 struct nmb_name called
, calling
;
440 char *p
, *server_n
= server
;
448 get_auth_data_fn(server
, share
, &workgroup
, &username
, &password
);
450 /* try to use an existing connection */
451 for (srv
=smbw_srvs
;srv
;srv
=srv
->next
) {
452 if (strcmp(server
,srv
->server_name
)==0 &&
453 strcmp(share
,srv
->share_name
)==0 &&
454 strcmp(workgroup
,srv
->workgroup
)==0 &&
455 strcmp(username
, srv
->username
) == 0)
459 if (server
[0] == 0) {
464 make_nmb_name(&calling
, global_myname(), 0x0);
465 make_nmb_name(&called
, server
, 0x20);
467 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n
, server
));
469 if ((p
=strchr_m(server_n
,'#')) &&
470 (strcmp(p
+1,"1D")==0 || strcmp(p
+1,"01")==0)) {
474 fstrcpy(group
, server_n
);
475 p
= strchr_m(group
,'#');
478 /* cache the workgroup master lookup */
479 slprintf(s
,sizeof(s
)-1,"MASTER_%s", group
);
480 if (!(server_n
= smbw_getshared(s
))) {
481 if (!find_master_ip(group
, &sip
)) {
485 fstrcpy(group
, inet_ntoa(sip
));
487 smbw_setshared(s
,server_n
);
491 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n
, server
));
494 slprintf(ipenv
,sizeof(ipenv
)-1,"HOST_%s", server_n
);
497 if ((p
=smbw_getshared(ipenv
))) {
498 ip
= *(interpret_addr2(p
));
501 /* have to open a new connection */
502 if (!cli_initialise(&c
) || !cli_connect(&c
, server_n
, &ip
)) {
507 if (!cli_session_request(&c
, &calling
, &called
)) {
509 if (strcmp(called
.name
, "*SMBSERVER")) {
510 make_nmb_name(&called
, "*SMBSERVER", 0x20);
517 DEBUG(4,(" session request ok\n"));
519 if (!cli_negprot(&c
)) {
525 if (!cli_session_setup(&c
, username
,
526 password
, strlen(password
),
527 password
, strlen(password
),
529 /* try an anonymous login if it failed */
530 !cli_session_setup(&c
, "", "", 1,"", 0, workgroup
)) {
536 DEBUG(4,(" session setup ok\n"));
538 if (!cli_send_tconX(&c
, share
, "?????",
539 password
, strlen(password
)+1)) {
540 errno
= smbw_errno(&c
);
545 smbw_setshared(ipenv
,inet_ntoa(ip
));
547 DEBUG(4,(" tconx ok\n"));
549 srv
= (struct smbw_server
*)malloc(sizeof(*srv
));
559 srv
->dev
= (dev_t
)(str_checksum(server
) ^ str_checksum(share
));
561 srv
->server_name
= strdup(server
);
562 if (!srv
->server_name
) {
567 srv
->share_name
= strdup(share
);
568 if (!srv
->share_name
) {
573 srv
->workgroup
= strdup(workgroup
);
574 if (!srv
->workgroup
) {
579 srv
->username
= strdup(username
);
580 if (!srv
->username
) {
585 /* some programs play with file descriptors fairly intimately. We
586 try to get out of the way by duping to a high fd number */
587 if (fcntl(SMBW_CLI_FD
+ srv
->cli
.fd
, F_GETFD
) && errno
== EBADF
) {
588 if (dup2(srv
->cli
.fd
,SMBW_CLI_FD
+srv
->cli
.fd
) ==
589 srv
->cli
.fd
+SMBW_CLI_FD
) {
591 srv
->cli
.fd
+= SMBW_CLI_FD
;
595 DLIST_ADD(smbw_srvs
, srv
);
601 if (!srv
) return NULL
;
603 SAFE_FREE(srv
->server_name
);
604 SAFE_FREE(srv
->share_name
);
610 /*****************************************************
611 map a fd to a smbw_file structure
612 *******************************************************/
613 struct smbw_file
*smbw_file(int fd
)
615 struct smbw_file
*file
;
617 for (file
=smbw_files
;file
;file
=file
->next
) {
618 if (file
->fd
== fd
) return file
;
623 /*****************************************************
625 *******************************************************/
626 int smbw_open(const char *fname
, int flags
, mode_t mode
)
628 fstring server
, share
;
630 struct smbw_server
*srv
=NULL
;
632 struct smbw_file
*file
=NULL
;
643 /* work out what server they are after */
644 smbw_parse_path(fname
, server
, share
, path
);
646 /* get a connection to the server */
647 srv
= smbw_server(server
, share
);
649 /* smbw_server sets errno */
653 if (path
[strlen(path
)-1] == '\\') {
656 fd
= cli_open(&srv
->cli
, path
, flags
, DENY_NONE
);
659 /* it might be a directory. Maybe we should use chkpath? */
660 eno
= smbw_errno(&srv
->cli
);
661 fd
= smbw_dir_open(fname
);
662 if (fd
== -1) errno
= eno
;
667 file
= (struct smbw_file
*)malloc(sizeof(*file
));
675 file
->f
= (struct smbw_filedes
*)malloc(sizeof(*(file
->f
)));
681 ZERO_STRUCTP(file
->f
);
683 file
->f
->cli_fd
= fd
;
684 file
->f
->fname
= strdup(path
);
685 if (!file
->f
->fname
) {
690 file
->fd
= open(SMBW_DUMMY
, O_WRONLY
);
691 if (file
->fd
== -1) {
696 if (bitmap_query(smbw_file_bmap
, file
->fd
)) {
697 DEBUG(0,("ERROR: fd used in smbw_open\n"));
702 file
->f
->ref_count
=1;
704 bitmap_set(smbw_file_bmap
, file
->fd
);
706 DLIST_ADD(smbw_files
, file
);
708 DEBUG(4,("opened %s\n", fname
));
715 cli_close(&srv
->cli
, fd
);
719 SAFE_FREE(file
->f
->fname
);
729 /*****************************************************
730 a wrapper for pread()
731 *******************************************************/
732 ssize_t
smbw_pread(int fd
, void *buf
, size_t count
, off_t ofs
)
734 struct smbw_file
*file
;
739 file
= smbw_file(fd
);
746 ret
= cli_read(&file
->srv
->cli
, file
->f
->cli_fd
, buf
, ofs
, count
);
749 errno
= smbw_errno(&file
->srv
->cli
);
758 /*****************************************************
760 *******************************************************/
761 ssize_t
smbw_read(int fd
, void *buf
, size_t count
)
763 struct smbw_file
*file
;
766 DEBUG(4,("smbw_read(%d, %d)\n", fd
, (int)count
));
770 file
= smbw_file(fd
);
777 ret
= cli_read(&file
->srv
->cli
, file
->f
->cli_fd
, buf
,
778 file
->f
->offset
, count
);
781 errno
= smbw_errno(&file
->srv
->cli
);
786 file
->f
->offset
+= ret
;
788 DEBUG(4,(" -> %d\n", ret
));
796 /*****************************************************
797 a wrapper for write()
798 *******************************************************/
799 ssize_t
smbw_write(int fd
, void *buf
, size_t count
)
801 struct smbw_file
*file
;
806 file
= smbw_file(fd
);
813 ret
= cli_write(&file
->srv
->cli
, file
->f
->cli_fd
, 0, buf
, file
->f
->offset
, count
);
816 errno
= smbw_errno(&file
->srv
->cli
);
821 file
->f
->offset
+= ret
;
827 /*****************************************************
828 a wrapper for pwrite()
829 *******************************************************/
830 ssize_t
smbw_pwrite(int fd
, void *buf
, size_t count
, off_t ofs
)
832 struct smbw_file
*file
;
837 file
= smbw_file(fd
);
844 ret
= cli_write(&file
->srv
->cli
, file
->f
->cli_fd
, 0, buf
, ofs
, count
);
847 errno
= smbw_errno(&file
->srv
->cli
);
856 /*****************************************************
857 a wrapper for close()
858 *******************************************************/
859 int smbw_close(int fd
)
861 struct smbw_file
*file
;
865 file
= smbw_file(fd
);
867 int ret
= smbw_dir_close(fd
);
872 if (file
->f
->ref_count
== 1 &&
873 !cli_close(&file
->srv
->cli
, file
->f
->cli_fd
)) {
874 errno
= smbw_errno(&file
->srv
->cli
);
880 bitmap_clear(smbw_file_bmap
, file
->fd
);
883 DLIST_REMOVE(smbw_files
, file
);
885 file
->f
->ref_count
--;
886 if (file
->f
->ref_count
== 0) {
887 SAFE_FREE(file
->f
->fname
);
899 /*****************************************************
900 a wrapper for fcntl()
901 *******************************************************/
902 int smbw_fcntl(int fd
, int cmd
, long arg
)
908 /*****************************************************
909 a wrapper for access()
910 *******************************************************/
911 int smbw_access(const char *name
, int mode
)
915 DEBUG(4,("smbw_access(%s, 0x%x)\n", name
, mode
));
917 if (smbw_stat(name
, &st
)) return -1;
919 if (((mode
& R_OK
) && !(st
.st_mode
& S_IRUSR
)) ||
920 ((mode
& W_OK
) && !(st
.st_mode
& S_IWUSR
)) ||
921 ((mode
& X_OK
) && !(st
.st_mode
& S_IXUSR
))) {
929 /*****************************************************
930 a wrapper for realink() - needed for correct errno setting
931 *******************************************************/
932 int smbw_readlink(const char *path
, char *buf
, size_t bufsize
)
937 ret
= smbw_stat(path
, &st
);
939 DEBUG(4,("readlink(%s) failed\n", path
));
943 /* it exists - say it isn't a link */
944 DEBUG(4,("readlink(%s) not a link\n", path
));
951 /*****************************************************
952 a wrapper for unlink()
953 *******************************************************/
954 int smbw_unlink(const char *fname
)
956 struct smbw_server
*srv
;
957 fstring server
, share
;
969 /* work out what server they are after */
970 smbw_parse_path(fname
, server
, share
, path
);
972 /* get a connection to the server */
973 srv
= smbw_server(server
, share
);
975 /* smbw_server sets errno */
979 if (strncmp(srv
->cli
.dev
, "LPT", 3) == 0) {
980 int job
= smbw_stat_printjob(srv
, path
, NULL
, NULL
);
984 if (cli_printjob_del(&srv
->cli
, job
) != 0) {
987 } else if (!cli_unlink(&srv
->cli
, path
)) {
988 errno
= smbw_errno(&srv
->cli
);
1001 /*****************************************************
1002 a wrapper for rename()
1003 *******************************************************/
1004 int smbw_rename(const char *oldname
, const char *newname
)
1006 struct smbw_server
*srv
;
1007 fstring server1
, share1
;
1009 fstring server2
, share2
;
1012 if (!oldname
|| !newname
) {
1019 DEBUG(4,("smbw_rename(%s,%s)\n", oldname
, newname
));
1023 /* work out what server they are after */
1024 smbw_parse_path(oldname
, server1
, share1
, path1
);
1025 smbw_parse_path(newname
, server2
, share2
, path2
);
1027 if (strcmp(server1
, server2
) || strcmp(share1
, share2
)) {
1028 /* can't cross filesystems */
1033 /* get a connection to the server */
1034 srv
= smbw_server(server1
, share1
);
1036 /* smbw_server sets errno */
1040 if (!cli_rename(&srv
->cli
, path1
, path2
)) {
1041 int eno
= smbw_errno(&srv
->cli
);
1042 if (eno
!= EEXIST
||
1043 !cli_unlink(&srv
->cli
, path2
) ||
1044 !cli_rename(&srv
->cli
, path1
, path2
)) {
1059 /*****************************************************
1060 a wrapper for utime and utimes
1061 *******************************************************/
1062 static int smbw_settime(const char *fname
, time_t t
)
1064 struct smbw_server
*srv
;
1065 fstring server
, share
;
1078 /* work out what server they are after */
1079 smbw_parse_path(fname
, server
, share
, path
);
1081 /* get a connection to the server */
1082 srv
= smbw_server(server
, share
);
1084 /* smbw_server sets errno */
1088 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1089 errno
= smbw_errno(&srv
->cli
);
1093 if (!cli_setatr(&srv
->cli
, path
, mode
, t
)) {
1094 /* some servers always refuse directory changes */
1095 if (!(mode
& aDIR
)) {
1096 errno
= smbw_errno(&srv
->cli
);
1109 /*****************************************************
1111 *******************************************************/
1112 int smbw_utime(const char *fname
, void *buf
)
1114 struct utimbuf
*tbuf
= (struct utimbuf
*)buf
;
1115 return smbw_settime(fname
, tbuf
?tbuf
->modtime
:time(NULL
));
1118 /*****************************************************
1120 *******************************************************/
1121 int smbw_utimes(const char *fname
, void *buf
)
1123 struct timeval
*tbuf
= (struct timeval
*)buf
;
1124 return smbw_settime(fname
, tbuf
?tbuf
->tv_sec
:time(NULL
));
1128 /*****************************************************
1129 a wrapper for chown()
1130 *******************************************************/
1131 int smbw_chown(const char *fname
, uid_t owner
, gid_t group
)
1133 struct smbw_server
*srv
;
1134 fstring server
, share
;
1147 /* work out what server they are after */
1148 smbw_parse_path(fname
, server
, share
, path
);
1150 /* get a connection to the server */
1151 srv
= smbw_server(server
, share
);
1153 /* smbw_server sets errno */
1157 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1158 errno
= smbw_errno(&srv
->cli
);
1162 /* assume success */
1172 /*****************************************************
1173 a wrapper for chmod()
1174 *******************************************************/
1175 int smbw_chmod(const char *fname
, mode_t newmode
)
1177 struct smbw_server
*srv
;
1178 fstring server
, share
;
1191 /* work out what server they are after */
1192 smbw_parse_path(fname
, server
, share
, path
);
1194 /* get a connection to the server */
1195 srv
= smbw_server(server
, share
);
1197 /* smbw_server sets errno */
1203 if (!(newmode
& (S_IWUSR
| S_IWGRP
| S_IWOTH
))) mode
|= aRONLY
;
1204 if ((newmode
& S_IXUSR
) && lp_map_archive(-1)) mode
|= aARCH
;
1205 if ((newmode
& S_IXGRP
) && lp_map_system(-1)) mode
|= aSYSTEM
;
1206 if ((newmode
& S_IXOTH
) && lp_map_hidden(-1)) mode
|= aHIDDEN
;
1208 if (!cli_setatr(&srv
->cli
, path
, mode
, 0)) {
1209 errno
= smbw_errno(&srv
->cli
);
1221 /*****************************************************
1222 a wrapper for lseek()
1223 *******************************************************/
1224 off_t
smbw_lseek(int fd
, off_t offset
, int whence
)
1226 struct smbw_file
*file
;
1231 file
= smbw_file(fd
);
1233 off_t ret
= smbw_dir_lseek(fd
, offset
, whence
);
1240 file
->f
->offset
= offset
;
1243 file
->f
->offset
+= offset
;
1246 if (!cli_qfileinfo(&file
->srv
->cli
, file
->f
->cli_fd
,
1247 NULL
, &size
, NULL
, NULL
, NULL
,
1249 !cli_getattrE(&file
->srv
->cli
, file
->f
->cli_fd
,
1250 NULL
, &size
, NULL
, NULL
, NULL
)) {
1255 file
->f
->offset
= size
+ offset
;
1260 return file
->f
->offset
;
1264 /*****************************************************
1266 *******************************************************/
1267 int smbw_dup(int fd
)
1270 struct smbw_file
*file
, *file2
;
1274 file
= smbw_file(fd
);
1280 fd2
= dup(file
->fd
);
1285 if (bitmap_query(smbw_file_bmap
, fd2
)) {
1286 DEBUG(0,("ERROR: fd already open in dup!\n"));
1291 file2
= (struct smbw_file
*)malloc(sizeof(*file2
));
1298 ZERO_STRUCTP(file2
);
1303 file
->f
->ref_count
++;
1305 bitmap_set(smbw_file_bmap
, fd2
);
1307 DLIST_ADD(smbw_files
, file2
);
1318 /*****************************************************
1319 a wrapper for dup2()
1320 *******************************************************/
1321 int smbw_dup2(int fd
, int fd2
)
1323 struct smbw_file
*file
, *file2
;
1327 file
= smbw_file(fd
);
1333 if (bitmap_query(smbw_file_bmap
, fd2
)) {
1334 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1339 if (dup2(file
->fd
, fd2
) != fd2
) {
1343 file2
= (struct smbw_file
*)malloc(sizeof(*file2
));
1350 ZERO_STRUCTP(file2
);
1355 file
->f
->ref_count
++;
1357 bitmap_set(smbw_file_bmap
, fd2
);
1359 DLIST_ADD(smbw_files
, file2
);
1370 /*****************************************************
1371 close a connection to a server
1372 *******************************************************/
1373 static void smbw_srv_close(struct smbw_server
*srv
)
1377 cli_shutdown(&srv
->cli
);
1379 SAFE_FREE(srv
->server_name
);
1380 SAFE_FREE(srv
->share_name
);
1382 DLIST_REMOVE(smbw_srvs
, srv
);
1391 /*****************************************************
1392 when we fork we have to close all connections and files
1394 *******************************************************/
1402 struct smbw_file
*file
, *next_file
;
1403 struct smbw_server
*srv
, *next_srv
;
1405 if (pipe(p
)) return real_fork();
1407 child
= real_fork();
1410 /* block the parent for a moment until the sockets are
1420 /* close all files */
1421 for (file
=smbw_files
;file
;file
=next_file
) {
1422 next_file
= file
->next
;
1426 /* close all server connections */
1427 for (srv
=smbw_srvs
;srv
;srv
=next_srv
) {
1428 next_srv
= srv
->next
;
1429 smbw_srv_close(srv
);
1432 slprintf(line
,sizeof(line
)-1,"PWD_%d", (int)getpid());
1433 smbw_setshared(line
,smbw_cwd
);
1435 /* unblock the parent */
1439 /* and continue in the child */
1443 #ifndef NO_ACL_WRAPPER
1444 /*****************************************************
1446 *******************************************************/
1447 int smbw_acl(const char *pathp
, int cmd
, int nentries
, aclent_t
*aclbufp
)
1449 if (cmd
== GETACL
|| cmd
== GETACLCNT
) return 0;
1455 #ifndef NO_FACL_WRAPPER
1456 /*****************************************************
1458 *******************************************************/
1459 int smbw_facl(int fd
, int cmd
, int nentries
, aclent_t
*aclbufp
)
1461 if (cmd
== GETACL
|| cmd
== GETACLCNT
) return 0;
1467 #ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
1469 /* this can't be in wrapped.c because of include conflicts */
1470 void stat64_convert(struct stat
*st
, struct stat64
*st64
)
1472 st64
->st_size
= st
->st_size
;
1473 st64
->st_mode
= st
->st_mode
;
1474 st64
->st_ino
= st
->st_ino
;
1475 st64
->st_dev
= st
->st_dev
;
1476 st64
->st_rdev
= st
->st_rdev
;
1477 st64
->st_nlink
= st
->st_nlink
;
1478 st64
->st_uid
= st
->st_uid
;
1479 st64
->st_gid
= st
->st_gid
;
1480 st64
->st_atime
= st
->st_atime
;
1481 st64
->st_mtime
= st
->st_mtime
;
1482 st64
->st_ctime
= st
->st_ctime
;
1483 st64
->st_blksize
= st
->st_blksize
;
1484 st64
->st_blocks
= st
->st_blocks
;
1488 #ifdef HAVE_READDIR64
1489 void dirent64_convert(struct dirent
*d
, struct dirent64
*d64
)
1491 d64
->d_ino
= d
->d_ino
;
1492 d64
->d_off
= d
->d_off
;
1493 d64
->d_reclen
= d
->d_reclen
;
1494 pstrcpy(d64
->d_name
, d
->d_name
);
1501 /* Definition of `struct stat' used in the linux kernel.. */
1502 struct kernel_stat
{
1503 unsigned short int st_dev
;
1504 unsigned short int __pad1
;
1505 unsigned long int st_ino
;
1506 unsigned short int st_mode
;
1507 unsigned short int st_nlink
;
1508 unsigned short int st_uid
;
1509 unsigned short int st_gid
;
1510 unsigned short int st_rdev
;
1511 unsigned short int __pad2
;
1512 unsigned long int st_size
;
1513 unsigned long int st_blksize
;
1514 unsigned long int st_blocks
;
1515 unsigned long int st_atime
;
1516 unsigned long int __unused1
;
1517 unsigned long int st_mtime
;
1518 unsigned long int __unused2
;
1519 unsigned long int st_ctime
;
1520 unsigned long int __unused3
;
1521 unsigned long int __unused4
;
1522 unsigned long int __unused5
;
1526 * Prototype for gcc in 'fussy' mode.
1528 void xstat_convert(int vers
, struct stat
*st
, struct kernel_stat
*kbuf
);
1529 void xstat_convert(int vers
, struct stat
*st
, struct kernel_stat
*kbuf
)
1531 #ifdef _STAT_VER_LINUX_OLD
1532 if (vers
== _STAT_VER_LINUX_OLD
) {
1533 memcpy(st
, kbuf
, sizeof(*st
));
1540 st
->st_dev
= kbuf
->st_dev
;
1541 st
->st_ino
= kbuf
->st_ino
;
1542 st
->st_mode
= kbuf
->st_mode
;
1543 st
->st_nlink
= kbuf
->st_nlink
;
1544 st
->st_uid
= kbuf
->st_uid
;
1545 st
->st_gid
= kbuf
->st_gid
;
1546 st
->st_rdev
= kbuf
->st_rdev
;
1547 st
->st_size
= kbuf
->st_size
;
1548 st
->st_blksize
= kbuf
->st_blksize
;
1549 st
->st_blocks
= kbuf
->st_blocks
;
1550 st
->st_atime
= kbuf
->st_atime
;
1551 st
->st_mtime
= kbuf
->st_mtime
;
1552 st
->st_ctime
= kbuf
->st_ctime
;