1 module beangle.fs.file; 2 3 import std.stdio; 4 import std.file; 5 import std.zip; 6 import std..string; 7 import std.conv; 8 import vibe.core.log; 9 10 uint unzip(string zipfile,string base,string innerDir=null){ 11 string prefix=innerDir; 12 if (null!=prefix && !prefix.endsWith( "/")){ 13 prefix ~="/"; 14 } 15 uint count=0; 16 if (exists( zipfile)){ 17 auto zip = new ZipArchive( read( zipfile)); 18 mkdirRecurse( base); 19 foreach (name, am; zip.directory) { 20 if (null==prefix || name.startsWith( prefix)){ 21 auto targetName=name; 22 if (null!=prefix && name.startsWith( prefix)){ 23 targetName =targetName[prefix.length .. $]; 24 } 25 if (targetName.endsWith( "/")){ 26 mkdirRecurse( base~"/"~targetName); 27 } else if (targetName.length>0) { 28 auto lastSlash=targetName.lastIndexOf( "/"); 29 if (lastSlash>0){ 30 mkdirRecurse( base~"/"~ targetName[0..lastSlash]); 31 } 32 zip.expand( am); 33 assert(am.expandedData.length == am.expandedSize); 34 std.file.write( base~"/"~targetName,am.expandedData); 35 count +=1; 36 } 37 } 38 } 39 } 40 return count; 41 } 42 43 uint refreshUnzip(string zipfile,string base,string innerDir=null){ 44 string prefix=innerDir; 45 if (null!=prefix && !prefix.endsWith( "/")){ 46 prefix ~="/"; 47 } 48 uint count=0; 49 if (exists( zipfile)){ 50 auto zip = new ZipArchive( read( zipfile)); 51 mkdirRecurse( base); 52 foreach (name, am; zip.directory) { 53 if (null==prefix || name.startsWith( prefix)){ 54 auto targetName=name; 55 if (null!=prefix && name.startsWith( prefix)){ 56 targetName =targetName[prefix.length .. $]; 57 } 58 if (targetName.endsWith( "/")){ 59 mkdirRecurse( base~"/"~targetName); 60 } else if (targetName.length>0) { 61 auto lastSlash=targetName.lastIndexOf( "/"); 62 if (lastSlash>0){ 63 mkdirRecurse( base~"/"~ targetName[0..lastSlash]); 64 } 65 auto targetFile = base~"/"~targetName; 66 bool spawn=true; 67 if (exists( targetFile) && getSize( targetFile) == am.expandedSize){ 68 spawn=false; 69 } 70 if (spawn){ 71 zip.expand( am); 72 assert(am.expandedData.length == am.expandedSize); 73 std.file.write( targetFile,am.expandedData); 74 } 75 count +=1; 76 } 77 } 78 } 79 } 80 return count; 81 } 82 83 void setReadOnly(string dir){ 84 if (!exists( dir)){ 85 return ; 86 } 87 doSetReadOnly( dir); 88 } 89 90 private void doSetReadOnly(string dir){ 91 if (dir.isDir){ 92 dir.setAttributes( octal!555); 93 foreach (d; dirEntries( dir, SpanMode.shallow)) { 94 if (!d.isSymlink){ 95 if (d.isDir) { 96 doSetReadOnly( d); 97 }else { 98 d.setAttributes( octal!444); 99 } 100 } 101 } 102 }else { 103 dir.setAttributes( octal!444); 104 } 105 } 106 107 void setWritable(string dir){ 108 if (!exists( dir)){ 109 return ; 110 } 111 doSetWritable( dir); 112 } 113 114 private void doSetWritable(string dir){ 115 if (dir.isDir){ 116 dir.setAttributes( dir.getAttributes | octal!700); 117 foreach (d; dirEntries( dir, SpanMode.breadth)) { 118 if (!d.isSymlink){ 119 if (d.isDir) { 120 doSetWritable( d); 121 }else { 122 d.setAttributes( d.getAttributes | octal!200); 123 } 124 } 125 } 126 }else { 127 dir.setAttributes( dir.getAttributes | octal!600); 128 } 129 } 130 131 unittest{ 132 import std.file : read; 133 import std.stdio; 134 auto zipPath="/tmp/beangle-bundles-bui-0.2.1.jar"; 135 if (exists( zipPath)){ 136 auto base="/tmp/beangle-bundles-bui-0.2.1"; 137 unzip( zipPath,base,"META-INF/resources/bui"); 138 setReadOnly( base); 139 setWritable( base); 140 base.rmdirRecurse(); 141 } 142 }