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.
26 static pstring smb_cwd
;
29 struct smbw_server
*next
, *prev
;
36 struct smbw_file
*next
, *prev
;
40 struct smbw_server
*srv
;
44 struct smbw_dir
*next
, *prev
;
46 int offset
, count
, malloced
;
47 struct smbw_server
*srv
;
48 struct file_info
*list
;
51 static struct smbw_file
*smbw_files
;
52 static struct smbw_dir
*smbw_dirs
;
53 static struct smbw_server
*smbw_srvs
;
55 static struct bitmap
*file_bmap
;
56 static pstring local_machine
;
57 extern int DEBUGLEVEL
;
61 /*****************************************************
63 *******************************************************/
66 extern BOOL in_client
;
67 static int initialised
;
68 static pstring servicesf
= CONFIGFILE
;
72 if (initialised
) return;
78 setup_logging("smbw",True
);
82 if ((p
=getenv("SMBW_LOGFILE"))) {
86 file_bmap
= bitmap_allocate(SMBW_MAX_OPEN
);
95 if (!lp_load(servicesf
,True
,False
,False
)) {
99 get_myname(local_machine
,NULL
);
101 if ((p
=getenv("SMBW_DEBUG"))) {
102 DEBUGLEVEL
= atoi(p
);
105 if ((p
=getenv(SMBW_PWD_ENV
))) {
107 DEBUG(4,("Initial cwd from smb_cwd is %s\n", smb_cwd
));
110 DEBUG(4,("Initial cwd from getwd is %s\n", smb_cwd
));
115 /*****************************************************
116 determine if a file descriptor is a smb one
117 *******************************************************/
120 if (smbw_busy
) return False
;
121 return (fd
>= SMBW_FD_OFFSET
);
125 /*****************************************************
126 remove redundent stuff from a filename
127 *******************************************************/
128 void clean_fname(char *name
)
139 DEBUG(5,("cleaning %s\n", name
));
141 if ((p
=strstr(name
,"/./"))) {
149 if ((p
=strstr(name
,"//"))) {
157 if (strcmp(name
,"/../")==0) {
162 if ((p
=strstr(name
,"/../"))) {
164 for (p2
=(p
>name
?p
-1:p
);p2
>name
;p2
--) {
165 if (p2
[0] == '/') break;
173 if (strcmp(name
,"/..")==0) {
179 p
= l
>=3?(name
+l
-3):name
;
180 if (strcmp(p
,"/..")==0) {
182 for (p2
=p
-1;p2
>name
;p2
--) {
183 if (p2
[0] == '/') break;
194 p
= l
>=2?(name
+l
-2):name
;
195 if (strcmp(p
,"/.")==0) {
203 if (strncmp(p
=name
,"./",2) == 0) {
211 if (l
> 1 && p
[l
-1] == '/') {
219 /*****************************************************
220 parse a smb path into its components.
221 *******************************************************/
222 char *smbw_parse_path(const char *fname
, char *server
, char *share
, char *path
)
228 *server
= *share
= *path
= 0;
230 if (fname
[0] == '/') {
233 slprintf(s
,sizeof(s
)-1, "%s/%s", smb_cwd
, fname
);
237 DEBUG(5,("cleaned %s (fname=%s cwd=%s)\n",
240 if (strncmp(s
,SMBW_PREFIX
,strlen(SMBW_PREFIX
))) return s
;
242 p
= s
+ strlen(SMBW_PREFIX
);
251 len
= MIN(len
,sizeof(fstring
)-1);
253 strncpy(server
, p
, len
);
258 fstrcpy(share
,"IPC$");
272 len
= MIN(len
,sizeof(fstring
)-1);
274 strncpy(share
, p
, len
);
285 string_sub(path
, "/", "\\");
288 DEBUG(5,("parsed path name=%s cwd=%s [%s] [%s] [%s]\n",
290 server
, share
, path
));
295 /*****************************************************
296 determine if a path name (possibly relative) is in the
298 *******************************************************/
299 BOOL
smbw_path(const char *path
)
301 fstring server
, share
;
304 int l
=strlen(SMBW_PREFIX
)-1;
306 if (path
[0] == '/' && strncmp(path
,SMBW_PREFIX
,l
)) {
310 if (smbw_busy
) return False
;
314 DEBUG(3,("smbw_path(%s)\n", path
));
316 cwd
= smbw_parse_path(path
, server
, share
, s
);
318 if (strncmp(cwd
,SMBW_PREFIX
,l
) == 0 &&
319 (cwd
[l
] == '/' || cwd
[l
] == 0)) {
326 /*****************************************************
327 return a unix errno from a SMB error pair
328 *******************************************************/
329 int smbw_errno(struct cli_state
*c
)
335 ret
= cli_error(c
, &eclass
, &ecode
);
338 DEBUG(3,("smbw_error %d %d (0x%x)\n",
339 (int)eclass
, (int)ecode
, (int)ecode
));
344 /*****************************************************
345 return a connection to a server (existing or new)
346 *******************************************************/
347 struct smbw_server
*smbw_server(char *server
, char *share
)
349 struct smbw_server
*srv
=NULL
;
350 static struct cli_state c
;
354 struct nmb_name called
, calling
;
356 username
= getenv("SMBW_USER");
357 if (!username
) username
= getenv("USER");
358 if (!username
) username
= "guest";
360 workgroup
= getenv("SMBW_WORKGROUP");
361 if (!workgroup
) workgroup
= lp_workgroup();
363 password
= getenv("SMBW_PASSWORD");
364 if (!password
) password
= "";
366 /* try to use an existing connection */
367 for (srv
=smbw_srvs
;srv
;srv
=srv
->next
) {
368 if (strcmp(server
,srv
->server_name
)==0 &&
369 strcmp(share
,srv
->share_name
)==0) return srv
;
372 if (server
[0] == 0) {
377 /* have to open a new connection */
378 if (!cli_initialise(&c
) || !cli_connect(&c
, server
, NULL
)) {
383 make_nmb_name(&calling
, local_machine
, 0x0, "");
384 make_nmb_name(&called
, server
, 0x20, "");
386 if (!cli_session_request(&c
, &calling
, &called
)) {
392 if (!cli_negprot(&c
)) {
398 if (!cli_session_setup(&c
, username
,
399 password
, strlen(password
),
400 password
, strlen(password
),
407 if (!cli_send_tconX(&c
, share
,
408 strstr(share
,"IPC$")?"IPC":"A:",
409 password
, strlen(password
)+1)) {
410 errno
= smbw_errno(&c
);
415 srv
= (struct smbw_server
*)malloc(sizeof(*srv
));
425 srv
->server_name
= strdup(server
);
426 if (!srv
->server_name
) {
431 srv
->share_name
= strdup(share
);
432 if (!srv
->share_name
) {
437 /* some programs play with file descriptors fairly intimately. We
438 try to get out of the way by duping to a high fd number */
439 if (fcntl(SMBW_CLI_FD
+ srv
->cli
.fd
, F_GETFD
) && errno
== EBADF
) {
440 if (dup2(srv
->cli
.fd
,SMBW_CLI_FD
+srv
->cli
.fd
) ==
441 srv
->cli
.fd
+SMBW_CLI_FD
) {
443 srv
->cli
.fd
+= SMBW_CLI_FD
;
447 DLIST_ADD(smbw_srvs
, srv
);
453 if (!srv
) return NULL
;
455 if (srv
->server_name
) free(srv
->server_name
);
456 if (srv
->share_name
) free(srv
->share_name
);
462 /*****************************************************
463 map a fd to a smbw_file structure
464 *******************************************************/
465 struct smbw_file
*smbw_file(int fd
)
467 struct smbw_file
*file
;
469 for (file
=smbw_files
;file
;file
=file
->next
) {
470 if (file
->fd
== fd
) return file
;
475 /*****************************************************
476 map a fd to a smbw_dir structure
477 *******************************************************/
478 struct smbw_dir
*smbw_dir(int fd
)
480 struct smbw_dir
*dir
;
482 for (dir
=smbw_dirs
;dir
;dir
=dir
->next
) {
483 if (dir
->fd
== fd
) return dir
;
488 /*****************************************************
489 setup basic info in a stat structure
490 *******************************************************/
491 void smbw_setup_stat(struct stat
*st
, char *fname
, size_t size
, int mode
)
495 if (IS_DOS_DIR(mode
)) {
496 st
->st_mode
= SMBW_DIR_MODE
;
498 st
->st_mode
= SMBW_FILE_MODE
;
502 st
->st_blksize
= 512;
503 st
->st_blocks
= (size
+511)/512;
504 st
->st_uid
= getuid();
505 st
->st_gid
= getgid();
509 /*****************************************************
510 try to do a QPATHINFO and if that fails then do a getatr
511 this is needed because win95 sometimes refuses the qpathinfo
512 *******************************************************/
513 static BOOL
smbw_getatr(struct smbw_server
*srv
, char *path
,
514 uint32
*mode
, size_t *size
,
515 time_t *c_time
, time_t *a_time
, time_t *m_time
)
517 if (cli_qpathinfo(&srv
->cli
, path
, c_time
, a_time
, m_time
,
518 size
, mode
)) return True
;
520 /* if this is NT then don't bother with the getatr */
521 if (srv
->cli
.capabilities
& CAP_NT_SMBS
) return False
;
523 if (cli_getatr(&srv
->cli
, path
, mode
, size
, m_time
)) {
524 a_time
= c_time
= m_time
;
530 /*****************************************************
531 free a smbw_dir structure and all entries
532 *******************************************************/
533 static void free_dir(struct smbw_dir
*dir
)
543 static struct smbw_dir
*cur_dir
;
545 /*****************************************************
546 add a entry to a directory listing
547 *******************************************************/
548 void smbw_dir_add(struct file_info
*finfo
)
550 DEBUG(5,("%s\n", finfo
->name
));
552 if (cur_dir
->malloced
== cur_dir
->count
) {
553 cur_dir
->list
= (struct file_info
*)Realloc(cur_dir
->list
,
554 sizeof(cur_dir
->list
[0])*
555 (cur_dir
->count
+100));
556 if (!cur_dir
->list
) {
560 cur_dir
->malloced
+= 100;
563 cur_dir
->list
[cur_dir
->count
] = *finfo
;
567 /*****************************************************
568 add a entry to a directory listing
569 *******************************************************/
570 void smbw_share_add(const char *share
, uint32 type
, const char *comment
)
572 struct file_info finfo
;
576 pstrcpy(finfo
.name
, share
);
577 finfo
.mode
= aRONLY
| aDIR
;
579 smbw_dir_add(&finfo
);
583 /*****************************************************
584 open a directory on the server
585 *******************************************************/
586 int smbw_dir_open(const char *fname
, int flags
)
588 fstring server
, share
;
590 struct smbw_server
*srv
=NULL
;
591 struct smbw_dir
*dir
=NULL
;
595 DEBUG(4,("%s\n", __FUNCTION__
));
604 /* work out what server they are after */
605 smbw_parse_path(fname
, server
, share
, path
);
607 DEBUG(4,("dir_open share=%s\n", share
));
609 /* get a connection to the server */
610 srv
= smbw_server(server
, share
);
612 /* smbw_server sets errno */
616 dir
= (struct smbw_dir
*)malloc(sizeof(*dir
));
626 slprintf(mask
, sizeof(mask
)-1, "%s\\*", path
);
627 string_sub(mask
,"\\\\","\\");
629 if (strcmp(share
,"IPC$") == 0) {
630 DEBUG(4,("doing NetShareEnum\n"));
631 if (cli_RNetShareEnum(&srv
->cli
, smbw_share_add
) <= 0) {
632 errno
= smbw_errno(&srv
->cli
);
636 if (cli_list(&srv
->cli
, mask
, aHIDDEN
|aSYSTEM
|aDIR
,
637 smbw_dir_add
) <= 0) {
638 errno
= smbw_errno(&srv
->cli
);
645 fd
= bitmap_find(file_bmap
, 0);
651 DLIST_ADD(smbw_dirs
, dir
);
653 bitmap_set(file_bmap
, fd
);
655 dir
->fd
= fd
+ SMBW_FD_OFFSET
;
668 /*****************************************************
670 *******************************************************/
671 int smbw_open(const char *fname
, int flags
, mode_t mode
)
673 fstring server
, share
;
675 struct smbw_server
*srv
=NULL
;
677 struct smbw_file
*file
=NULL
;
679 DEBUG(4,("%s\n", __FUNCTION__
));
690 /* work out what server they are after */
691 smbw_parse_path(fname
, server
, share
, path
);
693 /* get a connection to the server */
694 srv
= smbw_server(server
, share
);
696 /* smbw_server sets errno */
700 if (path
[strlen(path
)-1] == '\\') {
703 fd
= cli_open(&srv
->cli
, path
, flags
, DENY_NONE
);
706 /* it might be a directory. Maybe we should use chkpath? */
707 fd
= smbw_dir_open(fname
, flags
);
716 file
= (struct smbw_file
*)malloc(sizeof(*file
));
725 file
->fname
= strdup(path
);
731 file
->fd
= bitmap_find(file_bmap
, 0);
733 if (file
->fd
== -1) {
738 bitmap_set(file_bmap
, file
->fd
);
740 file
->fd
+= SMBW_FD_OFFSET
;
742 DLIST_ADD(smbw_files
, file
);
744 DEBUG(4,("opened %s\n", fname
));
751 cli_close(&srv
->cli
, fd
);
764 /*****************************************************
765 a wrapper for fstat() on a directory
766 *******************************************************/
767 int smbw_dir_fstat(int fd
, struct stat
*st
)
769 struct smbw_dir
*dir
;
771 DEBUG(4,("%s\n", __FUNCTION__
));
781 smbw_setup_stat(st
, "", dir
->count
*sizeof(struct dirent
), aDIR
);
786 /*****************************************************
787 a wrapper for fstat()
788 *******************************************************/
789 int smbw_fstat(int fd
, struct stat
*st
)
791 struct smbw_file
*file
;
792 time_t c_time
, a_time
, m_time
;
796 DEBUG(4,("%s\n", __FUNCTION__
));
800 file
= smbw_file(fd
);
802 int ret
= smbw_dir_fstat(fd
, st
);
807 if (!cli_qfileinfo(&file
->srv
->cli
, file
->cli_fd
,
808 &mode
, &size
, &c_time
, &a_time
, &m_time
) &&
809 !cli_getattrE(&file
->srv
->cli
, file
->cli_fd
,
810 &mode
, &size
, &c_time
, &a_time
, &m_time
)) {
816 smbw_setup_stat(st
, file
->fname
, size
, mode
);
818 st
->st_atime
= a_time
;
819 st
->st_ctime
= c_time
;
820 st
->st_mtime
= m_time
;
822 DEBUG(4,("%s - OK\n", __FUNCTION__
));
829 /*****************************************************
831 *******************************************************/
832 int smbw_stat(const char *fname
, struct stat
*st
)
834 struct smbw_server
*srv
;
835 fstring server
, share
;
837 time_t m_time
=0, a_time
=0, c_time
=0;
841 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
852 /* work out what server they are after */
853 smbw_parse_path(fname
, server
, share
, path
);
855 /* get a connection to the server */
856 srv
= smbw_server(server
, share
);
858 /* smbw_server sets errno */
862 if (strcmp(share
,"IPC$") == 0) {
863 mode
= aDIR
| aRONLY
;
865 if (!smbw_getatr(srv
, path
,
866 &mode
, &size
, &c_time
, &a_time
, &m_time
)) {
867 errno
= smbw_errno(&srv
->cli
);
872 smbw_setup_stat(st
, path
, size
, mode
);
874 st
->st_atime
= time(NULL
);
875 st
->st_ctime
= m_time
;
876 st
->st_mtime
= m_time
;
886 /*****************************************************
888 *******************************************************/
889 ssize_t
smbw_read(int fd
, void *buf
, size_t count
)
891 struct smbw_file
*file
;
894 DEBUG(4,("%s\n", __FUNCTION__
));
898 file
= smbw_file(fd
);
905 ret
= cli_read(&file
->srv
->cli
, file
->cli_fd
, buf
, file
->offset
, count
);
908 errno
= smbw_errno(&file
->srv
->cli
);
919 /*****************************************************
920 a wrapper for write()
921 *******************************************************/
922 ssize_t
smbw_write(int fd
, void *buf
, size_t count
)
924 struct smbw_file
*file
;
927 DEBUG(4,("%s\n", __FUNCTION__
));
931 file
= smbw_file(fd
);
933 DEBUG(3,("bad fd in read\n"));
939 ret
= cli_write(&file
->srv
->cli
, file
->cli_fd
, buf
, file
->offset
, count
);
942 errno
= smbw_errno(&file
->srv
->cli
);
953 /*****************************************************
954 close a directory handle
955 *******************************************************/
956 int smbw_dir_close(int fd
)
958 struct smbw_dir
*dir
;
960 DEBUG(4,("%s\n", __FUNCTION__
));
964 DEBUG(4,("%s(%d)\n", __FUNCTION__
, __LINE__
));
969 bitmap_clear(file_bmap
, dir
->fd
- SMBW_FD_OFFSET
);
971 DLIST_REMOVE(smbw_dirs
, dir
);
978 /*****************************************************
979 a wrapper for close()
980 *******************************************************/
981 int smbw_close(int fd
)
983 struct smbw_file
*file
;
985 DEBUG(4,("%s\n", __FUNCTION__
));
989 file
= smbw_file(fd
);
991 int ret
= smbw_dir_close(fd
);
996 if (!cli_close(&file
->srv
->cli
, file
->cli_fd
)) {
997 errno
= smbw_errno(&file
->srv
->cli
);
1003 bitmap_clear(file_bmap
, file
->fd
- SMBW_FD_OFFSET
);
1005 DLIST_REMOVE(smbw_files
, file
);
1017 /*****************************************************
1018 a wrapper for fcntl()
1019 *******************************************************/
1020 int smbw_fcntl(int fd
, int cmd
, long arg
)
1022 DEBUG(4,("%s\n", __FUNCTION__
));
1027 /*****************************************************
1028 a wrapper for getdents()
1029 *******************************************************/
1030 int smbw_getdents(unsigned int fd
, struct dirent
*dirp
, int count
)
1032 struct smbw_dir
*dir
;
1035 DEBUG(4,("%s\n", __FUNCTION__
));
1046 while (count
>=sizeof(*dirp
) && (dir
->offset
< dir
->count
)) {
1047 dirp
->d_ino
= dir
->offset
+ 0x10000;
1048 dirp
->d_off
= (dir
->offset
+1)*sizeof(*dirp
);
1049 dirp
->d_reclen
= sizeof(*dirp
);
1050 /* what's going on with the -1 here? maybe d_type
1051 isn't really there? */
1052 safe_strcpy(&dirp
->d_name
[-1], dir
->list
[dir
->offset
].name
,
1053 sizeof(dirp
->d_name
)-1);
1055 count
-= dirp
->d_reclen
;
1061 return n
*sizeof(*dirp
);
1065 /*****************************************************
1066 a wrapper for access()
1067 *******************************************************/
1068 int smbw_access(const char *name
, int mode
)
1071 /* how do we map this properly ?? */
1072 return smbw_stat(name
, &st
) == 0;
1075 /*****************************************************
1076 a wrapper for realink() - needed for correct errno setting
1077 *******************************************************/
1078 int smbw_readlink(const char *path
, char *buf
, size_t bufsize
)
1083 ret
= smbw_stat(path
, &st
);
1085 DEBUG(4,("readlink(%s) failed\n", path
));
1089 /* it exists - say it isn't a link */
1090 DEBUG(4,("readlink(%s) not a link\n", path
));
1097 /*****************************************************
1098 a wrapper for chdir()
1099 *******************************************************/
1100 int smbw_chdir(const char *name
)
1102 struct smbw_server
*srv
;
1103 fstring server
, share
;
1110 if (smbw_busy
) return real_chdir(cwd
);
1119 DEBUG(4,("%s (%s)\n", __FUNCTION__
, name
));
1121 /* work out what server they are after */
1122 cwd
= smbw_parse_path(name
, server
, share
, path
);
1124 if (strncmp(cwd
,SMBW_PREFIX
,strlen(SMBW_PREFIX
))) {
1125 if (real_chdir(cwd
) == 0) {
1126 DEBUG(4,("set SMBW_CWD to %s\n", cwd
));
1127 pstrcpy(smb_cwd
, cwd
);
1128 if (setenv(SMBW_PWD_ENV
, smb_cwd
, 1)) {
1129 DEBUG(4,("setenv failed\n"));
1137 /* get a connection to the server */
1138 srv
= smbw_server(server
, share
);
1140 /* smbw_server sets errno */
1144 if (strcmp(share
,"IPC$") &&
1145 !smbw_getatr(srv
, path
,
1146 &mode
, NULL
, NULL
, NULL
, NULL
)) {
1147 errno
= smbw_errno(&srv
->cli
);
1151 if (!(mode
& aDIR
)) {
1156 DEBUG(4,("set SMBW_CWD2 to %s\n", cwd
));
1157 pstrcpy(smb_cwd
, cwd
);
1158 if (setenv(SMBW_PWD_ENV
, smb_cwd
, 1)) {
1159 DEBUG(4,("setenv failed\n"));
1162 /* we don't want the old directory to be busy */
1175 /*****************************************************
1176 a wrapper for unlink()
1177 *******************************************************/
1178 int smbw_unlink(const char *fname
)
1180 struct smbw_server
*srv
;
1181 fstring server
, share
;
1184 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1195 /* work out what server they are after */
1196 smbw_parse_path(fname
, server
, share
, path
);
1198 /* get a connection to the server */
1199 srv
= smbw_server(server
, share
);
1201 /* smbw_server sets errno */
1205 if (!cli_unlink(&srv
->cli
, path
)) {
1206 errno
= smbw_errno(&srv
->cli
);
1219 /*****************************************************
1220 a wrapper for rename()
1221 *******************************************************/
1222 int smbw_rename(const char *oldname
, const char *newname
)
1224 struct smbw_server
*srv
;
1225 fstring server1
, share1
;
1227 fstring server2
, share2
;
1230 DEBUG(4,("%s (%s, %s)\n", __FUNCTION__
, oldname
, newname
));
1232 if (!oldname
|| !newname
) {
1241 /* work out what server they are after */
1242 smbw_parse_path(oldname
, server1
, share1
, path1
);
1243 smbw_parse_path(newname
, server2
, share2
, path2
);
1245 if (strcmp(server1
, server2
) || strcmp(share1
, share2
)) {
1246 /* can't cross filesystems */
1251 /* get a connection to the server */
1252 srv
= smbw_server(server1
, share1
);
1254 /* smbw_server sets errno */
1258 if (!cli_rename(&srv
->cli
, path1
, path2
)) {
1259 errno
= smbw_errno(&srv
->cli
);
1272 /*****************************************************
1273 a wrapper for utime()
1274 *******************************************************/
1275 int smbw_utime(const char *fname
, struct utimbuf
*buf
)
1277 struct smbw_server
*srv
;
1278 fstring server
, share
;
1282 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1293 /* work out what server they are after */
1294 smbw_parse_path(fname
, server
, share
, path
);
1296 /* get a connection to the server */
1297 srv
= smbw_server(server
, share
);
1299 /* smbw_server sets errno */
1303 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1304 errno
= smbw_errno(&srv
->cli
);
1308 if (!cli_setatr(&srv
->cli
, path
, mode
, buf
->modtime
)) {
1309 errno
= smbw_errno(&srv
->cli
);
1321 /*****************************************************
1322 a wrapper for chown()
1323 *******************************************************/
1324 int smbw_chown(const char *fname
, uid_t owner
, gid_t group
)
1326 struct smbw_server
*srv
;
1327 fstring server
, share
;
1331 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1342 /* work out what server they are after */
1343 smbw_parse_path(fname
, server
, share
, path
);
1345 /* get a connection to the server */
1346 srv
= smbw_server(server
, share
);
1348 /* smbw_server sets errno */
1352 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1353 errno
= smbw_errno(&srv
->cli
);
1357 /* assume success */
1367 /*****************************************************
1368 a wrapper for chmod()
1369 *******************************************************/
1370 int smbw_chmod(const char *fname
, mode_t newmode
)
1372 struct smbw_server
*srv
;
1373 fstring server
, share
;
1377 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1388 /* work out what server they are after */
1389 smbw_parse_path(fname
, server
, share
, path
);
1391 /* get a connection to the server */
1392 srv
= smbw_server(server
, share
);
1394 /* smbw_server sets errno */
1398 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1399 errno
= smbw_errno(&srv
->cli
);
1403 /* assume success for the moment - need to add attribute mapping */
1413 /*****************************************************
1414 a wrapper for lseek()
1415 *******************************************************/
1416 ssize_t
smbw_lseek(int fd
, off_t offset
, int whence
)
1418 struct smbw_file
*file
;
1421 DEBUG(4,("%s\n", __FUNCTION__
));
1425 file
= smbw_file(fd
);
1434 file
->offset
= offset
;
1437 file
->offset
+= offset
;
1440 if (!cli_qfileinfo(&file
->srv
->cli
, file
->cli_fd
,
1441 NULL
, &size
, NULL
, NULL
, NULL
) &&
1442 !cli_getattrE(&file
->srv
->cli
, file
->cli_fd
,
1443 NULL
, &size
, NULL
, NULL
, NULL
)) {
1448 file
->offset
= size
+ offset
;
1453 return file
->offset
;