1 module easyd.unix; 2 3 // (C) 2014-2018 by Matthias Rossmy 4 // This file is distributed under the "Fair Use License v2" 5 6 public import std.file; //must be imported here as public instead of easyd/package.d, otherwise the resolving of some functions would be ambigious 7 8 import std.path; 9 import std.format; 10 import std.conv; 11 import std.algorithm; 12 import std.process; 13 import std.stdio; 14 15 import easyd.base; 16 import easyd..string; 17 import easyd.stream; 18 19 unittest 20 { 21 assert(parentDir("/home/test")=="/home"); 22 assert(pathEqual("/home/test/bla/../","/home/test")); 23 assert("/home/test".slash=="/home/test/"); 24 assert("/home/test/".slash=="/home/test/"); 25 assert("/home/test".unslash=="/home/test"); 26 assert("/home/test/".unslash=="/home/test"); 27 assert(fullPath("~/test")=="/home/"~userName~"/test"); 28 assert("../test/my.file".fullPathFrom("/home/bla")=="/home/test/my.file"); 29 assert(pureName("/tmp/test.tar.gz",false)=="test.tar"); 30 assert(pureName("/tmp/test.tar.gz",true)=="test"); 31 32 auto stream = new StdoutStream("echo test"); 33 assert(stream.readLine=="test"); 34 } 35 36 string parentDir(string s) 37 { 38 return s.fullPath.dirName; 39 } 40 41 bool resetDir(string d) 42 { 43 Try(rmdirRecurse(d)); 44 return Try(mkdirRecurse(d)); 45 } 46 47 bool isExecutable(string fn, bool acceptDirs=true) 48 { 49 try 50 { 51 return (acceptDirs || !isDir(fn)) && (format("%o",getAttributes(fn)).getEnd(1).to!int & 1) > 0; 52 }catch(Exception e){ 53 return false; 54 } 55 } 56 57 bool isDir(string s) 58 { 59 bool result = false; 60 try 61 { 62 result = std.file.isDir(s); 63 }catch(Exception e){} 64 return result; 65 } 66 67 bool pathEqual(string p1,string p2) 68 { 69 return p1.fullPath.unslash==p2.fullPath.unslash; 70 } 71 72 string slash(string s) 73 { 74 return s.endsWith(dirSeparator)? s : s ~ dirSeparator; 75 } 76 77 string unslash(string s) 78 { 79 return s.endsWith(dirSeparator)? s.cutEnd(1) : s; 80 } 81 82 string fullPath(string s) 83 { 84 return s.expandTilde.absolutePath.buildNormalizedPath; 85 } 86 87 string fullPathFrom(string s, string refPath) 88 { 89 string refdir; 90 if(refPath.exists && !refPath.isDir) 91 { 92 refdir = refPath.dirName; 93 }else{ 94 refdir = refPath; 95 } 96 return s.expandTilde.absolutePath(refdir).buildNormalizedPath; 97 } 98 99 string pureName(string s, bool multiStrip=false) 100 { 101 s = s.baseName; 102 if(multiStrip) 103 { 104 while(s.contains('.')) s = s.stripExtension; 105 return s; 106 }else{ 107 return s.stripExtension; 108 } 109 } 110 111 string userName() 112 { 113 return fullPath("~").baseName; 114 } 115 116 struct ScopedChdir 117 { 118 string prevDir; 119 string newDir; 120 bool isTemp; 121 122 this(string newdir, bool istemp=false) 123 { 124 prevDir = getcwd; 125 newDir = newdir.absolutePath; 126 isTemp = istemp; 127 chdir(newDir); 128 } 129 130 ~this() 131 { 132 chdir(prevDir); 133 if(isTemp) rmdirRecurse(newDir); 134 } 135 } 136 137 void symLink(string source,string dest,bool relative=true) 138 { 139 source = source.absolutePath; 140 if(relative) source = source.relativePath(dest.dirName.absolutePath); 141 Try(remove(dest)); 142 symlink(source,dest); 143 } 144 145 string resolveLink(string symlink) 146 { 147 try 148 { 149 symlink = symlink.absolutePath; 150 return readLink(symlink).absolutePath(symlink.dirName); 151 }catch(Exception e){ 152 return ""; 153 } 154 } 155 156 bool isLink(string symlink) 157 { 158 return resolveLink(symlink)!=""; 159 } 160 161 class StdoutStream : FileReader 162 { 163 this(string command) 164 { 165 auto pipes = pipeShell(command,Redirect.stdout | Redirect.stderrToStdout); 166 file = pipes.stdout; 167 } 168 } 169 170 class TarStream : StdoutStream 171 { 172 this(string path) 173 { 174 super("tar -c "~path); 175 } 176 } 177 178 class UntarStream : FileWriter 179 { 180 this() 181 { 182 auto pipes = pipeShell("tar -x",Redirect.stdin); 183 file = pipes.stdin; 184 } 185 } 186 187 bool shellExec(string command, bool w=true, bool dbg=false) 188 { 189 try 190 { 191 if(!w) command = "("~command~" &)"; 192 if(dbg) writeln(getcwd,"> ",command); 193 auto pid = spawnShell(command); 194 if(w) 195 { 196 auto rc = wait(pid); 197 if(rc!=0 && dbg) writeln("Return code = ",rc); 198 return rc==0; 199 } 200 return true; 201 }catch(Exception e){ 202 if(dbg) writeln(e); 203 return false; 204 } 205 } 206 207 bool isWritable(string fn) 208 { 209 return shellExec("test -w \""~fn~"\""); 210 } 211 212 bool rootPermissions() 213 { 214 return isWritable("/"); 215 } 216