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.
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;
36 /*****************************************************
38 *******************************************************/
41 extern BOOL in_client;
42 static int initialised;
43 static pstring servicesf = CONFIGFILE;
47 if (initialised) return;
53 setup_logging("smbw",True);
57 if ((p=getenv("SMBW_LOGFILE"))) {
61 smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
62 if (!smbw_file_bmap) {
72 if (!lp_load(servicesf,True,False,False)) {
76 get_myname(global_myname,NULL);
78 if ((p=getenv("SMBW_DEBUG"))) {
82 if ((p=getenv(SMBW_PWD_ENV))) {
84 DEBUG(4,("Initial cwd from smb_cwd is %s\n", smb_cwd));
87 DEBUG(4,("Initial cwd from getwd is %s\n", smb_cwd));
92 /*****************************************************
93 determine if a file descriptor is a smb one
94 *******************************************************/
97 if (smbw_busy) return 0;
98 return (fd >= SMBW_FD_OFFSET);
101 /*****************************************************
102 a crude inode number generator
103 *******************************************************/
104 ino_t smbw_inode(const char *name)
106 return (ino_t)str_checksum(name);
109 /*****************************************************
110 remove redundent stuff from a filename
111 *******************************************************/
112 void clean_fname(char *name)
123 DEBUG(5,("cleaning %s\n", name));
125 if ((p=strstr(name,"/./"))) {
133 if ((p=strstr(name,"//"))) {
141 if (strcmp(name,"/../")==0) {
146 if ((p=strstr(name,"/../"))) {
148 for (p2=(p>name?p-1:p);p2>name;p2--) {
149 if (p2[0] == '/') break;
157 if (strcmp(name,"/..")==0) {
163 p = l>=3?(name+l-3):name;
164 if (strcmp(p,"/..")==0) {
166 for (p2=p-1;p2>name;p2--) {
167 if (p2[0] == '/') break;
178 p = l>=2?(name+l-2):name;
179 if (strcmp(p,"/.")==0) {
187 if (strncmp(p=name,"./",2) == 0) {
195 if (l > 1 && p[l-1] == '/') {
203 /*****************************************************
204 parse a smb path into its components.
205 *******************************************************/
206 char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
212 *server = *share = *path = 0;
214 if (fname[0] == '/') {
217 slprintf(s,sizeof(s)-1, "%s/%s", smb_cwd, fname);
221 DEBUG(5,("cleaned %s (fname=%s cwd=%s)\n",
224 if (strncmp(s,SMBW_PREFIX,strlen(SMBW_PREFIX))) return s;
226 p = s + strlen(SMBW_PREFIX);
235 len = MIN(len,sizeof(fstring)-1);
237 strncpy(server, p, len);
242 fstrcpy(share,"IPC$");
256 len = MIN(len,sizeof(fstring)-1);
258 strncpy(share, p, len);
269 string_sub(path, "/", "\\");
272 DEBUG(5,("parsed path name=%s cwd=%s [%s] [%s] [%s]\n",
274 server, share, path));
279 /*****************************************************
280 determine if a path name (possibly relative) is in the
282 *******************************************************/
283 int smbw_path(const char *path)
285 fstring server, share;
288 int l=strlen(SMBW_PREFIX)-1;
290 if (path[0] == '/' && strncmp(path,SMBW_PREFIX,l)) {
294 if (smbw_busy) return 0;
298 DEBUG(3,("smbw_path(%s)\n", path));
300 cwd = smbw_parse_path(path, server, share, s);
302 if (strncmp(cwd,SMBW_PREFIX,l) == 0 &&
303 (cwd[l] == '/' || cwd[l] == 0)) {
310 /*****************************************************
311 return a unix errno from a SMB error pair
312 *******************************************************/
313 int smbw_errno(struct cli_state *c)
319 ret = cli_error(c, &eclass, &ecode);
322 DEBUG(3,("smbw_error %d %d (0x%x)\n",
323 (int)eclass, (int)ecode, (int)ecode));
328 /*****************************************************
329 return a connection to a server (existing or new)
330 *******************************************************/
331 struct smbw_server *smbw_server(char *server, char *share)
333 struct smbw_server *srv=NULL;
338 struct nmb_name called, calling;
342 username = getenv("SMBW_USER");
343 if (!username) username = getenv("USER");
344 if (!username) username = "guest";
346 workgroup = getenv("SMBW_WORKGROUP");
347 if (!workgroup) workgroup = lp_workgroup();
349 password = getenv("SMBW_PASSWORD");
350 if (!password) password = "";
352 /* try to use an existing connection */
353 for (srv=smbw_srvs;srv;srv=srv->next) {
354 if (strcmp(server,srv->server_name)==0 &&
355 strcmp(share,srv->share_name)==0) return srv;
358 if (server[0] == 0) {
363 /* have to open a new connection */
364 if (!cli_initialise(&c) || !cli_connect(&c, server, NULL)) {
369 make_nmb_name(&calling, global_myname, 0x0, "");
370 make_nmb_name(&called , server, 0x20, "");
372 if (!cli_session_request(&c, &calling, &called)) {
378 if (!cli_negprot(&c)) {
384 if (!cli_session_setup(&c, username,
385 password, strlen(password),
386 password, strlen(password),
393 if (!cli_send_tconX(&c, share,
394 strstr(share,"IPC$")?"IPC":"A:",
395 password, strlen(password)+1)) {
396 errno = smbw_errno(&c);
401 srv = (struct smbw_server *)malloc(sizeof(*srv));
411 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
413 srv->server_name = strdup(server);
414 if (!srv->server_name) {
419 srv->share_name = strdup(share);
420 if (!srv->share_name) {
425 /* some programs play with file descriptors fairly intimately. We
426 try to get out of the way by duping to a high fd number */
427 if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
428 if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
429 srv->cli.fd+SMBW_CLI_FD) {
431 srv->cli.fd += SMBW_CLI_FD;
435 DLIST_ADD(smbw_srvs, srv);
441 if (!srv) return NULL;
443 if (srv->server_name) free(srv->server_name);
444 if (srv->share_name) free(srv->share_name);
450 /*****************************************************
451 map a fd to a smbw_file structure
452 *******************************************************/
453 struct smbw_file *smbw_file(int fd)
455 struct smbw_file *file;
457 for (file=smbw_files;file;file=file->next) {
458 if (file->fd == fd) return file;
463 /*****************************************************
465 *******************************************************/
466 int smbw_open(const char *fname, int flags, mode_t mode)
468 fstring server, share;
470 struct smbw_server *srv=NULL;
472 struct smbw_file *file=NULL;
474 DEBUG(4,("%s\n", __FUNCTION__));
485 /* work out what server they are after */
486 smbw_parse_path(fname, server, share, path);
488 /* get a connection to the server */
489 srv = smbw_server(server, share);
491 /* smbw_server sets errno */
495 if (path[strlen(path)-1] == '\\') {
498 fd = cli_open(&srv->cli, path, flags, DENY_NONE);
501 /* it might be a directory. Maybe we should use chkpath? */
502 fd = smbw_dir_open(fname);
511 file = (struct smbw_file *)malloc(sizeof(*file));
520 file->fname = strdup(path);
526 file->fd = bitmap_find(smbw_file_bmap, 0);
528 if (file->fd == -1) {
533 bitmap_set(smbw_file_bmap, file->fd);
535 file->fd += SMBW_FD_OFFSET;
537 DLIST_ADD(smbw_files, file);
539 DEBUG(4,("opened %s\n", fname));
546 cli_close(&srv->cli, fd);
559 /*****************************************************
561 *******************************************************/
562 ssize_t smbw_read(int fd, void *buf, size_t count)
564 struct smbw_file *file;
567 DEBUG(4,("%s %d\n", __FUNCTION__, (int)count));
571 file = smbw_file(fd);
578 ret = cli_read(&file->srv->cli, file->cli_fd, buf, file->offset, count);
581 errno = smbw_errno(&file->srv->cli);
592 /*****************************************************
593 a wrapper for write()
594 *******************************************************/
595 ssize_t smbw_write(int fd, void *buf, size_t count)
597 struct smbw_file *file;
600 DEBUG(4,("%s\n", __FUNCTION__));
604 file = smbw_file(fd);
606 DEBUG(3,("bad fd in read\n"));
612 ret = cli_write(&file->srv->cli, file->cli_fd, buf, file->offset, count);
615 errno = smbw_errno(&file->srv->cli);
626 /*****************************************************
627 a wrapper for close()
628 *******************************************************/
629 int smbw_close(int fd)
631 struct smbw_file *file;
633 DEBUG(4,("%s\n", __FUNCTION__));
637 file = smbw_file(fd);
639 int ret = smbw_dir_close(fd);
644 if (!cli_close(&file->srv->cli, file->cli_fd)) {
645 errno = smbw_errno(&file->srv->cli);
651 bitmap_clear(smbw_file_bmap, file->fd - SMBW_FD_OFFSET);
653 DLIST_REMOVE(smbw_files, file);
665 /*****************************************************
666 a wrapper for fcntl()
667 *******************************************************/
668 int smbw_fcntl(int fd, int cmd, long arg)
670 DEBUG(4,("%s\n", __FUNCTION__));
675 /*****************************************************
676 a wrapper for access()
677 *******************************************************/
678 int smbw_access(const char *name, int mode)
681 /* how do we map this properly ?? */
682 return smbw_stat(name, &st);
685 /*****************************************************
686 a wrapper for realink() - needed for correct errno setting
687 *******************************************************/
688 int smbw_readlink(const char *path, char *buf, size_t bufsize)
693 ret = smbw_stat(path, &st);
695 DEBUG(4,("readlink(%s) failed\n", path));
699 /* it exists - say it isn't a link */
700 DEBUG(4,("readlink(%s) not a link\n", path));
707 /*****************************************************
708 a wrapper for unlink()
709 *******************************************************/
710 int smbw_unlink(const char *fname)
712 struct smbw_server *srv;
713 fstring server, share;
716 DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
727 /* work out what server they are after */
728 smbw_parse_path(fname, server, share, path);
730 /* get a connection to the server */
731 srv = smbw_server(server, share);
733 /* smbw_server sets errno */
737 if (!cli_unlink(&srv->cli, path)) {
738 errno = smbw_errno(&srv->cli);
751 /*****************************************************
752 a wrapper for rename()
753 *******************************************************/
754 int smbw_rename(const char *oldname, const char *newname)
756 struct smbw_server *srv;
757 fstring server1, share1;
759 fstring server2, share2;
762 DEBUG(4,("%s (%s, %s)\n", __FUNCTION__, oldname, newname));
764 if (!oldname || !newname) {
773 /* work out what server they are after */
774 smbw_parse_path(oldname, server1, share1, path1);
775 smbw_parse_path(newname, server2, share2, path2);
777 if (strcmp(server1, server2) || strcmp(share1, share2)) {
778 /* can't cross filesystems */
783 /* get a connection to the server */
784 srv = smbw_server(server1, share1);
786 /* smbw_server sets errno */
790 if (!cli_rename(&srv->cli, path1, path2)) {
791 errno = smbw_errno(&srv->cli);
804 /*****************************************************
805 a wrapper for utime()
806 *******************************************************/
807 int smbw_utime(const char *fname, void *buf)
809 struct utimbuf *tbuf = (struct utimbuf *)buf;
810 struct smbw_server *srv;
811 fstring server, share;
815 DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
826 /* work out what server they are after */
827 smbw_parse_path(fname, server, share, path);
829 /* get a connection to the server */
830 srv = smbw_server(server, share);
832 /* smbw_server sets errno */
836 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
837 errno = smbw_errno(&srv->cli);
841 if (!cli_setatr(&srv->cli, path, mode, tbuf->modtime)) {
842 errno = smbw_errno(&srv->cli);
854 /*****************************************************
855 a wrapper for chown()
856 *******************************************************/
857 int smbw_chown(const char *fname, uid_t owner, gid_t group)
859 struct smbw_server *srv;
860 fstring server, share;
864 DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
875 /* work out what server they are after */
876 smbw_parse_path(fname, server, share, path);
878 /* get a connection to the server */
879 srv = smbw_server(server, share);
881 /* smbw_server sets errno */
885 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
886 errno = smbw_errno(&srv->cli);
900 /*****************************************************
901 a wrapper for chmod()
902 *******************************************************/
903 int smbw_chmod(const char *fname, mode_t newmode)
905 struct smbw_server *srv;
906 fstring server, share;
910 DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
921 /* work out what server they are after */
922 smbw_parse_path(fname, server, share, path);
924 /* get a connection to the server */
925 srv = smbw_server(server, share);
927 /* smbw_server sets errno */
931 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
932 errno = smbw_errno(&srv->cli);
936 /* assume success for the moment - need to add attribute mapping */
946 /*****************************************************
947 a wrapper for lseek()
948 *******************************************************/
949 off_t smbw_lseek(int fd, off_t offset, int whence)
951 struct smbw_file *file;
954 DEBUG(4,("%s\n", __FUNCTION__));
958 file = smbw_file(fd);
960 off_t ret = smbw_dir_lseek(fd, offset, whence);
967 file->offset = offset;
970 file->offset += offset;
973 if (!cli_qfileinfo(&file->srv->cli, file->cli_fd,
974 NULL, &size, NULL, NULL, NULL) &&
975 !cli_getattrE(&file->srv->cli, file->cli_fd,
976 NULL, &size, NULL, NULL, NULL)) {
981 file->offset = size + offset;