📄 smbw.c
字号:
/* Unix SMB/Netbios implementation. Version 2.0 SMB wrapper functions Copyright (C) Andrew Tridgell 1998 Copyright (C) Derrell Lipman 2003-2005 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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.*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <stdarg.h>#include <assert.h>#include "smbw.h"#include "bsd-strlfunc.h"typedef enum StartupType{ StartupType_Fake, StartupType_Real} StartupType;int smbw_fd_map[__FD_SETSIZE];int smbw_ref_count[__FD_SETSIZE];char smbw_cwd[PATH_MAX];char smbw_prefix[] = SMBW_PREFIX;/* needs to be here because of dumb include files on some systems */int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;int smbw_initialized = 0;static int debug_level = 0;static SMBCCTX *smbw_ctx;extern int smbw_debug;/*****************************************************smbw_ref -- manipulate reference counts******************************************************/int smbw_ref(int client_fd, Ref_Count_Type type, ...){ va_list ap; /* client id values begin at SMBC_BASE_FC. */ client_fd -= SMBC_BASE_FD; va_start(ap, type); switch(type) { case SMBW_RCT_Increment: return ++smbw_ref_count[client_fd]; case SMBW_RCT_Decrement: return --smbw_ref_count[client_fd]; case SMBW_RCT_Get: return smbw_ref_count[client_fd]; case SMBW_RCT_Set: return (smbw_ref_count[client_fd] = va_arg(ap, int)); } va_end(ap); /* never gets here */ return -1;}/* * Return a username and password given a server and share name * * Returns 0 upon success; * non-zero otherwise, and errno is set to indicate the error. */static void get_envvar_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen){ char *u; char *p; char *w; /* Fall back to environment variables */ w = getenv("WORKGROUP"); if (w == NULL) w = ""; u = getenv("USER"); if (u == NULL) u = ""; p = getenv("PASSWORD"); if (p == NULL) p = ""; smbw_strlcpy(wg, w, wglen); smbw_strlcpy(un, u, unlen); smbw_strlcpy(pw, p, pwlen);}static smbc_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;/*****************************************************set the get auth data function******************************************************/void smbw_set_auth_data_fn(smbc_get_auth_data_fn fn){ get_auth_data_fn = fn;}/*****************************************************ensure that all connections are terminated upon exit******************************************************/static void do_shutdown(void){ if (smbw_ctx != NULL) { smbc_free_context(smbw_ctx, 1); }}/***************************************************** initialise structures*******************************************************/static void do_init(StartupType startupType){ int i; char *p; smbw_initialized = 1; /* this must be first to avoid recursion! */ smbw_ctx = NULL; /* don't free context until it's established */ /* initially, no file descriptors are mapped */ for (i = 0; i < __FD_SETSIZE; i++) { smbw_fd_map[i] = -1; smbw_ref_count[i] = 0; } /* See if we've been told to start in a particular directory */ if ((p=getenv("SMBW_DIR")) != NULL) { smbw_strlcpy(smbw_cwd, p, PATH_MAX); /* we don't want the old directory to be busy */ (* smbw_libc.chdir)("/"); } else { *smbw_cwd = '\0'; } if ((p=getenv("DEBUG"))) { debug_level = atoi(p); } if ((smbw_ctx = smbc_new_context()) == NULL) { fprintf(stderr, "Could not create a context.\n"); exit(1); } smbw_ctx->debug = debug_level; smbw_ctx->callbacks.auth_fn = get_auth_data_fn; smbw_ctx->options.browse_max_lmb_count = 0; smbw_ctx->options.urlencode_readdir_entries = 1; smbw_ctx->options.one_share_per_server = 1; if (smbc_init_context(smbw_ctx) == NULL) { fprintf(stderr, "Could not initialize context.\n"); exit(1); } smbc_set_context(smbw_ctx); /* if not real startup, exit handler has already been established */ if (startupType == StartupType_Real) { atexit(do_shutdown); }}/***************************************************** initialise structures, real start up vs a fork()*******************************************************/void smbw_init(void){ do_init(StartupType_Real);}/***************************************************** determine if a file descriptor is a smb one*******************************************************/int smbw_fd(int smbw_fd){ SMBW_INIT(); return (smbw_fd >= 0 && smbw_fd < __FD_SETSIZE && smbw_fd_map[smbw_fd] >= SMBC_BASE_FD); /* minimum smbc_ fd */}/***************************************************** determine if a path is a smb one*******************************************************/int smbw_path(const char *name){ int len; int ret; int saved_errno; saved_errno = errno; SMBW_INIT(); len = strlen(smbw_prefix); ret = ((strncmp(name, smbw_prefix, len) == 0 && (name[len] == '\0' || name[len] == '/')) || (*name != '/' && *smbw_cwd != '\0')); errno = saved_errno; return ret;}/***************************************************** remove redundent stuff from a filename*******************************************************/void smbw_clean_fname(char *name){ char *p, *p2; int l; int modified = 1; if (!name) return; DEBUG(10, ("Clean [%s]...\n", name)); while (modified) { modified = 0; if ((p=strstr(name,"/./"))) { modified = 1; while (*p) { p[0] = p[2]; p++; } DEBUG(10, ("\tclean 1 (/./) produced [%s]\n", name)); } if ((p=strstr(name,"//"))) { modified = 1; while (*p) { p[0] = p[1]; p++; } DEBUG(10, ("\tclean 2 (//) produced [%s]\n", name)); } if (strcmp(name,"/../")==0) { modified = 1; name[1] = 0; DEBUG(10,("\tclean 3 (^/../$) produced [%s]\n", name)); } if ((p=strstr(name,"/../"))) { modified = 1; for (p2 = (p > name ? p-1 : p); p2 > name; p2--) { if (p2[0] == '/') break; } if (p2 > name) p2++; while (*p2) { p2[0] = p[3]; p2++; p++; } DEBUG(10, ("\tclean 4 (/../) produced [%s]\n", name)); } if (strcmp(name,"/..")==0) { modified = 1; name[1] = 0; DEBUG(10, ("\tclean 5 (^/..$) produced [%s]\n", name)); } l = strlen(name); p = l>=3?(name+l-3):name; if (strcmp(p,"/..")==0) { modified = 1; for (p2=p-1;p2>name;p2--) { if (p2[0] == '/') break; } if (p2==name) { p[0] = '/'; p[1] = 0; } else { p2[0] = 0; } DEBUG(10, ("\tclean 6 (/..) produced [%s]\n", name)); } l = strlen(name); p = l>=2?(name+l-2):name; if (strcmp(p,"/.")==0) { modified = 1; if (p == name) { p[1] = 0; } else { p[0] = 0; } DEBUG(10, ("\tclean 7 (/.) produced [%s]\n", name)); } if (strncmp(p=name,"./",2) == 0) { modified = 1; do { p[0] = p[2]; } while (*p++); DEBUG(10, ("\tclean 8 (^./) produced [%s]\n", name)); } l = strlen(p=name); if (l > 1 && p[l-1] == '/') { modified = 1; p[l-1] = 0; DEBUG(10, ("\tclean 9 (/) produced [%s]\n", name)); } }}void smbw_fix_path(const char *src, char *dest){ const char *p; int len = strlen(smbw_prefix); if (*src == '/') { for (p = src + len; *p == '/'; p++) ; snprintf(dest, PATH_MAX, "smb://%s", p); } else { snprintf(dest, PATH_MAX, "%s/%s", smbw_cwd, src); } smbw_clean_fname(dest + 5); DEBUG(10, ("smbw_fix_path(%s) returning [%s]\n", src, dest));}/***************************************************** a wrapper for open()*******************************************************/int smbw_open(const char *fname, int flags, mode_t mode){ int client_fd; int smbw_fd; char path[PATH_MAX]; SMBW_INIT(); if (!fname) { errno = EINVAL; return -1; } smbw_fd = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200); if (smbw_fd == -1) { errno = EMFILE; return -1; } smbw_fix_path(fname, path); if (flags == creat_bits) { client_fd = smbc_creat(path, mode); } else { client_fd = smbc_open(path, flags, mode); } if (client_fd < 0) { (* smbw_libc.close)(smbw_fd); return -1; } smbw_fd_map[smbw_fd] = client_fd; smbw_ref(client_fd, SMBW_RCT_Increment); return smbw_fd;}/***************************************************** a wrapper for pread()there should really be an smbc_pread() to avoid the twolseek()s required in this kludge.*******************************************************/ssize_t smbw_pread(int smbw_fd, void *buf, size_t count, SMBW_OFF_T ofs){ int client_fd; ssize_t ret; int saved_errno; SMBW_OFF_T old_ofs; if (count == 0) { return 0; } client_fd = smbw_fd_map[smbw_fd]; if ((old_ofs = smbc_lseek(client_fd, 0, SEEK_CUR)) < 0 || smbc_lseek(client_fd, ofs, SEEK_SET) < 0) { return -1; } if ((ret = smbc_read(client_fd, buf, count)) < 0) { saved_errno = errno; (void) smbc_lseek(client_fd, old_ofs, SEEK_SET); errno = saved_errno; return -1; } return ret;}/***************************************************** a wrapper for read()*******************************************************/ssize_t smbw_read(int smbw_fd, void *buf, size_t count){ int client_fd; client_fd = smbw_fd_map[smbw_fd]; return smbc_read(client_fd, buf, count);} /***************************************************** a wrapper for write()*******************************************************/ssize_t smbw_write(int smbw_fd, void *buf, size_t count){ int client_fd; client_fd = smbw_fd_map[smbw_fd]; return smbc_write(client_fd, buf, count);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -