1 module unde.path_mnt; 2 3 import unde.global_state; 4 import unde.lib; 5 import unde.lsblk; 6 import unde.slash; 7 8 import std.stdio; 9 import std..string; 10 import std.format; 11 12 import std.file; 13 import core.sys.posix.sys.types; 14 15 version (Windows) 16 { 17 import berkeleydb.all: ssize_t; 18 } 19 20 struct PathMnt 21 { 22 string path; 23 string _next; 24 string mnt; 25 version (Windows) 26 { 27 alias char dev_t; 28 } 29 dev_t dev; 30 alias _next this; 31 32 this(string p) 33 { 34 path = p; 35 mnt = p; 36 _next = p; 37 38 version(Posix) 39 { 40 DirEntry de = DirEntry(p); 41 dev = de.statBuf.st_dev; 42 } 43 else version(Windows) 44 { 45 dev=p[0]; 46 //assert(p[1] == ':'); 47 } 48 } 49 50 this(ref LsblkInfo[string] lsblk, string path) 51 out 52 { 53 assert(this.path == path, 54 format("this.path=%s, path=%s", this.path, path)); 55 } 56 body 57 { 58 if (path.length > 1 && path[0] == path[1] && path[0] == SL[0]) 59 path = path[1..$]; 60 version(Windows) 61 { 62 if (path.length > 1 && path[1] == ':') 63 this(path[0..2]); 64 else 65 this(SL); 66 } 67 else 68 { 69 this(SL); 70 } 71 string wrkpath = this.path; 72 while (wrkpath < path) 73 { 74 bool found = false; 75 version (Windows) 76 { 77 if (wrkpath == SL && path[1] == ':') 78 { 79 wrkpath = path[0..2]; 80 found = true; 81 } 82 } 83 if (!found) 84 { 85 string after = path[wrkpath.length+1 .. $]; 86 if (wrkpath[$-1] == SL[0]) after = path[wrkpath.length .. $]; 87 //writefln("wrkpath=%s, path=%s, after=%s", wrkpath, path, after); 88 ssize_t i = after.indexOf(SL); 89 if (i < 0) i = after.length; 90 ssize_t new_len = wrkpath.length + i + 1; 91 if (wrkpath[$-1] == SL[0]) new_len--; 92 wrkpath = path[0..new_len]; 93 //writefln("wrkpath=%s", wrkpath); 94 } 95 96 _next = wrkpath; 97 update(lsblk); 98 } 99 } 100 101 this(string path, string mnt, dev_t dev) 102 { 103 this.path = path; 104 this.mnt = mnt; 105 this.next = path; 106 this.dev = dev; 107 } 108 109 PathMnt next(string next) 110 { 111 PathMnt new_path = this; 112 new_path._next = next; 113 return new_path; 114 } 115 116 string get_key(in LsblkInfo[string] lsblk) 117 { 118 string key; 119 120 LsblkInfo info = lsblk[mnt]; 121 122 string subpath = subpath(_next, mnt); 123 string path0 = info.uuid ~ subpath.replace(SL, "\0"); 124 return path0; 125 } 126 127 void update(ref LsblkInfo[string] lsblkinfo) 128 in 129 { 130 size_t i = path.length; 131 version(Windows) 132 { 133 if (path != "\\") 134 { 135 assert(_next[0..i] == path, _next[0..i]~" == "~path); 136 if (_next != path) 137 { 138 assert(_next[i] == SL[0] || path == SL, format("path=%s, _next=%s", path, _next)); 139 assert(_next[i+1..$].indexOf(SL) < 0, format("path=%s, _next=%s", path, _next)); 140 } 141 } 142 } 143 else 144 { 145 assert(_next[0..i] == path, _next[0..i]~" == "~path); 146 if (_next != path) 147 { 148 assert(_next[i] == SL[0] || path == SL, format("path=%s, _next=%s", path, _next)); 149 assert(_next[i+1..$].indexOf(SL) < 0, format("path=%s, _next=%s", path, _next)); 150 } 151 } 152 } 153 out 154 { 155 assert(path == _next); 156 } 157 body 158 { 159 if (_next == path) return; 160 161 DirEntry de; 162 bool direntry_success = true; 163 version(Posix) 164 { 165 try 166 { 167 de = DirEntry(_next); 168 } 169 catch (FileException e) 170 { 171 direntry_success = false; 172 } 173 174 bool not_the_same_filesystem = direntry_success && !de.isSymlink && de.statBuf.st_dev != dev; 175 } 176 else version(Windows) 177 { 178 bool not_the_same_filesystem = _next[0] != dev; 179 } 180 if (not_the_same_filesystem) 181 { 182 version(Posix) 183 { 184 dev = de.statBuf.st_dev; 185 } 186 else 187 { 188 dev = _next[0]; 189 } 190 char major = (dev & 0xFF00) >> 8; 191 if ( (major == 7 || major == 8 || major == 179) && 192 path !in lsblkinfo ) 193 { 194 lsblk(lsblkinfo); 195 assert(_next in lsblkinfo, "Path "~path~" not in lsblk"); 196 } 197 } 198 199 if (_next in lsblkinfo) 200 { 201 mnt = _next; 202 } 203 path = _next; 204 } 205 }