Initial revamp of the libsmbclient interface.
[samba.git] / source / libsmb / libsmb_compat.c
index bba90c648ebe807b32c9ef5ae6cfa2745f106b40..7a0536a92d60183a222d2243f0b2f9483d8bf3d9 100644 (file)
@@ -5,10 +5,11 @@
    Copyright (C) Richard Sharpe 2000
    Copyright (C) John Terpstra 2000
    Copyright (C) Tom Jansen (Ninja ISD) 2002 
+   Copyright (C) Derrell Lipman 2003, 2008
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 
 #include "includes.h"
-
-/*
- * Define this to get the real SMBCFILE and SMBCSRV structures 
- */
-#define _SMBC_INTERNAL
-#include "../include/libsmbclient.h"
+#include "libsmb_internal.h"
 
 struct smbc_compat_fdlist {
        SMBCFILE * file;
@@ -38,14 +33,15 @@ struct smbc_compat_fdlist {
 
 static SMBCCTX * statcont = NULL;
 static int smbc_compat_initialized = 0;
-static int smbc_currentfd = 10000;
-static struct smbc_compat_fdlist * smbc_compat_fdlist = NULL;
-
+static int smbc_compat_nextfd = 0;
+static struct smbc_compat_fdlist * smbc_compat_fd_in_use = NULL;
+static struct smbc_compat_fdlist * smbc_compat_fd_avail = NULL;
 
 /* Find an fd and return the SMBCFILE * or NULL on failure */
-static SMBCFILE * find_fd(int fd)
+static SMBCFILE *
+find_fd(int fd)
 {
-       struct smbc_compat_fdlist * f = smbc_compat_fdlist;
+       struct smbc_compat_fdlist * f = smbc_compat_fd_in_use;
        while (f) {
                if (f->fd == fd) 
                        return f->file;
@@ -55,18 +51,39 @@ static SMBCFILE * find_fd(int fd)
 }
 
 /* Add an fd, returns 0 on success, -1 on error with errno set */
-static int add_fd(SMBCFILE * file)
+static int
+add_fd(SMBCFILE * file)
 {
-       struct smbc_compat_fdlist * f = malloc(sizeof(struct smbc_compat_fdlist));
-       if (!f) {
-               errno = ENOMEM;
-               return -1;
-       }
+        struct smbc_compat_fdlist * f = smbc_compat_fd_avail;
+
+       if (f) {
+                /* We found one that's available */
+                DLIST_REMOVE(smbc_compat_fd_avail, f);
+
+       } else {
+                /*
+                 * None were available, so allocate one.  Keep the number of
+                 * file descriptors determinate.  This allows the application
+                 * to allocate bitmaps or mapping of file descriptors based on
+                 * a known maximum number of file descriptors that will ever
+                 * be returned.
+                 */
+                if (smbc_compat_nextfd >= FD_SETSIZE) {
+                        errno = EMFILE;
+                        return -1;
+                }
+
+                f = SMB_MALLOC_P(struct smbc_compat_fdlist);
+                if (!f) {
+                        errno = ENOMEM;
+                        return -1;
+                }
        
-       f->fd = smbc_currentfd++;
+                f->fd = SMBC_BASE_FD + smbc_compat_nextfd++;
+        }
+
        f->file = file;
-       
-       DLIST_ADD(smbc_compat_fdlist, f);
+       DLIST_ADD(smbc_compat_fd_in_use, f);
 
        return f->fd;
 }
@@ -74,18 +91,22 @@ static int add_fd(SMBCFILE * file)
 
 
 /* Delete an fd, returns 0 on success */
-static int del_fd(int fd)
+static int
+del_fd(int fd)
 {
-       struct smbc_compat_fdlist * f = smbc_compat_fdlist;
+       struct smbc_compat_fdlist * f = smbc_compat_fd_in_use;
+
        while (f) {
                if (f->fd == fd) 
                        break;
                f = f->next;
        }
+
        if (f) {
                /* found */
-               DLIST_REMOVE(smbc_compat_fdlist, f);
-               SAFE_FREE(f);
+               DLIST_REMOVE(smbc_compat_fd_in_use, f);
+                f->file = NULL;
+                DLIST_ADD(smbc_compat_fd_avail, f);
                return 0;
        }
        return 1;
@@ -93,15 +114,17 @@ static int del_fd(int fd)
  
 
 
-int smbc_init(smbc_get_auth_data_fn fn, int debug)
+int
+smbc_init(smbc_get_auth_data_fn fn,
+          int debug)
 {
        if (!smbc_compat_initialized) {
                statcont = smbc_new_context();
                if (!statcont) 
                        return -1;
 
-               statcont->debug = debug;
-               statcont->callbacks.auth_fn = fn;
+                smbc_setDebug(statcont, debug);
+                smbc_setFunctionAuthData(statcont, fn);
                
                if (!smbc_init_context(statcont)) {
                        smbc_free_context(statcont, False);
@@ -116,170 +139,404 @@ int smbc_init(smbc_get_auth_data_fn fn, int debug)
 }
 
 
-int smbc_open(const char *furl, int flags, mode_t mode)
+SMBCCTX *
+smbc_set_context(SMBCCTX * context)
+{
+        SMBCCTX *old_context = statcont;
+
+        if (context) {
+                /* Save provided context.  It must have been initialized! */
+                statcont = context;
+
+                /* You'd better know what you're doing.  We won't help you. */
+               smbc_compat_initialized = 1;
+        }
+        
+        return old_context;
+}
+
+
+int
+smbc_open(const char *furl,
+          int flags,
+          mode_t mode)
 {
        SMBCFILE * file;
        int fd;
 
-       file = statcont->open(statcont, furl, flags, mode);
+        file = smbc_getFunctionOpen(statcont)(statcont, furl, flags, mode);
        if (!file)
                return -1;
 
        fd = add_fd(file);
        if (fd == -1) 
-               statcont->close(statcont, file);
+                smbc_getFunctionClose(statcont)(statcont, file);
        return fd;
 }
 
 
-int smbc_creat(const char *furl, mode_t mode)
+int
+smbc_creat(const char *furl,
+           mode_t mode)
 {
        SMBCFILE * file;
        int fd;
 
-       file = statcont->creat(statcont, furl, mode);
+        file = smbc_getFunctionCreat(statcont)(statcont, furl, mode);
        if (!file)
                return -1;
 
        fd = add_fd(file);
        if (fd == -1) {
                /* Hmm... should we delete the file too ? I guess we could try */
-               statcont->close(statcont, file);
-               statcont->unlink(statcont, furl);
+                smbc_getFunctionClose(statcont)(statcont, file);
+                smbc_getFunctionUnlink(statcont)(statcont, furl);
        }
        return fd;
 }
 
 
-ssize_t smbc_read(int fd, void *buf, size_t bufsize)
+ssize_t
+smbc_read(int fd,
+          void *buf,
+          size_t bufsize)
 {
        SMBCFILE * file = find_fd(fd);
-       return statcont->read(statcont, file, buf, bufsize);
+        return smbc_getFunctionRead(statcont)(statcont, file, buf, bufsize);
 }
 
-ssize_t smbc_write(int fd, void *buf, size_t bufsize)
+ssize_t
+smbc_write(int fd,
+           void *buf,
+           size_t bufsize)
 {
        SMBCFILE * file = find_fd(fd);
-       return statcont->write(statcont, file, buf, bufsize);
+        return smbc_getFunctionWrite(statcont)(statcont, file, buf, bufsize);
 }
 
-off_t smbc_lseek(int fd, off_t offset, int whence)
+off_t
+smbc_lseek(int fd,
+           off_t offset,
+           int whence)
 {
        SMBCFILE * file = find_fd(fd);
-       return statcont->lseek(statcont, file, offset, whence);
+        return smbc_getFunctionLseek(statcont)(statcont, file, offset, whence);
 }
 
-int smbc_close(int fd)
+int
+smbc_close(int fd)
 {
        SMBCFILE * file = find_fd(fd);
        del_fd(fd);
-       return statcont->close(statcont, file);
+        return smbc_getFunctionClose(statcont)(statcont, file);
 }
 
-int smbc_unlink(const char *fname)
+int
+smbc_unlink(const char *fname)
 {
-        return statcont->unlink(statcont, fname);
+        return smbc_getFunctionUnlink(statcont)(statcont, fname);
 }
 
-int smbc_rename(const char *ourl, const char *nurl)
+int
+smbc_rename(const char *ourl,
+            const char *nurl)
 {
-       return statcont->rename(statcont, ourl, statcont, nurl);
+        return smbc_getFunctionRename(statcont)(statcont, ourl,
+                                                statcont, nurl);
 }
 
-int smbc_opendir(const char *durl)
+int
+smbc_opendir(const char *durl)
 {
        SMBCFILE * file;
        int fd;
 
-       file = statcont->opendir(statcont, durl);
+        file = smbc_getFunctionOpendir(statcont)(statcont, durl);
        if (!file)
                return -1;
 
        fd = add_fd(file);
        if (fd == -1) 
-               statcont->closedir(statcont, file);
+                smbc_getFunctionClosedir(statcont)(statcont, file);
 
        return fd;
 }
 
-int smbc_closedir(int dh) 
+int
+smbc_closedir(int dh) 
 {
        SMBCFILE * file = find_fd(dh);
        del_fd(dh);
-       return statcont->closedir(statcont, file);
+        return smbc_getFunctionClosedir(statcont)(statcont, file);
 }
 
-int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count)
+int
+smbc_getdents(unsigned int dh,
+              struct smbc_dirent *dirp,
+              int count)
 {
        SMBCFILE * file = find_fd(dh);
-       return statcont->getdents(statcont, file,dirp, count);
+        return smbc_getFunctionGetdents(statcont)(statcont, file, dirp, count);
 }
 
-struct smbc_dirent* smbc_readdir(unsigned int dh)
+struct smbc_dirent *
+smbc_readdir(unsigned int dh)
 {
        SMBCFILE * file = find_fd(dh);
-       return statcont->readdir(statcont, file);
+        return smbc_getFunctionReaddir(statcont)(statcont, file);
 }
 
-off_t smbc_telldir(int dh)
+off_t
+smbc_telldir(int dh)
 {
        SMBCFILE * file = find_fd(dh);
-       return statcont->telldir(statcont, file);
+        return smbc_getFunctionTelldir(statcont)(statcont, file);
+}
+
+int
+smbc_lseekdir(int fd,
+              off_t offset)
+{
+       SMBCFILE * file = find_fd(fd);
+        return smbc_getFunctionLseekdir(statcont)(statcont, file, offset);
+}
+
+int
+smbc_mkdir(const char *durl,
+           mode_t mode)
+{
+        return smbc_getFunctionMkdir(statcont)(statcont, durl, mode);
+}
+
+int
+smbc_rmdir(const char *durl)
+{
+        return smbc_getFunctionRmdir(statcont)(statcont, durl);
+}
+
+int
+smbc_stat(const char *url,
+          struct stat *st)
+{
+        return smbc_getFunctionStat(statcont)(statcont, url, st);
+}
+
+int
+smbc_fstat(int fd,
+           struct stat *st)
+{
+       SMBCFILE * file = find_fd(fd);
+        return smbc_getFunctionFstat(statcont)(statcont, file, st);
+}
+
+int
+smbc_ftruncate(int fd,
+               off_t size)
+{
+       SMBCFILE * file = find_fd(fd);
+        return smbc_getFunctionFtruncate(statcont)(statcont, file, size);
+}
+
+int
+smbc_chmod(const char *url,
+           mode_t mode)
+{
+        return smbc_getFunctionChmod(statcont)(statcont, url, mode);
+}
+
+int
+smbc_utimes(const char *fname,
+            struct timeval *tbuf)
+{
+        return smbc_getFunctionUtimes(statcont)(statcont, fname, tbuf);
+}
+
+#ifdef HAVE_UTIME_H
+int
+smbc_utime(const char *fname,
+           struct utimbuf *utbuf)
+{
+        struct timeval tv[2];
+
+        if (utbuf == NULL)
+                return smbc_getFunctionUtimes(statcont)(statcont, fname, NULL);
+
+        tv[0].tv_sec = utbuf->actime;
+        tv[1].tv_sec = utbuf->modtime;
+        tv[0].tv_usec = tv[1].tv_usec = 0;
+
+        return smbc_getFunctionUtimes(statcont)(statcont, fname, tv);
+}
+#endif
+
+int
+smbc_setxattr(const char *fname,
+              const char *name,
+              const void *value,
+              size_t size,
+              int flags)
+{
+        return smbc_getFunctionSetxattr(statcont)(statcont,
+                                                  fname, name,
+                                                  value, size, flags);
+}
+
+int
+smbc_lsetxattr(const char *fname,
+               const char *name,
+               const void *value,
+               size_t size,
+               int flags)
+{
+        return smbc_getFunctionSetxattr(statcont)(statcont,
+                                                  fname, name,
+                                                  value, size, flags);
 }
 
-int smbc_lseekdir(int fd, off_t offset)
+int
+smbc_fsetxattr(int fd,
+               const char *name,
+               const void *value,
+               size_t size,
+               int flags)
 {
        SMBCFILE * file = find_fd(fd);
-       return statcont->lseekdir(statcont, file, offset);
+       if (file == NULL) {
+               errno = EBADF;
+               return -1;
+       }
+        return smbc_getFunctionSetxattr(statcont)(statcont,
+                                                  file->fname, name,
+                                                  value, size, flags);
 }
 
-int smbc_mkdir(const char *durl, mode_t mode)
+int
+smbc_getxattr(const char *fname,
+              const char *name,
+              const void *value,
+              size_t size)
 {
-       return statcont->mkdir(statcont, durl, mode);
+        return smbc_getFunctionGetxattr(statcont)(statcont,
+                                                  fname, name,
+                                                  value, size);
 }
 
-int smbc_rmdir(const char *durl)
+int
+smbc_lgetxattr(const char *fname,
+               const char *name,
+               const void *value,
+               size_t size)
 {
-       return statcont->rmdir(statcont, durl);
+        return smbc_getFunctionGetxattr(statcont)(statcont,
+                                                  fname, name,
+                                                  value, size);
 }
 
-int smbc_stat(const char *url, struct stat *st)
+int
+smbc_fgetxattr(int fd,
+               const char *name,
+               const void *value,
+               size_t size)
 {
-       return statcont->stat(statcont, url, st);
+       SMBCFILE * file = find_fd(fd);
+       if (file == NULL) {
+               errno = EBADF;
+               return -1;
+       }
+        return smbc_getFunctionGetxattr(statcont)(statcont,
+                                                  file->fname, name,
+                                                  value, size);
+}
+
+int
+smbc_removexattr(const char *fname,
+                 const char *name)
+{
+        return smbc_getFunctionRemovexattr(statcont)(statcont, fname, name);
+}
+
+int
+smbc_lremovexattr(const char *fname,
+                  const char *name)
+{
+        return smbc_getFunctionRemovexattr(statcont)(statcont, fname, name);
 }
 
-int smbc_fstat(int fd, struct stat *st)
+int
+smbc_fremovexattr(int fd,
+                  const char *name)
 {
        SMBCFILE * file = find_fd(fd);
-       return statcont->fstat(statcont, file, st);
+       if (file == NULL) {
+               errno = EBADF;
+               return -1;
+       }
+        return smbc_getFunctionRemovexattr(statcont)(statcont,
+                                                     file->fname, name);
 }
 
-int smbc_chmod(const char *url, mode_t mode)
+int
+smbc_listxattr(const char *fname,
+               char *list,
+               size_t size)
 {
-       /* NOT IMPLEMENTED IN LIBSMBCLIENT YET */
-       return -1;
+        return smbc_getFunctionListxattr(statcont)(statcont,
+                                                   fname, list, size);
 }
 
-int smbc_print_file(const char *fname, const char *printq)
+int
+smbc_llistxattr(const char *fname,
+                char *list,
+                size_t size)
 {
-       return statcont->print_file(statcont, fname, statcont, printq);
+        return smbc_getFunctionListxattr(statcont)(statcont,
+                                                   fname, list, size);
 }
 
-int smbc_open_print_job(const char *fname)
+int
+smbc_flistxattr(int fd,
+                char *list,
+                size_t size)
 {
-       SMBCFILE * file = statcont->open_print_job(statcont, fname);
+       SMBCFILE * file = find_fd(fd);
+       if (file == NULL) {
+               errno = EBADF;
+               return -1;
+       }
+        return smbc_getFunctionListxattr(statcont)(statcont,
+                                                   file->fname, list, size);
+}
+
+int
+smbc_print_file(const char *fname,
+                const char *printq)
+{
+        return smbc_getFunctionPrintFile(statcont)(statcont, fname,
+                                                   statcont, printq);
+}
+
+int
+smbc_open_print_job(const char *fname)
+{
+        SMBCFILE * file;
+
+        file = smbc_getFunctionOpenPrintJob(statcont)(statcont, fname);
        if (!file) return -1;
-       return (int) file;
+       return file->cli_fd;
 }
 
-int smbc_list_print_jobs(const char *purl, smbc_get_print_job_info fn)
+int
+smbc_list_print_jobs(const char *purl,
+                     smbc_list_print_job_fn fn)
 {
-       return statcont->list_print_jobs(statcont, purl, fn);
+        return smbc_getFunctionListPrintJobs(statcont)(statcont, purl, fn);
 }
 
-int smbc_unlink_print_job(const char *purl, int id)
+int
+smbc_unlink_print_job(const char *purl,
+                      int id)
 {
-       return statcont->unlink_print_job(statcont, purl, id);
+        return smbc_getFunctionUnlinkPrintJob(statcont)(statcont, purl, id);
 }