root/source4/ntvfs/posix/pvfs_util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pvfs_has_wildcard
  2. pvfs_map_errno
  3. pvfs_match_attrib
  4. pvfs_attrib_normalise
  5. pvfs_copy_file
  6. pvfs_name_hash
  7. pvfs_round_alloc_size

   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 */
  29 bool pvfs_has_wildcard(const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
  30 {
  31         if (strpbrk(str, "*?<>\"")) {
  32                 return true;
  33         }
  34         return false;
  35 }
  36 
  37 /*
  38   map a unix errno to a NTSTATUS
  39 */
  40 NTSTATUS pvfs_map_errno(struct pvfs_state *pvfs, int unix_errno)
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42         return map_nt_error_from_unix(unix_errno);
  43 }
  44 
  45 
  46 /*
  47   check if a filename has an attribute matching the given attribute search value
  48   this is used by calls like unlink and search which take an attribute
  49   and only include special files if they match the given attribute
  50 */
  51 NTSTATUS pvfs_match_attrib(struct pvfs_state *pvfs, struct pvfs_filename *name, 
     /* [<][>][^][v][top][bottom][index][help] */
  52                            uint32_t attrib, uint32_t must_attrib)
  53 {
  54         if ((name->dos.attrib & ~attrib) & FILE_ATTRIBUTE_DIRECTORY) {
  55                 return NT_STATUS_FILE_IS_A_DIRECTORY;
  56         }
  57         if ((name->dos.attrib & ~attrib) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
  58                 return NT_STATUS_NO_SUCH_FILE;
  59         }
  60         if (must_attrib & ~name->dos.attrib) {
  61                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
  62         }
  63         return NT_STATUS_OK;
  64 }
  65 
  66 
  67 /*
  68   normalise a file attribute
  69 */
  70 uint32_t pvfs_attrib_normalise(uint32_t attrib, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
  71 {
  72         if (attrib != FILE_ATTRIBUTE_NORMAL) {
  73                 attrib &= ~FILE_ATTRIBUTE_NORMAL;
  74         }
  75         if (S_ISDIR(mode)) {
  76                 attrib |= FILE_ATTRIBUTE_DIRECTORY;
  77         } else {
  78                 attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
  79         }
  80         return attrib;
  81 }
  82 
  83 
  84 /*
  85   copy a file. Caller is supposed to have already ensured that the
  86   operation is allowed. The destination file must not exist.
  87 */
  88 NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
     /* [<][>][^][v][top][bottom][index][help] */
  89                         struct pvfs_filename *name1, 
  90                         struct pvfs_filename *name2)
  91 {
  92         int fd1, fd2;
  93         mode_t mode;
  94         NTSTATUS status;
  95         size_t buf_size = 0x10000;
  96         uint8_t *buf = talloc_array(name2, uint8_t, buf_size);
  97 
  98         if (buf == NULL) {
  99                 return NT_STATUS_NO_MEMORY;
 100         }
 101 
 102         fd1 = open(name1->full_name, O_RDONLY);
 103         if (fd1 == -1) {
 104                 talloc_free(buf);
 105                 return pvfs_map_errno(pvfs, errno);
 106         }
 107 
 108         fd2 = open(name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0);
 109         if (fd2 == -1) {
 110                 close(fd1);
 111                 talloc_free(buf);
 112                 return pvfs_map_errno(pvfs, errno);
 113         }
 114 
 115         while (1) {
 116                 ssize_t ret2, ret = read(fd1, buf, buf_size);
 117                 if (ret == -1 && 
 118                     (errno == EINTR || errno == EAGAIN)) {
 119                         continue;
 120                 }
 121                 if (ret <= 0) break;
 122 
 123                 ret2 = write(fd2, buf, ret);
 124                 if (ret2 == -1 &&
 125                     (errno == EINTR || errno == EAGAIN)) {
 126                         continue;
 127                 }
 128                 
 129                 if (ret2 != ret) {
 130                         close(fd1);
 131                         close(fd2);
 132                         talloc_free(buf);
 133                         unlink(name2->full_name);
 134                         if (ret2 == -1) {
 135                                 return pvfs_map_errno(pvfs, errno);
 136                         }
 137                         return NT_STATUS_DISK_FULL;
 138                 }
 139         }
 140 
 141         talloc_free(buf);
 142         close(fd1);
 143 
 144         mode = pvfs_fileperms(pvfs, name1->dos.attrib);
 145         if (fchmod(fd2, mode) == -1) {
 146                 status = pvfs_map_errno(pvfs, errno);
 147                 close(fd2);
 148                 unlink(name2->full_name);
 149                 return status;
 150         }
 151 
 152         name2->st.st_mode = mode;
 153         name2->dos = name1->dos;
 154 
 155         status = pvfs_dosattrib_save(pvfs, name2, fd2);
 156         if (!NT_STATUS_IS_OK(status)) {
 157                 close(fd2);
 158                 unlink(name2->full_name);
 159                 return status;
 160         }
 161 
 162         close(fd2);
 163 
 164         return NT_STATUS_OK;
 165 }
 166 
 167 
 168 /* 
 169    hash a string of the specified length. The string does not need to be
 170    null terminated 
 171 
 172    hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce).
 173    see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a
 174    discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors
 175 */
 176 uint32_t pvfs_name_hash(const char *key, size_t length)
     /* [<][>][^][v][top][bottom][index][help] */
 177 {
 178         const uint32_t fnv1_prime = 0x01000193;
 179         const uint32_t fnv1_init = 0xa6b93095;
 180         uint32_t value = fnv1_init;
 181 
 182         while (*key && length--) {
 183                 size_t c_size;
 184                 codepoint_t c = next_codepoint(key, &c_size);
 185                 c = toupper_m(c);
 186                 value *= fnv1_prime;
 187                 value ^= (uint32_t)c;
 188                 key += c_size;
 189         }
 190 
 191         return value;
 192 }
 193 
 194 
 195 /*
 196   file allocation size rounding. This is required to pass ifstest
 197 */
 198 uint64_t pvfs_round_alloc_size(struct pvfs_state *pvfs, uint64_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200         const uint32_t round_value = pvfs->alloc_size_rounding;
 201         return round_value * ((size + round_value - 1)/round_value);
 202 }

/* [<][>][^][v][top][bottom][index][help] */