- don't use env variables for passwords and usernames (yeah!)
[Samba/gbeck.git] / source / smbwrapper / smbw.c
blob7ddc46ca9b0e111fe983c2d5f99ba7cf0001958b
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.0
4 SMB wrapper functions
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.
22 #include "includes.h"
23 #include "realcalls.h"
25 pstring smbw_cwd;
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;
36 int smbw_busy=0;
38 /* needs to be here because of dumb include files on some systems */
39 int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;
41 /*****************************************************
42 initialise structures
43 *******************************************************/
44 void smbw_init(void)
46 extern BOOL in_client;
47 static int initialised;
48 static pstring servicesf = CONFIGFILE;
49 extern FILE *dbf;
50 char *p;
51 int eno;
53 if (initialised) return;
54 initialised = 1;
56 eno = errno;
58 smbw_busy++;
60 DEBUGLEVEL = 0;
61 setup_logging("smbsh",True);
63 dbf = stderr;
65 if ((p=smbw_getshared("LOGFILE"))) {
66 dbf = fopen(p, "a");
69 smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
70 if (!smbw_file_bmap) {
71 exit(1);
74 charset_initialise();
76 in_client = True;
78 load_interfaces();
80 lp_load(servicesf,True,False,False);
82 get_myname(global_myname,NULL);
84 if ((p=smbw_getshared("DEBUG"))) {
85 DEBUGLEVEL = atoi(p);
88 if ((p=smbw_getshared("PREFIX"))) {
89 slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);
90 string_sub(smbw_prefix,"//", "/");
91 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));
94 if ((p=getenv(SMBW_PWD_ENV))) {
95 pstrcpy(smbw_cwd, p);
96 DEBUG(4,("Initial cwd from smbw_cwd is %s\n", smbw_cwd));
97 } else {
98 sys_getwd(smbw_cwd);
99 DEBUG(4,("Initial cwd from getwd is %s\n", smbw_cwd));
101 smbw_busy--;
103 set_maxfiles(SMBW_MAX_OPEN);
105 errno = eno;
108 /*****************************************************
109 determine if a file descriptor is a smb one
110 *******************************************************/
111 int smbw_fd(int fd)
113 if (smbw_busy) return 0;
114 return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);
117 /*****************************************************
118 a crude inode number generator
119 *******************************************************/
120 ino_t smbw_inode(const char *name)
122 return (ino_t)str_checksum(name);
125 /*****************************************************
126 remove redundent stuff from a filename
127 *******************************************************/
128 void clean_fname(char *name)
130 char *p, *p2;
131 int l;
132 int modified = 1;
134 if (!name) return;
136 while (modified) {
137 modified = 0;
139 DEBUG(5,("cleaning %s\n", name));
141 if ((p=strstr(name,"/./"))) {
142 modified = 1;
143 while (*p) {
144 p[0] = p[2];
145 p++;
149 if ((p=strstr(name,"//"))) {
150 modified = 1;
151 while (*p) {
152 p[0] = p[1];
153 p++;
157 if (strcmp(name,"/../")==0) {
158 modified = 1;
159 name[1] = 0;
162 if ((p=strstr(name,"/../"))) {
163 modified = 1;
164 for (p2=(p>name?p-1:p);p2>name;p2--) {
165 if (p2[0] == '/') break;
167 while (*p2) {
168 p2[0] = p2[3];
169 p2++;
173 if (strcmp(name,"/..")==0) {
174 modified = 1;
175 name[1] = 0;
178 l = strlen(name);
179 p = l>=3?(name+l-3):name;
180 if (strcmp(p,"/..")==0) {
181 modified = 1;
182 for (p2=p-1;p2>name;p2--) {
183 if (p2[0] == '/') break;
185 if (p2==name) {
186 p[0] = '/';
187 p[1] = 0;
188 } else {
189 p2[0] = 0;
193 l = strlen(name);
194 p = l>=2?(name+l-2):name;
195 if (strcmp(p,"/.")==0) {
196 if (p == name) {
197 p[1] = 0;
198 } else {
199 p[0] = 0;
203 if (strncmp(p=name,"./",2) == 0) {
204 modified = 1;
205 do {
206 p[0] = p[2];
207 } while (*p++);
210 l = strlen(p=name);
211 if (l > 1 && p[l-1] == '/') {
212 modified = 1;
213 p[l-1] = 0;
219 /*****************************************************
220 parse a smb path into its components.
221 *******************************************************/
222 char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
224 static pstring s;
225 char *p, *p2;
226 int len = strlen(smbw_prefix)-1;
228 *server = *share = *path = 0;
230 if (fname[0] == '/') {
231 pstrcpy(s, fname);
232 } else {
233 slprintf(s,sizeof(s)-1, "%s/%s", smbw_cwd, fname);
235 clean_fname(s);
237 DEBUG(5,("cleaned %s (fname=%s cwd=%s)\n",
238 s, fname, smbw_cwd));
240 if (strncmp(s,smbw_prefix,len) ||
241 (s[len] != '/' && s[len] != 0)) return s;
243 p = s + len;
244 if (*p == '/') p++;
246 p2 = strchr(p,'/');
248 if (p2) {
249 len = (int)(p2-p);
250 } else {
251 len = strlen(p);
254 len = MIN(len,sizeof(fstring)-1);
256 strncpy(server, p, len);
257 server[len] = 0;
259 p = p2;
260 if (!p) {
261 if (len == 0) {
262 char *workgroup = smbw_getshared("WORKGROUP");
263 if (!workgroup) workgroup = lp_workgroup();
264 slprintf(server,sizeof(fstring)-1, "%s#1D", workgroup);
266 fstrcpy(share,"IPC$");
267 pstrcpy(path,"");
268 goto ok;
271 p++;
272 p2 = strchr(p,'/');
274 if (p2) {
275 len = (int)(p2-p);
276 } else {
277 len = strlen(p);
280 len = MIN(len,sizeof(fstring)-1);
282 strncpy(share, p, len);
283 share[len] = 0;
285 p = p2;
286 if (!p) {
287 pstrcpy(path,"\\");
288 goto ok;
291 pstrcpy(path,p);
293 string_sub(path, "/", "\\");
296 DEBUG(4,("parsed path name=%s cwd=%s [%s] [%s] [%s]\n",
297 fname, smbw_cwd,
298 server, share, path));
300 return s;
303 /*****************************************************
304 determine if a path name (possibly relative) is in the
305 smb name space
306 *******************************************************/
307 int smbw_path(const char *path)
309 fstring server, share;
310 pstring s;
311 char *cwd;
312 int len;
314 smbw_init();
316 len = strlen(smbw_prefix)-1;
318 if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {
319 return 0;
322 if (smbw_busy) return 0;
324 DEBUG(3,("smbw_path(%s)\n", path));
326 cwd = smbw_parse_path(path, server, share, s);
328 if (strncmp(cwd,smbw_prefix,len) == 0 &&
329 (cwd[len] == '/' || cwd[len] == 0)) {
330 return 1;
333 return 0;
336 /*****************************************************
337 return a unix errno from a SMB error pair
338 *******************************************************/
339 int smbw_errno(struct cli_state *c)
341 uint8 eclass;
342 uint32 ecode;
343 int ret;
345 ret = cli_error(c, &eclass, &ecode);
347 if (ret) {
348 DEBUG(3,("smbw_error %d %d (0x%x) -> %d\n",
349 (int)eclass, (int)ecode, (int)ecode, ret));
351 return ret;
354 /*****************************************************
355 return a connection to a server (existing or new)
356 *******************************************************/
357 struct smbw_server *smbw_server(char *server, char *share)
359 struct smbw_server *srv=NULL;
360 struct cli_state c;
361 char *username;
362 char *password;
363 char *workgroup;
364 struct nmb_name called, calling;
365 char *p, *server_n = server;
366 fstring group;
367 pstring ipenv;
368 struct in_addr ip;
369 extern struct in_addr ipzero;
371 ip = ipzero;
372 ZERO_STRUCT(c);
374 username = smbw_getshared("USER");
375 if (!username) username = getenv("USER");
376 if (!username) username = "guest";
378 workgroup = smbw_getshared("WORKGROUP");
379 if (!workgroup) workgroup = lp_workgroup();
381 password = smbw_getshared("PASSWORD");
382 if (!password) password = "";
384 /* try to use an existing connection */
385 for (srv=smbw_srvs;srv;srv=srv->next) {
386 if (strcmp(server,srv->server_name)==0 &&
387 strcmp(share,srv->share_name)==0) return srv;
390 if (server[0] == 0) {
391 errno = EPERM;
392 return NULL;
395 make_nmb_name(&calling, global_myname, 0x0, "");
396 make_nmb_name(&called , server, 0x20, "");
398 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));
400 if ((p=strchr(server_n,'#')) && strcmp(p+1,"1D")==0) {
401 struct in_addr ip;
402 pstring s;
404 fstrcpy(group, server_n);
405 p = strchr(group,'#');
406 *p = 0;
408 /* cache the workgroup master lookup */
409 slprintf(s,sizeof(s)-1,"MASTER_%s", group);
410 if (!(server_n = smbw_getshared(s))) {
411 if (!find_master_ip(group, &ip)) {
412 errno = ENOENT;
413 return NULL;
415 fstrcpy(group, inet_ntoa(ip));
416 server_n = group;
417 smbw_setshared(s,server_n);
421 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
423 again:
424 slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
426 ip = ipzero;
427 if ((p=smbw_getshared(ipenv))) {
428 ip = *(interpret_addr2(p));
431 /* have to open a new connection */
432 if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
433 errno = ENOENT;
434 return NULL;
437 if (!cli_session_request(&c, &calling, &called)) {
438 cli_shutdown(&c);
439 if (strcmp(called.name, "*SMBSERVER")) {
440 make_nmb_name(&called , "*SMBSERVER", 0x20, "");
441 goto again;
443 errno = ENOENT;
444 return NULL;
447 DEBUG(4,(" session request ok\n"));
449 if (!cli_negprot(&c)) {
450 cli_shutdown(&c);
451 errno = ENOENT;
452 return NULL;
455 if (!cli_session_setup(&c, username,
456 password, strlen(password),
457 password, strlen(password),
458 workgroup) &&
459 /* try an anonymous login if it failed */
460 !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
461 cli_shutdown(&c);
462 errno = EPERM;
463 return NULL;
466 DEBUG(4,(" session setup ok\n"));
468 if (!cli_send_tconX(&c, share, "?????",
469 password, strlen(password)+1)) {
470 errno = smbw_errno(&c);
471 cli_shutdown(&c);
472 return NULL;
475 smbw_setshared(ipenv,inet_ntoa(ip));
477 DEBUG(4,(" tconx ok\n"));
479 srv = (struct smbw_server *)malloc(sizeof(*srv));
480 if (!srv) {
481 errno = ENOMEM;
482 goto failed;
485 ZERO_STRUCTP(srv);
487 srv->cli = c;
489 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
491 srv->server_name = strdup(server);
492 if (!srv->server_name) {
493 errno = ENOMEM;
494 goto failed;
497 srv->share_name = strdup(share);
498 if (!srv->share_name) {
499 errno = ENOMEM;
500 goto failed;
503 /* some programs play with file descriptors fairly intimately. We
504 try to get out of the way by duping to a high fd number */
505 if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
506 if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
507 srv->cli.fd+SMBW_CLI_FD) {
508 close(srv->cli.fd);
509 srv->cli.fd += SMBW_CLI_FD;
513 DLIST_ADD(smbw_srvs, srv);
515 return srv;
517 failed:
518 cli_shutdown(&c);
519 if (!srv) return NULL;
521 if (srv->server_name) free(srv->server_name);
522 if (srv->share_name) free(srv->share_name);
523 free(srv);
524 return NULL;
528 /*****************************************************
529 map a fd to a smbw_file structure
530 *******************************************************/
531 struct smbw_file *smbw_file(int fd)
533 struct smbw_file *file;
535 for (file=smbw_files;file;file=file->next) {
536 if (file->fd == fd) return file;
538 return NULL;
541 /*****************************************************
542 a wrapper for open()
543 *******************************************************/
544 int smbw_open(const char *fname, int flags, mode_t mode)
546 fstring server, share;
547 pstring path;
548 struct smbw_server *srv=NULL;
549 int eno=0, fd = -1;
550 struct smbw_file *file=NULL;
552 smbw_init();
554 if (!fname) {
555 errno = EINVAL;
556 return -1;
559 smbw_busy++;
561 /* work out what server they are after */
562 smbw_parse_path(fname, server, share, path);
564 /* get a connection to the server */
565 srv = smbw_server(server, share);
566 if (!srv) {
567 /* smbw_server sets errno */
568 goto failed;
571 if (path[strlen(path)-1] == '\\') {
572 fd = -1;
573 } else {
574 fd = cli_open(&srv->cli, path, flags, DENY_NONE);
576 if (fd == -1) {
577 /* it might be a directory. Maybe we should use chkpath? */
578 eno = smbw_errno(&srv->cli);
579 fd = smbw_dir_open(fname);
580 if (fd == -1) errno = eno;
581 smbw_busy--;
582 return fd;
585 file = (struct smbw_file *)malloc(sizeof(*file));
586 if (!file) {
587 errno = ENOMEM;
588 goto failed;
591 ZERO_STRUCTP(file);
593 file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
594 if (!file->f) {
595 errno = ENOMEM;
596 goto failed;
599 ZERO_STRUCTP(file->f);
601 file->f->cli_fd = fd;
602 file->f->fname = strdup(path);
603 if (!file->f->fname) {
604 errno = ENOMEM;
605 goto failed;
607 file->srv = srv;
608 file->fd = open(SMBW_DUMMY, O_WRONLY);
609 if (file->fd == -1) {
610 errno = EMFILE;
611 goto failed;
614 if (bitmap_query(smbw_file_bmap, file->fd)) {
615 DEBUG(0,("ERROR: fd used in smbw_open\n"));
616 errno = EIO;
617 goto failed;
620 file->f->ref_count=1;
622 bitmap_set(smbw_file_bmap, file->fd);
624 DLIST_ADD(smbw_files, file);
626 DEBUG(4,("opened %s\n", fname));
628 smbw_busy--;
629 return file->fd;
631 failed:
632 if (fd != -1) {
633 cli_close(&srv->cli, fd);
635 if (file) {
636 if (file->f) {
637 if (file->f->fname) {
638 free(file->f->fname);
640 free(file->f);
642 free(file);
644 smbw_busy--;
645 return -1;
649 /*****************************************************
650 a wrapper for pread()
651 *******************************************************/
652 ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs)
654 struct smbw_file *file;
655 int ret;
657 smbw_busy++;
659 file = smbw_file(fd);
660 if (!file) {
661 errno = EBADF;
662 smbw_busy--;
663 return -1;
666 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count);
668 if (ret == -1) {
669 errno = smbw_errno(&file->srv->cli);
670 smbw_busy--;
671 return -1;
674 smbw_busy--;
675 return ret;
678 /*****************************************************
679 a wrapper for read()
680 *******************************************************/
681 ssize_t smbw_read(int fd, void *buf, size_t count)
683 struct smbw_file *file;
684 int ret;
686 DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));
688 smbw_busy++;
690 file = smbw_file(fd);
691 if (!file) {
692 errno = EBADF;
693 smbw_busy--;
694 return -1;
697 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf,
698 file->f->offset, count);
700 if (ret == -1) {
701 errno = smbw_errno(&file->srv->cli);
702 smbw_busy--;
703 return -1;
706 file->f->offset += ret;
708 DEBUG(4,(" -> %d\n", ret));
710 smbw_busy--;
711 return ret;
716 /*****************************************************
717 a wrapper for write()
718 *******************************************************/
719 ssize_t smbw_write(int fd, void *buf, size_t count)
721 struct smbw_file *file;
722 int ret;
724 smbw_busy++;
726 file = smbw_file(fd);
727 if (!file) {
728 DEBUG(3,("bad fd in read\n"));
729 errno = EBADF;
730 smbw_busy--;
731 return -1;
734 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count);
736 if (ret == -1) {
737 errno = smbw_errno(&file->srv->cli);
738 smbw_busy--;
739 return -1;
742 file->f->offset += ret;
744 smbw_busy--;
745 return ret;
748 /*****************************************************
749 a wrapper for pwrite()
750 *******************************************************/
751 ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
753 struct smbw_file *file;
754 int ret;
756 smbw_busy++;
758 file = smbw_file(fd);
759 if (!file) {
760 DEBUG(3,("bad fd in read\n"));
761 errno = EBADF;
762 smbw_busy--;
763 return -1;
766 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);
768 if (ret == -1) {
769 errno = smbw_errno(&file->srv->cli);
770 smbw_busy--;
771 return -1;
774 smbw_busy--;
775 return ret;
778 /*****************************************************
779 a wrapper for close()
780 *******************************************************/
781 int smbw_close(int fd)
783 struct smbw_file *file;
785 smbw_busy++;
787 file = smbw_file(fd);
788 if (!file) {
789 int ret = smbw_dir_close(fd);
790 smbw_busy--;
791 return ret;
794 if (file->f->ref_count == 1 &&
795 !cli_close(&file->srv->cli, file->f->cli_fd)) {
796 errno = smbw_errno(&file->srv->cli);
797 smbw_busy--;
798 return -1;
802 bitmap_clear(smbw_file_bmap, file->fd);
803 close(file->fd);
805 DLIST_REMOVE(smbw_files, file);
807 file->f->ref_count--;
808 if (file->f->ref_count == 0) {
809 free(file->f->fname);
810 free(file->f);
812 ZERO_STRUCTP(file);
813 free(file);
815 smbw_busy--;
817 return 0;
821 /*****************************************************
822 a wrapper for fcntl()
823 *******************************************************/
824 int smbw_fcntl(int fd, int cmd, long arg)
826 return 0;
830 /*****************************************************
831 a wrapper for access()
832 *******************************************************/
833 int smbw_access(const char *name, int mode)
835 struct stat st;
837 DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode));
839 if (smbw_stat(name, &st)) return -1;
841 if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) ||
842 ((mode & W_OK) && !(st.st_mode & S_IWUSR)) ||
843 ((mode & X_OK) && !(st.st_mode & S_IXUSR))) {
844 errno = EACCES;
845 return -1;
848 return 0;
851 /*****************************************************
852 a wrapper for realink() - needed for correct errno setting
853 *******************************************************/
854 int smbw_readlink(const char *path, char *buf, size_t bufsize)
856 struct stat st;
857 int ret;
859 ret = smbw_stat(path, &st);
860 if (ret != 0) {
861 DEBUG(4,("readlink(%s) failed\n", path));
862 return -1;
865 /* it exists - say it isn't a link */
866 DEBUG(4,("readlink(%s) not a link\n", path));
868 errno = EINVAL;
869 return -1;
873 /*****************************************************
874 a wrapper for unlink()
875 *******************************************************/
876 int smbw_unlink(const char *fname)
878 struct smbw_server *srv;
879 fstring server, share;
880 pstring path;
882 if (!fname) {
883 errno = EINVAL;
884 return -1;
887 smbw_init();
889 smbw_busy++;
891 /* work out what server they are after */
892 smbw_parse_path(fname, server, share, path);
894 /* get a connection to the server */
895 srv = smbw_server(server, share);
896 if (!srv) {
897 /* smbw_server sets errno */
898 goto failed;
901 if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
902 int job = smbw_stat_printjob(srv, path, NULL, NULL);
903 if (job == -1) {
904 goto failed;
906 if (cli_printjob_del(&srv->cli, job) != 0) {
907 goto failed;
909 } else if (!cli_unlink(&srv->cli, path)) {
910 errno = smbw_errno(&srv->cli);
911 goto failed;
914 smbw_busy--;
915 return 0;
917 failed:
918 smbw_busy--;
919 return -1;
923 /*****************************************************
924 a wrapper for rename()
925 *******************************************************/
926 int smbw_rename(const char *oldname, const char *newname)
928 struct smbw_server *srv;
929 fstring server1, share1;
930 pstring path1;
931 fstring server2, share2;
932 pstring path2;
934 if (!oldname || !newname) {
935 errno = EINVAL;
936 return -1;
939 smbw_init();
941 DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
943 smbw_busy++;
945 /* work out what server they are after */
946 smbw_parse_path(oldname, server1, share1, path1);
947 smbw_parse_path(newname, server2, share2, path2);
949 if (strcmp(server1, server2) || strcmp(share1, share2)) {
950 /* can't cross filesystems */
951 errno = EXDEV;
952 return -1;
955 /* get a connection to the server */
956 srv = smbw_server(server1, share1);
957 if (!srv) {
958 /* smbw_server sets errno */
959 goto failed;
962 if (!cli_rename(&srv->cli, path1, path2)) {
963 int eno = smbw_errno(&srv->cli);
964 if (eno != EEXIST ||
965 !cli_unlink(&srv->cli, path2) ||
966 !cli_rename(&srv->cli, path1, path2)) {
967 errno = eno;
968 goto failed;
972 smbw_busy--;
973 return 0;
975 failed:
976 smbw_busy--;
977 return -1;
981 /*****************************************************
982 a wrapper for utime and utimes
983 *******************************************************/
984 static int smbw_settime(const char *fname, time_t t)
986 struct smbw_server *srv;
987 fstring server, share;
988 pstring path;
989 uint32 mode;
991 if (!fname) {
992 errno = EINVAL;
993 return -1;
996 smbw_init();
998 smbw_busy++;
1000 /* work out what server they are after */
1001 smbw_parse_path(fname, server, share, path);
1003 /* get a connection to the server */
1004 srv = smbw_server(server, share);
1005 if (!srv) {
1006 /* smbw_server sets errno */
1007 goto failed;
1010 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1011 errno = smbw_errno(&srv->cli);
1012 goto failed;
1015 if (!cli_setatr(&srv->cli, path, mode, t)) {
1016 /* some servers always refuse directory changes */
1017 if (!(mode & aDIR)) {
1018 errno = smbw_errno(&srv->cli);
1019 goto failed;
1023 smbw_busy--;
1024 return 0;
1026 failed:
1027 smbw_busy--;
1028 return -1;
1031 /*****************************************************
1032 a wrapper for utime
1033 *******************************************************/
1034 int smbw_utime(const char *fname, void *buf)
1036 struct utimbuf *tbuf = (struct utimbuf *)buf;
1037 return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL));
1040 /*****************************************************
1041 a wrapper for utime
1042 *******************************************************/
1043 int smbw_utimes(const char *fname, void *buf)
1045 struct timeval *tbuf = (struct timeval *)buf;
1046 return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL));
1050 /*****************************************************
1051 a wrapper for chown()
1052 *******************************************************/
1053 int smbw_chown(const char *fname, uid_t owner, gid_t group)
1055 struct smbw_server *srv;
1056 fstring server, share;
1057 pstring path;
1058 uint32 mode;
1060 if (!fname) {
1061 errno = EINVAL;
1062 return -1;
1065 smbw_init();
1067 smbw_busy++;
1069 /* work out what server they are after */
1070 smbw_parse_path(fname, server, share, path);
1072 /* get a connection to the server */
1073 srv = smbw_server(server, share);
1074 if (!srv) {
1075 /* smbw_server sets errno */
1076 goto failed;
1079 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1080 errno = smbw_errno(&srv->cli);
1081 goto failed;
1084 /* assume success */
1086 smbw_busy--;
1087 return 0;
1089 failed:
1090 smbw_busy--;
1091 return -1;
1094 /*****************************************************
1095 a wrapper for chmod()
1096 *******************************************************/
1097 int smbw_chmod(const char *fname, mode_t newmode)
1099 struct smbw_server *srv;
1100 fstring server, share;
1101 pstring path;
1102 uint32 mode;
1104 if (!fname) {
1105 errno = EINVAL;
1106 return -1;
1109 smbw_init();
1111 smbw_busy++;
1113 /* work out what server they are after */
1114 smbw_parse_path(fname, server, share, path);
1116 /* get a connection to the server */
1117 srv = smbw_server(server, share);
1118 if (!srv) {
1119 /* smbw_server sets errno */
1120 goto failed;
1123 mode = 0;
1125 if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
1126 if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
1127 if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
1128 if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
1130 if (!cli_setatr(&srv->cli, path, mode, 0)) {
1131 errno = smbw_errno(&srv->cli);
1132 goto failed;
1135 smbw_busy--;
1136 return 0;
1138 failed:
1139 smbw_busy--;
1140 return -1;
1143 /*****************************************************
1144 a wrapper for lseek()
1145 *******************************************************/
1146 off_t smbw_lseek(int fd, off_t offset, int whence)
1148 struct smbw_file *file;
1149 size_t size;
1151 smbw_busy++;
1153 file = smbw_file(fd);
1154 if (!file) {
1155 off_t ret = smbw_dir_lseek(fd, offset, whence);
1156 smbw_busy--;
1157 return ret;
1160 switch (whence) {
1161 case SEEK_SET:
1162 file->f->offset = offset;
1163 break;
1164 case SEEK_CUR:
1165 file->f->offset += offset;
1166 break;
1167 case SEEK_END:
1168 if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
1169 NULL, &size, NULL, NULL, NULL) &&
1170 !cli_getattrE(&file->srv->cli, file->f->cli_fd,
1171 NULL, &size, NULL, NULL, NULL)) {
1172 errno = EINVAL;
1173 smbw_busy--;
1174 return -1;
1176 file->f->offset = size + offset;
1177 break;
1180 smbw_busy--;
1181 return file->f->offset;
1185 /*****************************************************
1186 a wrapper for dup()
1187 *******************************************************/
1188 int smbw_dup(int fd)
1190 int fd2;
1191 struct smbw_file *file, *file2;
1193 smbw_busy++;
1195 file = smbw_file(fd);
1196 if (!file) {
1197 errno = EBADF;
1198 goto failed;
1201 fd2 = dup(file->fd);
1202 if (fd2 == -1) {
1203 goto failed;
1206 if (bitmap_query(smbw_file_bmap, fd2)) {
1207 DEBUG(0,("ERROR: fd already open in dup!\n"));
1208 errno = EIO;
1209 goto failed;
1212 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1213 if (!file2) {
1214 close(fd2);
1215 errno = ENOMEM;
1216 goto failed;
1219 ZERO_STRUCTP(file2);
1221 *file2 = *file;
1222 file2->fd = fd2;
1224 file->f->ref_count++;
1226 bitmap_set(smbw_file_bmap, fd2);
1228 DLIST_ADD(smbw_files, file2);
1230 smbw_busy--;
1231 return fd2;
1233 failed:
1234 smbw_busy--;
1235 return -1;
1239 /*****************************************************
1240 a wrapper for dup2()
1241 *******************************************************/
1242 int smbw_dup2(int fd, int fd2)
1244 struct smbw_file *file, *file2;
1246 smbw_busy++;
1248 file = smbw_file(fd);
1249 if (!file) {
1250 errno = EBADF;
1251 goto failed;
1254 if (bitmap_query(smbw_file_bmap, fd2)) {
1255 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1256 errno = EIO;
1257 goto failed;
1260 if (dup2(file->fd, fd2) != fd2) {
1261 goto failed;
1264 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1265 if (!file2) {
1266 close(fd2);
1267 errno = ENOMEM;
1268 goto failed;
1271 ZERO_STRUCTP(file2);
1273 *file2 = *file;
1274 file2->fd = fd2;
1276 file->f->ref_count++;
1278 bitmap_set(smbw_file_bmap, fd2);
1280 DLIST_ADD(smbw_files, file2);
1282 smbw_busy--;
1283 return fd2;
1285 failed:
1286 smbw_busy--;
1287 return -1;
1291 /*****************************************************
1292 close a connection to a server
1293 *******************************************************/
1294 static void smbw_srv_close(struct smbw_server *srv)
1296 smbw_busy++;
1298 cli_shutdown(&srv->cli);
1300 free(srv->server_name);
1301 free(srv->share_name);
1303 DLIST_REMOVE(smbw_srvs, srv);
1305 ZERO_STRUCTP(srv);
1307 free(srv);
1309 smbw_busy--;
1312 /*****************************************************
1313 when we fork we have to close all connections and files
1314 in the child
1315 *******************************************************/
1316 int smbw_fork(void)
1318 pid_t child;
1319 int p[2];
1320 char c=0;
1322 struct smbw_file *file, *next_file;
1323 struct smbw_server *srv, *next_srv;
1325 if (pipe(p)) return real_fork();
1327 child = real_fork();
1329 if (child) {
1330 /* block the parent for a moment until the sockets are
1331 closed */
1332 close(p[1]);
1333 read(p[0], &c, 1);
1334 close(p[0]);
1335 return child;
1338 close(p[0]);
1340 /* close all files */
1341 for (file=smbw_files;file;file=next_file) {
1342 next_file = file->next;
1343 close(file->fd);
1346 /* close all server connections */
1347 for (srv=smbw_srvs;srv;srv=next_srv) {
1348 next_srv = srv->next;
1349 smbw_srv_close(srv);
1352 /* unblock the parent */
1353 write(p[1], &c, 1);
1354 close(p[1]);
1356 /* and continue in the child */
1357 return 0;
1360 #ifndef NO_ACL_WRAPPER
1361 /*****************************************************
1362 say no to acls
1363 *******************************************************/
1364 int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp)
1366 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1367 errno = ENOSYS;
1368 return -1;
1370 #endif
1372 #ifndef NO_FACL_WRAPPER
1373 /*****************************************************
1374 say no to acls
1375 *******************************************************/
1376 int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp)
1378 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1379 errno = ENOSYS;
1380 return -1;
1382 #endif
1385 #ifdef HAVE_STAT64
1386 /* this can't be in wrapped.c because of include conflicts */
1387 void stat64_convert(struct stat *st, struct stat64 *st64)
1389 st64->st_size = st->st_size;
1390 st64->st_mode = st->st_mode;
1391 st64->st_ino = st->st_ino;
1392 st64->st_dev = st->st_dev;
1393 st64->st_rdev = st->st_rdev;
1394 st64->st_nlink = st->st_nlink;
1395 st64->st_uid = st->st_uid;
1396 st64->st_gid = st->st_gid;
1397 st64->st_atime = st->st_atime;
1398 st64->st_mtime = st->st_mtime;
1399 st64->st_ctime = st->st_ctime;
1400 st64->st_blksize = st->st_blksize;
1401 st64->st_blocks = st->st_blocks;
1403 #endif
1405 #ifdef HAVE_READDIR64
1406 void dirent64_convert(struct dirent *d, struct dirent64 *d64)
1408 d64->d_ino = d->d_ino;
1409 d64->d_off = d->d_off;
1410 d64->d_reclen = d->d_reclen;
1411 pstrcpy(d64->d_name, d->d_name);
1413 #endif
1416 #ifdef HAVE___XSTAT
1417 /* Definition of `struct stat' used in the linux kernel.. */
1418 struct kernel_stat {
1419 unsigned short int st_dev;
1420 unsigned short int __pad1;
1421 unsigned long int st_ino;
1422 unsigned short int st_mode;
1423 unsigned short int st_nlink;
1424 unsigned short int st_uid;
1425 unsigned short int st_gid;
1426 unsigned short int st_rdev;
1427 unsigned short int __pad2;
1428 unsigned long int st_size;
1429 unsigned long int st_blksize;
1430 unsigned long int st_blocks;
1431 unsigned long int st_atime;
1432 unsigned long int __unused1;
1433 unsigned long int st_mtime;
1434 unsigned long int __unused2;
1435 unsigned long int st_ctime;
1436 unsigned long int __unused3;
1437 unsigned long int __unused4;
1438 unsigned long int __unused5;
1442 * Prototype for gcc in 'fussy' mode.
1444 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf);
1445 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf)
1447 #ifdef _STAT_VER_LINUX_OLD
1448 if (vers == _STAT_VER_LINUX_OLD) {
1449 memcpy(st, kbuf, sizeof(*st));
1450 return;
1452 #endif
1454 ZERO_STRUCTP(st);
1456 st->st_dev = kbuf->st_dev;
1457 st->st_ino = kbuf->st_ino;
1458 st->st_mode = kbuf->st_mode;
1459 st->st_nlink = kbuf->st_nlink;
1460 st->st_uid = kbuf->st_uid;
1461 st->st_gid = kbuf->st_gid;
1462 st->st_rdev = kbuf->st_rdev;
1463 st->st_size = kbuf->st_size;
1464 st->st_blksize = kbuf->st_blksize;
1465 st->st_blocks = kbuf->st_blocks;
1466 st->st_atime = kbuf->st_atime;
1467 st->st_mtime = kbuf->st_mtime;
1468 st->st_ctime = kbuf->st_ctime;
1470 #endif