add smbc_ftruncate() to emulate POSIX ftruncate()
authorDerrell Lipman <derrell.lipman@unwireduniverse.com>
Wed, 27 Feb 2008 02:44:51 +0000 (21:44 -0500)
committerDerrell Lipman <derrell.lipman@unwireduniverse.com>
Wed, 27 Feb 2008 02:44:51 +0000 (21:44 -0500)
source/include/libsmbclient.h
source/libsmb/libsmb_compat.c
source/libsmb/libsmbclient.c

index 07242f795675005bbd6eb86fc0f8f89266bdff08..64afc094991b0faa1361fc913420eee145796ee4 100644 (file)
@@ -427,6 +427,8 @@ struct _SMBCCTX {
        off_t      (*lseek)   (SMBCCTX *c, SMBCFILE * file, off_t offset, int whence);
        int        (*stat)    (SMBCCTX *c, const char *fname, struct stat *st);
        int        (*fstat)   (SMBCCTX *c, SMBCFILE *file, struct stat *st);
+        /* ftruncate added near _internal for ABI compatibility */
+                
        int        (*close_fn) (SMBCCTX *c, SMBCFILE *file);
 
        /** callable functions for dirs
@@ -520,6 +522,12 @@ struct _SMBCCTX {
        int flags;
        
         /** user options selections that apply to this session
+         *
+         *  NEW OPTIONS ARE NOT ADDED HERE!
+         *
+         *  We must maintain ABI backward compatibility.  We now use
+         *  smbc_option_set() and smbc_option_get() for all newly added
+         *  options.
          */
         struct _smbc_options {
 
@@ -580,6 +588,9 @@ struct _SMBCCTX {
                 int one_share_per_server;
         } options;
        
+        /* Add additional functions here for ABI backward compatibility */
+        int        (*ftruncate)(SMBCCTX *c, SMBCFILE *f, off_t size);
+
        /** INTERNAL DATA
         * do _NOT_ touch this from your program !
         */
@@ -1193,6 +1204,26 @@ int smbc_stat(const char *url, struct stat *st);
 int smbc_fstat(int fd, struct stat *st);
 
 
+/**@ingroup attribute
+ * Truncate a file given a file descriptor
+ * 
+ * @param fd        Open file handle from smbc_open() or smbc_creat()
+ *
+ * @param size      size to truncate the file to
+ * 
+ * @return          EBADF  filedes is bad.
+ *                  - EACCES Permission denied.
+ *                  - EBADF fd is not a valid file descriptor
+ *                  - EINVAL Problems occurred in the underlying routines
+ *                   or smbc_init not called.
+ *                  - ENOMEM Out of memory
+ *
+ * @see             , Unix ftruncate()
+ *
+ */
+int smbc_ftruncate(int fd, off_t size);
+
+
 /**@ingroup attribue
  * Change the ownership of a file or directory.
  *
index 573d087d6e30c4de94e9ebe2272f3f67f725683d..6042464fd231501c303d04818a942bee64bad62a 100644 (file)
@@ -289,6 +289,12 @@ int smbc_fstat(int fd, struct stat *st)
        return (statcont->fstat)(statcont, file, st);
 }
 
+int smbc_ftruncate(int fd, off_t size)
+{
+       SMBCFILE * file = find_fd(fd);
+       return (statcont->ftruncate)(statcont, file, size);
+}
+
 int smbc_chmod(const char *url, mode_t mode)
 {
        return (statcont->chmod)(statcont, url, mode);
index e84de596374e7be61794e53cc99f0822b187295f..fe008ed6b670dfac357a151689e3a02ba75adf86 100644 (file)
@@ -2482,6 +2482,80 @@ smbc_fstat_ctx(SMBCCTX *context,
 
 }
 
+/*
+ * Routine to truncate a file given by its file descriptor, to a specified size
+ */
+
+static int
+smbc_ftruncate_ctx(SMBCCTX *context,
+                   SMBCFILE *file,
+                   off_t length)
+{
+       SMB_OFF_T size = length;
+       char *server = NULL;
+       char *share = NULL;
+       char *user = NULL;
+       char *password = NULL;
+       char *path = NULL;
+        char *targetpath = NULL;
+       struct cli_state *targetcli = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       if (!context || !context->internal ||
+           !context->internal->_initialized) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+               errno = EBADF;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       if (!file->file) {
+               errno = EINVAL;
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
+       if (smbc_parse_path(frame,
+                            context,
+                            file->fname,
+                            NULL,
+                            &server,
+                            &share,
+                            &path,
+                            &user,
+                            &password,
+                            NULL)) {
+                errno = EINVAL;
+               TALLOC_FREE(frame);
+                return -1;
+        }
+
+       /*d_printf(">>>fstat: resolving %s\n", path);*/
+       if (!cli_resolve_path(frame, "", file->srv->cli, path,
+                              &targetcli, &targetpath)) {
+               d_printf("Could not resolve %s\n", path);
+               TALLOC_FREE(frame);
+               return -1;
+       }
+       /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
+
+        if (!cli_ftruncate(targetcli, file->cli_fd, size)) {
+                errno = EINVAL;
+                TALLOC_FREE(frame);
+                return -1;
+        }
+
+       TALLOC_FREE(frame);
+       return 0;
+
+}
+
 /*
  * Routine to open a directory
  * We accept the URL syntax explained in smbc_parse_path(), above.
@@ -6703,6 +6777,7 @@ smbc_new_context(void)
         context->telldir                           = smbc_telldir_ctx;
         context->lseekdir                          = smbc_lseekdir_ctx;
         context->fstatdir                          = smbc_fstatdir_ctx;
+        context->ftruncate                         = smbc_ftruncate_ctx;
         context->chmod                             = smbc_chmod_ctx;
         context->utimes                            = smbc_utimes_ctx;
         context->setxattr                          = smbc_setxattr_ctx;