2 #include <msp/core/application.h>
3 #include <msp/core/getopt.h>
4 #include <msp/fs/dir.h>
5 #include <msp/fs/stat.h>
6 #include <msp/fs/utils.h>
7 #include <msp/io/file.h>
8 #include <msp/io/print.h>
9 #include <msp/strings/format.h>
14 class SyncDir: public RegisteredApplication<SyncDir>
21 SyncDir(int, char **);
25 void sync_directory(const FS::Path &, const FS::Path &);
26 void copy_file(const FS::Path &, const FS::Path &);
29 SyncDir::SyncDir(int argc, char **argv)
32 throw usage_error("Missing arguments", format("Usage: %s <source> <destination>", argv[0]));
35 destination = argv[2];
40 sync_directory(source, destination);
44 void SyncDir::sync_directory(const FS::Path &src, const FS::Path &dest)
46 IO::print("Syncing %s to %s\n", src, dest);
48 FS::Stat st = FS::stat(dest);
50 FS::mkpath(dest, 0755);
51 else if(!st.is_directory())
54 FS::mkdir(dest, 0755);
57 list<string> src_files = FS::list_files(src);
58 for(list<string>::const_iterator i=src_files.begin(); i!=src_files.end(); ++i)
60 const string &fn = *i;
61 FS::Stat ss = FS::stat(src/fn);
63 sync_directory(src/fn, dest/fn);
66 FS::Stat ds = FS::stat(dest/fn);
67 if(!ds || ds.get_size()!=ss.get_size())
68 copy_file(src/fn, dest/fn);
72 list<string> dest_files = FS::list_files(dest);
73 for(list<string>::const_iterator i=dest_files.begin(); i!=dest_files.end(); ++i)
75 if(find(src_files.begin(), src_files.end(), *i)==src_files.end())
77 const string &fn = *i;
78 IO::print("Removing obsolete %s\n", dest/fn);
79 if(FS::is_dir(dest/fn))
87 void SyncDir::copy_file(const FS::Path &src, const FS::Path &dest)
89 IO::File in(src.str(), IO::M_READ);
90 IO::File out(dest.str(), IO::M_WRITE);
94 unsigned len = in.read(buf, sizeof(buf));