1 /** 2 Copyright: Copyright (c) 2019, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 */ 6 module dsnapshot.cmdgroup.remote; 7 8 import logger = std.experimental.logger; 9 10 import dsnapshot.config; 11 import dsnapshot.types; 12 13 int cmdRemote(const Config.Remotecmd conf) nothrow { 14 import std.algorithm : map, filter; 15 import std.exception : collectException; 16 import std.file : dirEntries, SpanMode, exists, mkdirRecurse, rmdirRecurse, rename; 17 import std.path : baseName; 18 import std.stdio : writeln; 19 20 final switch (conf.cmd) { 21 case RemoteSubCmd.none: 22 break; 23 case RemoteSubCmd.lsDirs: 24 try { 25 foreach (p; dirEntries(conf.path, SpanMode.shallow).filter!(a => a.isDir) 26 .map!(a => a.name.baseName)) { 27 writeln(p); 28 } 29 } catch (Exception e) { 30 } 31 break; 32 case RemoteSubCmd.mkdirRecurse: 33 try { 34 if (!exists(conf.path)) 35 mkdirRecurse(conf.path); 36 } catch (Exception e) { 37 logger.warning(e.msg).collectException; 38 } 39 break; 40 case RemoteSubCmd.rmdirRecurse: 41 if (!exists(conf.path)) 42 return 0; 43 44 try { 45 // can fail because a directory is write protected. 46 rmdirRecurse(conf.path); 47 return 0; 48 } catch (Exception e) { 49 } 50 51 try { 52 foreach (const p; dirEntries(conf.path, SpanMode.depth).filter!(a => a.isDir)) { 53 import core.sys.posix.sys.stat; 54 import std.file : getAttributes, setAttributes; 55 56 const attrs = getAttributes(p); 57 setAttributes(p, attrs | S_IRWXU); 58 } 59 rmdirRecurse(conf.path); 60 } catch (Exception e) { 61 logger.warning(e.msg).collectException; 62 } 63 break; 64 case RemoteSubCmd.publishSnapshot: 65 if (!exists(conf.path)) { 66 logger.infof("Snapshot %s do not exist", conf.path).collectException; 67 return 1; 68 } 69 70 publishSnapshot(conf.path); 71 break; 72 case RemoteSubCmd.fakerootStats: 73 import std.stdio : File; 74 import std.path : buildPath; 75 import dsnapshot.stats; 76 77 const fakerootEnv = buildPath(conf.path, snapshotFakerootEnv); 78 if (!exists(fakerootEnv)) { 79 logger.infof("Unable to find or open %s", conf.path).collectException; 80 return 1; 81 } 82 try { 83 auto fkdb = fromFakerootEnv(fakerootEnv.Path); 84 writeln; // make sure we start at a new line 85 foreach (const ps; fromFakeroot(fkdb, conf.path, buildPath(conf.path, snapshotData))) 86 writeln(ps.toString); 87 } catch (Exception e) { 88 logger.warning(e.msg).collectException; 89 } 90 } 91 return 0; 92 } 93 94 /// Publish a snapshot that has the status "in-progress". 95 int publishSnapshot(const string snapshot) nothrow @safe { 96 import std.algorithm : map, filter; 97 import std.exception : collectException; 98 import std.file : dirEntries, SpanMode, exists, mkdirRecurse, rmdirRecurse, rename; 99 import std.path : baseName; 100 import std.stdio : writeln; 101 102 const dst = () { 103 if (snapshot.length < snapshotInProgressSuffix.length) 104 return null; 105 return snapshot[0 .. $ - snapshotInProgressSuffix.length]; 106 }(); 107 108 if (exists(dst)) { 109 logger.errorf("Destination %s already exist thus unable to publish snapshot %s", 110 dst, snapshot).collectException; 111 return 1; 112 } 113 114 try { 115 rename(snapshot, dst); 116 } catch (Exception e) { 117 logger.error(e.msg).collectException; 118 return 1; 119 } 120 121 return 0; 122 }