1/* 2 Unix SMB/CIFS implementation. 3 4 Copyright (C) Andrew Tridgell 2004 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19/* 20 utility functions for posix backend 21*/ 22 23#include "includes.h" 24#include "vfs_posix.h" 25 26/* 27 return true if a string contains one of the CIFS wildcard characters 28*/ 29bool pvfs_has_wildcard(const char *str) 30{ 31 if (strpbrk(str, "*?<>\"")) { 32 return true; 33 } 34 return false; 35} 36 37/* 38 map a unix errno to a NTSTATUS 39*/ 40NTSTATUS pvfs_map_errno(struct pvfs_state *pvfs, int unix_errno) 41{ 42 NTSTATUS status; 43 status = map_nt_error_from_unix(unix_errno); 44 DEBUG(10,(__location__ " mapped unix errno %d -> %s\n", unix_errno, nt_errstr(status))); 45 return status; 46} 47 48 49/* 50 check if a filename has an attribute matching the given attribute search value 51 this is used by calls like unlink and search which take an attribute 52 and only include special files if they match the given attribute 53*/ 54NTSTATUS pvfs_match_attrib(struct pvfs_state *pvfs, struct pvfs_filename *name, 55 uint32_t attrib, uint32_t must_attrib) 56{ 57 if ((name->dos.attrib & ~attrib) & FILE_ATTRIBUTE_DIRECTORY) { 58 return NT_STATUS_FILE_IS_A_DIRECTORY; 59 } 60 if ((name->dos.attrib & ~attrib) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) { 61 return NT_STATUS_NO_SUCH_FILE; 62 } 63 if (must_attrib & ~name->dos.attrib) { 64 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 65 } 66 return NT_STATUS_OK; 67} 68 69 70/* 71 normalise a file attribute 72*/ 73uint32_t pvfs_attrib_normalise(uint32_t attrib, mode_t mode) 74{ 75 if (attrib != FILE_ATTRIBUTE_NORMAL) { 76 attrib &= ~FILE_ATTRIBUTE_NORMAL; 77 } 78 if (S_ISDIR(mode)) { 79 attrib |= FILE_ATTRIBUTE_DIRECTORY; 80 } else { 81 attrib &= ~FILE_ATTRIBUTE_DIRECTORY; 82 } 83 return attrib; 84} 85 86 87/* 88 copy a file. Caller is supposed to have already ensured that the 89 operation is allowed. The destination file must not exist. 90*/ 91NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, 92 struct pvfs_filename *name1, 93 struct pvfs_filename *name2) 94{ 95 int fd1, fd2; 96 mode_t mode; 97 NTSTATUS status; 98 size_t buf_size = 0x10000; 99 uint8_t *buf = talloc_array(name2, uint8_t, buf_size); 100 101 if (buf == NULL) { 102 return NT_STATUS_NO_MEMORY; 103 } 104 105 fd1 = open(name1->full_name, O_RDONLY); 106 if (fd1 == -1) { 107 talloc_free(buf); 108 return pvfs_map_errno(pvfs, errno); 109 } 110 111 fd2 = open(name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0); 112 if (fd2 == -1) { 113 close(fd1); 114 talloc_free(buf); 115 return pvfs_map_errno(pvfs, errno); 116 } 117 118 while (1) { 119 ssize_t ret2, ret = read(fd1, buf, buf_size); 120 if (ret == -1 && 121 (errno == EINTR || errno == EAGAIN)) { 122 continue; 123 } 124 if (ret <= 0) break; 125 126 ret2 = write(fd2, buf, ret); 127 if (ret2 == -1 && 128 (errno == EINTR || errno == EAGAIN)) { 129 continue; 130 } 131 132 if (ret2 != ret) { 133 close(fd1); 134 close(fd2); 135 talloc_free(buf); 136 unlink(name2->full_name); 137 if (ret2 == -1) { 138 return pvfs_map_errno(pvfs, errno); 139 } 140 return NT_STATUS_DISK_FULL; 141 } 142 } 143 144 talloc_free(buf); 145 close(fd1); 146 147 mode = pvfs_fileperms(pvfs, name1->dos.attrib); 148 if (fchmod(fd2, mode) == -1) { 149 status = pvfs_map_errno(pvfs, errno); 150 close(fd2); 151 unlink(name2->full_name); 152 return status; 153 } 154 155 name2->st.st_mode = mode; 156 name2->dos = name1->dos; 157 158 status = pvfs_dosattrib_save(pvfs, name2, fd2); 159 if (!NT_STATUS_IS_OK(status)) { 160 close(fd2); 161 unlink(name2->full_name); 162 return status; 163 } 164 165 close(fd2); 166 167 return NT_STATUS_OK; 168} 169 170 171/* 172 hash a string of the specified length. The string does not need to be 173 null terminated 174 175 hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce). 176 see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a 177 discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors 178*/ 179uint32_t pvfs_name_hash(const char *key, size_t length) 180{ 181 const uint32_t fnv1_prime = 0x01000193; 182 const uint32_t fnv1_init = 0xa6b93095; 183 uint32_t value = fnv1_init; 184 185 while (*key && length--) { 186 size_t c_size; 187 codepoint_t c = next_codepoint(key, &c_size); 188 c = toupper_m(c); 189 value *= fnv1_prime; 190 value ^= (uint32_t)c; 191 key += c_size; 192 } 193 194 return value; 195} 196 197 198/* 199 file allocation size rounding. This is required to pass ifstest 200*/ 201uint64_t pvfs_round_alloc_size(struct pvfs_state *pvfs, uint64_t size) 202{ 203 const uint32_t round_value = pvfs->alloc_size_rounding; 204 return round_value * ((size + round_value - 1)/round_value); 205} 206