Move RefPtr refcount into a struct
[libs/core.git] / examples / syncdir.cpp
1 #include <algorithm>
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>
10
11 using namespace std;
12 using namespace Msp;
13
14 class SyncDir: public RegisteredApplication<SyncDir>
15 {
16 private:
17         FS::Path source;
18         FS::Path destination;
19
20 public:
21         SyncDir(int, char **);
22
23         int main();
24 private:
25         void sync_directory(const FS::Path &, const FS::Path &);
26         void copy_file(const FS::Path &, const FS::Path &);
27 };
28
29 SyncDir::SyncDir(int argc, char **argv)
30 {
31         if(argc<3)
32                 throw usage_error("Missing arguments", format("Usage: %s <source> <destination>", argv[0]));
33
34         source = argv[1];
35         destination = argv[2];
36 }
37
38 int SyncDir::main()
39 {
40         sync_directory(source, destination);
41         return 0;
42 }
43
44 void SyncDir::sync_directory(const FS::Path &src, const FS::Path &dest)
45 {
46         IO::print("Syncing %s to %s\n", src, dest);
47
48         FS::Stat st = FS::stat(dest);
49         if(!st)
50                 FS::mkpath(dest, 0755);
51         else if(!st.is_directory())
52         {
53                 FS::unlink(dest);
54                 FS::mkdir(dest, 0755);
55         }
56
57         list<string> src_files = FS::list_files(src);
58         for(list<string>::const_iterator i=src_files.begin(); i!=src_files.end(); ++i)
59         {
60                 const string &fn = *i;
61                 FS::Stat ss = FS::stat(src/fn);
62                 if(ss.is_directory())
63                         sync_directory(src/fn, dest/fn);
64                 else
65                 {
66                         FS::Stat ds = FS::stat(dest/fn);
67                         if(!ds || ds.get_size()!=ss.get_size())
68                                 copy_file(src/fn, dest/fn);
69                 }
70         }
71
72         list<string> dest_files = FS::list_files(dest);
73         for(list<string>::const_iterator i=dest_files.begin(); i!=dest_files.end(); ++i)
74         {
75                 if(find(src_files.begin(), src_files.end(), *i)==src_files.end())
76                 {
77                         const string &fn = *i;
78                         IO::print("Removing obsolete %s\n", dest/fn);
79                         if(FS::is_dir(dest/fn))
80                                 FS::rmpath(dest/fn);
81                         else
82                                 FS::unlink(dest/fn);
83                 }
84         }
85 }
86
87 void SyncDir::copy_file(const FS::Path &src, const FS::Path &dest)
88 {
89         IO::File in(src.str(), IO::M_READ);
90         IO::File out(dest.str(), IO::M_WRITE);
91         char buf[16384];
92         while(!in.eof())
93         {
94                 unsigned len = in.read(buf, sizeof(buf));
95                 out.write(buf, len);
96         }
97 }