Initial revamp of the libsmbclient interface.
[samba.git] / source / libsmb / libsmb_context.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-2008
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 #include "libsmbclient.h"
27 #include "libsmb_internal.h"
28
29
30 /*
31  * Is the logging working / configfile read ? 
32  */
33 static int SMBC_initialized = 0;
34
35
36
37 /*
38  * Get a new empty handle to fill in with your own info
39  */
40 SMBCCTX *
41 smbc_new_context(void)
42 {
43     SMBCCTX *context;
44     
45     context = SMB_MALLOC_P(SMBCCTX);
46     if (!context) {
47         errno = ENOMEM;
48         return NULL;
49     }
50     
51     
52     /* Initialize the context and establish reasonable defaults */
53     ZERO_STRUCTP(context);
54     
55     context->debug            = 0;
56     context->timeout          = 20000; /* 20 seconds */
57     
58     context->full_time_names           = False;
59     context->share_mode                = SMBC_SHAREMODE_DENY_NONE;
60     context->smb_encryption_level      = 0;
61     context->browse_max_lmb_count      = 3;    /* # LMBs to query */
62     context->urlencode_readdir_entries = False;
63     context->one_share_per_server      = False;
64     context->use_kerberos              = False;
65     context->fallback_after_kerberos   = False;
66     context->no_auto_anonymous_login   = False;
67     
68     context->server.get_auth_data_fn        = SMBC_get_auth_data;
69     context->server.check_server_fn         = SMBC_check_server;
70     context->server.remove_unused_server_fn = SMBC_remove_unused_server;
71     
72     context->cache.server_cache_data        = NULL;
73     context->cache.add_cached_server_fn     = SMBC_add_cached_server;
74     context->cache.get_cached_server_fn     = SMBC_get_cached_server;
75     context->cache.remove_cached_server_fn  = SMBC_remove_cached_server;
76     context->cache.purge_cached_server_fn   = SMBC_purge_cached_servers;
77     
78     context->posix_emu.open_fn             = SMBC_open_ctx;
79     context->posix_emu.creat_fn            = SMBC_creat_ctx;
80     context->posix_emu.read_fn             = SMBC_read_ctx;
81     context->posix_emu.write_fn            = SMBC_write_ctx;
82     context->posix_emu.close_fn            = SMBC_close_ctx;
83     context->posix_emu.unlink_fn           = SMBC_unlink_ctx;
84     context->posix_emu.rename_fn           = SMBC_rename_ctx;
85     context->posix_emu.lseek_fn            = SMBC_lseek_ctx;
86     context->posix_emu.ftruncate_fn        = SMBC_ftruncate_ctx;
87     context->posix_emu.stat_fn             = SMBC_stat_ctx;
88     context->posix_emu.fstat_fn            = SMBC_fstat_ctx;
89     context->posix_emu.opendir_fn          = SMBC_opendir_ctx;
90     context->posix_emu.closedir_fn         = SMBC_closedir_ctx;
91     context->posix_emu.readdir_fn          = SMBC_readdir_ctx;
92     context->posix_emu.getdents_fn         = SMBC_getdents_ctx;
93     context->posix_emu.mkdir_fn            = SMBC_mkdir_ctx;
94     context->posix_emu.rmdir_fn            = SMBC_rmdir_ctx;
95     context->posix_emu.telldir_fn          = SMBC_telldir_ctx;
96     context->posix_emu.lseekdir_fn         = SMBC_lseekdir_ctx;
97     context->posix_emu.fstatdir_fn         = SMBC_fstatdir_ctx;
98     context->posix_emu.chmod_fn            = SMBC_chmod_ctx;
99     context->posix_emu.utimes_fn           = SMBC_utimes_ctx;
100     context->posix_emu.setxattr_fn         = SMBC_setxattr_ctx;
101     context->posix_emu.getxattr_fn         = SMBC_getxattr_ctx;
102     context->posix_emu.removexattr_fn      = SMBC_removexattr_ctx;
103     context->posix_emu.listxattr_fn        = SMBC_listxattr_ctx;
104     
105     context->printing.open_print_job_fn   = SMBC_open_print_job_ctx;
106     context->printing.print_file_fn       = SMBC_print_file_ctx;
107     context->printing.list_print_jobs_fn  = SMBC_list_print_jobs_ctx;
108     context->printing.unlink_print_job_fn = SMBC_unlink_print_job_ctx;
109     
110     return context;
111 }
112
113 /*
114  * Free a context
115  *
116  * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed
117  * and thus you'll be leaking memory if not handled properly.
118  *
119  */
120 int
121 smbc_free_context(SMBCCTX *context,
122                   int shutdown_ctx)
123 {
124     if (!context) {
125         errno = EBADF;
126         return 1;
127     }
128     
129     if (shutdown_ctx) {
130         SMBCFILE * f;
131         DEBUG(1,("Performing aggressive shutdown.\n"));
132         
133         f = context->files;
134         while (f) {
135             (context->posix_emu.close_fn)(context, f);
136             f = f->next;
137         }
138         context->files = NULL;
139         
140         /* First try to remove the servers the nice way. */
141         if (context->cache.purge_cached_server_fn(context)) {
142             SMBCSRV * s;
143             SMBCSRV * next;
144             DEBUG(1, ("Could not purge all servers, "
145                       "Nice way shutdown failed.\n"));
146             s = context->servers;
147             while (s) {
148                 DEBUG(1, ("Forced shutdown: %p (fd=%d)\n",
149                           s, s->cli->fd));
150                 cli_shutdown(s->cli);
151                 (context->cache.remove_cached_server_fn)(context,
152                                                          s);
153                 next = s->next;
154                 DLIST_REMOVE(context->servers, s);
155                 SAFE_FREE(s);
156                 s = next;
157             }
158             context->servers = NULL;
159         }
160     }
161     else {
162         /* This is the polite way */
163         if ((context->cache.purge_cached_server_fn)(context)) {
164             DEBUG(1, ("Could not purge all servers, "
165                       "free_context failed.\n"));
166             errno = EBUSY;
167             return 1;
168         }
169         if (context->servers) {
170             DEBUG(1, ("Active servers in context, "
171                       "free_context failed.\n"));
172             errno = EBUSY;
173             return 1;
174         }
175         if (context->files) {
176             DEBUG(1, ("Active files in context, "
177                       "free_context failed.\n"));
178             errno = EBUSY;
179             return 1;
180         }
181     }
182     
183     /* Things we have to clean up */
184     SAFE_FREE(context->workgroup);
185     SAFE_FREE(context->netbios_name);
186     SAFE_FREE(context->user);
187     
188     DEBUG(3, ("Context %p successfully freed\n", context));
189     SAFE_FREE(context);
190     return 0;
191 }
192
193
194 /*
195  * Each time the context structure is changed, we have binary backward
196  * compatibility issues.  Instead of modifying the public portions of the
197  * context structure to add new options, instead, we put them in the internal
198  * portion of the context structure and provide a set function for these new
199  * options.
200  */
201 void
202 smbc_option_set(SMBCCTX *context,
203                 char *option_name,
204                 ... /* option_value */)
205 {
206     va_list ap;
207     union {
208         int i;
209         bool b;
210         smbc_get_auth_data_with_context_fn auth_fn;
211         void *v;
212         const char *s;
213     } option_value;
214     
215     va_start(ap, option_name);
216     
217     if (strcmp(option_name, "debug_to_stderr") == 0) {
218         /*
219          * Log to standard error instead of standard output.
220          */
221         option_value.b = (bool) va_arg(ap, int);
222         context->debug_stderr = option_value.b;
223         
224     } else if (strcmp(option_name, "full_time_names") == 0) {
225         /*
226          * Use new-style time attribute names, e.g. WRITE_TIME rather
227          * than the old-style names such as M_TIME.  This allows also
228          * setting/getting CREATE_TIME which was previously
229          * unimplemented.  (Note that the old C_TIME was supposed to
230          * be CHANGE_TIME but was confused and sometimes referred to
231          * CREATE_TIME.)
232          */
233         option_value.b = (bool) va_arg(ap, int);
234         context->full_time_names = option_value.b;
235         
236     } else if (strcmp(option_name, "open_share_mode") == 0) {
237         /*
238          * The share mode to use for files opened with
239          * SMBC_open_ctx().  The default is SMBC_SHAREMODE_DENY_NONE.
240          */
241         option_value.i = va_arg(ap, int);
242         context->share_mode = (smbc_share_mode) option_value.i;
243         
244     } else if (strcmp(option_name, "user_data") == 0) {
245         /*
246          * Save a user data handle which may be retrieved by the user
247          * with smbc_option_get()
248          */
249         option_value.v = va_arg(ap, void *);
250         context->user_data = option_value.v;
251     } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
252         /*
253          * Save an encoded value for encryption level.
254          * 0 = off, 1 = attempt, 2 = required.
255          */
256         option_value.s = va_arg(ap, const char *);
257         if (strcmp(option_value.s, "none") == 0) {
258             context->smb_encryption_level = 0;
259         } else if (strcmp(option_value.s, "request") == 0) {
260             context->smb_encryption_level = 1;
261         } else if (strcmp(option_value.s, "require") == 0) {
262             context->smb_encryption_level = 2;
263         }
264     } else if (strcmp(option_name, "browse_max_lmb_count") == 0) {
265         /*
266          * From how many local master browsers should the list of
267          * workgroups be retrieved?  It can take up to 12 minutes or
268          * longer after a server becomes a local master browser, for
269          * it to have the entire browse list (the list of
270          * workgroups/domains) from an entire network.  Since a client
271          * never knows which local master browser will be found first,
272          * the one which is found first and used to retrieve a browse
273          * list may have an incomplete or empty browse list.  By
274          * requesting the browse list from multiple local master
275          * browsers, a more complete list can be generated.  For small
276          * networks (few workgroups), it is recommended that this
277          * value be set to 0, causing the browse lists from all found
278          * local master browsers to be retrieved and merged.  For
279          * networks with many workgroups, a suitable value for this
280          * variable is probably somewhere around 3. (Default: 3).
281          */
282         option_value.i = va_arg(ap, int);
283         context->browse_max_lmb_count = option_value.i;
284         
285     } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) {
286         /*
287          * There is a difference in the desired return strings from
288          * smbc_readdir() depending upon whether the filenames are to
289          * be displayed to the user, or whether they are to be
290          * appended to the path name passed to smbc_opendir() to call
291          * a further smbc_ function (e.g. open the file with
292          * smbc_open()).  In the former case, the filename should be
293          * in "human readable" form.  In the latter case, the smbc_
294          * functions expect a URL which must be url-encoded.  Those
295          * functions decode the URL.  If, for example, smbc_readdir()
296          * returned a file name of "abc%20def.txt", passing a path
297          * with this file name attached to smbc_open() would cause
298          * smbc_open to attempt to open the file "abc def.txt" since
299          * the %20 is decoded into a space.
300          *
301          * Set this option to True if the names returned by
302          * smbc_readdir() should be url-encoded such that they can be
303          * passed back to another smbc_ call.  Set it to False if the
304          * names returned by smbc_readdir() are to be presented to the
305          * user.
306          *
307          * For backwards compatibility, this option defaults to False.
308          */
309         option_value.b = (bool) va_arg(ap, int);
310         context->urlencode_readdir_entries = option_value.b;
311         
312     } else if (strcmp(option_name, "one_share_per_server") == 0) {
313         /*
314          * Some Windows versions appear to have a limit to the number
315          * of concurrent SESSIONs and/or TREE CONNECTions.  In
316          * one-shot programs (i.e. the program runs and then quickly
317          * ends, thereby shutting down all connections), it is
318          * probably reasonable to establish a new connection for each
319          * share.  In long-running applications, the limitation can be
320          * avoided by using only a single connection to each server,
321          * and issuing a new TREE CONNECT when the share is accessed.
322          */
323         option_value.b = (bool) va_arg(ap, int);
324         context->one_share_per_server = option_value.b;
325         
326     } else if (strcmp(option_name, "use_kerberos") == 0) {
327         option_value.b = (bool) va_arg(ap, int);
328         context->use_kerberos = option_value.b;
329         
330     } else if (strcmp(option_name, "fallback_after_kerberos") == 0) {
331         option_value.b = (bool) va_arg(ap, int);
332         context->fallback_after_kerberos = option_value.b;
333         
334     } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) {
335         option_value.b = (bool) va_arg(ap, int);
336         context->no_auto_anonymous_login = option_value.b;
337     }
338     
339     va_end(ap);
340 }
341
342
343 /*
344  * Retrieve the current value of an option
345  */
346 void *
347 smbc_option_get(SMBCCTX *context,
348                 char *option_name)
349 {
350     if (strcmp(option_name, "debug_stderr") == 0) {
351         /*
352          * Log to standard error instead of standard output.
353          */
354 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
355         return (void *) (intptr_t) context->debug_stderr;
356 #else
357         return (void *) context->debug_stderr;
358 #endif
359         
360     } else if (strcmp(option_name, "full_time_names") == 0) {
361         /*
362          * Use new-style time attribute names, e.g. WRITE_TIME rather
363          * than the old-style names such as M_TIME.  This allows also
364          * setting/getting CREATE_TIME which was previously
365          * unimplemented.  (Note that the old C_TIME was supposed to
366          * be CHANGE_TIME but was confused and sometimes referred to
367          * CREATE_TIME.)
368          */
369 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
370         return (void *) (intptr_t) context->full_time_names;
371 #else
372         return (void *) context->full_time_names;
373 #endif
374         
375     } else if (strcmp(option_name, "user_data") == 0) {
376         /*
377          * Return the user data handle which was saved by the user
378          * with smbc_option_set()
379          */
380         return context->user_data;
381         
382     } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
383         /*
384          * Return the current smb encrypt negotiate option as a string.
385          */
386         switch (context->smb_encryption_level) {
387         case 0:
388             return (void *) "none";
389         case 1:
390             return (void *) "request";
391         case 2:
392             return (void *) "require";
393         }
394         
395     } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
396         /*
397          * Return the current smb encrypt status option as a bool.
398          * false = off, true = on. We don't know what server is
399          * being requested, so we only return true if all servers
400          * are using an encrypted connection.
401          */
402         SMBCSRV *s;
403         unsigned int num_servers = 0;
404         
405         for (s = context->servers; s; s = s->next) {
406             num_servers++;
407             if (s->cli->trans_enc_state == NULL) {
408                 return (void *)false;
409             }
410         }
411 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
412         return (void *) (intptr_t) (bool) (num_servers > 0);
413 #else
414         return (void *) (bool) (num_servers > 0);
415 #endif
416         
417     } else if (strcmp(option_name, "browse_max_lmb_count") == 0) {
418         /*
419          * From how many local master browsers should the list of
420          * workgroups be retrieved?  It can take up to 12 minutes or
421          * longer after a server becomes a local master browser, for
422          * it to have the entire browse list (the list of
423          * workgroups/domains) from an entire network.  Since a client
424          * never knows which local master browser will be found first,
425          * the one which is found first and used to retrieve a browse
426          * list may have an incomplete or empty browse list.  By
427          * requesting the browse list from multiple local master
428          * browsers, a more complete list can be generated.  For small
429          * networks (few workgroups), it is recommended that this
430          * value be set to 0, causing the browse lists from all found
431          * local master browsers to be retrieved and merged.  For
432          * networks with many workgroups, a suitable value for this
433          * variable is probably somewhere around 3. (Default: 3).
434          */
435 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
436         return (void *) (intptr_t) context->browse_max_lmb_count;
437 #else
438         return (void *) context->browse_max_lmb_count;
439 #endif
440         
441     } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) {
442         /*
443          * There is a difference in the desired return strings from
444          * smbc_readdir() depending upon whether the filenames are to
445          * be displayed to the user, or whether they are to be
446          * appended to the path name passed to smbc_opendir() to call
447          * a further smbc_ function (e.g. open the file with
448          * smbc_open()).  In the former case, the filename should be
449          * in "human readable" form.  In the latter case, the smbc_
450          * functions expect a URL which must be url-encoded.  Those
451          * functions decode the URL.  If, for example, smbc_readdir()
452          * returned a file name of "abc%20def.txt", passing a path
453          * with this file name attached to smbc_open() would cause
454          * smbc_open to attempt to open the file "abc def.txt" since
455          * the %20 is decoded into a space.
456          *
457          * Set this option to True if the names returned by
458          * smbc_readdir() should be url-encoded such that they can be
459          * passed back to another smbc_ call.  Set it to False if the
460          * names returned by smbc_readdir() are to be presented to the
461          * user.
462          *
463          * For backwards compatibility, this option defaults to False.
464          */
465 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
466         return (void *) (intptr_t) context->urlencode_readdir_entries;
467 #else
468         return (void *) (bool) context->urlencode_readdir_entries;
469 #endif
470         
471     } else if (strcmp(option_name, "one_share_per_server") == 0) {
472         /*
473          * Some Windows versions appear to have a limit to the number
474          * of concurrent SESSIONs and/or TREE CONNECTions.  In
475          * one-shot programs (i.e. the program runs and then quickly
476          * ends, thereby shutting down all connections), it is
477          * probably reasonable to establish a new connection for each
478          * share.  In long-running applications, the limitation can be
479          * avoided by using only a single connection to each server,
480          * and issuing a new TREE CONNECT when the share is accessed.
481          */
482 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
483         return (void *) (intptr_t) context->one_share_per_server;
484 #else
485         return (void *) (bool) context->one_share_per_server;
486 #endif
487         
488     } else if (strcmp(option_name, "use_kerberos") == 0) {
489 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
490         return (void *) (intptr_t) context->use_kerberos;
491 #else
492         return (void *) (bool) context->use_kerberos;
493 #endif
494         
495     } else if (strcmp(option_name, "fallback_after_kerberos") == 0) {
496 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
497         return (void *) (intptr_t) context->fallback_after_kerberos;
498 #else
499         return (void *) (bool) context->fallback_after_kerberos;
500 #endif
501         
502     } else if (strcmp(option_name, "no_auto_anonymous_login") == 0) {
503 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
504         return (void *) (intptr_t) context->no_auto_anonymous_login;
505 #else
506         return (void *) (bool) context->no_auto_anonymous_login;
507 #endif
508     }
509     
510     return NULL;
511 }
512
513
514 /*
515  * Initialize the library, etc.
516  *
517  * We accept a struct containing handle information.
518  * valid values for info->debug from 0 to 100,
519  * and insist that info->fn must be non-null.
520  */
521 SMBCCTX *
522 smbc_init_context(SMBCCTX *context)
523 {
524     int pid;
525     char *user = NULL;
526     char *home = NULL;
527     extern bool in_client;
528     
529     if (!context) {
530         errno = EBADF;
531         return NULL;
532     }
533     
534     /* Do not initialise the same client twice */
535     if (context->initialized) {
536         return 0;
537     }
538     
539     if (!context->server.get_auth_data_fn ||
540         context->debug < 0 ||
541         context->debug > 100) {
542         
543         errno = EINVAL;
544         return NULL;
545         
546     }
547     
548     if (!SMBC_initialized) {
549         /*
550          * Do some library-wide intializations the first time we get
551          * called
552          */
553         bool conf_loaded = False;
554         TALLOC_CTX *frame = talloc_stackframe();
555         
556         /* Set this to what the user wants */
557         DEBUGLEVEL = context->debug;
558         
559         load_case_tables();
560         
561         setup_logging("libsmbclient", True);
562         if (context->debug_stderr) {
563             dbf = x_stderr;
564             x_setbuf(x_stderr, NULL);
565         }
566         
567         /* Here we would open the smb.conf file if needed ... */
568         
569         in_client = True; /* FIXME, make a param */
570         
571         home = getenv("HOME");
572         if (home) {
573             char *conf = NULL;
574             if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
575                 if (lp_load(conf, True, False, False, True)) {
576                     conf_loaded = True;
577                 } else {
578                     DEBUG(5, ("Could not load config file: %s\n",
579                               conf));
580                 }
581                 SAFE_FREE(conf);
582             }
583         }
584         
585         if (!conf_loaded) {
586             /*
587              * Well, if that failed, try the get_dyn_CONFIGFILE
588              * Which points to the standard locn, and if that
589              * fails, silently ignore it and use the internal
590              * defaults ...
591              */
592             
593             if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
594                 DEBUG(5, ("Could not load config file: %s\n",
595                           get_dyn_CONFIGFILE()));
596             } else if (home) {
597                 char *conf;
598                 /*
599                  * We loaded the global config file.  Now lets
600                  * load user-specific modifications to the
601                  * global config.
602                  */
603                 if (asprintf(&conf,
604                              "%s/.smb/smb.conf.append",
605                              home) > 0) {
606                     if (!lp_load(conf, True, False, False, False)) {
607                         DEBUG(10,
608                               ("Could not append config file: "
609                                "%s\n",
610                                conf));
611                     }
612                     SAFE_FREE(conf);
613                 }
614             }
615         }
616         
617         load_interfaces();  /* Load the list of interfaces ... */
618         
619         reopen_logs();  /* Get logging working ... */
620         
621         /*
622          * Block SIGPIPE (from lib/util_sock.c: write())
623          * It is not needed and should not stop execution
624          */
625         BlockSignals(True, SIGPIPE);
626         
627         /* Done with one-time initialisation */
628         SMBC_initialized = 1;
629         
630         TALLOC_FREE(frame);
631     }
632     
633     if (!context->user) {
634         /*
635          * FIXME: Is this the best way to get the user info?
636          */
637         user = getenv("USER");
638         /* walk around as "guest" if no username can be found */
639         if (!user) context->user = SMB_STRDUP("guest");
640         else context->user = SMB_STRDUP(user);
641     }
642     
643     if (!context->netbios_name) {
644         /*
645          * We try to get our netbios name from the config. If that
646          * fails we fall back on constructing our netbios name from
647          * our hostname etc
648          */
649         if (global_myname()) {
650             context->netbios_name = SMB_STRDUP(global_myname());
651         }
652         else {
653             /*
654              * Hmmm, I want to get hostname as well, but I am too
655              * lazy for the moment
656              */
657             pid = sys_getpid();
658             context->netbios_name = (char *)SMB_MALLOC(17);
659             if (!context->netbios_name) {
660                 errno = ENOMEM;
661                 return NULL;
662             }
663             slprintf(context->netbios_name, 16,
664                      "smbc%s%d", context->user, pid);
665         }
666     }
667     
668     DEBUG(1, ("Using netbios name %s.\n", context->netbios_name));
669     
670     if (!context->workgroup) {
671         if (lp_workgroup()) {
672             context->workgroup = SMB_STRDUP(lp_workgroup());
673         }
674         else {
675             /* TODO: Think about a decent default workgroup */
676             context->workgroup = SMB_STRDUP("samba");
677         }
678     }
679     
680     DEBUG(1, ("Using workgroup %s.\n", context->workgroup));
681     
682     /* shortest timeout is 1 second */
683     if (context->timeout > 0 && context->timeout < 1000)
684         context->timeout = 1000;
685     
686     /*
687      * FIXME: Should we check the function pointers here?
688      */
689     
690     context->initialized = True;
691     
692     return context;
693 }
694
695
696 /* Return the verion of samba, and thus libsmbclient */
697 const char *
698 smbc_version(void)
699 {
700     return samba_version_string();
701 }
702
703
704 /** Get the netbios name used for making connections */
705 char *
706 smbc_getNetbiosName(SMBCCTX *c)
707 {
708     return c->netbios_name;
709 }
710
711 /** Set the netbios name used for making connections */
712 void
713 smbc_setNetbiosName(SMBCCTX *c, char * netbios_name)
714 {
715     c->netbios_name = netbios_name;
716 }
717
718 /** Get the workgroup used for making connections */
719 char *
720 smbc_getWorkgroup(SMBCCTX *c)
721 {
722     return c->workgroup;
723 }
724
725 /** Set the workgroup used for making connections */
726 void
727 smbc_setWorkgroup(SMBCCTX *c, char * workgroup)
728 {
729     c->workgroup = workgroup;
730 }
731
732 /** Get the username used for making connections */
733 char *
734 smbc_getUser(SMBCCTX *c)
735 {
736     return c->user;
737 }
738
739 /** Set the username used for making connections */
740 void
741 smbc_setUser(SMBCCTX *c, char * user)
742 {
743     c->user = user;
744 }
745
746 /** Get the debug level */
747 int
748 smbc_getDebug(SMBCCTX *c)
749 {
750     return c->debug;
751 }
752
753 /** Set the debug level */
754 void
755 smbc_setDebug(SMBCCTX *c, int debug)
756 {
757     c->debug = debug;
758 }
759
760 /**
761  * Get the timeout used for waiting on connections and response data
762  * (in milliseconds)
763  */
764 int
765 smbc_getTimeout(SMBCCTX *c)
766 {
767     return c->timeout;
768 }
769
770 /**
771  * Set the timeout used for waiting on connections and response data
772  * (in milliseconds)
773  */
774 void
775 smbc_setTimeout(SMBCCTX *c, int timeout)
776 {
777     c->timeout = timeout;
778 }
779
780 /** Get the function for obtaining authentication data */
781
782 smbc_get_auth_data_fn
783 smbc_getFunctionAuthData(SMBCCTX *c)
784 {
785     return c->server.get_auth_data_fn;
786 }
787
788 /** Set the function for obtaining authentication data */
789 void
790 smbc_setFunctionAuthData(SMBCCTX *c, smbc_get_auth_data_fn fn)
791 {
792     c->server.get_auth_data_fn = fn;
793 }
794
795 /** Get the function for checking if a server is still good */
796 smbc_check_server_fn
797 smbc_getFunctionCheckServer(SMBCCTX *c)
798 {
799     return c->server.check_server_fn;
800 }
801
802 /** Set the function for checking if a server is still good */
803 void
804 smbc_setFunctionCheckServer(SMBCCTX *c, smbc_check_server_fn fn)
805 {
806     c->server.check_server_fn = fn;
807 }
808
809 /** Get the function for removing a server if unused */
810 smbc_remove_unused_server_fn
811 smbc_getFunctionRemoveUnusedServer(SMBCCTX *c)
812 {
813     return c->server.remove_unused_server_fn;
814 }
815
816 /** Set the function for removing a server if unused */
817 void
818 smbc_setFunctionRemoveUnusedServer(SMBCCTX *c,
819                                    smbc_remove_unused_server_fn fn)
820 {
821     c->server.remove_unused_server_fn = fn;
822 }
823
824 /** Get the function to store private data of the server cache */
825 struct
826 smbc_server_cache * smbc_getServerCacheData(SMBCCTX *c)
827 {
828     return c->cache.server_cache_data;
829 }
830
831 /** Set the function to store private data of the server cache */
832 void
833 smbc_setServerCacheData(SMBCCTX *c, struct smbc_server_cache * cache)
834 {
835     c->cache.server_cache_data = cache;
836 }
837
838
839 /** Get the function for adding a cached server */
840 smbc_add_cached_srv_fn
841 smbc_getFunctionAddCachedServer(SMBCCTX *c)
842 {
843     return c->cache.add_cached_server_fn;
844 }
845
846 /** Set the function for adding a cached server */
847 void
848 smbc_setFunctionAddCachedServer(SMBCCTX *c, smbc_add_cached_srv_fn fn)
849 {
850     c->cache.add_cached_server_fn = fn;
851 }
852
853 /** Get the function for server cache lookup */
854 smbc_get_cached_srv_fn
855 smbc_getFunctionGetCachedServer(SMBCCTX *c)
856 {
857     return c->cache.get_cached_server_fn;
858 }
859
860 /** Set the function for server cache lookup */
861 void
862 smbc_setFunctionGetCachedServer(SMBCCTX *c, smbc_get_cached_srv_fn fn)
863 {
864     c->cache.get_cached_server_fn = fn;
865 }
866
867 /** Get the function for server cache removal */
868 smbc_remove_cached_srv_fn
869 smbc_getFunctionRemoveCachedServer(SMBCCTX *c)
870 {
871     return c->cache.remove_cached_server_fn;
872 }
873
874 /** Set the function for server cache removal */
875 void
876 smbc_setFunctionRemoveCachedServer(SMBCCTX *c,
877                                    smbc_remove_cached_srv_fn fn)
878 {
879     c->cache.remove_cached_server_fn = fn;
880 }
881
882 /**
883  * Get the function for server cache purging.  This function tries to
884  * remove all cached servers (e.g. on disconnect)
885  */
886 smbc_purge_cached_srv_fn
887 smbc_getFunctionPurgeCachedServers(SMBCCTX *c)
888 {
889     return c->cache.purge_cached_server_fn;
890 }
891
892 /**
893  * Set the function for server cache purging.  This function tries to
894  * remove all cached servers (e.g. on disconnect)
895  */
896 void
897 smbc_setFunctionPurgeCachedServers(SMBCCTX *c, smbc_purge_cached_srv_fn fn)
898 {
899     c->cache.purge_cached_server_fn = fn;
900 }
901
902 /**
903  * Callable functions for files.
904  */
905
906 smbc_open_fn
907 smbc_getFunctionOpen(SMBCCTX *c)
908 {
909     return c->posix_emu.open_fn;
910 }
911
912 void
913 smbc_setFunctionOpen(SMBCCTX *c, smbc_open_fn fn)
914 {
915     c->posix_emu.open_fn = fn;
916 }
917
918 smbc_creat_fn
919 smbc_getFunctionCreat(SMBCCTX *c)
920 {
921     return c->posix_emu.creat_fn;
922 }
923
924 void
925 smbc_setFunctionCreat(SMBCCTX *c, smbc_creat_fn fn)
926 {
927     c->posix_emu.creat_fn = fn;
928 }
929
930 smbc_read_fn
931 smbc_getFunctionRead(SMBCCTX *c)
932 {
933     return c->posix_emu.read_fn;
934 }
935
936 void
937 smbc_setFunctionRead(SMBCCTX *c, smbc_read_fn fn)
938 {
939     c->posix_emu.read_fn = fn;
940 }
941
942 smbc_write_fn
943 smbc_getFunctionWrite(SMBCCTX *c)
944 {
945     return c->posix_emu.write_fn;
946 }
947
948 void
949 smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn)
950 {
951     c->posix_emu.write_fn = fn;
952 }
953
954 smbc_unlink_fn
955 smbc_getFunctionUnlink(SMBCCTX *c)
956 {
957     return c->posix_emu.unlink_fn;
958 }
959
960 void
961 smbc_setFunctionUnlink(SMBCCTX *c, smbc_unlink_fn fn)
962 {
963     c->posix_emu.unlink_fn = fn;
964 }
965
966 smbc_rename_fn
967 smbc_getFunctionRename(SMBCCTX *c)
968 {
969     return c->posix_emu.rename_fn;
970 }
971
972 void
973 smbc_setFunctionRename(SMBCCTX *c, smbc_rename_fn fn)
974 {
975     c->posix_emu.rename_fn = fn;
976 }
977
978 smbc_lseek_fn
979 smbc_getFunctionLseek(SMBCCTX *c)
980 {
981     return c->posix_emu.lseek_fn;
982 }
983
984 void
985 smbc_setFunctionLseek(SMBCCTX *c, smbc_lseek_fn fn)
986 {
987     c->posix_emu.lseek_fn = fn;
988 }
989
990 smbc_stat_fn
991 smbc_getFunctionStat(SMBCCTX *c)
992 {
993     return c->posix_emu.stat_fn;
994 }
995
996 void
997 smbc_setFunctionStat(SMBCCTX *c, smbc_stat_fn fn)
998 {
999     c->posix_emu.stat_fn = fn;
1000 }
1001
1002 smbc_fstat_fn
1003 smbc_getFunctionFstat(SMBCCTX *c)
1004 {
1005     return c->posix_emu.fstat_fn;
1006 }
1007
1008 void
1009 smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn)
1010 {
1011     c->posix_emu.fstat_fn = fn;
1012 }
1013
1014 smbc_ftruncate_fn
1015 smbc_getFunctionFtruncate(SMBCCTX *c)
1016 {
1017     return c->posix_emu.ftruncate_fn;
1018 }
1019
1020 void
1021 smbc_setFunctionFtruncate(SMBCCTX *c, smbc_ftruncate_fn fn)
1022 {
1023     c->posix_emu.ftruncate_fn = fn;
1024 }
1025
1026 smbc_close_fn
1027 smbc_getFunctionClose(SMBCCTX *c)
1028 {
1029     return c->posix_emu.close_fn;
1030 }
1031
1032 void
1033 smbc_setFunctionClose(SMBCCTX *c, smbc_close_fn fn)
1034 {
1035     c->posix_emu.close_fn = fn;
1036 }
1037
1038
1039 /**
1040  * Callable functions for directories.
1041  */
1042
1043 smbc_opendir_fn
1044 smbc_getFunctionOpendir(SMBCCTX *c)
1045 {
1046     return c->posix_emu.opendir_fn;
1047 }
1048
1049 void
1050 smbc_setFunctionOpendir(SMBCCTX *c, smbc_opendir_fn fn)
1051 {
1052     c->posix_emu.opendir_fn = fn;
1053 }
1054
1055 smbc_closedir_fn
1056 smbc_getFunctionClosedir(SMBCCTX *c)
1057 {
1058     return c->posix_emu.closedir_fn;
1059 }
1060
1061 void
1062 smbc_setFunctionClosedir(SMBCCTX *c, smbc_closedir_fn fn)
1063 {
1064     c->posix_emu.closedir_fn = fn;
1065 }
1066
1067 smbc_readdir_fn
1068 smbc_getFunctionReaddir(SMBCCTX *c)
1069 {
1070     return c->posix_emu.readdir_fn;
1071 }
1072
1073 void
1074 smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn)
1075 {
1076     c->posix_emu.readdir_fn = fn;
1077 }
1078
1079 smbc_getdents_fn
1080 smbc_getFunctionGetdents(SMBCCTX *c)
1081 {
1082     return c->posix_emu.getdents_fn;
1083 }
1084
1085 void
1086 smbc_setFunctionGetdents(SMBCCTX *c, smbc_getdents_fn fn)
1087 {
1088     c->posix_emu.getdents_fn = fn;
1089 }
1090
1091 smbc_mkdir_fn
1092 smbc_getFunctionMkdir(SMBCCTX *c)
1093 {
1094     return c->posix_emu.mkdir_fn;
1095 }
1096
1097 void
1098 smbc_setFunctionMkdir(SMBCCTX *c, smbc_mkdir_fn fn)
1099 {
1100     c->posix_emu.mkdir_fn = fn;
1101 }
1102
1103 smbc_rmdir_fn
1104 smbc_getFunctionRmdir(SMBCCTX *c)
1105 {
1106     return c->posix_emu.rmdir_fn;
1107 }
1108
1109 void
1110 smbc_setFunctionRmdir(SMBCCTX *c, smbc_rmdir_fn fn)
1111 {
1112     c->posix_emu.rmdir_fn = fn;
1113 }
1114
1115 smbc_telldir_fn
1116 smbc_getFunctionTelldir(SMBCCTX *c)
1117 {
1118     return c->posix_emu.telldir_fn;
1119 }
1120
1121 void
1122 smbc_setFunctionTelldir(SMBCCTX *c, smbc_telldir_fn fn)
1123 {
1124     c->posix_emu.telldir_fn = fn;
1125 }
1126
1127 smbc_lseekdir_fn
1128 smbc_getFunctionLseekdir(SMBCCTX *c)
1129 {
1130     return c->posix_emu.lseekdir_fn;
1131 }
1132
1133 void
1134 smbc_setFunctionLseekdir(SMBCCTX *c, smbc_lseekdir_fn fn)
1135 {
1136     c->posix_emu.lseekdir_fn = fn;
1137 }
1138
1139 smbc_fstatdir_fn
1140 smbc_getFunctionFstatdir(SMBCCTX *c)
1141 {
1142     return c->posix_emu.fstatdir_fn;
1143 }
1144
1145 void
1146 smbc_setFunctionFstatdir(SMBCCTX *c, smbc_fstatdir_fn fn)
1147 {
1148     c->posix_emu.fstatdir_fn = fn;
1149 }
1150
1151
1152 /**
1153  * Callable functions applicable to both files and directories.
1154  */
1155
1156 smbc_chmod_fn
1157 smbc_getFunctionChmod(SMBCCTX *c)
1158 {
1159     return c->posix_emu.chmod_fn;
1160 }
1161
1162 void
1163 smbc_setFunctionChmod(SMBCCTX *c, smbc_chmod_fn fn)
1164 {
1165     c->posix_emu.chmod_fn = fn;
1166 }
1167
1168 smbc_utimes_fn
1169 smbc_getFunctionUtimes(SMBCCTX *c)
1170 {
1171     return c->posix_emu.utimes_fn;
1172 }
1173
1174 void
1175 smbc_setFunctionUtimes(SMBCCTX *c, smbc_utimes_fn fn)
1176 {
1177     c->posix_emu.utimes_fn = fn;
1178 }
1179
1180 smbc_setxattr_fn
1181 smbc_getFunctionSetxattr(SMBCCTX *c)
1182 {
1183     return c->posix_emu.setxattr_fn;
1184 }
1185
1186 void
1187 smbc_setFunctionSetxattr(SMBCCTX *c, smbc_setxattr_fn fn)
1188 {
1189     c->posix_emu.setxattr_fn = fn;
1190 }
1191
1192 smbc_getxattr_fn
1193 smbc_getFunctionGetxattr(SMBCCTX *c)
1194 {
1195     return c->posix_emu.getxattr_fn;
1196 }
1197
1198 void
1199 smbc_setFunctionGetxattr(SMBCCTX *c, smbc_getxattr_fn fn)
1200 {
1201     c->posix_emu.getxattr_fn = fn;
1202 }
1203
1204 smbc_removexattr_fn
1205 smbc_getFunctionRemovexattr(SMBCCTX *c)
1206 {
1207     return c->posix_emu.removexattr_fn;
1208 }
1209
1210 void
1211 smbc_setFunctionRemovexattr(SMBCCTX *c, smbc_removexattr_fn fn)
1212 {
1213     c->posix_emu.removexattr_fn = fn;
1214 }
1215
1216 smbc_listxattr_fn
1217 smbc_getFunctionListxattr(SMBCCTX *c)
1218 {
1219     return c->posix_emu.listxattr_fn;
1220 }
1221
1222 void
1223 smbc_setFunctionListxattr(SMBCCTX *c, smbc_listxattr_fn fn)
1224 {
1225     c->posix_emu.listxattr_fn = fn;
1226 }
1227
1228
1229 /**
1230  * Callable functions related to printing
1231  */
1232
1233 smbc_print_file_fn
1234 smbc_getFunctionPrintFile(SMBCCTX *c)
1235 {
1236     return c->printing.print_file_fn;
1237 }
1238
1239 void
1240 smbc_setFunctionPrintFile(SMBCCTX *c, smbc_print_file_fn fn)
1241 {
1242     c->printing.print_file_fn = fn;
1243 }
1244
1245 smbc_open_print_job_fn
1246 smbc_getFunctionOpenPrintJob(SMBCCTX *c)
1247 {
1248     return c->printing.open_print_job_fn;
1249 }
1250
1251 void
1252 smbc_setFunctionOpenPrintJob(SMBCCTX *c,
1253                              smbc_open_print_job_fn fn)
1254 {
1255     c->printing.open_print_job_fn = fn;
1256 }
1257
1258 smbc_list_print_jobs_fn
1259 smbc_getFunctionListPrintJobs(SMBCCTX *c)
1260 {
1261     return c->printing.list_print_jobs_fn;
1262 }
1263
1264 void
1265 smbc_setFunctionListPrintJobs(SMBCCTX *c,
1266                               smbc_list_print_jobs_fn fn)
1267 {
1268     c->printing.list_print_jobs_fn = fn;
1269 }
1270
1271 smbc_unlink_print_job_fn
1272 smbc_getFunctionUnlinkPrintJob(SMBCCTX *c)
1273 {
1274     return c->printing.unlink_print_job_fn;
1275 }
1276
1277 void
1278 smbc_setFunctionUnlinkPrintJob(SMBCCTX *c,
1279                                 smbc_unlink_print_job_fn fn)
1280 {
1281     c->printing.unlink_print_job_fn = fn;
1282 }
1283