1 /* NFSv4.1 client for Windows 2 * Copyright � 2012 The Regents of the University of Michigan 3 * 4 * Olga Kornievskaia <aglo@umich.edu> 5 * Casey Bodley <cbodley@umich.edu> 6 * 7 * This library is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU Lesser General Public License as published by 9 * the Free Software Foundation; either version 2.1 of the License, or (at 10 * your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, but 13 * without any warranty; without even the implied warranty of merchantability 14 * or fitness for a particular purpose. See the GNU Lesser General Public 15 * License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with this library; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 */ 21 22 #ifndef __NFS41_DAEMON_UTIL_H__ 23 #define __NFS41_DAEMON_UTIL_H__ 24 25 #include "nfs41_types.h" 26 #include "from_kernel.h" 27 28 extern DWORD NFS41D_VERSION; 29 struct __nfs41_session; 30 struct __nfs41_write_verf; 31 enum stable_how4; 32 33 int safe_read(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len); 34 int safe_write(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len); 35 int get_name(unsigned char **pos, uint32_t *remaining, const char **out_name); 36 37 const char* strip_path( 38 IN const char *path, 39 OUT uint32_t *len_out OPTIONAL); 40 41 uint32_t max_read_size( 42 IN const struct __nfs41_session *session, 43 IN const nfs41_fh *fh); 44 uint32_t max_write_size( 45 IN const struct __nfs41_session *session, 46 IN const nfs41_fh *fh); 47 48 bool_t verify_write( 49 IN nfs41_write_verf *verf, 50 IN OUT enum stable_how4 *stable); 51 bool_t verify_commit( 52 IN nfs41_write_verf *verf); 53 54 /* bitmap4 */ 55 static __inline bool_t bitmap_isset( 56 IN const bitmap4 *mask, 57 IN uint32_t word, 58 IN uint32_t flag) 59 { 60 return mask->count > word && mask->arr[word] & flag; 61 } 62 static __inline void bitmap_set( 63 IN bitmap4 *mask, 64 IN uint32_t word, 65 IN uint32_t flag) 66 { 67 if (mask->count > word) 68 mask->arr[word] |= flag; 69 else { 70 mask->count = word + 1; 71 mask->arr[word] = flag; 72 } 73 } 74 static __inline void bitmap_unset( 75 IN bitmap4 *mask, 76 IN uint32_t word, 77 IN uint32_t flag) 78 { 79 if (mask->count > word) { 80 mask->arr[word] &= ~flag; 81 while (mask->count && mask->arr[mask->count-1] == 0) 82 mask->count--; 83 } 84 } 85 static __inline void bitmap_intersect( 86 IN bitmap4 *dst, 87 IN const bitmap4 *src) 88 { 89 uint32_t i, count = 0; 90 for (i = 0; i < 3; i++) { 91 dst->arr[i] &= src->arr[i]; 92 if (dst->arr[i]) 93 count = i+1; 94 } 95 dst->count = min(dst->count, count); 96 } 97 98 ULONG nfs_file_info_to_attributes( 99 IN const nfs41_file_info *info); 100 void nfs_to_basic_info( 101 IN const nfs41_file_info *info, 102 OUT PFILE_BASIC_INFO basic_out); 103 void nfs_to_standard_info( 104 IN const nfs41_file_info *info, 105 OUT PFILE_STANDARD_INFO std_out); 106 void nfs_to_network_openinfo( 107 IN const nfs41_file_info *info, 108 OUT PFILE_NETWORK_OPEN_INFORMATION std_out); 109 110 /* http://msdn.microsoft.com/en-us/library/ms724290%28VS.85%29.aspx: 111 * A file time is a 64-bit value that represents the number of 112 * 100-nanosecond intervals that have elapsed since 12:00 A.M. 113 * January 1, 1601 Coordinated Universal Time (UTC). */ 114 #define FILETIME_EPOCH 116444736000000000LL 115 116 static __inline void file_time_to_nfs_time( 117 IN const PLARGE_INTEGER file_time, 118 OUT nfstime4 *nfs_time) 119 { 120 LONGLONG diff = file_time->QuadPart - FILETIME_EPOCH; 121 nfs_time->seconds = diff / 10000000; 122 nfs_time->nseconds = (uint32_t)((diff % 10000000)*100); 123 } 124 125 static __inline void nfs_time_to_file_time( 126 IN const nfstime4 *nfs_time, 127 OUT PLARGE_INTEGER file_time) 128 { 129 file_time->QuadPart = FILETIME_EPOCH + 130 nfs_time->seconds * 10000000 + 131 nfs_time->nseconds / 100; 132 } 133 134 void get_file_time( 135 OUT PLARGE_INTEGER file_time); 136 void get_nfs_time( 137 OUT nfstime4 *nfs_time); 138 139 static __inline void nfstime_normalize( 140 IN OUT nfstime4 *nfstime) 141 { 142 /* return time in normalized form (0 <= nsec < 1s) */ 143 while ((int32_t)nfstime->nseconds < 0) { 144 nfstime->nseconds += 1000000000; 145 nfstime->seconds--; 146 } 147 } 148 static __inline void nfstime_diff( 149 IN const nfstime4 *lhs, 150 IN const nfstime4 *rhs, 151 OUT nfstime4 *result) 152 { 153 /* result = lhs - rhs */ 154 result->seconds = lhs->seconds - rhs->seconds; 155 result->nseconds = lhs->nseconds - rhs->nseconds; 156 nfstime_normalize(result); 157 } 158 static __inline void nfstime_abs( 159 IN const nfstime4 *nt, 160 OUT nfstime4 *result) 161 { 162 if (nt->seconds < 0) { 163 const nfstime4 zero = { 0, 0 }; 164 nfstime_diff(&zero, nt, result); /* result = 0 - nt */ 165 } else if (result != nt) 166 memcpy(result, nt, sizeof(nfstime4)); 167 } 168 169 170 int create_silly_rename( 171 IN nfs41_abs_path *path, 172 IN const nfs41_fh *fh, 173 OUT nfs41_component *silly); 174 175 bool_t multi_addr_find( 176 IN const multi_addr4 *addrs, 177 IN const netaddr4 *addr, 178 OUT OPTIONAL uint32_t *index_out); 179 180 /* nfs_to_windows_error 181 * Returns a windows ERROR_ code corresponding to the given NFS4ERR_ status. 182 * If the status is outside the range of valid NFS4ERR_ values, it is returned 183 * unchanged. Otherwise, if the status does not match a value in the mapping, 184 * a debug warning is generated and the default_error value is returned. 185 */ 186 int nfs_to_windows_error(int status, int default_error); 187 188 int map_symlink_errors(int status); 189 190 #ifndef __REACTOS__ 191 __inline uint32_t align8(uint32_t offset) { 192 #else 193 FORCEINLINE uint32_t align8(uint32_t offset) { 194 #endif 195 return 8 + ((offset - 1) & ~7); 196 } 197 #ifndef __REACTOS__ 198 __inline uint32_t align4(uint32_t offset) { 199 #else 200 FORCEINLINE uint32_t align4(uint32_t offset) { 201 #endif 202 return 4 + ((offset - 1) & ~3); 203 } 204 205 /* path parsing */ 206 #ifndef __REACTOS__ 207 __inline int is_delimiter(char c) { 208 #else 209 FORCEINLINE int is_delimiter(char c) { 210 #endif 211 return c == '\\' || c == '/' || c == '\0'; 212 } 213 #ifndef __REACTOS__ 214 __inline const char* next_delimiter(const char *pos, const char *end) { 215 #else 216 FORCEINLINE const char* next_delimiter(const char *pos, const char *end) { 217 #endif 218 while (pos < end && !is_delimiter(*pos)) 219 pos++; 220 return pos; 221 } 222 #ifndef __REACTOS__ 223 __inline const char* prev_delimiter(const char *pos, const char *start) { 224 #else 225 FORCEINLINE const char* prev_delimiter(const char *pos, const char *start) { 226 #endif 227 while (pos > start && !is_delimiter(*pos)) 228 pos--; 229 return pos; 230 } 231 #ifndef __REACTOS__ 232 __inline const char* next_non_delimiter(const char *pos, const char *end) { 233 #else 234 FORCEINLINE const char* next_non_delimiter(const char *pos, const char *end) { 235 #endif 236 while (pos < end && is_delimiter(*pos)) 237 pos++; 238 return pos; 239 } 240 #ifndef __REACTOS__ 241 __inline const char* prev_non_delimiter(const char *pos, const char *start) { 242 #else 243 FORCEINLINE const char* prev_non_delimiter(const char *pos, const char *start) { 244 #endif 245 while (pos > start && is_delimiter(*pos)) 246 pos--; 247 return pos; 248 } 249 250 bool_t next_component( 251 IN const char *path, 252 IN const char *path_end, 253 OUT nfs41_component *component); 254 255 bool_t last_component( 256 IN const char *path, 257 IN const char *path_end, 258 OUT nfs41_component *component); 259 260 bool_t is_last_component( 261 IN const char *path, 262 IN const char *path_end); 263 264 void abs_path_copy( 265 OUT nfs41_abs_path *dst, 266 IN const nfs41_abs_path *src); 267 268 void path_fh_init( 269 OUT nfs41_path_fh *file, 270 IN nfs41_abs_path *path); 271 272 void fh_copy( 273 OUT nfs41_fh *dst, 274 IN const nfs41_fh *src); 275 276 void path_fh_copy( 277 OUT nfs41_path_fh *dst, 278 IN const nfs41_path_fh *src); 279 280 #ifndef __REACTOS__ 281 __inline int valid_handle(HANDLE handle) { 282 #else 283 FORCEINLINE int valid_handle(HANDLE handle) { 284 #endif 285 return handle != INVALID_HANDLE_VALUE && handle != 0; 286 } 287 288 #endif /* !__NFS41_DAEMON_UTIL_H__ */ 289