1 /* 2 * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "FileAttributes.h" 27 28 #include <algorithm> 29 #include <list> 30 #include <sys/stat.h> 31 32 FileAttributes::FileAttributes(const TString FileName, bool FollowLink) { 33 FFileName = FileName; 34 FFollowLink = FollowLink; 35 ReadAttributes(); 36 } 37 38 bool FileAttributes::WriteAttributes() { 39 bool result = false; 40 41 mode_t attributes = 0; 42 43 for (std::vector<FileAttribute>::const_iterator iterator = 44 FAttributes.begin(); 45 iterator != FAttributes.end(); iterator++) { 46 switch (*iterator) { 47 case faBlockSpecial: 48 { 49 attributes |= S_IFBLK; 50 break; 51 } 52 case faCharacterSpecial: 53 { 54 attributes |= S_IFCHR; 55 break; 56 } 57 case faFIFOSpecial: 58 { 59 attributes |= S_IFIFO; 60 break; 61 } 62 case faNormal: 63 { 64 attributes |= S_IFREG; 65 break; 66 } 67 case faDirectory: 68 { 69 attributes |= S_IFDIR; 70 break; 71 } 72 case faSymbolicLink: 73 { 74 attributes |= S_IFLNK; 75 break; 76 } 77 case faSocket: 78 { 79 attributes |= S_IFSOCK; 80 break; 81 } 82 83 // Owner 84 case faReadOnly: 85 { 86 attributes |= S_IRUSR; 87 break; 88 } 89 case faWriteOnly: 90 { 91 attributes |= S_IWUSR; 92 break; 93 } 94 case faReadWrite: 95 { 96 attributes |= S_IRUSR; 97 attributes |= S_IWUSR; 98 break; 99 } 100 case faExecute: 101 { 102 attributes |= S_IXUSR; 103 break; 104 } 105 106 // Group 107 case faGroupReadOnly: 108 { 109 attributes |= S_IRGRP; 110 break; 111 } 112 case faGroupWriteOnly: 113 { 114 attributes |= S_IWGRP; 115 break; 116 } 117 case faGroupReadWrite: 118 { 119 attributes |= S_IRGRP; 120 attributes |= S_IWGRP; 121 break; 122 } 123 case faGroupExecute: 124 { 125 attributes |= S_IXGRP; 126 break; 127 } 128 129 // Others 130 case faOthersReadOnly: 131 { 132 attributes |= S_IROTH; 133 break; 134 } 135 case faOthersWriteOnly: 136 { 137 attributes |= S_IWOTH; 138 break; 139 } 140 case faOthersReadWrite: 141 { 142 attributes |= S_IROTH; 143 attributes |= S_IWOTH; 144 break; 145 } 146 case faOthersExecute: 147 { 148 attributes |= S_IXOTH; 149 break; 150 } 151 default: 152 break; 153 } 154 } 155 156 if (chmod(FFileName.data(), attributes) == 0) { 157 result = true; 158 } 159 160 return result; 161 } 162 163 #define S_ISRUSR(m) (((m) & S_IRWXU) == S_IRUSR) 164 #define S_ISWUSR(m) (((m) & S_IRWXU) == S_IWUSR) 165 #define S_ISXUSR(m) (((m) & S_IRWXU) == S_IXUSR) 166 167 #define S_ISRGRP(m) (((m) & S_IRWXG) == S_IRGRP) 168 #define S_ISWGRP(m) (((m) & S_IRWXG) == S_IWGRP) 169 #define S_ISXGRP(m) (((m) & S_IRWXG) == S_IXGRP) 170 171 #define S_ISROTH(m) (((m) & S_IRWXO) == S_IROTH) 172 #define S_ISWOTH(m) (((m) & S_IRWXO) == S_IWOTH) 173 #define S_ISXOTH(m) (((m) & S_IRWXO) == S_IXOTH) 174 175 bool FileAttributes::ReadAttributes() { 176 bool result = false; 177 178 struct stat status; 179 180 if (stat(StringToFileSystemString(FFileName), &status) == 0) { 181 result = true; 182 183 if (S_ISBLK(status.st_mode) != 0) { 184 FAttributes.push_back(faBlockSpecial); 185 } 186 if (S_ISCHR(status.st_mode) != 0) { 187 FAttributes.push_back(faCharacterSpecial); 188 } 189 if (S_ISFIFO(status.st_mode) != 0) { 190 FAttributes.push_back(faFIFOSpecial); 191 } 192 if (S_ISREG(status.st_mode) != 0) { 193 FAttributes.push_back(faNormal); 194 } 195 if (S_ISDIR(status.st_mode) != 0) { 196 FAttributes.push_back(faDirectory); 197 } 198 if (S_ISLNK(status.st_mode) != 0) { 199 FAttributes.push_back(faSymbolicLink); 200 } 201 if (S_ISSOCK(status.st_mode) != 0) { 202 FAttributes.push_back(faSocket); 203 } 204 205 // Owner 206 if (S_ISRUSR(status.st_mode) != 0) { 207 if (S_ISWUSR(status.st_mode) != 0) { 208 FAttributes.push_back(faReadWrite); 209 } else { 210 FAttributes.push_back(faReadOnly); 211 } 212 } else if (S_ISWUSR(status.st_mode) != 0) { 213 FAttributes.push_back(faWriteOnly); 214 } 215 216 if (S_ISXUSR(status.st_mode) != 0) { 217 FAttributes.push_back(faExecute); 218 } 219 220 // Group 221 if (S_ISRGRP(status.st_mode) != 0) { 222 if (S_ISWGRP(status.st_mode) != 0) { 223 FAttributes.push_back(faGroupReadWrite); 224 } else { 225 FAttributes.push_back(faGroupReadOnly); 226 } 227 } else if (S_ISWGRP(status.st_mode) != 0) { 228 FAttributes.push_back(faGroupWriteOnly); 229 } 230 231 if (S_ISXGRP(status.st_mode) != 0) { 232 FAttributes.push_back(faGroupExecute); 233 } 234 235 236 // Others 237 if (S_ISROTH(status.st_mode) != 0) { 238 if (S_ISWOTH(status.st_mode) != 0) { 239 FAttributes.push_back(faOthersReadWrite); 240 } else { 241 FAttributes.push_back(faOthersReadOnly); 242 } 243 } else if (S_ISWOTH(status.st_mode) != 0) { 244 FAttributes.push_back(faOthersWriteOnly); 245 } 246 247 if (S_ISXOTH(status.st_mode) != 0) { 248 FAttributes.push_back(faOthersExecute); 249 } 250 251 if (FFileName.size() > 0 && FFileName[0] == '.') { 252 FAttributes.push_back(faHidden); 253 } 254 } 255 256 return result; 257 } 258 259 bool FileAttributes::Valid(const FileAttribute Value) { 260 bool result = false; 261 262 switch (Value) { 263 case faReadWrite: 264 case faWriteOnly: 265 case faExecute: 266 267 case faGroupReadWrite: 268 case faGroupWriteOnly: 269 case faGroupReadOnly: 270 case faGroupExecute: 271 272 case faOthersReadWrite: 273 case faOthersWriteOnly: 274 case faOthersReadOnly: 275 case faOthersExecute: 276 277 case faReadOnly: 278 result = true; 279 break; 280 281 default: 282 break; 283 } 284 285 return result; 286 } 287 288 void FileAttributes::Append(FileAttribute Value) { 289 if (Valid(Value) == true) { 290 if ((Value == faReadOnly && Contains(faWriteOnly) == true) || 291 (Value == faWriteOnly && Contains(faReadOnly) == true)) { 292 Value = faReadWrite; 293 } 294 295 FAttributes.push_back(Value); 296 WriteAttributes(); 297 } 298 } 299 300 bool FileAttributes::Contains(FileAttribute Value) { 301 bool result = false; 302 303 std::vector<FileAttribute>::const_iterator iterator = 304 std::find(FAttributes.begin(), FAttributes.end(), Value); 305 306 if (iterator != FAttributes.end()) { 307 result = true; 308 } 309 310 return result; 311 } 312 313 void FileAttributes::Remove(FileAttribute Value) { 314 if (Valid(Value) == true) { 315 if (Value == faReadOnly && Contains(faReadWrite) == true) { 316 Append(faWriteOnly); 317 Remove(faReadWrite); 318 } else if (Value == faWriteOnly && Contains(faReadWrite) == true) { 319 Append(faReadOnly); 320 Remove(faReadWrite); 321 } 322 323 std::vector<FileAttribute>::iterator iterator = 324 std::find(FAttributes.begin(), FAttributes.end(), Value); 325 326 if (iterator != FAttributes.end()) { 327 FAttributes.erase(iterator); 328 WriteAttributes(); 329 } 330 } 331 }