Fix typo that disabled setting group id. Thanks, Henrik.
[kai/samba.git] / source3 / libsmb / libsmbclient.c
1 /* 
2    Unix SMB/Netbios implementation.
3    SMB client library implementation
4    Copyright (C) Andrew Tridgell 1998
5    Copyright (C) Richard Sharpe 2000, 2002
6    Copyright (C) John Terpstra 2000
7    Copyright (C) Tom Jansen (Ninja ISD) 2002 
8    Copyright (C) Derrell Lipman 2003, 2004
9    Copyright (C) Jeremy Allison 2007, 2008
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26
27 #include "include/libsmb_internal.h"
28
29 struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir);
30 struct smbc_dir_list *smbc_check_dir_ent(struct smbc_dir_list *list, 
31                                          struct smbc_dirent *dirent);
32
33 /*
34  * DOS Attribute values (used internally)
35  */
36 typedef struct DOS_ATTR_DESC {
37         int mode;
38         SMB_OFF_T size;
39         time_t create_time;
40         time_t access_time;
41         time_t write_time;
42         time_t change_time;
43         SMB_INO_T inode;
44 } DOS_ATTR_DESC;
45
46
47 /*
48  * Internal flags for extended attributes
49  */
50
51 /* internal mode values */
52 #define SMBC_XATTR_MODE_ADD          1
53 #define SMBC_XATTR_MODE_REMOVE       2
54 #define SMBC_XATTR_MODE_REMOVE_ALL   3
55 #define SMBC_XATTR_MODE_SET          4
56 #define SMBC_XATTR_MODE_CHOWN        5
57 #define SMBC_XATTR_MODE_CHGRP        6
58
59 #define CREATE_ACCESS_READ      READ_CONTROL_ACCESS
60
61 /*We should test for this in configure ... */
62 #ifndef ENOTSUP
63 #define ENOTSUP EOPNOTSUPP
64 #endif
65
66 /*
67  * Functions exported by libsmb_cache.c that we need here
68  */
69 int smbc_default_cache_functions(SMBCCTX *context);
70
71 /* 
72  * check if an element is part of the list. 
73  * FIXME: Does not belong here !  
74  * Can anyone put this in a macro in dlinklist.h ?
75  * -- Tom
76  */
77 static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) {
78         if (!p || !list) return False;
79         do {
80                 if (p == list) return True;
81                 list = list->next;
82         } while (list);
83         return False;
84 }
85
86 /*
87  * Find an lsa pipe handle associated with a cli struct.
88  */
89 static struct rpc_pipe_client *
90 find_lsa_pipe_hnd(struct cli_state *ipc_cli)
91 {
92         struct rpc_pipe_client *pipe_hnd;
93
94         for (pipe_hnd = ipc_cli->pipe_list;
95              pipe_hnd;
96              pipe_hnd = pipe_hnd->next) {
97             
98                 if (pipe_hnd->pipe_idx == PI_LSARPC) {
99                         return pipe_hnd;
100                 }
101         }
102
103         return NULL;
104 }
105
106 static int
107 smbc_close_ctx(SMBCCTX *context,
108                SMBCFILE *file);
109 static off_t
110 smbc_lseek_ctx(SMBCCTX *context,
111                SMBCFILE *file,
112                off_t offset,
113                int whence);
114
115 extern bool in_client;
116
117 /*
118  * Is the logging working / configfile read ? 
119  */
120 static int smbc_initialized = 0;
121
122 static int 
123 hex2int( unsigned int _char )
124 {
125     if ( _char >= 'A' && _char <='F')
126         return _char - 'A' + 10;
127     if ( _char >= 'a' && _char <='f')
128         return _char - 'a' + 10;
129     if ( _char >= '0' && _char <='9')
130         return _char - '0';
131     return -1;
132 }
133
134 /*
135  * smbc_urldecode()
136  * and smbc_urldecode_talloc() (internal fn.)
137  *
138  * Convert strings of %xx to their single character equivalent.  Each 'x' must
139  * be a valid hexadecimal digit, or that % sequence is left undecoded.
140  *
141  * dest may, but need not be, the same pointer as src.
142  *
143  * Returns the number of % sequences which could not be converted due to lack
144  * of two following hexadecimal digits.
145  */
146 static int
147 smbc_urldecode_talloc(TALLOC_CTX *ctx, char **pp_dest, const char *src)
148 {
149         int old_length = strlen(src);
150         int i = 0;
151         int err_count = 0;
152         size_t newlen = 1;
153         char *p, *dest;
154
155         if (old_length == 0) {
156                 return 0;
157         }
158
159         *pp_dest = NULL;
160         for (i = 0; i < old_length; ) {
161                 unsigned char character = src[i++];
162
163                 if (character == '%') {
164                         int a = i+1 < old_length ? hex2int(src[i]) : -1;
165                         int b = i+1 < old_length ? hex2int(src[i+1]) : -1;
166
167                         /* Replace valid sequence */
168                         if (a != -1 && b != -1) {
169                                 /* Replace valid %xx sequence with %dd */
170                                 character = (a * 16) + b;
171                                 if (character == '\0') {
172                                         break; /* Stop at %00 */
173                                 }
174                                 i += 2;
175                         } else {
176                                 err_count++;
177                         }
178                 }
179                 newlen++;
180         }
181
182         dest = TALLOC_ARRAY(ctx, char, newlen);
183         if (!dest) {
184                 return err_count;
185         }
186
187         err_count = 0;
188         for (p = dest, i = 0; i < old_length; ) {
189                 unsigned char character = src[i++];
190
191                 if (character == '%') {
192                         int a = i+1 < old_length ? hex2int(src[i]) : -1;
193                         int b = i+1 < old_length ? hex2int(src[i+1]) : -1;
194
195                         /* Replace valid sequence */
196                         if (a != -1 && b != -1) {
197                                 /* Replace valid %xx sequence with %dd */
198                                 character = (a * 16) + b;
199                                 if (character == '\0') {
200                                         break; /* Stop at %00 */
201                                 }
202                                 i += 2;
203                         } else {
204                                 err_count++;
205                         }
206                 }
207                 *p++ = character;
208         }
209
210         *p = '\0';
211         *pp_dest = dest;
212         return err_count;
213 }
214
215 int
216 smbc_urldecode(char *dest, char *src, size_t max_dest_len)
217 {
218         TALLOC_CTX *frame = talloc_stackframe();
219         char *pdest;
220         int ret = smbc_urldecode_talloc(frame, &pdest, src);
221
222         if (pdest) {
223                 strlcpy(dest, pdest, max_dest_len);
224         }
225         TALLOC_FREE(frame);
226         return ret;
227 }
228
229 /*
230  * smbc_urlencode()
231  *
232  * Convert any characters not specifically allowed in a URL into their %xx
233  * equivalent.
234  *
235  * Returns the remaining buffer length.
236  */
237 int
238 smbc_urlencode(char *dest, char *src, int max_dest_len)
239 {
240         char hex[] = "0123456789ABCDEF";
241
242         for (; *src != '\0' && max_dest_len >= 3; src++) {
243
244                 if ((*src < '0' &&
245                      *src != '-' &&
246                      *src != '.') ||
247                     (*src > '9' &&
248                      *src < 'A') ||
249                     (*src > 'Z' &&
250                      *src < 'a' &&
251                      *src != '_') ||
252                     (*src > 'z')) {
253                         *dest++ = '%';
254                         *dest++ = hex[(*src >> 4) & 0x0f];
255                         *dest++ = hex[*src & 0x0f];
256                         max_dest_len -= 3;
257                 } else {
258                         *dest++ = *src;
259                         max_dest_len--;
260                 }
261         }
262
263         *dest++ = '\0';
264         max_dest_len--;
265
266         return max_dest_len;
267 }
268
269 /*
270  * Function to parse a path and turn it into components
271  *
272  * The general format of an SMB URI is explain in Christopher Hertel's CIFS
273  * book, at http://ubiqx.org/cifs/Appendix-D.html.  We accept a subset of the
274  * general format ("smb:" only; we do not look for "cifs:").
275  *
276  *
277  * We accept:
278  *  smb://[[[domain;]user[:password]@]server[/share[/path[/file]]]][?options]
279  *
280  * Meaning of URLs:
281  *
282  * smb://           Show all workgroups.
283  *
284  *                  The method of locating the list of workgroups varies
285  *                  depending upon the setting of the context variable
286  *                  context->options.browse_max_lmb_count.  This value
287  *                  determine the maximum number of local master browsers to
288  *                  query for the list of workgroups.  In order to ensure that
289  *                  a complete list of workgroups is obtained, all master
290  *                  browsers must be queried, but if there are many
291  *                  workgroups, the time spent querying can begin to add up.
292  *                  For small networks (not many workgroups), it is suggested
293  *                  that this variable be set to 0, indicating query all local
294  *                  master browsers.  When the network has many workgroups, a
295  *                  reasonable setting for this variable might be around 3.
296  *
297  * smb://name/      if name<1D> or name<1B> exists, list servers in
298  *                  workgroup, else, if name<20> exists, list all shares
299  *                  for server ...
300  *
301  * If "options" are provided, this function returns the entire option list as a
302  * string, for later parsing by the caller.  Note that currently, no options
303  * are supported.
304  */
305
306 static const char *smbc_prefix = "smb:";
307
308 static int
309 smbc_parse_path(TALLOC_CTX *ctx,
310                 SMBCCTX *context,
311                 const char *fname,
312                 char **pp_workgroup,
313                 char **pp_server,
314                 char **pp_share,
315                 char **pp_path,
316                 char **pp_user,
317                 char **pp_password,
318                 char **pp_options)
319 {
320         char *s;
321         const char *p;
322         char *q, *r;
323         int len;
324
325         /* Ensure these returns are at least valid pointers. */
326         *pp_server = talloc_strdup(ctx, "");
327         *pp_share = talloc_strdup(ctx, "");
328         *pp_path = talloc_strdup(ctx, "");
329         *pp_user = talloc_strdup(ctx, "");
330         *pp_password = talloc_strdup(ctx, "");
331
332         if (!*pp_server || !*pp_share || !*pp_path ||
333                         !*pp_user || !*pp_password) {
334                 return -1;
335         }
336
337         /*
338          * Assume we wont find an authentication domain to parse, so default
339          * to the workgroup in the provided context.
340          */
341         if (pp_workgroup != NULL) {
342                 *pp_workgroup = talloc_strdup(ctx, context->workgroup);
343         }
344
345         if (pp_options) {
346                 *pp_options = talloc_strdup(ctx, "");
347         }
348         s = talloc_strdup(ctx, fname);
349
350         /* see if it has the right prefix */
351         len = strlen(smbc_prefix);
352         if (strncmp(s,smbc_prefix,len) || (s[len] != '/' && s[len] != 0)) {
353                 return -1; /* What about no smb: ? */
354         }
355
356         p = s + len;
357
358         /* Watch the test below, we are testing to see if we should exit */
359
360         if (strncmp(p, "//", 2) && strncmp(p, "\\\\", 2)) {
361                 DEBUG(1, ("Invalid path (does not begin with smb://"));
362                 return -1;
363         }
364
365         p += 2;  /* Skip the double slash */
366
367         /* See if any options were specified */
368         if ((q = strrchr(p, '?')) != NULL ) {
369                 /* There are options.  Null terminate here and point to them */
370                 *q++ = '\0';
371
372                 DEBUG(4, ("Found options '%s'", q));
373
374                 /* Copy the options */
375                 if (*pp_options != NULL) {
376                         TALLOC_FREE(*pp_options);
377                         *pp_options = talloc_strdup(ctx, q);
378                 }
379         }
380
381         if (*p == '\0') {
382                 goto decoding;
383         }
384
385         if (*p == '/') {
386                 int wl = strlen(context->workgroup);
387
388                 if (wl > 16) {
389                         wl = 16;
390                 }
391
392                 *pp_server = talloc_strdup(ctx, context->workgroup);
393                 if (!*pp_server) {
394                         return -1;
395                 }
396                 *pp_server[wl] = '\0';
397                 return 0;
398         }
399
400         /*
401          * ok, its for us. Now parse out the server, share etc.
402          *
403          * However, we want to parse out [[domain;]user[:password]@] if it
404          * exists ...
405          */
406
407         /* check that '@' occurs before '/', if '/' exists at all */
408         q = strchr_m(p, '@');
409         r = strchr_m(p, '/');
410         if (q && (!r || q < r)) {
411                 char *userinfo = NULL;
412                 const char *u;
413
414                 next_token_no_ltrim_talloc(ctx, &p, &userinfo, "@");
415                 if (!userinfo) {
416                         return -1;
417                 }
418                 u = userinfo;
419
420                 if (strchr_m(u, ';')) {
421                         char *workgroup;
422                         next_token_no_ltrim_talloc(ctx, &u, &workgroup, ";");
423                         if (!workgroup) {
424                                 return -1;
425                         }
426                         if (pp_workgroup) {
427                                 *pp_workgroup = workgroup;
428                         }
429                 }
430
431                 if (strchr_m(u, ':')) {
432                         next_token_no_ltrim_talloc(ctx, &u, pp_user, ":");
433                         if (!*pp_user) {
434                                 return -1;
435                         }
436                         *pp_password = talloc_strdup(ctx, u);
437                         if (!*pp_password) {
438                                 return -1;
439                         }
440                 } else {
441                         *pp_user = talloc_strdup(ctx, u);
442                         if (!*pp_user) {
443                                 return -1;
444                         }
445                 }
446         }
447
448         if (!next_token_talloc(ctx, &p, pp_server, "/")) {
449                 return -1;
450         }
451
452         if (*p == (char)0) {
453                 goto decoding;  /* That's it ... */
454         }
455
456         if (!next_token_talloc(ctx, &p, pp_share, "/")) {
457                 return -1;
458         }
459
460         /*
461          * Prepend a leading slash if there's a file path, as required by
462          * NetApp filers.
463          */
464         if (*p != '\0') {
465                 *pp_path = talloc_asprintf(ctx,
466                                         "\\%s",
467                                         p);
468         } else {
469                 *pp_path = talloc_strdup(ctx, "");
470         }
471         if (!*pp_path) {
472                 return -1;
473         }
474         string_replace(*pp_path, '/', '\\');
475
476  decoding:
477
478         (void) smbc_urldecode_talloc(ctx, pp_path, *pp_path);
479         (void) smbc_urldecode_talloc(ctx, pp_server, *pp_server);
480         (void) smbc_urldecode_talloc(ctx, pp_share, *pp_share);
481         (void) smbc_urldecode_talloc(ctx, pp_user, *pp_user);
482         (void) smbc_urldecode_talloc(ctx, pp_password, *pp_password);
483
484         return 0;
485 }
486
487 /*
488  * Verify that the options specified in a URL are valid
489  */
490 static int
491 smbc_check_options(char *server,
492                    char *share,
493                    char *path,
494                    char *options)
495 {
496         DEBUG(4, ("smbc_check_options(): server='%s' share='%s' "
497                   "path='%s' options='%s'\n",
498                   server, share, path, options));
499
500         /* No options at all is always ok */
501         if (! *options) return 0;
502
503         /* Currently, we don't support any options. */
504         return -1;
505 }
506
507 /*
508  * Convert an SMB error into a UNIX error ...
509  */
510 static int
511 smbc_errno(SMBCCTX *context,
512            struct cli_state *c)
513 {
514         int ret = cli_errno(c);
515         
516         if (cli_is_dos_error(c)) {
517                 uint8 eclass;
518                 uint32 ecode;
519
520                 cli_dos_error(c, &eclass, &ecode);
521                 
522                 DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n", 
523                          (int)eclass, (int)ecode, (int)ecode, ret));
524         } else {
525                 NTSTATUS status;
526
527                 status = cli_nt_error(c);
528
529                 DEBUG(3,("smbc errno %s -> %d\n",
530                          nt_errstr(status), ret));
531         }
532
533         return ret;
534 }
535
536 /* 
537  * Check a server for being alive and well.
538  * returns 0 if the server is in shape. Returns 1 on error 
539  * 
540  * Also useable outside libsmbclient to enable external cache
541  * to do some checks too.
542  */
543 static int
544 smbc_check_server(SMBCCTX * context,
545                   SMBCSRV * server) 
546 {
547         socklen_t size;
548         struct sockaddr addr;
549
550         size = sizeof(addr);
551         return (getpeername(server->cli->fd, &addr, &size) == -1);
552 }
553
554 /* 
555  * Remove a server from the cached server list it's unused.
556  * On success, 0 is returned. 1 is returned if the server could not be removed.
557  * 
558  * Also useable outside libsmbclient
559  */
560 int
561 smbc_remove_unused_server(SMBCCTX * context,
562                           SMBCSRV * srv)
563 {
564         SMBCFILE * file;
565
566         /* are we being fooled ? */
567         if (!context || !context->internal ||
568             !context->internal->_initialized || !srv) return 1;
569
570         
571         /* Check all open files/directories for a relation with this server */
572         for (file = context->internal->_files; file; file=file->next) {
573                 if (file->srv == srv) {
574                         /* Still used */
575                         DEBUG(3, ("smbc_remove_usused_server: "
576                                   "%p still used by %p.\n",
577                                   srv, file));
578                         return 1;
579                 }
580         }
581
582         DLIST_REMOVE(context->internal->_servers, srv);
583
584         cli_shutdown(srv->cli);
585         srv->cli = NULL;
586
587         DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
588
589         (context->callbacks.remove_cached_srv_fn)(context, srv);
590
591         SAFE_FREE(srv);
592         return 0;
593 }
594
595 /****************************************************************
596  * Call the auth_fn with fixed size (fstring) buffers.
597  ***************************************************************/
598
599 static void call_auth_fn(TALLOC_CTX *ctx,
600                         SMBCCTX *context,
601                         const char *server,
602                         const char *share,
603                         char **pp_workgroup,
604                         char **pp_username,
605                         char **pp_password)
606 {
607         fstring workgroup;
608         fstring username;
609         fstring password;
610
611         strlcpy(workgroup, *pp_workgroup, sizeof(workgroup));
612         strlcpy(username, *pp_username, sizeof(username));
613         strlcpy(password, *pp_password, sizeof(password));
614
615         if (context->internal->_auth_fn_with_context != NULL) {
616                         (context->internal->_auth_fn_with_context)(
617                                 context,
618                                 server, share,
619                                 workgroup, sizeof(workgroup),
620                                 username, sizeof(username),
621                                 password, sizeof(password));
622         } else {
623                 (context->callbacks.auth_fn)(
624                         server, share,
625                         workgroup, sizeof(workgroup),
626                         username, sizeof(username),
627                         password, sizeof(password));
628         }
629
630         TALLOC_FREE(*pp_workgroup);
631         TALLOC_FREE(*pp_username);
632         TALLOC_FREE(*pp_password);
633
634         *pp_workgroup = talloc_strdup(ctx, workgroup);
635         *pp_username = talloc_strdup(ctx, username);
636         *pp_password = talloc_strdup(ctx, password);
637 }
638
639 static SMBCSRV *
640 find_server(TALLOC_CTX *ctx,
641                 SMBCCTX *context,
642                 const char *server,
643                 const char *share,
644                 char **pp_workgroup,
645                 char **pp_username,
646                 char **pp_password)
647 {
648         SMBCSRV *srv;
649         int auth_called = 0;
650
651  check_server_cache:
652
653         srv = (context->callbacks.get_cached_srv_fn)(context, server, share,
654                                                 *pp_workgroup, *pp_username);
655
656         if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] ||
657                                 !*pp_password || !(*pp_password)[0])) {
658                 call_auth_fn(ctx, context, server, share,
659                                 pp_workgroup, pp_username, pp_password);
660
661                 if (!pp_workgroup || !pp_username || !pp_password) {
662                         return NULL;
663                 }
664
665                 /*
666                  * However, smbc_auth_fn may have picked up info relating to
667                  * an existing connection, so try for an existing connection
668                  * again ...
669                  */
670                 auth_called = 1;
671                 goto check_server_cache;
672
673         }
674
675         if (srv) {
676                 if ((context->callbacks.check_server_fn)(context, srv)) {
677                         /*
678                          * This server is no good anymore
679                          * Try to remove it and check for more possible
680                          * servers in the cache
681                          */
682                         if ((context->callbacks.remove_unused_server_fn)(context,
683                                                                          srv)) { 
684                                 /*
685                                  * We could not remove the server completely,
686                                  * remove it from the cache so we will not get
687                                  * it again. It will be removed when the last
688                                  * file/dir is closed.
689                                  */
690                                 (context->callbacks.remove_cached_srv_fn)(context,
691                                                                           srv);
692                         }
693
694                         /*
695                          * Maybe there are more cached connections to this
696                          * server
697                          */
698                         goto check_server_cache;
699                 }
700
701                 return srv;
702         }
703
704         return NULL;
705 }
706
707 /*
708  * Connect to a server, possibly on an existing connection
709  *
710  * Here, what we want to do is: If the server and username
711  * match an existing connection, reuse that, otherwise, establish a
712  * new connection.
713  *
714  * If we have to create a new connection, call the auth_fn to get the
715  * info we need, unless the username and password were passed in.
716  */
717
718 static SMBCSRV *
719 smbc_server(TALLOC_CTX *ctx,
720                 SMBCCTX *context,
721                 bool connect_if_not_found,
722                 const char *server,
723                 const char *share,
724                 char **pp_workgroup,
725                 char **pp_username,
726                 char **pp_password)
727 {
728         SMBCSRV *srv=NULL;
729         struct cli_state *c;
730         struct nmb_name called, calling;
731         const char *server_n = server;
732         struct sockaddr_storage ss;
733         int tried_reverse = 0;
734         int port_try_first;
735         int port_try_next;
736         const char *username_used;
737         NTSTATUS status;
738
739         zero_addr(&ss);
740         ZERO_STRUCT(c);
741
742         if (server[0] == 0) {
743                 errno = EPERM;
744                 return NULL;
745         }
746
747         /* Look for a cached connection */
748         srv = find_server(ctx, context, server, share,
749                           pp_workgroup, pp_username, pp_password);
750
751         /*
752          * If we found a connection and we're only allowed one share per
753          * server...
754          */
755         if (srv && *share != '\0' && context->options.one_share_per_server) {
756
757                 /*
758                  * ... then if there's no current connection to the share,
759                  * connect to it.  find_server(), or rather the function
760                  * pointed to by context->callbacks.get_cached_srv_fn which
761                  * was called by find_server(), will have issued a tree
762                  * disconnect if the requested share is not the same as the
763                  * one that was already connected.
764                  */
765                 if (srv->cli->cnum == (uint16) -1) {
766                         /* Ensure we have accurate auth info */
767                         call_auth_fn(ctx, context, server, share,
768                                 pp_workgroup, pp_username, pp_password);
769
770                         if (!*pp_workgroup || !*pp_username || !*pp_password) {
771                                 errno = ENOMEM;
772                                 cli_shutdown(srv->cli);
773                                 srv->cli = NULL;
774                                 (context->callbacks.remove_cached_srv_fn)(context,
775                                                                         srv);
776                                 return NULL;
777                         }
778
779                         /*
780                          * We don't need to renegotiate encryption
781                          * here as the encryption context is not per
782                          * tid.
783                          */
784
785                         if (!cli_send_tconX(srv->cli, share, "?????",
786                                                 *pp_password,
787                                                 strlen(*pp_password)+1)) {
788
789                                 errno = smbc_errno(context, srv->cli);
790                                 cli_shutdown(srv->cli);
791                                 srv->cli = NULL;
792                                 (context->callbacks.remove_cached_srv_fn)(context,
793                                                                           srv);
794                                 srv = NULL;
795                         }
796
797                         /*
798                          * Regenerate the dev value since it's based on both
799                          * server and share
800                          */
801                         if (srv) {
802                                 srv->dev = (dev_t)(str_checksum(server) ^
803                                                    str_checksum(share));
804                         }
805                 }
806         }
807
808         /* If we have a connection... */
809         if (srv) {
810
811                 /* ... then we're done here.  Give 'em what they came for. */
812                 return srv;
813         }
814
815         /* If we're not asked to connect when a connection doesn't exist... */
816         if (! connect_if_not_found) {
817                 /* ... then we're done here. */
818                 return NULL;
819         }
820
821         if (!*pp_workgroup || !*pp_username || !*pp_password) {
822                 errno = ENOMEM;
823                 return NULL;
824         }
825
826         make_nmb_name(&calling, context->netbios_name, 0x0);
827         make_nmb_name(&called , server, 0x20);
828
829         DEBUG(4,("smbc_server: server_n=[%s] server=[%s]\n", server_n, server));
830
831         DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
832
833  again:
834
835         zero_addr(&ss);
836
837         /* have to open a new connection */
838         if ((c = cli_initialise()) == NULL) {
839                 errno = ENOMEM;
840                 return NULL;
841         }
842
843         if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) {
844                 c->use_kerberos = True;
845         }
846         if (context->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) {
847                 c->fallback_after_kerberos = True;
848         }
849
850         c->timeout = context->timeout;
851
852         /*
853          * Force use of port 139 for first try if share is $IPC, empty, or
854          * null, so browse lists can work
855          */
856         if (share == NULL || *share == '\0' || strcmp(share, "IPC$") == 0) {
857                 port_try_first = 139;
858                 port_try_next = 445;
859         } else {
860                 port_try_first = 445;
861                 port_try_next = 139;
862         }
863
864         c->port = port_try_first;
865
866         status = cli_connect(c, server_n, &ss);
867         if (!NT_STATUS_IS_OK(status)) {
868
869                 /* First connection attempt failed.  Try alternate port. */
870                 c->port = port_try_next;
871
872                 status = cli_connect(c, server_n, &ss);
873                 if (!NT_STATUS_IS_OK(status)) {
874                         cli_shutdown(c);
875                         errno = ETIMEDOUT;
876                         return NULL;
877                 }
878         }
879
880         if (!cli_session_request(c, &calling, &called)) {
881                 cli_shutdown(c);
882                 if (strcmp(called.name, "*SMBSERVER")) {
883                         make_nmb_name(&called , "*SMBSERVER", 0x20);
884                         goto again;
885                 } else {  /* Try one more time, but ensure we don't loop */
886
887                         /* Only try this if server is an IP address ... */
888
889                         if (is_ipaddress(server) && !tried_reverse) {
890                                 fstring remote_name;
891                                 struct sockaddr_storage rem_ss;
892
893                                 if (!interpret_string_addr(&rem_ss, server,
894                                                         NI_NUMERICHOST)) {
895                                         DEBUG(4, ("Could not convert IP address "
896                                                 "%s to struct sockaddr_storage\n",
897                                                 server));
898                                         errno = ETIMEDOUT;
899                                         return NULL;
900                                 }
901
902                                 tried_reverse++; /* Yuck */
903
904                                 if (name_status_find("*", 0, 0, &rem_ss, remote_name)) {
905                                         make_nmb_name(&called, remote_name, 0x20);
906                                         goto again;
907                                 }
908                         }
909                 }
910                 errno = ETIMEDOUT;
911                 return NULL;
912         }
913
914         DEBUG(4,(" session request ok\n"));
915
916         if (!cli_negprot(c)) {
917                 cli_shutdown(c);
918                 errno = ETIMEDOUT;
919                 return NULL;
920         }
921
922         username_used = *pp_username;
923
924         if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
925                                                *pp_password, strlen(*pp_password),
926                                                *pp_password, strlen(*pp_password),
927                                                *pp_workgroup))) {
928
929                 /* Failed.  Try an anonymous login, if allowed by flags. */
930                 username_used = "";
931
932                 if ((context->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) ||
933                      !NT_STATUS_IS_OK(cli_session_setup(c, username_used,
934                                                         *pp_password, 1,
935                                                         *pp_password, 0,
936                                                         *pp_workgroup))) {
937
938                         cli_shutdown(c);
939                         errno = EPERM;
940                         return NULL;
941                 }
942         }
943
944         DEBUG(4,(" session setup ok\n"));
945
946         if (!cli_send_tconX(c, share, "?????",
947                             *pp_password, strlen(*pp_password)+1)) {
948                 errno = smbc_errno(context, c);
949                 cli_shutdown(c);
950                 return NULL;
951         }
952
953         DEBUG(4,(" tconx ok\n"));
954
955         if (context->internal->_smb_encryption_level) {
956                 /* Attempt UNIX smb encryption. */
957                 if (!NT_STATUS_IS_OK(cli_force_encryption(c,
958                                                 username_used,
959                                                 *pp_password,
960                                                 *pp_workgroup))) {
961
962                         /*
963                          * context->internal->_smb_encryption_level == 1
964                          * means don't fail if encryption can't be negotiated,
965                          * == 2 means fail if encryption can't be negotiated.
966                          */
967
968                         DEBUG(4,(" SMB encrypt failed\n"));
969
970                         if (context->internal->_smb_encryption_level == 2) {
971                                 cli_shutdown(c);
972                                 errno = EPERM;
973                                 return NULL;
974                         }
975                 }
976                 DEBUG(4,(" SMB encrypt ok\n"));
977         }
978
979         /*
980          * Ok, we have got a nice connection
981          * Let's allocate a server structure.
982          */
983
984         srv = SMB_MALLOC_P(SMBCSRV);
985         if (!srv) {
986                 errno = ENOMEM;
987                 goto failed;
988         }
989
990         ZERO_STRUCTP(srv);
991         srv->cli = c;
992         srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
993         srv->no_pathinfo = False;
994         srv->no_pathinfo2 = False;
995         srv->no_nt_session = False;
996
997         /* now add it to the cache (internal or external)  */
998         /* Let the cache function set errno if it wants to */
999         errno = 0;
1000         if ((context->callbacks.add_cached_srv_fn)(context, srv,
1001                                                 server, share,
1002                                                 *pp_workgroup,
1003                                                 *pp_username)) {
1004                 int saved_errno = errno;
1005                 DEBUG(3, (" Failed to add server to cache\n"));
1006                 errno = saved_errno;
1007                 if (errno == 0) {
1008                         errno = ENOMEM;
1009                 }
1010                 goto failed;
1011         }
1012
1013         DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
1014                   server, share, srv));
1015
1016         DLIST_ADD(context->internal->_servers, srv);
1017         return srv;
1018
1019  failed:
1020         cli_shutdown(c);
1021         if (!srv) {
1022                 return NULL;
1023         }
1024
1025         SAFE_FREE(srv);
1026         return NULL;
1027 }
1028
1029 /*
1030  * Connect to a server for getting/setting attributes, possibly on an existing
1031  * connection.  This works similarly to smbc_server().
1032  */
1033 static SMBCSRV *
1034 smbc_attr_server(TALLOC_CTX *ctx,
1035                 SMBCCTX *context,
1036                 const char *server,
1037                 const char *share,
1038                 char **pp_workgroup,
1039                 char **pp_username,
1040                 char **pp_password)
1041 {
1042         int flags;
1043         struct sockaddr_storage ss;
1044         struct cli_state *ipc_cli;
1045         struct rpc_pipe_client *pipe_hnd;
1046         NTSTATUS nt_status;
1047         SMBCSRV *ipc_srv=NULL;
1048
1049         /*
1050          * See if we've already created this special connection.  Reference
1051          * our "special" share name '*IPC$', which is an impossible real share
1052          * name due to the leading asterisk.
1053          */
1054         ipc_srv = find_server(ctx, context, server, "*IPC$",
1055                               pp_workgroup, pp_username, pp_password);
1056         if (!ipc_srv) {
1057
1058                 /* We didn't find a cached connection.  Get the password */
1059                 if (!*pp_password || (*pp_password)[0] == '\0') {
1060                         /* ... then retrieve it now. */
1061                         call_auth_fn(ctx, context, server, share,
1062                                 pp_workgroup, pp_username, pp_password);
1063                         if (!*pp_workgroup || !*pp_username || !*pp_password) {
1064                                 errno = ENOMEM;
1065                                 return NULL;
1066                         }
1067                 }
1068
1069                 flags = 0;
1070                 if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) {
1071                         flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
1072                 }
1073
1074                 zero_addr(&ss);
1075                 nt_status = cli_full_connection(&ipc_cli,
1076                                                 global_myname(), server,
1077                                                 &ss, 0, "IPC$", "?????",
1078                                                 *pp_username,
1079                                                 *pp_workgroup,
1080                                                 *pp_password,
1081                                                 flags,
1082                                                 Undefined, NULL);
1083                 if (! NT_STATUS_IS_OK(nt_status)) {
1084                         DEBUG(1,("cli_full_connection failed! (%s)\n",
1085                                  nt_errstr(nt_status)));
1086                         errno = ENOTSUP;
1087                         return NULL;
1088                 }
1089
1090                 if (context->internal->_smb_encryption_level) {
1091                         /* Attempt UNIX smb encryption. */
1092                         if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
1093                                                 *pp_username,
1094                                                 *pp_password,
1095                                                 *pp_workgroup))) {
1096
1097                                 /*
1098                                  * context->internal->_smb_encryption_level == 1
1099                                  * means don't fail if encryption can't be negotiated,
1100                                  * == 2 means fail if encryption can't be negotiated.
1101                                  */
1102
1103                                 DEBUG(4,(" SMB encrypt failed on IPC$\n"));
1104
1105                                 if (context->internal->_smb_encryption_level == 2) {
1106                                         cli_shutdown(ipc_cli);
1107                                         errno = EPERM;
1108                                         return NULL;
1109                                 }
1110                         }
1111                         DEBUG(4,(" SMB encrypt ok on IPC$\n"));
1112                 }
1113
1114                 ipc_srv = SMB_MALLOC_P(SMBCSRV);
1115                 if (!ipc_srv) {
1116                         errno = ENOMEM;
1117                         cli_shutdown(ipc_cli);
1118                         return NULL;
1119                 }
1120
1121                 ZERO_STRUCTP(ipc_srv);
1122                 ipc_srv->cli = ipc_cli;
1123
1124                 pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
1125                                                     PI_LSARPC,
1126                                                     &nt_status);
1127                 if (!pipe_hnd) {
1128                     DEBUG(1, ("cli_nt_session_open fail!\n"));
1129                     errno = ENOTSUP;
1130                     cli_shutdown(ipc_srv->cli);
1131                     free(ipc_srv);
1132                     return NULL;
1133                 }
1134
1135                 /*
1136                  * Some systems don't support
1137                  * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000
1138                  * so we might as well do it too.
1139                  */
1140
1141                 nt_status = rpccli_lsa_open_policy(
1142                     pipe_hnd,
1143                     talloc_tos(),
1144                     True,
1145                     GENERIC_EXECUTE_ACCESS,
1146                     &ipc_srv->pol);
1147
1148                 if (!NT_STATUS_IS_OK(nt_status)) {
1149                     errno = smbc_errno(context, ipc_srv->cli);
1150                     cli_shutdown(ipc_srv->cli);
1151                     return NULL;
1152                 }
1153
1154                 /* now add it to the cache (internal or external) */
1155
1156                 errno = 0;      /* let cache function set errno if it likes */
1157                 if ((context->callbacks.add_cached_srv_fn)(context, ipc_srv,
1158                                                         server,
1159                                                         "*IPC$",
1160                                                         *pp_workgroup,
1161                                                         *pp_username)) {
1162                         DEBUG(3, (" Failed to add server to cache\n"));
1163                         if (errno == 0) {
1164                                 errno = ENOMEM;
1165                         }
1166                         cli_shutdown(ipc_srv->cli);
1167                         free(ipc_srv);
1168                         return NULL;
1169                 }
1170
1171                 DLIST_ADD(context->internal->_servers, ipc_srv);
1172         }
1173
1174         return ipc_srv;
1175 }
1176
1177 /*
1178  * Routine to open() a file ...
1179  */
1180
1181 static SMBCFILE *
1182 smbc_open_ctx(SMBCCTX *context,
1183               const char *fname,
1184               int flags,
1185               mode_t mode)
1186 {
1187         char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL;
1188         char *path = NULL;
1189         char *targetpath = NULL;
1190         struct cli_state *targetcli = NULL;
1191         SMBCSRV *srv   = NULL;
1192         SMBCFILE *file = NULL;
1193         int fd;
1194         TALLOC_CTX *frame = talloc_stackframe();
1195
1196         if (!context || !context->internal ||
1197             !context->internal->_initialized) {
1198
1199                 errno = EINVAL;  /* Best I can think of ... */
1200                 TALLOC_FREE(frame);
1201                 return NULL;
1202
1203         }
1204
1205         if (!fname) {
1206
1207                 errno = EINVAL;
1208                 TALLOC_FREE(frame);
1209                 return NULL;
1210
1211         }
1212
1213         if (smbc_parse_path(frame,
1214                                 context,
1215                                 fname,
1216                                 &workgroup,
1217                                 &server,
1218                                 &share,
1219                                 &path,
1220                                 &user,
1221                                 &password,
1222                                 NULL)) {
1223                 errno = EINVAL;
1224                 TALLOC_FREE(frame);
1225                 return NULL;
1226         }
1227
1228         if (!user || user[0] == (char)0) {
1229                 user = talloc_strdup(frame, context->user);
1230                 if (!user) {
1231                         errno = ENOMEM;
1232                         TALLOC_FREE(frame);
1233                         return NULL;
1234                 }
1235         }
1236
1237         srv = smbc_server(frame, context, True,
1238                           server, share, &workgroup, &user, &password);
1239
1240         if (!srv) {
1241                 if (errno == EPERM) errno = EACCES;
1242                 TALLOC_FREE(frame);
1243                 return NULL;  /* smbc_server sets errno */
1244         }
1245
1246         /* Hmmm, the test for a directory is suspect here ... FIXME */
1247
1248         if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') {
1249                 fd = -1;
1250         } else {
1251                 file = SMB_MALLOC_P(SMBCFILE);
1252
1253                 if (!file) {
1254                         errno = ENOMEM;
1255                         TALLOC_FREE(frame);
1256                         return NULL;
1257                 }
1258
1259                 ZERO_STRUCTP(file);
1260
1261                 /*d_printf(">>>open: resolving %s\n", path);*/
1262                 if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) {
1263                         d_printf("Could not resolve %s\n", path);
1264                         SAFE_FREE(file);
1265                         TALLOC_FREE(frame);
1266                         return NULL;
1267                 }
1268                 /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
1269
1270                 if ((fd = cli_open(targetcli, targetpath, flags,
1271                                    context->internal->_share_mode)) < 0) {
1272
1273                         /* Handle the error ... */
1274
1275                         SAFE_FREE(file);
1276                         errno = smbc_errno(context, targetcli);
1277                         TALLOC_FREE(frame);
1278                         return NULL;
1279
1280                 }
1281
1282                 /* Fill in file struct */
1283
1284                 file->cli_fd  = fd;
1285                 file->fname   = SMB_STRDUP(fname);
1286                 file->srv     = srv;
1287                 file->offset  = 0;
1288                 file->file    = True;
1289
1290                 DLIST_ADD(context->internal->_files, file);
1291
1292                 /*
1293                  * If the file was opened in O_APPEND mode, all write
1294                  * operations should be appended to the file.  To do that,
1295                  * though, using this protocol, would require a getattrE()
1296                  * call for each and every write, to determine where the end
1297                  * of the file is. (There does not appear to be an append flag
1298                  * in the protocol.)  Rather than add all of that overhead of
1299                  * retrieving the current end-of-file offset prior to each
1300                  * write operation, we'll assume that most append operations
1301                  * will continuously write, so we'll just set the offset to
1302                  * the end of the file now and hope that's adequate.
1303                  *
1304                  * Note to self: If this proves inadequate, and O_APPEND
1305                  * should, in some cases, be forced for each write, add a
1306                  * field in the context options structure, for
1307                  * "strict_append_mode" which would select between the current
1308                  * behavior (if FALSE) or issuing a getattrE() prior to each
1309                  * write and forcing the write to the end of the file (if
1310                  * TRUE).  Adding that capability will likely require adding
1311                  * an "append" flag into the _SMBCFILE structure to track
1312                  * whether a file was opened in O_APPEND mode.  -- djl
1313                  */
1314                 if (flags & O_APPEND) {
1315                         if (smbc_lseek_ctx(context, file, 0, SEEK_END) < 0) {
1316                                 (void) smbc_close_ctx(context, file);
1317                                 errno = ENXIO;
1318                                 TALLOC_FREE(frame);
1319                                 return NULL;
1320                         }
1321                 }
1322
1323                 TALLOC_FREE(frame);
1324                 return file;
1325
1326         }
1327
1328         /* Check if opendir needed ... */
1329
1330         if (fd == -1) {
1331                 int eno = 0;
1332
1333                 eno = smbc_errno(context, srv->cli);
1334                 file = (context->opendir)(context, fname);
1335                 if (!file) errno = eno;
1336                 TALLOC_FREE(frame);
1337                 return file;
1338
1339         }
1340
1341         errno = EINVAL; /* FIXME, correct errno ? */
1342         TALLOC_FREE(frame);
1343         return NULL;
1344
1345 }
1346
1347 /*
1348  * Routine to create a file 
1349  */
1350
1351 static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC; /* FIXME: Do we need this */
1352
1353 static SMBCFILE *
1354 smbc_creat_ctx(SMBCCTX *context,
1355                const char *path,
1356                mode_t mode)
1357 {
1358
1359         if (!context || !context->internal ||
1360             !context->internal->_initialized) {
1361
1362                 errno = EINVAL;
1363                 return NULL;
1364
1365         }
1366
1367         return smbc_open_ctx(context, path, creat_bits, mode);
1368 }
1369
1370 /*
1371  * Routine to read() a file ...
1372  */
1373
1374 static ssize_t
1375 smbc_read_ctx(SMBCCTX *context,
1376               SMBCFILE *file,
1377               void *buf,
1378               size_t count)
1379 {
1380         int ret;
1381         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
1382         char *path = NULL;
1383         char *targetpath = NULL;
1384         struct cli_state *targetcli = NULL;
1385         TALLOC_CTX *frame = talloc_stackframe();
1386
1387         /*
1388          * offset:
1389          *
1390          * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) --
1391          * appears to pass file->offset (which is type off_t) differently than
1392          * a local variable of type off_t.  Using local variable "offset" in
1393          * the call to cli_read() instead of file->offset fixes a problem
1394          * retrieving data at an offset greater than 4GB.
1395          */
1396         off_t offset;
1397
1398         if (!context || !context->internal ||
1399             !context->internal->_initialized) {
1400                 errno = EINVAL;
1401                 TALLOC_FREE(frame);
1402                 return -1;
1403
1404         }
1405
1406         DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count));
1407
1408         if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
1409                 errno = EBADF;
1410                 TALLOC_FREE(frame);
1411                 return -1;
1412
1413         }
1414
1415         offset = file->offset;
1416
1417         /* Check that the buffer exists ... */
1418
1419         if (buf == NULL) {
1420                 errno = EINVAL;
1421                 TALLOC_FREE(frame);
1422                 return -1;
1423
1424         }
1425
1426         /*d_printf(">>>read: parsing %s\n", file->fname);*/
1427         if (smbc_parse_path(frame,
1428                                 context,
1429                                 file->fname,
1430                                 NULL,
1431                                 &server,
1432                                 &share,
1433                                 &path,
1434                                 &user,
1435                                 &password,
1436                                 NULL)) {
1437                 errno = EINVAL;
1438                 TALLOC_FREE(frame);
1439                 return -1;
1440         }
1441
1442         /*d_printf(">>>read: resolving %s\n", path);*/
1443         if (!cli_resolve_path(frame, "", file->srv->cli, path,
1444                               &targetcli, &targetpath)) {
1445                 d_printf("Could not resolve %s\n", path);
1446                 TALLOC_FREE(frame);
1447                 return -1;
1448         }
1449         /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
1450
1451         ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count);
1452
1453         if (ret < 0) {
1454
1455                 errno = smbc_errno(context, targetcli);
1456                 TALLOC_FREE(frame);
1457                 return -1;
1458
1459         }
1460
1461         file->offset += ret;
1462
1463         DEBUG(4, ("  --> %d\n", ret));
1464
1465         TALLOC_FREE(frame);
1466         return ret;  /* Success, ret bytes of data ... */
1467
1468 }
1469
1470 /*
1471  * Routine to write() a file ...
1472  */
1473
1474 static ssize_t
1475 smbc_write_ctx(SMBCCTX *context,
1476                SMBCFILE *file,
1477                void *buf,
1478                size_t count)
1479 {
1480         int ret;
1481         off_t offset;
1482         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
1483         char *path = NULL;
1484         char *targetpath = NULL;
1485         struct cli_state *targetcli = NULL;
1486         TALLOC_CTX *frame = talloc_stackframe();
1487
1488         /* First check all pointers before dereferencing them */
1489
1490         if (!context || !context->internal ||
1491             !context->internal->_initialized) {
1492                 errno = EINVAL;
1493                 TALLOC_FREE(frame);
1494                 return -1;
1495
1496         }
1497
1498         if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
1499                 errno = EBADF;
1500                 TALLOC_FREE(frame);
1501                 return -1;
1502         }
1503
1504         /* Check that the buffer exists ... */
1505
1506         if (buf == NULL) {
1507                 errno = EINVAL;
1508                 TALLOC_FREE(frame);
1509                 return -1;
1510
1511         }
1512
1513         offset = file->offset; /* See "offset" comment in smbc_read_ctx() */
1514
1515         /*d_printf(">>>write: parsing %s\n", file->fname);*/
1516         if (smbc_parse_path(frame,
1517                                 context,
1518                                 file->fname,
1519                                 NULL,
1520                                 &server,
1521                                 &share,
1522                                 &path,
1523                                 &user,
1524                                 &password,
1525                                 NULL)) {
1526                 errno = EINVAL;
1527                 TALLOC_FREE(frame);
1528                 return -1;
1529         }
1530
1531         /*d_printf(">>>write: resolving %s\n", path);*/
1532         if (!cli_resolve_path(frame, "", file->srv->cli, path,
1533                               &targetcli, &targetpath)) {
1534                 d_printf("Could not resolve %s\n", path);
1535                 TALLOC_FREE(frame);
1536                 return -1;
1537         }
1538         /*d_printf(">>>write: resolved path as %s\n", targetpath);*/
1539
1540         ret = cli_write(targetcli, file->cli_fd, 0, (char *)buf, offset, count);
1541
1542         if (ret <= 0) {
1543                 errno = smbc_errno(context, targetcli);
1544                 TALLOC_FREE(frame);
1545                 return -1;
1546
1547         }
1548
1549         file->offset += ret;
1550
1551         TALLOC_FREE(frame);
1552         return ret;  /* Success, 0 bytes of data ... */
1553 }
1554
1555 /*
1556  * Routine to close() a file ...
1557  */
1558
1559 static int
1560 smbc_close_ctx(SMBCCTX *context,
1561                SMBCFILE *file)
1562 {
1563         SMBCSRV *srv;
1564         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
1565         char *path = NULL;
1566         char *targetpath = NULL;
1567         struct cli_state *targetcli = NULL;
1568         TALLOC_CTX *frame = talloc_stackframe();
1569
1570         if (!context || !context->internal ||
1571             !context->internal->_initialized) {
1572
1573                 errno = EINVAL;
1574                 TALLOC_FREE(frame);
1575                 return -1;
1576         }
1577
1578         if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
1579                 errno = EBADF;
1580                 TALLOC_FREE(frame);
1581                 return -1;
1582         }
1583
1584         /* IS a dir ... */
1585         if (!file->file) {
1586                 TALLOC_FREE(frame);
1587                 return (context->closedir)(context, file);
1588         }
1589
1590         /*d_printf(">>>close: parsing %s\n", file->fname);*/
1591         if (smbc_parse_path(frame,
1592                                 context,
1593                                 file->fname,
1594                                 NULL,
1595                                 &server,
1596                                 &share,
1597                                 &path,
1598                                 &user,
1599                                 &password,
1600                                 NULL)) {
1601                 errno = EINVAL;
1602                 TALLOC_FREE(frame);
1603                 return -1;
1604         }
1605
1606         /*d_printf(">>>close: resolving %s\n", path);*/
1607         if (!cli_resolve_path(frame, "", file->srv->cli, path,
1608                               &targetcli, &targetpath)) {
1609                 d_printf("Could not resolve %s\n", path);
1610                 TALLOC_FREE(frame);
1611                 return -1;
1612         }
1613         /*d_printf(">>>close: resolved path as %s\n", targetpath);*/
1614
1615         if (!cli_close(targetcli, file->cli_fd)) {
1616
1617                 DEBUG(3, ("cli_close failed on %s. purging server.\n", 
1618                           file->fname));
1619                 /* Deallocate slot and remove the server 
1620                  * from the server cache if unused */
1621                 errno = smbc_errno(context, targetcli);
1622                 srv = file->srv;
1623                 DLIST_REMOVE(context->internal->_files, file);
1624                 SAFE_FREE(file->fname);
1625                 SAFE_FREE(file);
1626                 (context->callbacks.remove_unused_server_fn)(context, srv);
1627                 TALLOC_FREE(frame);
1628                 return -1;
1629
1630         }
1631
1632         DLIST_REMOVE(context->internal->_files, file);
1633         SAFE_FREE(file->fname);
1634         SAFE_FREE(file);
1635         TALLOC_FREE(frame);
1636
1637         return 0;
1638 }
1639
1640 /*
1641  * Get info from an SMB server on a file. Use a qpathinfo call first
1642  * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo
1643  */
1644 static bool
1645 smbc_getatr(SMBCCTX * context,
1646             SMBCSRV *srv,
1647             char *path,
1648             uint16 *mode,
1649             SMB_OFF_T *size,
1650             struct timespec *create_time_ts,
1651             struct timespec *access_time_ts,
1652             struct timespec *write_time_ts,
1653             struct timespec *change_time_ts,
1654             SMB_INO_T *ino)
1655 {
1656         char *fixedpath = NULL;
1657         char *targetpath = NULL;
1658         struct cli_state *targetcli = NULL;
1659         time_t write_time;
1660         TALLOC_CTX *frame = talloc_stackframe();
1661
1662         if (!context || !context->internal ||
1663             !context->internal->_initialized) {
1664                 errno = EINVAL;
1665                 TALLOC_FREE(frame);
1666                 return -1;
1667         }
1668
1669         /* path fixup for . and .. */
1670         if (strequal(path, ".") || strequal(path, "..")) {
1671                 fixedpath = talloc_strdup(frame, "\\");
1672                 if (!fixedpath) {
1673                         errno = ENOMEM;
1674                         TALLOC_FREE(frame);
1675                         return -1;
1676                 }
1677         } else {
1678                 fixedpath = talloc_strdup(frame, path);
1679                 if (!fixedpath) {
1680                         errno = ENOMEM;
1681                         TALLOC_FREE(frame);
1682                         return -1;
1683                 }
1684                 trim_string(fixedpath, NULL, "\\..");
1685                 trim_string(fixedpath, NULL, "\\.");
1686         }
1687         DEBUG(4,("smbc_getatr: sending qpathinfo\n"));
1688
1689         if (!cli_resolve_path(frame, "", srv->cli, fixedpath,
1690                                 &targetcli, &targetpath)) {
1691                 d_printf("Couldn't resolve %s\n", path);
1692                 TALLOC_FREE(frame);
1693                 return False;
1694         }
1695
1696         if (!srv->no_pathinfo2 &&
1697             cli_qpathinfo2(targetcli, targetpath,
1698                            create_time_ts,
1699                            access_time_ts,
1700                            write_time_ts,
1701                            change_time_ts,
1702                            size, mode, ino)) {
1703                 TALLOC_FREE(frame);
1704                 return True;
1705         }
1706
1707         /* if this is NT then don't bother with the getatr */
1708         if (targetcli->capabilities & CAP_NT_SMBS) {
1709                 errno = EPERM;
1710                 TALLOC_FREE(frame);
1711                 return False;
1712         }
1713
1714         if (cli_getatr(targetcli, targetpath, mode, size, &write_time)) {
1715
1716                 struct timespec w_time_ts;
1717
1718                 w_time_ts = convert_time_t_to_timespec(write_time);
1719
1720                 if (write_time_ts != NULL) {
1721                         *write_time_ts = w_time_ts;
1722                 }
1723
1724                 if (create_time_ts != NULL) {
1725                         *create_time_ts = w_time_ts;
1726                 }
1727
1728                 if (access_time_ts != NULL) {
1729                         *access_time_ts = w_time_ts;
1730                 }
1731
1732                 if (change_time_ts != NULL) {
1733                         *change_time_ts = w_time_ts;
1734                 }
1735
1736                 srv->no_pathinfo2 = True;
1737                 TALLOC_FREE(frame);
1738                 return True;
1739         }
1740
1741         errno = EPERM;
1742         TALLOC_FREE(frame);
1743         return False;
1744
1745 }
1746
1747 /*
1748  * Set file info on an SMB server.  Use setpathinfo call first.  If that
1749  * fails, use setattrE..
1750  *
1751  * Access and modification time parameters are always used and must be
1752  * provided.  Create time, if zero, will be determined from the actual create
1753  * time of the file.  If non-zero, the create time will be set as well.
1754  *
1755  * "mode" (attributes) parameter may be set to -1 if it is not to be set.
1756  */
1757 static bool
1758 smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, 
1759             time_t create_time,
1760             time_t access_time,
1761             time_t write_time,
1762             time_t change_time,
1763             uint16 mode)
1764 {
1765         int fd;
1766         int ret;
1767         TALLOC_CTX *frame = talloc_stackframe();
1768
1769         /*
1770          * First, try setpathinfo (if qpathinfo succeeded), for it is the
1771          * modern function for "new code" to be using, and it works given a
1772          * filename rather than requiring that the file be opened to have its
1773          * attributes manipulated.
1774          */
1775         if (srv->no_pathinfo ||
1776             ! cli_setpathinfo(srv->cli, path,
1777                               create_time,
1778                               access_time,
1779                               write_time,
1780                               change_time,
1781                               mode)) {
1782
1783                 /*
1784                  * setpathinfo is not supported; go to plan B. 
1785                  *
1786                  * cli_setatr() does not work on win98, and it also doesn't
1787                  * support setting the access time (only the modification
1788                  * time), so in all cases, we open the specified file and use
1789                  * cli_setattrE() which should work on all OS versions, and
1790                  * supports both times.
1791                  */
1792
1793                 /* Don't try {q,set}pathinfo() again, with this server */
1794                 srv->no_pathinfo = True;
1795
1796                 /* Open the file */
1797                 if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
1798
1799                         errno = smbc_errno(context, srv->cli);
1800                         TALLOC_FREE(frame);
1801                         return -1;
1802                 }
1803
1804                 /* Set the new attributes */
1805                 ret = cli_setattrE(srv->cli, fd,
1806                                    change_time,
1807                                    access_time,
1808                                    write_time);
1809
1810                 /* Close the file */
1811                 cli_close(srv->cli, fd);
1812
1813                 /*
1814                  * Unfortunately, setattrE() doesn't have a provision for
1815                  * setting the access mode (attributes).  We'll have to try
1816                  * cli_setatr() for that, and with only this parameter, it
1817                  * seems to work on win98.
1818                  */
1819                 if (ret && mode != (uint16) -1) {
1820                         ret = cli_setatr(srv->cli, path, mode, 0);
1821                 }
1822
1823                 if (! ret) {
1824                         errno = smbc_errno(context, srv->cli);
1825                         TALLOC_FREE(frame);
1826                         return False;
1827                 }
1828         }
1829
1830         TALLOC_FREE(frame);
1831         return True;
1832 }
1833
1834  /*
1835   * Routine to unlink() a file
1836   */
1837
1838 static int
1839 smbc_unlink_ctx(SMBCCTX *context,
1840                 const char *fname)
1841 {
1842         char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL;
1843         char *path = NULL;
1844         char *targetpath = NULL;
1845         struct cli_state *targetcli = NULL;
1846         SMBCSRV *srv = NULL;
1847         TALLOC_CTX *frame = talloc_stackframe();
1848
1849         if (!context || !context->internal ||
1850             !context->internal->_initialized) {
1851                 errno = EINVAL;  /* Best I can think of ... */
1852                 TALLOC_FREE(frame);
1853                 return -1;
1854
1855         }
1856
1857         if (!fname) {
1858                 errno = EINVAL;
1859                 TALLOC_FREE(frame);
1860                 return -1;
1861
1862         }
1863
1864         if (smbc_parse_path(frame,
1865                                 context,
1866                                 fname,
1867                                 &workgroup,
1868                                 &server,
1869                                 &share,
1870                                 &path,
1871                                 &user,
1872                                 &password,
1873                                 NULL)) {
1874                 errno = EINVAL;
1875                 TALLOC_FREE(frame);
1876                 return -1;
1877         }
1878
1879         if (!user || user[0] == (char)0) {
1880                 user = talloc_strdup(frame, context->user);
1881                 if (!user) {
1882                         errno = ENOMEM;
1883                         TALLOC_FREE(frame);
1884                         return -1;
1885                 }
1886         }
1887
1888         srv = smbc_server(frame, context, True,
1889                           server, share, &workgroup, &user, &password);
1890
1891         if (!srv) {
1892                 TALLOC_FREE(frame);
1893                 return -1;  /* smbc_server sets errno */
1894
1895         }
1896
1897         /*d_printf(">>>unlink: resolving %s\n", path);*/
1898         if (!cli_resolve_path(frame, "", srv->cli, path,
1899                                 &targetcli, &targetpath)) {
1900                 d_printf("Could not resolve %s\n", path);
1901                 TALLOC_FREE(frame);
1902                 return -1;
1903         }
1904         /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/
1905
1906         if (!cli_unlink(targetcli, targetpath)) {
1907
1908                 errno = smbc_errno(context, targetcli);
1909
1910                 if (errno == EACCES) { /* Check if the file is a directory */
1911
1912                         int saverr = errno;
1913                         SMB_OFF_T size = 0;
1914                         uint16 mode = 0;
1915                         struct timespec write_time_ts;
1916                         struct timespec access_time_ts;
1917                         struct timespec change_time_ts;
1918                         SMB_INO_T ino = 0;
1919
1920                         if (!smbc_getatr(context, srv, path, &mode, &size,
1921                                          NULL,
1922                                          &access_time_ts,
1923                                          &write_time_ts,
1924                                          &change_time_ts,
1925                                          &ino)) {
1926
1927                                 /* Hmmm, bad error ... What? */
1928
1929                                 errno = smbc_errno(context, targetcli);
1930                                 TALLOC_FREE(frame);
1931                                 return -1;
1932
1933                         }
1934                         else {
1935
1936                                 if (IS_DOS_DIR(mode))
1937                                         errno = EISDIR;
1938                                 else
1939                                         errno = saverr;  /* Restore this */
1940
1941                         }
1942                 }
1943
1944                 TALLOC_FREE(frame);
1945                 return -1;
1946
1947         }
1948
1949         TALLOC_FREE(frame);
1950         return 0;  /* Success ... */
1951
1952 }
1953
1954 /*
1955  * Routine to rename() a file
1956  */
1957
1958 static int
1959 smbc_rename_ctx(SMBCCTX *ocontext,
1960                 const char *oname, 
1961                 SMBCCTX *ncontext,
1962                 const char *nname)
1963 {
1964         char *server1 = NULL;
1965         char *share1 = NULL;
1966         char *server2 = NULL;
1967         char *share2 = NULL;
1968         char *user1 = NULL;
1969         char *user2 = NULL;
1970         char *password1 = NULL;
1971         char *password2 = NULL;
1972         char *workgroup = NULL;
1973         char *path1 = NULL;
1974         char *path2 = NULL;
1975         char *targetpath1 = NULL;
1976         char *targetpath2 = NULL;
1977         struct cli_state *targetcli1 = NULL;
1978         struct cli_state *targetcli2 = NULL;
1979         SMBCSRV *srv = NULL;
1980         TALLOC_CTX *frame = talloc_stackframe();
1981
1982         if (!ocontext || !ncontext ||
1983             !ocontext->internal || !ncontext->internal ||
1984             !ocontext->internal->_initialized ||
1985             !ncontext->internal->_initialized) {
1986                 errno = EINVAL;  /* Best I can think of ... */
1987                 TALLOC_FREE(frame);
1988                 return -1;
1989         }
1990
1991         if (!oname || !nname) {
1992                 errno = EINVAL;
1993                 TALLOC_FREE(frame);
1994                 return -1;
1995         }
1996
1997         DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname));
1998
1999         if (smbc_parse_path(frame,
2000                         ocontext,
2001                         oname,
2002                         &workgroup,
2003                         &server1,
2004                         &share1,
2005                         &path1,
2006                         &user1,
2007                         &password1,
2008                         NULL)) {
2009                 errno = EINVAL;
2010                 TALLOC_FREE(frame);
2011                 return -1;
2012         }
2013
2014         if (!user1 || user1[0] == (char)0) {
2015                 user1 = talloc_strdup(frame, ocontext->user);
2016                 if (!user1) {
2017                         errno = ENOMEM;
2018                         TALLOC_FREE(frame);
2019                         return -1;
2020                 }
2021         }
2022
2023         if (smbc_parse_path(frame,
2024                                 ncontext,
2025                                 nname,
2026                                 NULL,
2027                                 &server2,
2028                                 &share2,
2029                                 &path2,
2030                                 &user2,
2031                                 &password2,
2032                                 NULL)) {
2033                 errno = EINVAL;
2034                 TALLOC_FREE(frame);
2035                 return -1;
2036         }
2037
2038         if (!user2 || user2[0] == (char)0) {
2039                 user2 = talloc_strdup(frame, ncontext->user);
2040                 if (!user2) {
2041                         errno = ENOMEM;
2042                         TALLOC_FREE(frame);
2043                         return -1;
2044                 }
2045         }
2046
2047         if (strcmp(server1, server2) || strcmp(share1, share2) ||
2048             strcmp(user1, user2)) {
2049                 /* Can't rename across file systems, or users?? */
2050                 errno = EXDEV;
2051                 TALLOC_FREE(frame);
2052                 return -1;
2053         }
2054
2055         srv = smbc_server(frame, ocontext, True,
2056                           server1, share1, &workgroup, &user1, &password1);
2057         if (!srv) {
2058                 TALLOC_FREE(frame);
2059                 return -1;
2060
2061         }
2062
2063         /*d_printf(">>>rename: resolving %s\n", path1);*/
2064         if (!cli_resolve_path(frame, "", srv->cli, path1,
2065                                 &targetcli1, &targetpath1)) {
2066                 d_printf("Could not resolve %s\n", path1);
2067                 TALLOC_FREE(frame);
2068                 return -1;
2069         }
2070         /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/
2071         /*d_printf(">>>rename: resolving %s\n", path2);*/
2072         if (!cli_resolve_path(frame, "", srv->cli, path2,
2073                                 &targetcli2, &targetpath2)) {
2074                 d_printf("Could not resolve %s\n", path2);
2075                 TALLOC_FREE(frame);
2076                 return -1;
2077         }
2078         /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/
2079
2080         if (strcmp(targetcli1->desthost, targetcli2->desthost) ||
2081             strcmp(targetcli1->share, targetcli2->share))
2082         {
2083                 /* can't rename across file systems */
2084                 errno = EXDEV;
2085                 TALLOC_FREE(frame);
2086                 return -1;
2087         }
2088
2089         if (!cli_rename(targetcli1, targetpath1, targetpath2)) {
2090                 int eno = smbc_errno(ocontext, targetcli1);
2091
2092                 if (eno != EEXIST ||
2093                     !cli_unlink(targetcli1, targetpath2) ||
2094                     !cli_rename(targetcli1, targetpath1, targetpath2)) {
2095
2096                         errno = eno;
2097                         TALLOC_FREE(frame);
2098                         return -1;
2099
2100                 }
2101         }
2102
2103         TALLOC_FREE(frame);
2104         return 0; /* Success */
2105 }
2106
2107 /*
2108  * A routine to lseek() a file
2109  */
2110
2111 static off_t
2112 smbc_lseek_ctx(SMBCCTX *context,
2113                SMBCFILE *file,
2114                off_t offset,
2115                int whence)
2116 {
2117         SMB_OFF_T size;
2118         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
2119         char *path = NULL;
2120         char *targetpath = NULL;
2121         struct cli_state *targetcli = NULL;
2122         TALLOC_CTX *frame = talloc_stackframe();
2123
2124         if (!context || !context->internal ||
2125             !context->internal->_initialized) {
2126                 errno = EINVAL;
2127                 TALLOC_FREE(frame);
2128                 return -1;
2129         }
2130
2131         if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
2132
2133                 errno = EBADF;
2134                 TALLOC_FREE(frame);
2135                 return -1;
2136
2137         }
2138
2139         if (!file->file) {
2140
2141                 errno = EINVAL;
2142                 TALLOC_FREE(frame);
2143                 return -1;      /* Can't lseek a dir ... */
2144
2145         }
2146
2147         switch (whence) {
2148         case SEEK_SET:
2149                 file->offset = offset;
2150                 break;
2151
2152         case SEEK_CUR:
2153                 file->offset += offset;
2154                 break;
2155
2156         case SEEK_END:
2157                 /*d_printf(">>>lseek: parsing %s\n", file->fname);*/
2158                 if (smbc_parse_path(frame,
2159                                         context,
2160                                         file->fname,
2161                                         NULL,
2162                                         &server,
2163                                         &share,
2164                                         &path,
2165                                         &user,
2166                                         &password,
2167                                         NULL)) {
2168                         errno = EINVAL;
2169                         TALLOC_FREE(frame);
2170                         return -1;
2171                 }
2172
2173                 /*d_printf(">>>lseek: resolving %s\n", path);*/
2174                 if (!cli_resolve_path(frame, "", file->srv->cli, path,
2175                                       &targetcli, &targetpath)) {
2176                         d_printf("Could not resolve %s\n", path);
2177                         TALLOC_FREE(frame);
2178                         return -1;
2179                 }
2180                 /*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/
2181
2182                 if (!cli_qfileinfo(targetcli, file->cli_fd, NULL,
2183                                    &size, NULL, NULL, NULL, NULL, NULL))
2184                 {
2185                     SMB_OFF_T b_size = size;
2186                         if (!cli_getattrE(targetcli, file->cli_fd,
2187                                           NULL, &b_size, NULL, NULL, NULL))
2188                     {
2189                         errno = EINVAL;
2190                         TALLOC_FREE(frame);
2191                         return -1;
2192                     } else
2193                         size = b_size;
2194                 }
2195                 file->offset = size + offset;
2196                 break;
2197
2198         default:
2199                 errno = EINVAL;
2200                 break;
2201
2202         }
2203
2204         TALLOC_FREE(frame);
2205         return file->offset;
2206
2207 }
2208
2209 /* 
2210  * Generate an inode number from file name for those things that need it
2211  */
2212
2213 static ino_t
2214 smbc_inode(SMBCCTX *context,
2215            const char *name)
2216 {
2217         if (!context || !context->internal ||
2218             !context->internal->_initialized) {
2219
2220                 errno = EINVAL;
2221                 return -1;
2222
2223         }
2224
2225         if (!*name) return 2; /* FIXME, why 2 ??? */
2226         return (ino_t)str_checksum(name);
2227
2228 }
2229
2230 /*
2231  * Routine to put basic stat info into a stat structure ... Used by stat and
2232  * fstat below.
2233  */
2234
2235 static int
2236 smbc_setup_stat(SMBCCTX *context,
2237                 struct stat *st,
2238                 char *fname,
2239                 SMB_OFF_T size,
2240                 int mode)
2241 {
2242         TALLOC_CTX *frame = talloc_stackframe();
2243         
2244         st->st_mode = 0;
2245
2246         if (IS_DOS_DIR(mode)) {
2247                 st->st_mode = SMBC_DIR_MODE;
2248         } else {
2249                 st->st_mode = SMBC_FILE_MODE;
2250         }
2251
2252         if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR;
2253         if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP;
2254         if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH;
2255         if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR;
2256
2257         st->st_size = size;
2258 #ifdef HAVE_STAT_ST_BLKSIZE
2259         st->st_blksize = 512;
2260 #endif
2261 #ifdef HAVE_STAT_ST_BLOCKS
2262         st->st_blocks = (size+511)/512;
2263 #endif
2264 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2265         st->st_rdev = 0;
2266 #endif
2267         st->st_uid = getuid();
2268         st->st_gid = getgid();
2269
2270         if (IS_DOS_DIR(mode)) {
2271                 st->st_nlink = 2;
2272         } else {
2273                 st->st_nlink = 1;
2274         }
2275
2276         if (st->st_ino == 0) {
2277                 st->st_ino = smbc_inode(context, fname);
2278         }
2279         
2280         TALLOC_FREE(frame);
2281         return True;  /* FIXME: Is this needed ? */
2282
2283 }
2284
2285 /*
2286  * Routine to stat a file given a name
2287  */
2288
2289 static int
2290 smbc_stat_ctx(SMBCCTX *context,
2291               const char *fname,
2292               struct stat *st)
2293 {
2294         SMBCSRV *srv = NULL;
2295         char *server = NULL;
2296         char *share = NULL;
2297         char *user = NULL;
2298         char *password = NULL;
2299         char *workgroup = NULL;
2300         char *path = NULL;
2301         struct timespec write_time_ts;
2302         struct timespec access_time_ts;
2303         struct timespec change_time_ts;
2304         SMB_OFF_T size = 0;
2305         uint16 mode = 0;
2306         SMB_INO_T ino = 0;
2307         TALLOC_CTX *frame = talloc_stackframe();
2308
2309         if (!context || !context->internal ||
2310             !context->internal->_initialized) {
2311
2312                 errno = EINVAL;  /* Best I can think of ... */
2313                 TALLOC_FREE(frame);
2314                 return -1;
2315         }
2316
2317         if (!fname) {
2318                 errno = EINVAL;
2319                 TALLOC_FREE(frame);
2320                 return -1;
2321         }
2322
2323         DEBUG(4, ("smbc_stat(%s)\n", fname));
2324
2325         if (smbc_parse_path(frame,
2326                                 context,
2327                                 fname,
2328                                 &workgroup,
2329                                 &server,
2330                                 &share,
2331                                 &path,
2332                                 &user,
2333                                 &password,
2334                                 NULL)) {
2335                 errno = EINVAL;
2336                 TALLOC_FREE(frame);
2337                 return -1;
2338         }
2339
2340         if (!user || user[0] == (char)0) {
2341                 user = talloc_strdup(frame,context->user);
2342                 if (!user) {
2343                         errno = ENOMEM;
2344                         TALLOC_FREE(frame);
2345                         return -1;
2346                 }
2347         }
2348
2349         srv = smbc_server(frame, context, True,
2350                           server, share, &workgroup, &user, &password);
2351
2352         if (!srv) {
2353                 TALLOC_FREE(frame);
2354                 return -1;  /* errno set by smbc_server */
2355         }
2356
2357         if (!smbc_getatr(context, srv, path, &mode, &size,
2358                          NULL,
2359                          &access_time_ts,
2360                          &write_time_ts,
2361                          &change_time_ts,
2362                          &ino)) {
2363                 errno = smbc_errno(context, srv->cli);
2364                 TALLOC_FREE(frame);
2365                 return -1;
2366         }
2367
2368         st->st_ino = ino;
2369
2370         smbc_setup_stat(context, st, (char *) fname, size, mode);
2371
2372         set_atimespec(st, access_time_ts);
2373         set_ctimespec(st, change_time_ts);
2374         set_mtimespec(st, write_time_ts);
2375         st->st_dev   = srv->dev;
2376
2377         TALLOC_FREE(frame);
2378         return 0;
2379
2380 }
2381
2382 /*
2383  * Routine to stat a file given an fd
2384  */
2385
2386 static int
2387 smbc_fstat_ctx(SMBCCTX *context,
2388                SMBCFILE *file,
2389                struct stat *st)
2390 {
2391         struct timespec change_time_ts;
2392         struct timespec access_time_ts;
2393         struct timespec write_time_ts;
2394         SMB_OFF_T size;
2395         uint16 mode;
2396         char *server = NULL;
2397         char *share = NULL;
2398         char *user = NULL;
2399         char *password = NULL;
2400         char *path = NULL;
2401         char *targetpath = NULL;
2402         struct cli_state *targetcli = NULL;
2403         SMB_INO_T ino = 0;
2404         TALLOC_CTX *frame = talloc_stackframe();
2405
2406         if (!context || !context->internal ||
2407             !context->internal->_initialized) {
2408                 errno = EINVAL;
2409                 TALLOC_FREE(frame);
2410                 return -1;
2411         }
2412
2413         if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
2414                 errno = EBADF;
2415                 TALLOC_FREE(frame);
2416                 return -1;
2417         }
2418
2419         if (!file->file) {
2420                 TALLOC_FREE(frame);
2421                 return (context->fstatdir)(context, file, st);
2422         }
2423
2424         /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
2425         if (smbc_parse_path(frame,
2426                                 context,
2427                                 file->fname,
2428                                 NULL,
2429                                 &server,
2430                                 &share,
2431                                 &path,
2432                                 &user,
2433                                 &password,
2434                                 NULL)) {
2435                 errno = EINVAL;
2436                 TALLOC_FREE(frame);
2437                 return -1;
2438         }
2439
2440         /*d_printf(">>>fstat: resolving %s\n", path);*/
2441         if (!cli_resolve_path(frame, "", file->srv->cli, path,
2442                               &targetcli, &targetpath)) {
2443                 d_printf("Could not resolve %s\n", path);
2444                 TALLOC_FREE(frame);
2445                 return -1;
2446         }
2447         /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
2448
2449         if (!cli_qfileinfo(targetcli, file->cli_fd, &mode, &size,
2450                            NULL,
2451                            &access_time_ts,
2452                            &write_time_ts,
2453                            &change_time_ts,
2454                            &ino)) {
2455
2456                 time_t change_time, access_time, write_time;
2457
2458                 if (!cli_getattrE(targetcli, file->cli_fd, &mode, &size,
2459                                 &change_time, &access_time, &write_time)) {
2460
2461                         errno = EINVAL;
2462                         TALLOC_FREE(frame);
2463                         return -1;
2464                 }
2465
2466                 change_time_ts = convert_time_t_to_timespec(change_time);
2467                 access_time_ts = convert_time_t_to_timespec(access_time);
2468                 write_time_ts = convert_time_t_to_timespec(write_time);
2469         }
2470
2471         st->st_ino = ino;
2472
2473         smbc_setup_stat(context, st, file->fname, size, mode);
2474
2475         set_atimespec(st, access_time_ts);
2476         set_ctimespec(st, change_time_ts);
2477         set_mtimespec(st, write_time_ts);
2478         st->st_dev = file->srv->dev;
2479
2480         TALLOC_FREE(frame);
2481         return 0;
2482
2483 }
2484
2485 /*
2486  * Routine to open a directory
2487  * We accept the URL syntax explained in smbc_parse_path(), above.
2488  */
2489
2490 static void
2491 smbc_remove_dir(SMBCFILE *dir)
2492 {
2493         struct smbc_dir_list *d,*f;
2494
2495         d = dir->dir_list;
2496         while (d) {
2497
2498                 f = d; d = d->next;
2499
2500                 SAFE_FREE(f->dirent);
2501                 SAFE_FREE(f);
2502
2503         }
2504
2505         dir->dir_list = dir->dir_end = dir->dir_next = NULL;
2506
2507 }
2508
2509 static int
2510 add_dirent(SMBCFILE *dir,
2511            const char *name,
2512            const char *comment,
2513            uint32 type)
2514 {
2515         struct smbc_dirent *dirent;
2516         int size;
2517         int name_length = (name == NULL ? 0 : strlen(name));
2518         int comment_len = (comment == NULL ? 0 : strlen(comment));
2519
2520         /*
2521          * Allocate space for the dirent, which must be increased by the 
2522          * size of the name and the comment and 1 each for the null terminator.
2523          */
2524
2525         size = sizeof(struct smbc_dirent) + name_length + comment_len + 2;
2526     
2527         dirent = (struct smbc_dirent *)SMB_MALLOC(size);
2528
2529         if (!dirent) {
2530
2531                 dir->dir_error = ENOMEM;
2532                 return -1;
2533
2534         }
2535
2536         ZERO_STRUCTP(dirent);
2537
2538         if (dir->dir_list == NULL) {
2539
2540                 dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list);
2541                 if (!dir->dir_list) {
2542
2543                         SAFE_FREE(dirent);
2544                         dir->dir_error = ENOMEM;
2545                         return -1;
2546
2547                 }
2548                 ZERO_STRUCTP(dir->dir_list);
2549
2550                 dir->dir_end = dir->dir_next = dir->dir_list;
2551         }
2552         else {
2553
2554                 dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list);
2555                 
2556                 if (!dir->dir_end->next) {
2557                         
2558                         SAFE_FREE(dirent);
2559                         dir->dir_error = ENOMEM;
2560                         return -1;
2561
2562                 }
2563                 ZERO_STRUCTP(dir->dir_end->next);
2564
2565                 dir->dir_end = dir->dir_end->next;
2566         }
2567
2568         dir->dir_end->next = NULL;
2569         dir->dir_end->dirent = dirent;
2570         
2571         dirent->smbc_type = type;
2572         dirent->namelen = name_length;
2573         dirent->commentlen = comment_len;
2574         dirent->dirlen = size;
2575   
2576         /*
2577          * dirent->namelen + 1 includes the null (no null termination needed)
2578          * Ditto for dirent->commentlen.
2579          * The space for the two null bytes was allocated.
2580          */
2581         strncpy(dirent->name, (name?name:""), dirent->namelen + 1);
2582         dirent->comment = (char *)(&dirent->name + dirent->namelen + 1);
2583         strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1);
2584         
2585         return 0;
2586
2587 }
2588
2589 static void
2590 list_unique_wg_fn(const char *name,
2591                   uint32 type,
2592                   const char *comment,
2593                   void *state)
2594 {
2595         SMBCFILE *dir = (SMBCFILE *)state;
2596         struct smbc_dir_list *dir_list;
2597         struct smbc_dirent *dirent;
2598         int dirent_type;
2599         int do_remove = 0;
2600
2601         dirent_type = dir->dir_type;
2602
2603         if (add_dirent(dir, name, comment, dirent_type) < 0) {
2604
2605                 /* An error occurred, what do we do? */
2606                 /* FIXME: Add some code here */
2607         }
2608
2609         /* Point to the one just added */
2610         dirent = dir->dir_end->dirent;
2611
2612         /* See if this was a duplicate */
2613         for (dir_list = dir->dir_list;
2614              dir_list != dir->dir_end;
2615              dir_list = dir_list->next) {
2616                 if (! do_remove &&
2617                     strcmp(dir_list->dirent->name, dirent->name) == 0) {
2618                         /* Duplicate.  End end of list need to be removed. */
2619                         do_remove = 1;
2620                 }
2621
2622                 if (do_remove && dir_list->next == dir->dir_end) {
2623                         /* Found the end of the list.  Remove it. */
2624                         dir->dir_end = dir_list;
2625                         free(dir_list->next);
2626                         free(dirent);
2627                         dir_list->next = NULL;
2628                         break;
2629                 }
2630         }
2631 }
2632
2633 static void
2634 list_fn(const char *name,
2635         uint32 type,
2636         const char *comment,
2637         void *state)
2638 {
2639         SMBCFILE *dir = (SMBCFILE *)state;
2640         int dirent_type;
2641
2642         /*
2643          * We need to process the type a little ...
2644          *
2645          * Disk share     = 0x00000000
2646          * Print share    = 0x00000001
2647          * Comms share    = 0x00000002 (obsolete?)
2648          * IPC$ share     = 0x00000003
2649          *
2650          * administrative shares:
2651          * ADMIN$, IPC$, C$, D$, E$ ...  are type |= 0x80000000
2652          */
2653
2654         if (dir->dir_type == SMBC_FILE_SHARE) {
2655                 switch (type) {
2656                 case 0 | 0x80000000:
2657                 case 0:
2658                         dirent_type = SMBC_FILE_SHARE;
2659                         break;
2660
2661                 case 1:
2662                         dirent_type = SMBC_PRINTER_SHARE;
2663                         break;
2664
2665                 case 2:
2666                         dirent_type = SMBC_COMMS_SHARE;
2667                         break;
2668
2669                 case 3 | 0x80000000:
2670                 case 3:
2671                         dirent_type = SMBC_IPC_SHARE;
2672                         break;
2673
2674                 default:
2675                         dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */
2676                         break;
2677                 }
2678         }
2679         else {
2680                 dirent_type = dir->dir_type;
2681         }
2682
2683         if (add_dirent(dir, name, comment, dirent_type) < 0) {
2684
2685                 /* An error occurred, what do we do? */
2686                 /* FIXME: Add some code here */
2687
2688         }
2689 }
2690
2691 static void
2692 dir_list_fn(const char *mnt,
2693             file_info *finfo,
2694             const char *mask,
2695             void *state)
2696 {
2697
2698         if (add_dirent((SMBCFILE *)state, finfo->name, "", 
2699                        (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) {
2700
2701                 /* Handle an error ... */
2702
2703                 /* FIXME: Add some code ... */
2704
2705         } 
2706
2707 }
2708
2709 static int
2710 net_share_enum_rpc(struct cli_state *cli,
2711                    void (*fn)(const char *name,
2712                               uint32 type,
2713                               const char *comment,
2714                               void *state),
2715                    void *state)
2716 {
2717         int i;
2718         WERROR result;
2719         ENUM_HND enum_hnd;
2720         uint32 info_level = 1;
2721         uint32 preferred_len = 0xffffffff;
2722         uint32 type;
2723         SRV_SHARE_INFO_CTR ctr;
2724         fstring name = "";
2725         fstring comment = "";
2726         struct rpc_pipe_client *pipe_hnd;
2727         NTSTATUS nt_status;
2728
2729         /* Open the server service pipe */
2730         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status);
2731         if (!pipe_hnd) {
2732                 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));
2733                 return -1;
2734         }
2735
2736         /* Issue the NetShareEnum RPC call and retrieve the response */
2737         init_enum_hnd(&enum_hnd, 0);
2738         result = rpccli_srvsvc_net_share_enum(pipe_hnd,
2739                                               talloc_tos(),
2740                                               info_level,
2741                                               &ctr,
2742                                               preferred_len,
2743                                               &enum_hnd);
2744
2745         /* Was it successful? */
2746         if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) {
2747                 /*  Nope.  Go clean up. */
2748                 goto done;
2749         }
2750
2751         /* For each returned entry... */
2752         for (i = 0; i < ctr.num_entries; i++) {
2753
2754                 /* pull out the share name */
2755                 rpcstr_pull_unistr2_fstring(
2756                         name, &ctr.share.info1[i].info_1_str.uni_netname);
2757
2758                 /* pull out the share's comment */
2759                 rpcstr_pull_unistr2_fstring(
2760                         comment, &ctr.share.info1[i].info_1_str.uni_remark);
2761
2762                 /* Get the type value */
2763                 type = ctr.share.info1[i].info_1.type;
2764
2765                 /* Add this share to the list */
2766                 (*fn)(name, type, comment, state);
2767         }
2768
2769 done:
2770         /* Close the server service pipe */
2771         cli_rpc_pipe_close(pipe_hnd);
2772
2773         /* Tell 'em if it worked */
2774         return W_ERROR_IS_OK(result) ? 0 : -1;
2775 }
2776
2777
2778
2779 static SMBCFILE *
2780 smbc_opendir_ctx(SMBCCTX *context,
2781                  const char *fname)
2782 {
2783         int saved_errno;
2784         char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL;
2785         char *workgroup = NULL;
2786         char *path = NULL;
2787         uint16 mode;
2788         char *p = NULL;
2789         SMBCSRV *srv  = NULL;
2790         SMBCFILE *dir = NULL;
2791         struct _smbc_callbacks *cb = NULL;
2792         struct sockaddr_storage rem_ss;
2793         TALLOC_CTX *frame = talloc_stackframe();
2794
2795         if (!context || !context->internal ||
2796             !context->internal->_initialized) {
2797                 DEBUG(4, ("no valid context\n"));
2798                 errno = EINVAL + 8192;
2799                 TALLOC_FREE(frame);
2800                 return NULL;
2801
2802         }
2803
2804         if (!fname) {
2805                 DEBUG(4, ("no valid fname\n"));
2806                 errno = EINVAL + 8193;
2807                 TALLOC_FREE(frame);
2808                 return NULL;
2809         }
2810
2811         if (smbc_parse_path(frame,
2812                                 context,
2813                                 fname,
2814                                 &workgroup,
2815                                 &server,
2816                                 &share,
2817                                 &path,
2818                                 &user,
2819                                 &password,
2820                                 &options)) {
2821                 DEBUG(4, ("no valid path\n"));
2822                 errno = EINVAL + 8194;
2823                 TALLOC_FREE(frame);
2824                 return NULL;
2825         }
2826
2827         DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' "
2828                   "path='%s' options='%s'\n",
2829                   fname, server, share, path, options));
2830
2831         /* Ensure the options are valid */
2832         if (smbc_check_options(server, share, path, options)) {
2833                 DEBUG(4, ("unacceptable options (%s)\n", options));
2834                 errno = EINVAL + 8195;
2835                 TALLOC_FREE(frame);
2836                 return NULL;
2837         }
2838
2839         if (!user || user[0] == (char)0) {
2840                 user = talloc_strdup(frame, context->user);
2841                 if (!user) {
2842                         errno = ENOMEM;
2843                         TALLOC_FREE(frame);
2844                         return NULL;
2845                 }
2846         }
2847
2848         dir = SMB_MALLOC_P(SMBCFILE);
2849
2850         if (!dir) {
2851                 errno = ENOMEM;
2852                 TALLOC_FREE(frame);
2853                 return NULL;
2854         }
2855
2856         ZERO_STRUCTP(dir);
2857
2858         dir->cli_fd   = 0;
2859         dir->fname    = SMB_STRDUP(fname);
2860         dir->srv      = NULL;
2861         dir->offset   = 0;
2862         dir->file     = False;
2863         dir->dir_list = dir->dir_next = dir->dir_end = NULL;
2864
2865         if (server[0] == (char)0) {
2866
2867                 int i;
2868                 int count;
2869                 int max_lmb_count;
2870                 struct ip_service *ip_list;
2871                 struct ip_service server_addr;
2872                 struct user_auth_info u_info;
2873
2874                 if (share[0] != (char)0 || path[0] != (char)0) {
2875
2876                         errno = EINVAL + 8196;
2877                         if (dir) {
2878                                 SAFE_FREE(dir->fname);
2879                                 SAFE_FREE(dir);
2880                         }
2881                         TALLOC_FREE(frame);
2882                         return NULL;
2883                 }
2884
2885                 /* Determine how many local master browsers to query */
2886                 max_lmb_count = (context->options.browse_max_lmb_count == 0
2887                                  ? INT_MAX
2888                                  : context->options.browse_max_lmb_count);
2889
2890                 memset(&u_info, '\0', sizeof(u_info));
2891                 u_info.username = talloc_strdup(frame,user);
2892                 u_info.password = talloc_strdup(frame,password);
2893                 if (!u_info.username || !u_info.password) {
2894                         if (dir) {
2895                                 SAFE_FREE(dir->fname);
2896                                 SAFE_FREE(dir);
2897                         }
2898                         TALLOC_FREE(frame);
2899                         return NULL;
2900                 }
2901
2902                 /*
2903                  * We have server and share and path empty but options
2904                  * requesting that we scan all master browsers for their list
2905                  * of workgroups/domains.  This implies that we must first try
2906                  * broadcast queries to find all master browsers, and if that
2907                  * doesn't work, then try our other methods which return only
2908                  * a single master browser.
2909                  */
2910
2911                 ip_list = NULL;
2912                 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2913                                      &count)))
2914                 {
2915
2916                         SAFE_FREE(ip_list);
2917
2918                         if (!find_master_ip(workgroup, &server_addr.ss)) {
2919
2920                                 if (dir) {
2921                                         SAFE_FREE(dir->fname);
2922                                         SAFE_FREE(dir);
2923                                 }
2924                                 errno = ENOENT;
2925                                 TALLOC_FREE(frame);
2926                                 return NULL;
2927                         }
2928
2929                         ip_list = (struct ip_service *)memdup(
2930                                 &server_addr, sizeof(server_addr));
2931                         if (ip_list == NULL) {
2932                                 errno = ENOMEM;
2933                                 TALLOC_FREE(frame);
2934                                 return NULL;
2935                         }
2936                         count = 1;
2937                 }
2938
2939                 for (i = 0; i < count && i < max_lmb_count; i++) {
2940                         char addr[INET6_ADDRSTRLEN];
2941                         char *wg_ptr = NULL;
2942                         struct cli_state *cli = NULL;
2943
2944                         print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2945                         DEBUG(99, ("Found master browser %d of %d: %s\n",
2946                                    i+1, MAX(count, max_lmb_count),
2947                                    addr));
2948
2949                         cli = get_ipc_connect_master_ip(talloc_tos(),
2950                                                         &ip_list[i],
2951                                                         &u_info,
2952                                                         &wg_ptr);
2953                         /* cli == NULL is the master browser refused to talk or
2954                            could not be found */
2955                         if (!cli) {
2956                                 continue;
2957                         }
2958
2959                         workgroup = talloc_strdup(frame, wg_ptr);
2960                         server = talloc_strdup(frame, cli->desthost);
2961
2962                         cli_shutdown(cli);
2963
2964                         if (!workgroup || !server) {
2965                                 errno = ENOMEM;
2966                                 TALLOC_FREE(frame);
2967                                 return NULL;
2968                         }
2969
2970                         DEBUG(4, ("using workgroup %s %s\n",
2971                                   workgroup, server));
2972
2973                         /*
2974                          * For each returned master browser IP address, get a
2975                          * connection to IPC$ on the server if we do not
2976                          * already have one, and determine the
2977                          * workgroups/domains that it knows about.
2978                          */
2979
2980                         srv = smbc_server(frame, context, True, server, "IPC$",
2981                                           &workgroup, &user, &password);
2982                         if (!srv) {
2983                                 continue;
2984                         }
2985
2986                         dir->srv = srv;
2987                         dir->dir_type = SMBC_WORKGROUP;
2988
2989                         /* Now, list the stuff ... */
2990
2991                         if (!cli_NetServerEnum(srv->cli,
2992                                                workgroup,
2993                                                SV_TYPE_DOMAIN_ENUM,
2994                                                list_unique_wg_fn,
2995                                                (void *)dir)) {
2996                                 continue;
2997                         }
2998                 }
2999
3000                 SAFE_FREE(ip_list);
3001         } else {
3002                 /*
3003                  * Server not an empty string ... Check the rest and see what
3004                  * gives
3005                  */
3006                 if (*share == '\0') {
3007                         if (*path != '\0') {
3008
3009                                 /* Should not have empty share with path */
3010                                 errno = EINVAL + 8197;
3011                                 if (dir) {
3012                                         SAFE_FREE(dir->fname);
3013                                         SAFE_FREE(dir);
3014                                 }
3015                                 TALLOC_FREE(frame);
3016                                 return NULL;
3017
3018                         }
3019
3020                         /*
3021                          * We don't know if <server> is really a server name
3022                          * or is a workgroup/domain name.  If we already have
3023                          * a server structure for it, we'll use it.
3024                          * Otherwise, check to see if <server><1D>,
3025                          * <server><1B>, or <server><20> translates.  We check
3026                          * to see if <server> is an IP address first.
3027                          */
3028
3029                         /*
3030                          * See if we have an existing server.  Do not
3031                          * establish a connection if one does not already
3032                          * exist.
3033                          */
3034                         srv = smbc_server(frame, context, False, server, "IPC$",
3035                                           &workgroup, &user, &password);
3036
3037                         /*
3038                          * If no existing server and not an IP addr, look for
3039                          * LMB or DMB
3040                          */
3041                         if (!srv &&
3042                             !is_ipaddress(server) &&
3043                             (resolve_name(server, &rem_ss, 0x1d) ||   /* LMB */
3044                              resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */
3045
3046                                 fstring buserver;
3047
3048                                 dir->dir_type = SMBC_SERVER;
3049
3050                                 /*
3051                                  * Get the backup list ...
3052                                  */
3053                                 if (!name_status_find(server, 0, 0,
3054                                                       &rem_ss, buserver)) {
3055
3056                                         DEBUG(0, ("Could not get name of "
3057                                                   "local/domain master browser "
3058                                                   "for server %s\n", server));
3059                                         if (dir) {
3060                                                 SAFE_FREE(dir->fname);
3061                                                 SAFE_FREE(dir);
3062                                         }
3063                                         errno = EPERM;
3064                                         TALLOC_FREE(frame);
3065                                         return NULL;
3066
3067                                 }
3068
3069                                 /*
3070                                  * Get a connection to IPC$ on the server if
3071                                  * we do not already have one
3072                                  */
3073                                 srv = smbc_server(frame, context, True,
3074                                                   buserver, "IPC$",
3075                                                   &workgroup, &user, &password);
3076                                 if (!srv) {
3077                                         DEBUG(0, ("got no contact to IPC$\n"));
3078                                         if (dir) {
3079                                                 SAFE_FREE(dir->fname);
3080                                                 SAFE_FREE(dir);
3081                                         }
3082                                         TALLOC_FREE(frame);
3083                                         return NULL;
3084
3085                                 }
3086
3087                                 dir->srv = srv;
3088
3089                                 /* Now, list the servers ... */
3090                                 if (!cli_NetServerEnum(srv->cli, server,
3091                                                        0x0000FFFE, list_fn,
3092                                                        (void *)dir)) {
3093
3094                                         if (dir) {
3095                                                 SAFE_FREE(dir->fname);
3096                                                 SAFE_FREE(dir);
3097                                         }
3098                                         TALLOC_FREE(frame);
3099                                         return NULL;
3100                                 }
3101                         } else if (srv ||
3102                                    (resolve_name(server, &rem_ss, 0x20))) {
3103
3104                                 /* If we hadn't found the server, get one now */
3105                                 if (!srv) {
3106                                         srv = smbc_server(frame, context, True,
3107                                                           server, "IPC$",
3108                                                           &workgroup,
3109         &n