diff options
Diffstat (limited to 'source3/libsmb/libsmb_file.c')
-rw-r--r-- | source3/libsmb/libsmb_file.c | 393 |
1 files changed, 199 insertions, 194 deletions
diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 62b990ed00..73c9b96978 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -37,7 +37,11 @@ SMBC_open_ctx(SMBCCTX *context, int flags, mode_t mode) { - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; @@ -45,38 +49,38 @@ SMBC_open_ctx(SMBCCTX *context, SMBCFILE *file = NULL; int fd; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return NULL; - + } - + if (!fname) { - + errno = EINVAL; TALLOC_FREE(frame); return NULL; - + } - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return NULL; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -85,62 +89,63 @@ SMBC_open_ctx(SMBCCTX *context, return NULL; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { if (errno == EPERM) errno = EACCES; TALLOC_FREE(frame); return NULL; /* SMBC_server sets errno */ } - + /* Hmmm, the test for a directory is suspect here ... FIXME */ - + if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') { fd = -1; } else { file = SMB_MALLOC_P(SMBCFILE); - + if (!file) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + ZERO_STRUCTP(file); - + /*d_printf(">>>open: resolving %s\n", path);*/ - if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); SAFE_FREE(file); TALLOC_FREE(frame); return NULL; } /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/ - + if ((fd = cli_open(targetcli, targetpath, flags, context->internal->share_mode)) < 0) { - + /* Handle the error ... */ - + SAFE_FREE(file); errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return NULL; - + } - + /* Fill in file struct */ - + file->cli_fd = fd; file->fname = SMB_STRDUP(fname); file->srv = srv; file->offset = 0; file->file = True; - + DLIST_ADD(context->internal->files, file); - + /* * If the file was opened in O_APPEND mode, all write * operations should be appended to the file. To do that, @@ -171,51 +176,50 @@ SMBC_open_ctx(SMBCCTX *context, return NULL; } } - + TALLOC_FREE(frame); return file; - + } - + /* Check if opendir needed ... */ - + if (fd == -1) { int eno = 0; - + eno = SMBC_errno(context, srv->cli); file = (context->posix_emu.opendir_fn)(context, fname); if (!file) errno = eno; TALLOC_FREE(frame); return file; - + } - + errno = EINVAL; /* FIXME, correct errno ? */ TALLOC_FREE(frame); return NULL; - + } /* * Routine to create a file */ -static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC; /* FIXME: Do we need this */ - SMBCFILE * SMBC_creat_ctx(SMBCCTX *context, const char *path, mode_t mode) { - + if (!context || !context->internal->initialized) { - + errno = EINVAL; return NULL; - + } - - return SMBC_open_ctx(context, path, creat_bits, mode); + + return SMBC_open_ctx(context, path, + O_WRONLY | O_CREAT | O_TRUNC, mode); } /* @@ -234,7 +238,7 @@ SMBC_read_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + /* * offset: * @@ -245,51 +249,51 @@ SMBC_read_ctx(SMBCCTX *context, * retrieving data at an offset greater than 4GB. */ off_t offset; - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); - + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + offset = file->offset; - + /* Check that the buffer exists ... */ - + if (buf == NULL) { errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + /*d_printf(">>>read: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, - context, - file->fname, - NULL, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + file->fname, + NULL, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + /*d_printf(">>>read: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { @@ -298,24 +302,24 @@ SMBC_read_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/ - + ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count); - + if (ret < 0) { - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } - + file->offset += ret; - + DEBUG(4, (" --> %d\n", ret)); - + TALLOC_FREE(frame); return ret; /* Success, ret bytes of data ... */ - + } /* @@ -335,50 +339,50 @@ SMBC_write_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + /* First check all pointers before dereferencing them */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } - + /* Check that the buffer exists ... */ - + if (buf == NULL) { errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */ - + /*d_printf(">>>write: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, - context, - file->fname, - NULL, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + file->fname, + NULL, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + /*d_printf(">>>write: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { @@ -387,18 +391,19 @@ SMBC_write_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>write: resolved path as %s\n", targetpath);*/ - - ret = cli_write(targetcli, file->cli_fd, 0, (char *)buf, offset, count); - + + ret = cli_write(targetcli, file->cli_fd, + 0, (char *)buf, offset, count); + if (ret <= 0) { errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } - + file->offset += ret; - + TALLOC_FREE(frame); return ret; /* Success, 0 bytes of data ... */ } @@ -417,42 +422,42 @@ SMBC_close_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } - + /* IS a dir ... */ if (!file->file) { TALLOC_FREE(frame); return (context->posix_emu.closedir_fn)(context, file); } - + /*d_printf(">>>close: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, - context, - file->fname, - NULL, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + file->fname, + NULL, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + /*d_printf(">>>close: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { @@ -461,9 +466,9 @@ SMBC_close_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>close: resolved path as %s\n", targetpath);*/ - + if (!cli_close(targetcli, file->cli_fd)) { - + DEBUG(3, ("cli_close failed on %s. purging server.\n", file->fname)); /* Deallocate slot and remove the server @@ -476,14 +481,14 @@ SMBC_close_ctx(SMBCCTX *context, (context->server.remove_unused_server_fn)(context, srv); TALLOC_FREE(frame); return -1; - + } - + DLIST_REMOVE(context->internal->files, file); SAFE_FREE(file->fname); SAFE_FREE(file); TALLOC_FREE(frame); - + return 0; } @@ -508,14 +513,14 @@ SMBC_getatr(SMBCCTX * context, struct cli_state *targetcli = NULL; time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; } - + /* path fixup for . and .. */ if (strequal(path, ".") || strequal(path, "..")) { fixedpath = talloc_strdup(frame, "\\"); @@ -535,14 +540,14 @@ SMBC_getatr(SMBCCTX * context, trim_string(fixedpath, NULL, "\\."); } DEBUG(4,("SMBC_getatr: sending qpathinfo\n")); - + if (!cli_resolve_path(frame, "", srv->cli, fixedpath, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Couldn't resolve %s\n", path); TALLOC_FREE(frame); return False; } - + if (!srv->no_pathinfo2 && cli_qpathinfo2(targetcli, targetpath, create_time_ts, @@ -553,45 +558,45 @@ SMBC_getatr(SMBCCTX * context, TALLOC_FREE(frame); return True; } - + /* if this is NT then don't bother with the getatr */ if (targetcli->capabilities & CAP_NT_SMBS) { errno = EPERM; TALLOC_FREE(frame); return False; } - + if (cli_getatr(targetcli, targetpath, mode, size, &write_time)) { - + struct timespec w_time_ts; - + w_time_ts = convert_time_t_to_timespec(write_time); - + if (write_time_ts != NULL) { *write_time_ts = w_time_ts; } - + if (create_time_ts != NULL) { *create_time_ts = w_time_ts; } - + if (access_time_ts != NULL) { *access_time_ts = w_time_ts; } - + if (change_time_ts != NULL) { *change_time_ts = w_time_ts; } - + srv->no_pathinfo2 = True; TALLOC_FREE(frame); return True; } - + errno = EPERM; TALLOC_FREE(frame); return False; - + } /* @@ -615,7 +620,7 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, int fd; int ret; TALLOC_CTX *frame = talloc_stackframe(); - + /* * First, try setpathinfo (if qpathinfo succeeded), for it is the * modern function for "new code" to be using, and it works given a @@ -629,7 +634,7 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, write_time, change_time, mode)) { - + /* * setpathinfo is not supported; go to plan B. * @@ -639,27 +644,27 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, * cli_setattrE() which should work on all OS versions, and * supports both times. */ - + /* Don't try {q,set}pathinfo() again, with this server */ srv->no_pathinfo = True; - + /* Open the file */ if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) { - + errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return -1; } - + /* Set the new attributes */ ret = cli_setattrE(srv->cli, fd, change_time, access_time, write_time); - + /* Close the file */ cli_close(srv->cli, fd); - + /* * Unfortunately, setattrE() doesn't have a provision for * setting the access mode (attributes). We'll have to try @@ -669,14 +674,14 @@ SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, if (ret && mode != (uint16) -1) { ret = cli_setatr(srv->cli, path, mode, 0); } - + if (! ret) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return False; } } - + TALLOC_FREE(frame); return True; } @@ -697,56 +702,56 @@ SMBC_lseek_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (!file->file) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; /* Can't lseek a dir ... */ - + } - + switch (whence) { case SEEK_SET: file->offset = offset; break; - + case SEEK_CUR: file->offset += offset; break; - + case SEEK_END: /*d_printf(">>>lseek: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, - context, - file->fname, - NULL, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + file->fname, + NULL, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + /*d_printf(">>>lseek: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { @@ -755,32 +760,32 @@ SMBC_lseek_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/ - + if (!cli_qfileinfo(targetcli, file->cli_fd, NULL, &size, NULL, NULL, NULL, NULL, NULL)) { - SMB_OFF_T b_size = size; + SMB_OFF_T b_size = size; if (!cli_getattrE(targetcli, file->cli_fd, NULL, &b_size, NULL, NULL, NULL)) - { - errno = EINVAL; - TALLOC_FREE(frame); - return -1; - } else - size = b_size; + { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } else + size = b_size; } file->offset = size + offset; break; - + default: errno = EINVAL; break; - + } - + TALLOC_FREE(frame); return file->offset; - + } @@ -802,26 +807,26 @@ SMBC_ftruncate_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!file || !SMBC_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, @@ -837,7 +842,7 @@ SMBC_ftruncate_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + /*d_printf(">>>fstat: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { @@ -846,14 +851,14 @@ SMBC_ftruncate_ctx(SMBCCTX *context, 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; - + } |