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
;
657 DEBUG(4,(" -> %d\n", dir
->count
));
670 /*****************************************************
672 *******************************************************/
673 int smbw_open(const char *fname
, int flags
, mode_t mode
)
675 fstring server
, share
;
677 struct smbw_server
*srv
=NULL
;
679 struct smbw_file
*file
=NULL
;
681 DEBUG(4,("%s\n", __FUNCTION__
));
692 /* work out what server they are after */
693 smbw_parse_path(fname
, server
, share
, path
);
695 /* get a connection to the server */
696 srv
= smbw_server(server
, share
);
698 /* smbw_server sets errno */
702 if (path
[strlen(path
)-1] == '\\') {
705 fd
= cli_open(&srv
->cli
, path
, flags
, DENY_NONE
);
708 /* it might be a directory. Maybe we should use chkpath? */
709 fd
= smbw_dir_open(fname
, flags
);
718 file
= (struct smbw_file
*)malloc(sizeof(*file
));
727 file
->fname
= strdup(path
);
733 file
->fd
= bitmap_find(file_bmap
, 0);
735 if (file
->fd
== -1) {
740 bitmap_set(file_bmap
, file
->fd
);
742 file
->fd
+= SMBW_FD_OFFSET
;
744 DLIST_ADD(smbw_files
, file
);
746 DEBUG(4,("opened %s\n", fname
));
753 cli_close(&srv
->cli
, fd
);
766 /*****************************************************
767 a wrapper for fstat() on a directory
768 *******************************************************/
769 int smbw_dir_fstat(int fd
, struct stat
*st
)
771 struct smbw_dir
*dir
;
773 DEBUG(4,("%s\n", __FUNCTION__
));
783 smbw_setup_stat(st
, "", dir
->count
*sizeof(struct dirent
), aDIR
);
788 /*****************************************************
789 a wrapper for fstat()
790 *******************************************************/
791 int smbw_fstat(int fd
, struct stat
*st
)
793 struct smbw_file
*file
;
794 time_t c_time
, a_time
, m_time
;
798 DEBUG(4,("%s\n", __FUNCTION__
));
802 file
= smbw_file(fd
);
804 int ret
= smbw_dir_fstat(fd
, st
);
809 if (!cli_qfileinfo(&file
->srv
->cli
, file
->cli_fd
,
810 &mode
, &size
, &c_time
, &a_time
, &m_time
) &&
811 !cli_getattrE(&file
->srv
->cli
, file
->cli_fd
,
812 &mode
, &size
, &c_time
, &a_time
, &m_time
)) {
818 smbw_setup_stat(st
, file
->fname
, size
, mode
);
820 st
->st_atime
= a_time
;
821 st
->st_ctime
= c_time
;
822 st
->st_mtime
= m_time
;
824 DEBUG(4,("%s - OK\n", __FUNCTION__
));
831 /*****************************************************
833 *******************************************************/
834 int smbw_stat(const char *fname
, struct stat
*st
)
836 struct smbw_server
*srv
;
837 fstring server
, share
;
839 time_t m_time
=0, a_time
=0, c_time
=0;
843 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
854 /* work out what server they are after */
855 smbw_parse_path(fname
, server
, share
, path
);
857 /* get a connection to the server */
858 srv
= smbw_server(server
, share
);
860 /* smbw_server sets errno */
864 if (strcmp(share
,"IPC$") == 0) {
865 mode
= aDIR
| aRONLY
;
867 if (!smbw_getatr(srv
, path
,
868 &mode
, &size
, &c_time
, &a_time
, &m_time
)) {
869 errno
= smbw_errno(&srv
->cli
);
874 smbw_setup_stat(st
, path
, size
, mode
);
876 st
->st_atime
= time(NULL
);
877 st
->st_ctime
= m_time
;
878 st
->st_mtime
= m_time
;
888 /*****************************************************
890 *******************************************************/
891 ssize_t
smbw_read(int fd
, void *buf
, size_t count
)
893 struct smbw_file
*file
;
896 DEBUG(4,("%s\n", __FUNCTION__
));
900 file
= smbw_file(fd
);
907 ret
= cli_read(&file
->srv
->cli
, file
->cli_fd
, buf
, file
->offset
, count
);
910 errno
= smbw_errno(&file
->srv
->cli
);
921 /*****************************************************
922 a wrapper for write()
923 *******************************************************/
924 ssize_t
smbw_write(int fd
, void *buf
, size_t count
)
926 struct smbw_file
*file
;
929 DEBUG(4,("%s\n", __FUNCTION__
));
933 file
= smbw_file(fd
);
935 DEBUG(3,("bad fd in read\n"));
941 ret
= cli_write(&file
->srv
->cli
, file
->cli_fd
, buf
, file
->offset
, count
);
944 errno
= smbw_errno(&file
->srv
->cli
);
955 /*****************************************************
956 close a directory handle
957 *******************************************************/
958 int smbw_dir_close(int fd
)
960 struct smbw_dir
*dir
;
962 DEBUG(4,("%s\n", __FUNCTION__
));
966 DEBUG(4,("%s(%d)\n", __FUNCTION__
, __LINE__
));
971 bitmap_clear(file_bmap
, dir
->fd
- SMBW_FD_OFFSET
);
973 DLIST_REMOVE(smbw_dirs
, dir
);
980 /*****************************************************
981 a wrapper for close()
982 *******************************************************/
983 int smbw_close(int fd
)
985 struct smbw_file
*file
;
987 DEBUG(4,("%s\n", __FUNCTION__
));
991 file
= smbw_file(fd
);
993 int ret
= smbw_dir_close(fd
);
998 if (!cli_close(&file
->srv
->cli
, file
->cli_fd
)) {
999 errno
= smbw_errno(&file
->srv
->cli
);
1005 bitmap_clear(file_bmap
, file
->fd
- SMBW_FD_OFFSET
);
1007 DLIST_REMOVE(smbw_files
, file
);
1019 /*****************************************************
1020 a wrapper for fcntl()
1021 *******************************************************/
1022 int smbw_fcntl(int fd
, int cmd
, long arg
)
1024 DEBUG(4,("%s\n", __FUNCTION__
));
1029 /*****************************************************
1030 a wrapper for getdents()
1031 *******************************************************/
1032 int smbw_getdents(unsigned int fd
, struct dirent
*dirp
, int count
)
1034 struct smbw_dir
*dir
;
1037 DEBUG(4,("%s\n", __FUNCTION__
));
1048 while (count
>=sizeof(*dirp
) && (dir
->offset
< dir
->count
)) {
1049 dirp
->d_ino
= dir
->offset
+ 0x10000;
1050 dirp
->d_off
= (dir
->offset
+1)*sizeof(*dirp
);
1051 dirp
->d_reclen
= sizeof(*dirp
);
1052 /* what's going on with the -1 here? maybe d_type
1053 isn't really there? */
1054 safe_strcpy(&dirp
->d_name
[-1], dir
->list
[dir
->offset
].name
,
1055 sizeof(dirp
->d_name
)-1);
1057 count
-= dirp
->d_reclen
;
1058 if (dir
->offset
== dir
->count
) {
1066 return n
*sizeof(*dirp
);
1070 /*****************************************************
1071 a wrapper for access()
1072 *******************************************************/
1073 int smbw_access(const char *name
, int mode
)
1076 /* how do we map this properly ?? */
1077 return smbw_stat(name
, &st
) == 0;
1080 /*****************************************************
1081 a wrapper for realink() - needed for correct errno setting
1082 *******************************************************/
1083 int smbw_readlink(const char *path
, char *buf
, size_t bufsize
)
1088 ret
= smbw_stat(path
, &st
);
1090 DEBUG(4,("readlink(%s) failed\n", path
));
1094 /* it exists - say it isn't a link */
1095 DEBUG(4,("readlink(%s) not a link\n", path
));
1102 /*****************************************************
1103 a wrapper for chdir()
1104 *******************************************************/
1105 int smbw_chdir(const char *name
)
1107 struct smbw_server
*srv
;
1108 fstring server
, share
;
1115 if (smbw_busy
) return real_chdir(cwd
);
1124 DEBUG(4,("%s (%s)\n", __FUNCTION__
, name
));
1126 /* work out what server they are after */
1127 cwd
= smbw_parse_path(name
, server
, share
, path
);
1129 if (strncmp(cwd
,SMBW_PREFIX
,strlen(SMBW_PREFIX
))) {
1130 if (real_chdir(cwd
) == 0) {
1131 DEBUG(4,("set SMBW_CWD to %s\n", cwd
));
1132 pstrcpy(smb_cwd
, cwd
);
1133 if (setenv(SMBW_PWD_ENV
, smb_cwd
, 1)) {
1134 DEBUG(4,("setenv failed\n"));
1142 /* get a connection to the server */
1143 srv
= smbw_server(server
, share
);
1145 /* smbw_server sets errno */
1149 if (strcmp(share
,"IPC$") &&
1150 !smbw_getatr(srv
, path
,
1151 &mode
, NULL
, NULL
, NULL
, NULL
)) {
1152 errno
= smbw_errno(&srv
->cli
);
1156 if (!(mode
& aDIR
)) {
1161 DEBUG(4,("set SMBW_CWD2 to %s\n", cwd
));
1162 pstrcpy(smb_cwd
, cwd
);
1163 if (setenv(SMBW_PWD_ENV
, smb_cwd
, 1)) {
1164 DEBUG(4,("setenv failed\n"));
1167 /* we don't want the old directory to be busy */
1180 /*****************************************************
1181 a wrapper for unlink()
1182 *******************************************************/
1183 int smbw_unlink(const char *fname
)
1185 struct smbw_server
*srv
;
1186 fstring server
, share
;
1189 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1200 /* work out what server they are after */
1201 smbw_parse_path(fname
, server
, share
, path
);
1203 /* get a connection to the server */
1204 srv
= smbw_server(server
, share
);
1206 /* smbw_server sets errno */
1210 if (!cli_unlink(&srv
->cli
, path
)) {
1211 errno
= smbw_errno(&srv
->cli
);
1224 /*****************************************************
1225 a wrapper for rename()
1226 *******************************************************/
1227 int smbw_rename(const char *oldname
, const char *newname
)
1229 struct smbw_server
*srv
;
1230 fstring server1
, share1
;
1232 fstring server2
, share2
;
1235 DEBUG(4,("%s (%s, %s)\n", __FUNCTION__
, oldname
, newname
));
1237 if (!oldname
|| !newname
) {
1246 /* work out what server they are after */
1247 smbw_parse_path(oldname
, server1
, share1
, path1
);
1248 smbw_parse_path(newname
, server2
, share2
, path2
);
1250 if (strcmp(server1
, server2
) || strcmp(share1
, share2
)) {
1251 /* can't cross filesystems */
1256 /* get a connection to the server */
1257 srv
= smbw_server(server1
, share1
);
1259 /* smbw_server sets errno */
1263 if (!cli_rename(&srv
->cli
, path1
, path2
)) {
1264 errno
= smbw_errno(&srv
->cli
);
1277 /*****************************************************
1278 a wrapper for utime()
1279 *******************************************************/
1280 int smbw_utime(const char *fname
, struct utimbuf
*buf
)
1282 struct smbw_server
*srv
;
1283 fstring server
, share
;
1287 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1298 /* work out what server they are after */
1299 smbw_parse_path(fname
, server
, share
, path
);
1301 /* get a connection to the server */
1302 srv
= smbw_server(server
, share
);
1304 /* smbw_server sets errno */
1308 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1309 errno
= smbw_errno(&srv
->cli
);
1313 if (!cli_setatr(&srv
->cli
, path
, mode
, buf
->modtime
)) {
1314 errno
= smbw_errno(&srv
->cli
);
1326 /*****************************************************
1327 a wrapper for chown()
1328 *******************************************************/
1329 int smbw_chown(const char *fname
, uid_t owner
, gid_t group
)
1331 struct smbw_server
*srv
;
1332 fstring server
, share
;
1336 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1347 /* work out what server they are after */
1348 smbw_parse_path(fname
, server
, share
, path
);
1350 /* get a connection to the server */
1351 srv
= smbw_server(server
, share
);
1353 /* smbw_server sets errno */
1357 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1358 errno
= smbw_errno(&srv
->cli
);
1362 /* assume success */
1372 /*****************************************************
1373 a wrapper for chmod()
1374 *******************************************************/
1375 int smbw_chmod(const char *fname
, mode_t newmode
)
1377 struct smbw_server
*srv
;
1378 fstring server
, share
;
1382 DEBUG(4,("%s (%s)\n", __FUNCTION__
, fname
));
1393 /* work out what server they are after */
1394 smbw_parse_path(fname
, server
, share
, path
);
1396 /* get a connection to the server */
1397 srv
= smbw_server(server
, share
);
1399 /* smbw_server sets errno */
1403 if (!cli_getatr(&srv
->cli
, path
, &mode
, NULL
, NULL
)) {
1404 errno
= smbw_errno(&srv
->cli
);
1408 /* assume success for the moment - need to add attribute mapping */
1419 /*****************************************************
1420 a wrapper for lseek() on directories
1421 *******************************************************/
1422 off_t
smbw_dir_lseek(int fd
, off_t offset
, int whence
)
1424 struct smbw_dir
*dir
;
1427 DEBUG(4,("%s offset=%d whence=%d\n", __FUNCTION__
,
1428 (int)offset
, whence
));
1438 dir
->offset
= offset
/sizeof(struct dirent
);
1441 dir
->offset
+= offset
/sizeof(struct dirent
);
1444 dir
->offset
= (dir
->count
* sizeof(struct dirent
)) + offset
;
1445 dir
->offset
/= sizeof(struct dirent
);
1449 ret
= dir
->offset
* sizeof(struct dirent
);
1451 DEBUG(4,(" -> %d\n", (int)ret
));
1456 /*****************************************************
1457 a wrapper for lseek()
1458 *******************************************************/
1459 off_t
smbw_lseek(int fd
, off_t offset
, int whence
)
1461 struct smbw_file
*file
;
1464 DEBUG(4,("%s\n", __FUNCTION__
));
1468 file
= smbw_file(fd
);
1470 off_t ret
= smbw_dir_lseek(fd
, offset
, whence
);
1477 file
->offset
= offset
;
1480 file
->offset
+= offset
;
1483 if (!cli_qfileinfo(&file
->srv
->cli
, file
->cli_fd
,
1484 NULL
, &size
, NULL
, NULL
, NULL
) &&
1485 !cli_getattrE(&file
->srv
->cli
, file
->cli_fd
,
1486 NULL
, &size
, NULL
, NULL
, NULL
)) {
1491 file
->offset
= size
+ offset
;
1496 return file
->offset
;