1 module unde.file_manager.change_rights; 2 3 import unde.global_state; 4 import unde.lsblk; 5 import unde.lib; 6 import unde.scan; 7 import unde.path_mnt; 8 9 import std.stdio; 10 import std.conv; 11 import core.stdc.stdlib; 12 import std.math; 13 import berkeleydb.all; 14 import std.stdint; 15 import core.stdc.stdlib; 16 import std..string; 17 import std.algorithm.sorting; 18 import std.utf; 19 import std.process; 20 import std.concurrency; 21 import core.time; 22 import core.thread; 23 import core.stdc.errno; 24 import core.stdc..string; 25 import std.datetime; 26 import std.regex; 27 import std.algorithm.sorting; 28 29 import derelict.sdl2.sdl; 30 31 import std.file; 32 import core.sys.posix.sys.stat; 33 34 version(Posix) 35 { 36 enum DirOrFile 37 { 38 All, 39 Dir, 40 File 41 } 42 43 private void 44 save_errors(FMGlobalState cgs, PathMnt path, string e) 45 { 46 DbTxn txn = null; 47 Dbt key, data; 48 string path0 = path.get_key(cgs.lsblk); 49 key = path0; 50 auto res = cgs.db_map.get(txn, &key, &data); 51 52 RectSize rectsize; 53 if (res == 0) 54 rectsize = data.to!(RectSize); 55 56 ulong curr_time = Clock.currTime().toUnixTime(); 57 rectsize.msg = to_char_array!80(strip_error(e)); 58 rectsize.msg_time = curr_time; 59 rectsize.msg_color = 0x80FF8080; // ARGB 60 61 data = rectsize; 62 //writefln("WRITE - %s - %s", path0, rectsize); 63 res = cgs.db_map.put(txn, &key, &data); 64 if (res != 0) 65 throw new Exception("Path info to map-db not written"); 66 67 ssize_t first, last; 68 first = path0.indexOf("\0"); 69 while (first != last) 70 { 71 last = path0.lastIndexOf("\0"); 72 if (last > first) 73 path0 = path0[0..last]; 74 else 75 path0 = path0[0..first+1]; 76 key = path0; 77 res = cgs.db_map.get(txn, &key, &data); 78 if (res == 0) 79 { 80 rectsize = data.to!(RectSize); 81 82 if (curr_time > rectsize.newest_msg_time) 83 { 84 rectsize.newest_msg_time = curr_time; 85 86 data = rectsize; 87 //writefln("WRITE - %s - %s", path0, rectsize); 88 res = cgs.db_map.put(txn, &key, &data); 89 if (res != 0) 90 throw new Exception("Path info to map-db not written"); 91 } 92 } 93 } 94 } 95 96 private void 97 change_rights_ang_save_errors(FMGlobalState cgs, PathMnt path, mode_t mode) 98 { 99 //writefln("%s: %s", path, mode_to_string(mode)); 100 int res = chmod(toStringz(path), mode); 101 if (res < 0) 102 { 103 save_errors(cgs, path, fromStringz(strerror(errno)).idup()); 104 } 105 } 106 107 private void 108 change_rights_private(FMGlobalState cgs, PathMnt path, bool set, int bit, DirOrFile dof, bool recursive) 109 { 110 //writefln("remove_path(%s)", path); 111 // exits on exits of parent 112 receiveTimeout( 0.seconds, 113 (OwnerTerminated ot) { 114 writefln("Abort removing due stopping parent"); 115 cgs.finish = true; 116 } ); 117 118 if (cgs.finish) 119 return; 120 121 DirEntry de; 122 mode_t mode; 123 try 124 { 125 path.update(cgs.lsblk); 126 de = DirEntry(path); 127 128 mode = de.statBuf.st_mode; 129 final switch(dof) 130 { 131 case DirOrFile.Dir: 132 if (!de.isSymlink && de.isDir) 133 { 134 goto case DirOrFile.All; 135 } 136 break; 137 case DirOrFile.File: 138 if (de.isSymlink || de.isFile) 139 { 140 goto case DirOrFile.All; 141 } 142 break; 143 case DirOrFile.All: 144 if (set) 145 mode |= 1 << (11-bit); 146 else 147 mode &= ~(1 << (11-bit)); 148 break; 149 } 150 } 151 catch (Exception e) 152 { 153 save_errors(cgs, path, e.msg); 154 } 155 156 try 157 { 158 if (de.isSymlink) 159 { 160 change_rights_ang_save_errors(cgs, path, mode); 161 return; 162 } 163 else if (de.isDir) 164 { 165 if (recursive) 166 { 167 string[] paths; 168 try 169 { 170 foreach (string name; dirEntries(path, SpanMode.shallow)) 171 { 172 paths ~= name; 173 } 174 } 175 catch (Exception e) 176 { 177 return; 178 } 179 180 sort!("a < b")(paths); 181 182 foreach (string name; paths) 183 { 184 if (name != path) 185 { 186 change_rights_private(cgs, path.next(name), set, bit, dof, recursive); 187 } 188 } 189 } 190 191 change_rights_ang_save_errors(cgs, path, mode); 192 return; 193 } 194 else if (de.isFile) 195 { 196 change_rights_ang_save_errors(cgs, path, mode); 197 return; 198 } 199 else 200 { 201 change_rights_ang_save_errors(cgs, path, mode); 202 return; 203 } 204 } 205 catch (Exception e) 206 { 207 save_errors(cgs, path, e.msg); 208 } 209 } 210 211 private void 212 start_change_rights(shared LsblkInfo[string] lsblk, immutable string[] paths, 213 bool set, int bit, DirOrFile dof, bool recursive, Tid tid) 214 { 215 writefln("Start change rights %s", paths); 216 217 try { 218 FMGlobalState cgs = new FMGlobalState(); 219 scope(exit) 220 { 221 destroy(cgs); 222 } 223 224 cgs.lsblk = to!(LsblkInfo[string])(lsblk); 225 226 DbTxn txn = null;//dbenv.txn_begin(null); 227 string[] paths_dup = paths.dup; 228 sort!("a < b")(paths_dup); 229 foreach(path; paths_dup) 230 { 231 change_rights_private(cgs, PathMnt(cgs.lsblk, path), set, bit, dof, recursive); 232 } 233 //txn.commit(); 234 } catch (shared(Throwable) exc) { 235 send(tid, exc); 236 } 237 238 writefln("Finish change rights %s", paths); 239 send(tid, thisTid); 240 } 241 242 int change_rights(GlobalState gs, immutable string[] paths, bool set, int bit, 243 DirOrFile dof, bool recursive) 244 { 245 foreach(tid, paths2; gs.changers_rights) 246 { 247 if (paths2 == paths) 248 { 249 string msg = format("Wait till finished previous task on change rights"); 250 gs.messages ~= ConsoleMessage( 251 SDL_Color(0xFF, 0x00, 0x00, 0xFF), 252 msg, 253 SDL_GetTicks() 254 ); 255 writeln(msg); 256 return -1; 257 } 258 } 259 260 shared LsblkInfo[string] lsblk = to!(shared LsblkInfo[string])(gs.lsblk); 261 auto tid = spawn(&start_change_rights, lsblk, paths, set, bit, dof, 262 recursive, thisTid); 263 gs.changers_rights[tid] = paths.dup(); 264 return 0; 265 } 266 267 void check_changer_rights(GlobalState gs) 268 { 269 // Look check_scanners 270 } 271 }