56d113f31a221736c07454f2e7154b8711185def
[samba.git] / source3 / libsmb / libsmb_compat.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB client library implementation (Old interface compatibility)
4    Copyright (C) Andrew Tridgell 1998
5    Copyright (C) Richard Sharpe 2000
6    Copyright (C) John Terpstra 2000
7    Copyright (C) Tom Jansen (Ninja ISD) 2002 
8    Copyright (C) Derrell Lipman 2003, 2008
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24
25 #include "includes.h"
26 #include "libsmb_internal.h"
27
28 struct smbc_compat_fdlist {
29         SMBCFILE * file;
30         int fd;
31         struct smbc_compat_fdlist *next, *prev;
32 };
33
34 static SMBCCTX * statcont = NULL;
35 static int smbc_compat_initialized = 0;
36 static int smbc_compat_nextfd = 0;
37 static struct smbc_compat_fdlist * smbc_compat_fd_in_use = NULL;
38 static struct smbc_compat_fdlist * smbc_compat_fd_avail = NULL;
39
40 /* Find an fd and return the SMBCFILE * or NULL on failure */
41 static SMBCFILE *
42 find_fd(int fd)
43 {
44         struct smbc_compat_fdlist * f = smbc_compat_fd_in_use;
45         while (f) {
46                 if (f->fd == fd) 
47                         return f->file;
48                 f = f->next;
49         }
50         return NULL;
51 }
52
53 /* Add an fd, returns 0 on success, -1 on error with errno set */
54 static int
55 add_fd(SMBCFILE * file)
56 {
57         struct smbc_compat_fdlist * f = smbc_compat_fd_avail;
58         
59         if (f) {
60                 /* We found one that's available */
61                 DLIST_REMOVE(smbc_compat_fd_avail, f);
62                 
63         } else {
64                 /*
65                  * None were available, so allocate one.  Keep the number of
66                  * file descriptors determinate.  This allows the application
67                  * to allocate bitmaps or mapping of file descriptors based on
68                  * a known maximum number of file descriptors that will ever
69                  * be returned.
70                  */
71                 if (smbc_compat_nextfd >= FD_SETSIZE) {
72                         errno = EMFILE;
73                         return -1;
74                 }
75                 
76                 f = SMB_MALLOC_P(struct smbc_compat_fdlist);
77                 if (!f) {
78                         errno = ENOMEM;
79                         return -1;
80                 }
81                 
82                 f->fd = SMBC_BASE_FD + smbc_compat_nextfd++;
83         }
84         
85         f->file = file;
86         DLIST_ADD(smbc_compat_fd_in_use, f);
87         
88         return f->fd;
89 }
90
91
92
93 /* Delete an fd, returns 0 on success */
94 static int
95 del_fd(int fd)
96 {
97         struct smbc_compat_fdlist * f = smbc_compat_fd_in_use;
98         
99         while (f) {
100                 if (f->fd == fd) 
101                         break;
102                 f = f->next;
103         }
104         
105         if (f) {
106                 /* found */
107                 DLIST_REMOVE(smbc_compat_fd_in_use, f);
108                 f->file = NULL;
109                 DLIST_ADD(smbc_compat_fd_avail, f);
110                 return 0;
111         }
112         return 1;
113 }
114
115
116
117 int
118 smbc_init(smbc_get_auth_data_fn fn,
119           int debug)
120 {
121         if (!smbc_compat_initialized) {
122                 statcont = smbc_new_context();
123                 if (!statcont) 
124                         return -1;
125                 
126                 smbc_setDebug(statcont, debug);
127                 smbc_setFunctionAuthData(statcont, fn);
128                 
129                 if (!smbc_init_context(statcont)) {
130                         smbc_free_context(statcont, False);
131                         return -1;
132                 }
133                 
134                 smbc_compat_initialized = 1;
135                 
136                 return 0;
137         }
138         return 0;
139 }
140
141
142 SMBCCTX *
143 smbc_set_context(SMBCCTX * context)
144 {
145         SMBCCTX *old_context = statcont;
146         
147         if (context) {
148                 /* Save provided context.  It must have been initialized! */
149                 statcont = context;
150                 
151                 /* You'd better know what you're doing.  We won't help you. */
152                 smbc_compat_initialized = 1;
153         }
154         
155         return old_context;
156 }
157
158
159 int
160 smbc_open(const char *furl,
161           int flags,
162           mode_t mode)
163 {
164         SMBCFILE * file;
165         int fd;
166         
167         file = smbc_getFunctionOpen(statcont)(statcont, furl, flags, mode);
168         if (!file)
169                 return -1;
170         
171         fd = add_fd(file);
172         if (fd == -1) 
173                 smbc_getFunctionClose(statcont)(statcont, file);
174         return fd;
175 }
176
177
178 int
179 smbc_creat(const char *furl,
180            mode_t mode)
181 {
182         SMBCFILE * file;
183         int fd;
184         
185         file = smbc_getFunctionCreat(statcont)(statcont, furl, mode);
186         if (!file)
187                 return -1;
188         
189         fd = add_fd(file);
190         if (fd == -1) {
191                 /* Hmm... should we delete the file too ? I guess we could try */
192                 smbc_getFunctionClose(statcont)(statcont, file);
193                 smbc_getFunctionUnlink(statcont)(statcont, furl);
194         }
195         return fd;
196 }
197
198
199 ssize_t
200 smbc_read(int fd,
201           void *buf,
202           size_t bufsize)
203 {
204         SMBCFILE * file = find_fd(fd);
205         return smbc_getFunctionRead(statcont)(statcont, file, buf, bufsize);
206 }
207
208 ssize_t
209 smbc_write(int fd,
210            const void *buf,
211            size_t bufsize)
212 {
213         SMBCFILE * file = find_fd(fd);
214         return smbc_getFunctionWrite(statcont)(statcont, file, buf, bufsize);
215 }
216
217 off_t
218 smbc_lseek(int fd,
219            off_t offset,
220            int whence)
221 {
222         SMBCFILE * file = find_fd(fd);
223         return smbc_getFunctionLseek(statcont)(statcont, file, offset, whence);
224 }
225
226 int
227 smbc_close(int fd)
228 {
229         SMBCFILE * file = find_fd(fd);
230         del_fd(fd);
231         return smbc_getFunctionClose(statcont)(statcont, file);
232 }
233
234 int
235 smbc_unlink(const char *fname)
236 {
237         return smbc_getFunctionUnlink(statcont)(statcont, fname);
238 }
239
240 int
241 smbc_rename(const char *ourl,
242             const char *nurl)
243 {
244         return smbc_getFunctionRename(statcont)(statcont, ourl,
245                                                 statcont, nurl);
246 }
247
248 int
249 smbc_opendir(const char *durl)
250 {
251         SMBCFILE * file;
252         int fd;
253         
254         file = smbc_getFunctionOpendir(statcont)(statcont, durl);
255         if (!file)
256                 return -1;
257         
258         fd = add_fd(file);
259         if (fd == -1) 
260                 smbc_getFunctionClosedir(statcont)(statcont, file);
261         
262         return fd;
263 }
264
265 int
266 smbc_closedir(int dh) 
267 {
268         SMBCFILE * file = find_fd(dh);
269         del_fd(dh);
270         return smbc_getFunctionClosedir(statcont)(statcont, file);
271 }
272
273 int
274 smbc_getdents(unsigned int dh,
275               struct smbc_dirent *dirp,
276               int count)
277 {
278         SMBCFILE * file = find_fd(dh);
279         return smbc_getFunctionGetdents(statcont)(statcont, file, dirp, count);
280 }
281
282 struct smbc_dirent *
283 smbc_readdir(unsigned int dh)
284 {
285         SMBCFILE * file = find_fd(dh);
286         return smbc_getFunctionReaddir(statcont)(statcont, file);
287 }
288
289 off_t
290 smbc_telldir(int dh)
291 {
292         SMBCFILE * file = find_fd(dh);
293         return smbc_getFunctionTelldir(statcont)(statcont, file);
294 }
295
296 int
297 smbc_lseekdir(int fd,
298               off_t offset)
299 {
300         SMBCFILE * file = find_fd(fd);
301         return smbc_getFunctionLseekdir(statcont)(statcont, file, offset);
302 }
303
304 int
305 smbc_mkdir(const char *durl,
306            mode_t mode)
307 {
308         return smbc_getFunctionMkdir(statcont)(statcont, durl, mode);
309 }
310
311 int
312 smbc_rmdir(const char *durl)
313 {
314         return smbc_getFunctionRmdir(statcont)(statcont, durl);
315 }
316
317 int
318 smbc_stat(const char *url,
319           struct stat *st)
320 {
321         return smbc_getFunctionStat(statcont)(statcont, url, st);
322 }
323
324 int
325 smbc_fstat(int fd,
326            struct stat *st)
327 {
328         SMBCFILE * file = find_fd(fd);
329         return smbc_getFunctionFstat(statcont)(statcont, file, st);
330 }
331
332 int
333 smbc_statvfs(char *path,
334              struct statvfs *st)
335 {
336         return smbc_getFunctionStatVFS(statcont)(statcont, path, st);
337 }
338
339 int
340 smbc_fstatvfs(int fd,
341               struct statvfs *st)
342 {
343         SMBCFILE * file = find_fd(fd);
344         return smbc_getFunctionFstatVFS(statcont)(statcont, file, st);
345 }
346
347 int
348 smbc_ftruncate(int fd,
349                off_t size)
350 {
351         SMBCFILE * file = find_fd(fd);
352         return smbc_getFunctionFtruncate(statcont)(statcont, file, size);
353 }
354
355 int
356 smbc_chmod(const char *url,
357            mode_t mode)
358 {
359         return smbc_getFunctionChmod(statcont)(statcont, url, mode);
360 }
361
362 int
363 smbc_utimes(const char *fname,
364             struct timeval *tbuf)
365 {
366         return smbc_getFunctionUtimes(statcont)(statcont, fname, tbuf);
367 }
368
369 #ifdef HAVE_UTIME_H
370 int
371 smbc_utime(const char *fname,
372            struct utimbuf *utbuf)
373 {
374         struct timeval tv[2];
375         
376         if (utbuf == NULL)
377                 return smbc_getFunctionUtimes(statcont)(statcont, fname, NULL);
378         
379         tv[0].tv_sec = utbuf->actime;
380         tv[1].tv_sec = utbuf->modtime;
381         tv[0].tv_usec = tv[1].tv_usec = 0;
382         
383         return smbc_getFunctionUtimes(statcont)(statcont, fname, tv);
384 }
385 #endif
386
387 int
388 smbc_setxattr(const char *fname,
389               const char *name,
390               const void *value,
391               size_t size,
392               int flags)
393 {
394         return smbc_getFunctionSetxattr(statcont)(statcont,
395                                                   fname, name,
396                                                   value, size, flags);
397 }
398
399 int
400 smbc_lsetxattr(const char *fname,
401                const char *name,
402                const void *value,
403                size_t size,
404                int flags)
405 {
406         return smbc_getFunctionSetxattr(statcont)(statcont,
407                                                   fname, name,
408                                                   value, size, flags);
409 }
410
411 int
412 smbc_fsetxattr(int fd,
413                const char *name,
414                const void *value,
415                size_t size,
416                int flags)
417 {
418         SMBCFILE * file = find_fd(fd);
419         if (file == NULL) {
420                 errno = EBADF;
421                 return -1;
422         }
423         return smbc_getFunctionSetxattr(statcont)(statcont,
424                                                   file->fname, name,
425                                                   value, size, flags);
426 }
427
428 int
429 smbc_getxattr(const char *fname,
430               const char *name,
431               const void *value,
432               size_t size)
433 {
434         return smbc_getFunctionGetxattr(statcont)(statcont,
435                                                   fname, name,
436                                                   value, size);
437 }
438
439 int
440 smbc_lgetxattr(const char *fname,
441                const char *name,
442                const void *value,
443                size_t size)
444 {
445         return smbc_getFunctionGetxattr(statcont)(statcont,
446                                                   fname, name,
447                                                   value, size);
448 }
449
450 int
451 smbc_fgetxattr(int fd,
452                const char *name,
453                const void *value,
454                size_t size)
455 {
456         SMBCFILE * file = find_fd(fd);
457         if (file == NULL) {
458                 errno = EBADF;
459                 return -1;
460         }
461         return smbc_getFunctionGetxattr(statcont)(statcont,
462                                                   file->fname, name,
463                                                   value, size);
464 }
465
466 int
467 smbc_removexattr(const char *fname,
468                  const char *name)
469 {
470         return smbc_getFunctionRemovexattr(statcont)(statcont, fname, name);
471 }
472
473 int
474 smbc_lremovexattr(const char *fname,
475                   const char *name)
476 {
477         return smbc_getFunctionRemovexattr(statcont)(statcont, fname, name);
478 }
479
480 int
481 smbc_fremovexattr(int fd,
482                   const char *name)
483 {
484         SMBCFILE * file = find_fd(fd);
485         if (file == NULL) {
486                 errno = EBADF;
487                 return -1;
488         }
489         return smbc_getFunctionRemovexattr(statcont)(statcont,
490                                                      file->fname, name);
491 }
492
493 int
494 smbc_listxattr(const char *fname,
495                char *list,
496                size_t size)
497 {
498         return smbc_getFunctionListxattr(statcont)(statcont,
499                                                    fname, list, size);
500 }
501
502 int
503 smbc_llistxattr(const char *fname,
504                 char *list,
505                 size_t size)
506 {
507         return smbc_getFunctionListxattr(statcont)(statcont,
508                                                    fname, list, size);
509 }
510
511 int
512 smbc_flistxattr(int fd,
513                 char *list,
514                 size_t size)
515 {
516         SMBCFILE * file = find_fd(fd);
517         if (file == NULL) {
518                 errno = EBADF;
519                 return -1;
520         }
521         return smbc_getFunctionListxattr(statcont)(statcont,
522                                                    file->fname, list, size);
523 }
524
525 int
526 smbc_print_file(const char *fname,
527                 const char *printq)
528 {
529         return smbc_getFunctionPrintFile(statcont)(statcont, fname,
530                                                    statcont, printq);
531 }
532
533 int
534 smbc_open_print_job(const char *fname)
535 {
536         SMBCFILE * file;
537         
538         file = smbc_getFunctionOpenPrintJob(statcont)(statcont, fname);
539         if (!file) return -1;
540         return file->cli_fd;
541 }
542
543 int
544 smbc_list_print_jobs(const char *purl,
545                      smbc_list_print_job_fn fn)
546 {
547         return smbc_getFunctionListPrintJobs(statcont)(statcont, purl, fn);
548 }
549
550 int
551 smbc_unlink_print_job(const char *purl,
552                       int id)
553 {
554         return smbc_getFunctionUnlinkPrintJob(statcont)(statcont, purl, id);
555 }
556
557