trans2.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,183 行 · 第 1/5 页
C
2,183 行
/* Unix SMB/CIFS implementation. SMB transaction2 handling Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Volker Lendecke 2005 Copyright (C) Steve French 2005 Extensively modified by Andrew Tridgell, 1995 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 "includes.h"extern int max_send;extern enum protocol_types Protocol;extern int smb_read_error;extern uint32 global_client_caps;extern struct current_user current_user;#define get_file_size(sbuf) ((sbuf).st_size)#define DIR_ENTRY_SAFETY_MARGIN 4096/******************************************************************** Roundup a value to the nearest allocation roundup size boundary. Only do this for Windows clients.********************************************************************/SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val){ SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn)); /* Only roundup for Windows clients. */ enum remote_arch_types ra_type = get_remote_arch(); if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { val = SMB_ROUNDUP(val,rval); } return val;}/******************************************************************** Given a stat buffer return the allocated size on disk, taking into account sparse files.********************************************************************/SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf){ SMB_BIG_UINT ret; if(S_ISDIR(sbuf->st_mode)) { return 0; }#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;#else ret = (SMB_BIG_UINT)get_file_size(*sbuf);#endif if (fsp && fsp->initial_allocation_size) ret = MAX(ret,fsp->initial_allocation_size); return smb_roundup(conn, ret);}/**************************************************************************** Utility functions for dealing with extended attributes.****************************************************************************/static const char *prohibited_ea_names[] = { SAMBA_POSIX_INHERITANCE_EA_NAME, SAMBA_XATTR_DOS_ATTRIB, NULL};/**************************************************************************** Refuse to allow clients to overwrite our private xattrs.****************************************************************************/static BOOL samba_private_attr_name(const char *unix_ea_name){ int i; for (i = 0; prohibited_ea_names[i]; i++) { if (strequal( prohibited_ea_names[i], unix_ea_name)) return True; } return False;}/**************************************************************************** Get one EA value. Fill in a struct ea_struct.****************************************************************************/static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, char *ea_name, struct ea_struct *pea){ /* Get the value of this xattr. Max size is 64k. */ size_t attr_size = 256; char *val = NULL; ssize_t sizeret; again: val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size); if (!val) { return False; } if (fsp && fsp->fh->fd != -1) { sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size); } else { sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size); } if (sizeret == -1 && errno == ERANGE && attr_size != 65536) { attr_size = 65536; goto again; } if (sizeret == -1) { return False; } DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret)); dump_data(10, val, sizeret); pea->flags = 0; if (strnequal(ea_name, "user.", 5)) { pea->name = &ea_name[5]; } else { pea->name = ea_name; } pea->value.data = (unsigned char *)val; pea->value.length = (size_t)sizeret; return True;}/**************************************************************************** Return a linked list of the total EA's. Plus the total size****************************************************************************/static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len){ /* Get a list of all xattrs. Max namesize is 64k. */ size_t ea_namelist_size = 1024; char *ea_namelist; char *p; ssize_t sizeret; int i; struct ea_list *ea_list_head = NULL; *pea_total_len = 0; if (!lp_ea_support(SNUM(conn))) { return NULL; } for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6; ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { if (fsp && fsp->fh->fd != -1) { sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size); } else { sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size); } if (sizeret == -1 && errno == ERANGE) { ea_namelist_size *= 2; } else { break; } } if (sizeret == -1) return NULL; DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret )); if (sizeret) { for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { struct ea_list *listp, *tmp; if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) continue; listp = TALLOC_P(mem_ctx, struct ea_list); if (!listp) return NULL; if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) { return NULL; } { fstring dos_ea_name; push_ascii_fstring(dos_ea_name, listp->ea.name); *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n", (unsigned int)*pea_total_len, dos_ea_name, (unsigned int)listp->ea.value.length )); } DLIST_ADD_END(ea_list_head, listp, tmp); } /* Add on 4 for total length. */ if (*pea_total_len) { *pea_total_len += 4; } } DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len)); return ea_list_head;}/**************************************************************************** Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer that was filled.****************************************************************************/static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size, connection_struct *conn, struct ea_list *ea_list){ unsigned int ret_data_size = 4; char *p = pdata; SMB_ASSERT(total_data_size >= 4); if (!lp_ea_support(SNUM(conn))) { SIVAL(pdata,4,0); return 4; } for (p = pdata + 4; ea_list; ea_list = ea_list->next) { size_t dos_namelen; fstring dos_ea_name; push_ascii_fstring(dos_ea_name, ea_list->ea.name); dos_namelen = strlen(dos_ea_name); if (dos_namelen > 255 || dos_namelen == 0) { break; } if (ea_list->ea.value.length > 65535) { break; } if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) { break; } /* We know we have room. */ SCVAL(p,0,ea_list->ea.flags); SCVAL(p,1,dos_namelen); SSVAL(p,2,ea_list->ea.value.length); fstrcpy(p+4, dos_ea_name); memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length); total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length; p += 4 + dos_namelen + 1 + ea_list->ea.value.length; } ret_data_size = PTR_DIFF(p, pdata); DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size )); SIVAL(pdata,0,ret_data_size); return ret_data_size;}static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname){ size_t total_ea_len = 0; TALLOC_CTX *mem_ctx = NULL; if (!lp_ea_support(SNUM(conn))) { return 0; } mem_ctx = talloc_init("estimate_ea_size"); (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); talloc_destroy(mem_ctx); return total_ea_len;}/**************************************************************************** Ensure the EA name is case insensitive by matching any existing EA name.****************************************************************************/static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name){ size_t total_ea_len; TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name"); struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); for (; ea_list; ea_list = ea_list->next) { if (strequal(&unix_ea_name[5], ea_list->ea.name)) { DEBUG(10,("canonicalize_ea_name: %s -> %s\n", &unix_ea_name[5], ea_list->ea.name)); safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6); break; } } talloc_destroy(mem_ctx);}/**************************************************************************** Set or delete an extended attribute.****************************************************************************/NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list){ if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; } for (;ea_list; ea_list = ea_list->next) { int ret; fstring unix_ea_name; fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ fstrcat(unix_ea_name, ea_list->ea.name); canonicalize_ea_name(conn, fsp, fname, unix_ea_name); DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length)); if (samba_private_attr_name(unix_ea_name)) { DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); return NT_STATUS_ACCESS_DENIED; } if (ea_list->ea.value.length == 0) { /* Remove the attribute. */ if (fsp && (fsp->fh->fd != -1)) { DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", unix_ea_name, fsp->fsp_name)); ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name); } else { DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", unix_ea_name, fname)); ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); }#ifdef ENOATTR /* Removing a non existent attribute always succeeds. */ if (ret == -1 && errno == ENOATTR) { DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); ret = 0; }#endif } else { if (fsp && (fsp->fh->fd != -1)) { DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", unix_ea_name, fsp->fsp_name)); ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name, ea_list->ea.value.data, ea_list->ea.value.length, 0); } else { DEBUG(10,("set_ea: setting ea name %s on file %s.\n", unix_ea_name, fname)); ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, ea_list->ea.value.data, ea_list->ea.value.length, 0); } } if (ret == -1) {#ifdef ENOTSUP if (errno == ENOTSUP) { return NT_STATUS_EAS_NOT_SUPPORTED; }#endif return map_nt_error_from_unix(errno); } } return NT_STATUS_OK;}/**************************************************************************** Read a list of EA names from an incoming data buffer. Create an ea_list with them.****************************************************************************/static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size){ struct ea_list *ea_list_head = NULL; size_t offset = 0; while (offset + 2 < data_size) { struct ea_list *tmp; struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); unsigned int namelen = CVAL(pdata,offset); offset++; /* Go past the namelen byte. */ /* integer wrap paranioa. */ if ((offset + namelen < offset) || (offset + namelen < namelen) || (offset > data_size) || (namelen > data_size) || (offset + namelen >= data_size)) { break; } /* Ensure the name is null terminated. */ if (pdata[offset + namelen] != '\0') { return NULL; } pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]); if (!eal->ea.name) { return NULL; } offset += (namelen + 1); /* Go past the name + terminating zero. */ DLIST_ADD_END(ea_list_head, eal, tmp); DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); } return ea_list_head;}/**************************************************************************** Read one EA list entry from the buffer.****************************************************************************/struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used){ struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); uint16 val_len; unsigned int namelen; if (!eal) { return NULL; } if (data_size < 6) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?