📄 libsmbclient.c
字号:
!context->internal->_initialized) { errno = EINVAL; /* Best I can think of ... */ return NULL; } if (!fname) { errno = EINVAL; return NULL; } if (smbc_parse_path(context, fname, server, sizeof(server), share, sizeof(share), path, sizeof(path), user, sizeof(user), password, sizeof(password), NULL, 0)) { errno = EINVAL; return NULL; } if (user[0] == (char)0) fstrcpy(user, context->user); fstrcpy(workgroup, context->workgroup); srv = smbc_server(context, True, server, share, workgroup, user, password); if (!srv) { if (errno == EPERM) errno = EACCES; 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; return NULL; } ZERO_STRUCTP(file); /*d_printf(">>>open: resolving %s\n", path);*/ if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return NULL; } /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/ if ( targetcli->dfsroot ) { pstring temppath; pstrcpy(temppath, targetpath); cli_dfs_make_full_path( targetpath, targetcli->desthost, targetcli->share, temppath); } if ((fd = cli_open(targetcli, targetpath, flags, DENY_NONE)) < 0) { /* Handle the error ... */ SAFE_FREE(file); errno = smbc_errno(context, targetcli); 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, * though, using this protocol, would require a getattrE() * call for each and every write, to determine where the end * of the file is. (There does not appear to be an append flag * in the protocol.) Rather than add all of that overhead of * retrieving the current end-of-file offset prior to each * write operation, we'll assume that most append operations * will continuously write, so we'll just set the offset to * the end of the file now and hope that's adequate. * * Note to self: If this proves inadequate, and O_APPEND * should, in some cases, be forced for each write, add a * field in the context options structure, for * "strict_append_mode" which would select between the current * behavior (if FALSE) or issuing a getattrE() prior to each * write and forcing the write to the end of the file (if * TRUE). Adding that capability will likely require adding * an "append" flag into the _SMBCFILE structure to track * whether a file was opened in O_APPEND mode. -- djl */ if (flags & O_APPEND) { if (smbc_lseek_ctx(context, file, 0, SEEK_END) < 0) { (void) smbc_close_ctx(context, file); errno = ENXIO; return NULL; } } return file; } /* Check if opendir needed ... */ if (fd == -1) { int eno = 0; eno = smbc_errno(context, &srv->cli); file = context->opendir(context, fname); if (!file) errno = eno; return file; } errno = EINVAL; /* FIXME, correct errno ? */ return NULL;}/* * Routine to create a file */static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC; /* FIXME: Do we need this */static SMBCFILE *smbc_creat_ctx(SMBCCTX *context, const char *path, mode_t mode){ if (!context || !context->internal || !context->internal->_initialized) { errno = EINVAL; return NULL; } return smbc_open_ctx(context, path, creat_bits, mode);}/* * Routine to read() a file ... */static ssize_tsmbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count){ int ret; fstring server, share, user, password; pstring path, targetpath; struct cli_state *targetcli; /* * offset: * * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) -- * appears to pass file->offset (which is type off_t) differently than * a local variable of type off_t. Using local variable "offset" in * the call to cli_read() instead of file->offset fixes a problem * retrieving data at an offset greater than 4GB. */ off_t offset = file->offset; if (!context || !context->internal || !context->internal->_initialized) { errno = EINVAL; return -1; } DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); if (!file || !DLIST_CONTAINS(context->internal->_files, file)) { errno = EBADF; return -1; } /* Check that the buffer exists ... */ if (buf == NULL) { errno = EINVAL; return -1; } /*d_printf(">>>read: parsing %s\n", file->fname);*/ if (smbc_parse_path(context, file->fname, server, sizeof(server), share, sizeof(share), path, sizeof(path), user, sizeof(user), password, sizeof(password), NULL, 0)) { errno = EINVAL; return -1; } /*d_printf(">>>read: resolving %s\n", path);*/ if (!cli_resolve_path("", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; } /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/ ret = cli_read(targetcli, file->cli_fd, buf, offset, count); if (ret < 0) { errno = smbc_errno(context, targetcli); return -1; } file->offset += ret; DEBUG(4, (" --> %d\n", ret)); return ret; /* Success, ret bytes of data ... */}/* * Routine to write() a file ... */static ssize_tsmbc_write_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count){ int ret; off_t offset; fstring server, share, user, password; pstring path, targetpath; struct cli_state *targetcli; offset = file->offset; /* See "offset" comment in smbc_read_ctx() */ if (!context || !context->internal || !context->internal->_initialized) { errno = EINVAL; return -1; } if (!file || !DLIST_CONTAINS(context->internal->_files, file)) { errno = EBADF; return -1; } /* Check that the buffer exists ... */ if (buf == NULL) { errno = EINVAL; return -1; } /*d_printf(">>>write: parsing %s\n", file->fname);*/ if (smbc_parse_path(context, file->fname, server, sizeof(server), share, sizeof(share), path, sizeof(path), user, sizeof(user), password, sizeof(password), NULL, 0)) { errno = EINVAL; return -1; } /*d_printf(">>>write: resolving %s\n", path);*/ if (!cli_resolve_path("", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); return -1; } /*d_printf(">>>write: resolved path as %s\n", targetpath);*/ ret = cli_write(targetcli, file->cli_fd, 0, buf, offset, count); if (ret <= 0) { errno = smbc_errno(context, targetcli); return -1; } file->offset += ret; return ret; /* Success, 0 bytes of data ... */} /* * Routine to close() a file ... */static intsmbc_close_ctx(SMBCCTX *context, SMBCFILE *file){ SMBCSRV *srv; fstring server, share, user, password; pstring path, targetpath; struct cli_state *targetcli; if (!context || !context->internal || !context->internal->_initialized) { errno = EINVAL; return -1; } if (!file || !DLIST_CONTAINS(context->internal->_files, file)) { errno = EBADF; return -1; } /* IS a dir ... */ if (!file->file) { return context->closedir(context, file); } /*d_printf(">>>close: parsing %s\n", file->fname);*/ if (smbc_parse_path(context, file->fname, server, sizeof(server), share, sizeof(share), path, sizeof(path), user, sizeof(user), password, sizeof(password), NULL, 0)) { errno = EINVAL; return -1; } /*d_printf(">>>close: resolving %s\n", path);*/ if (!cli_resolve_path("", &file->srv->cli, path, &targetcli, targetpath)) { d_printf("Could not resolve %s\n", path); 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 * from the server cache if unused */ errno = smbc_errno(context, targetcli); srv = file->srv; DLIST_REMOVE(context->internal->_files, file); SAFE_FREE(file->fname); SAFE_FREE(file); context->callbacks.remove_unused_server_fn(context, srv); return -1; } DLIST_REMOVE(context->internal->_files, file); SAFE_FREE(file->fname); SAFE_FREE(file); return 0;}/* * Get info from an SMB server on a file. Use a qpathinfo call first * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo */static BOOLsmbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path, uint16 *mode, SMB_OFF_T *size, time_t *c_time, time_t *a_time, time_t *m_time, SMB_INO_T *ino){ pstring fixedpath; pstring targetpath; struct cli_state *targetcli; if (!context || !context->internal || !context->internal->_initialized) { errno = EINVAL; return -1; } /* path fixup for . and .. */ if (strequal(path, ".") || strequal(path, "..")) pstrcpy(fixedpath, "\\"); else { pstrcpy(fixedpath, path); trim_string(fixedpath, NULL, "\\.."); trim_string(fixedpath, NULL, "\\."); } DEBUG(4,("smbc_getatr: sending qpathinfo\n")); if (!cli_resolve_path( "", &srv->cli, fixedpath, &targetcli, targetpath)) { d_printf("Couldn't resolve %s\n", path); return False; } if ( targetcli->dfsroot ) { pstring temppath; pstrcpy(temppath, targetpath); cli_dfs_make_full_path(targetpath, targetcli->desthost, targetcli->share, temppath); } if (!srv->no_pathinfo2 && cli_qpathinfo2(targetcli, targetpath, c_time, a_time, m_time, NULL, size, mode, ino)) { return True; } /* if this is NT then don't bother with the getatr */ if (targetcli->capabilities & CAP_NT_SMBS) { errno = EPERM; return False; } if (cli_getatr(targetcli, targetpath, mode, size, m_time)) { if (m_time != NULL) { if (a_time != NULL) *a_time = *m_time; if (c_time != NULL) *c_time = *m_time; } srv->no_pathinfo2 = True; return True; } errno = EPERM; return False;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -