Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : POSIX NTVFS backend - 5 : 6 : Copyright (C) Andrew Tridgell 2004 7 : 8 : This program is free software; you can redistribute it and/or modify 9 : it under the terms of the GNU General Public License as published by 10 : the Free Software Foundation; either version 3 of the License, or 11 : (at your option) any later version. 12 : 13 : This program is distributed in the hope that it will be useful, 14 : but WITHOUT ANY WARRANTY; without even the implied warranty of 15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 : GNU General Public License for more details. 17 : 18 : You should have received a copy of the GNU General Public License 19 : along with this program. If not, see <http://www.gnu.org/licenses/>. 20 : */ 21 : 22 : #include "includes.h" 23 : #include "vfs_posix.h" 24 : #include "lib/util/time.h" 25 : 26 : /**************************************************************************** 27 : Change a unix mode to a dos mode. 28 : ****************************************************************************/ 29 806531 : static uint32_t dos_mode_from_stat(struct pvfs_state *pvfs, struct stat *st) 30 : { 31 806531 : int result = 0; 32 : 33 806531 : if ((st->st_mode & S_IWUSR) == 0) 34 0 : result |= FILE_ATTRIBUTE_READONLY; 35 : 36 806531 : if ((pvfs->flags & PVFS_FLAG_MAP_ARCHIVE) && ((st->st_mode & S_IXUSR) != 0)) 37 366836 : result |= FILE_ATTRIBUTE_ARCHIVE; 38 : 39 806531 : if ((pvfs->flags & PVFS_FLAG_MAP_SYSTEM) && ((st->st_mode & S_IXGRP) != 0)) 40 0 : result |= FILE_ATTRIBUTE_SYSTEM; 41 : 42 806531 : if ((pvfs->flags & PVFS_FLAG_MAP_HIDDEN) && ((st->st_mode & S_IXOTH) != 0)) 43 0 : result |= FILE_ATTRIBUTE_HIDDEN; 44 : 45 806531 : if (S_ISDIR(st->st_mode)) 46 366759 : result = FILE_ATTRIBUTE_DIRECTORY | (result & FILE_ATTRIBUTE_READONLY); 47 : 48 806531 : return result; 49 : } 50 : 51 : 52 : 53 : /* 54 : fill in the dos file attributes for a file 55 : */ 56 806531 : NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, 57 : unsigned int flags, int fd) 58 : { 59 0 : NTSTATUS status; 60 0 : DATA_BLOB lkey; 61 0 : NTTIME write_time; 62 : 63 : /* make directories appear as size 0 with 1 link */ 64 806531 : if (S_ISDIR(name->st.st_mode)) { 65 366759 : name->st.st_size = 0; 66 366759 : name->st.st_nlink = 1; 67 439772 : } else if (name->stream_id == 0) { 68 439249 : name->stream_name = NULL; 69 : } 70 : 71 : /* for now just use the simple samba mapping */ 72 806531 : unix_to_nt_time(&name->dos.create_time, name->st.st_ctime); 73 806531 : unix_to_nt_time(&name->dos.access_time, name->st.st_atime); 74 806531 : unix_to_nt_time(&name->dos.write_time, name->st.st_mtime); 75 806531 : unix_to_nt_time(&name->dos.change_time, name->st.st_ctime); 76 806531 : name->dos.create_time += get_ctimensec(&name->st) / 100; 77 806531 : name->dos.access_time += get_atimensec(&name->st) / 100; 78 806531 : name->dos.write_time += get_mtimensec(&name->st) / 100; 79 806531 : name->dos.change_time += get_ctimensec(&name->st) / 100; 80 806531 : name->dos.attrib = dos_mode_from_stat(pvfs, &name->st); 81 806531 : name->dos.alloc_size = pvfs_round_alloc_size(pvfs, name->st.st_size); 82 806531 : name->dos.nlink = name->st.st_nlink; 83 806531 : name->dos.ea_size = 4; /* TODO: Fill this in without hitting the stream bad in pvfs_doseas_load() */ 84 806531 : if (pvfs->ntvfs->ctx->protocol >= PROTOCOL_SMB2_02) { 85 : /* SMB2 represents a null EA with zero bytes */ 86 477470 : name->dos.ea_size = 0; 87 : } 88 : 89 806531 : name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino; 90 806531 : name->dos.flags = 0; 91 : 92 806531 : status = pvfs_dosattrib_load(pvfs, name, fd); 93 806531 : NT_STATUS_NOT_OK_RETURN(status); 94 : 95 806531 : if (flags & PVFS_RESOLVE_NO_OPENDB) { 96 444759 : return NT_STATUS_OK; 97 : } 98 : 99 361772 : status = pvfs_locking_key(name, name, &lkey); 100 361772 : NT_STATUS_NOT_OK_RETURN(status); 101 : 102 361772 : status = odb_get_file_infos(pvfs->odb_context, &lkey, 103 : NULL, &write_time); 104 361772 : data_blob_free(&lkey); 105 361772 : if (!NT_STATUS_IS_OK(status)) { 106 0 : DEBUG(1,("WARNING: odb_get_file_infos: %s\n", nt_errstr(status))); 107 0 : return status; 108 : } 109 : 110 361772 : if (!null_time(write_time)) { 111 19160 : name->dos.write_time = write_time; 112 : } 113 : 114 361772 : return NT_STATUS_OK; 115 : } 116 : 117 : 118 : /* 119 : return a set of unix file permissions for a new file or directory 120 : */ 121 105918 : mode_t pvfs_fileperms(struct pvfs_state *pvfs, uint32_t attrib) 122 : { 123 105918 : mode_t mode = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); 124 : 125 105918 : if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE) && 126 0 : (attrib & FILE_ATTRIBUTE_READONLY)) { 127 0 : mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); 128 : } 129 : 130 105918 : if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { 131 0 : if ((attrib & FILE_ATTRIBUTE_ARCHIVE) && 132 0 : (pvfs->flags & PVFS_FLAG_MAP_ARCHIVE)) { 133 0 : mode |= S_IXUSR; 134 : } 135 0 : if ((attrib & FILE_ATTRIBUTE_SYSTEM) && 136 0 : (pvfs->flags & PVFS_FLAG_MAP_SYSTEM)) { 137 0 : mode |= S_IXGRP; 138 : } 139 0 : if ((attrib & FILE_ATTRIBUTE_HIDDEN) && 140 0 : (pvfs->flags & PVFS_FLAG_MAP_HIDDEN)) { 141 0 : mode |= S_IXOTH; 142 : } 143 : } 144 : 145 105918 : if (attrib & FILE_ATTRIBUTE_DIRECTORY) { 146 7256 : mode |= (S_IFDIR | S_IWUSR); 147 7256 : mode |= (S_IXUSR | S_IXGRP | S_IXOTH); 148 7256 : mode &= pvfs->options.dir_mask; 149 7256 : mode |= pvfs->options.force_dir_mode; 150 : } else { 151 98662 : mode &= pvfs->options.create_mask; 152 98662 : mode |= pvfs->options.force_create_mode; 153 : } 154 : 155 105918 : return mode; 156 : } 157 : 158 :