ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Syncify/Syncify.cpp
(Generate patch)

Comparing Syncify/Syncify.cpp (file contents):
Revision 435 by douglas, 2005-04-03T15:42:59-07:00 vs.
Revision 444 by douglas, 2005-04-16T22:45:40-07:00

# Line 5 | Line 5
5   // $Id$
6  
7   #include "Syncify.hpp"
8 + #include "SambaReader.hpp"
9  
10   #include <menes-api/exename.hpp>
11   #include <menes-app/simple.hpp>
12  
13 + #include <stdio.h>
14 +
15   int Main(const app::Options& options)
16   {
17 <        //
17 >        ext::String local("."), remote, pattern("^.*$");
18          
19          _foreach (const app::ArgumentList, arg, app::GetArguments())
20          {
21 <                if (*arg == "-D")
21 >                Matcher matcher;
22 >
23 >                if (*arg == matcher("^-local=(.+)$"))
24 >                        local = matcher[1];
25 >                else if (*arg == matcher("^-remote=(.+)$"))
26 >                        remote = matcher[1];
27 >                else if (*arg == matcher("^-pattern=(.+)$"))
28 >                        pattern = matcher[1];
29 >                else if (*arg == "-D")
30                          Syncify::debug = true;
31                  else
32                  {
33 <                        api::Cerr << "Usage: " << Syncify::program << " [-D]" << ios::NewLine;
33 >                        api::Cerr << "Usage: " << Syncify::program << " [-local=local] -remote=remote [-pattern=pattern] [-D]" << ios::NewLine;
34  
35                          return 1;
36                  }
37          }
38  
39 <        //
39 >        if (remote.IsEmpty())
40 >        {
41 >                api::Cerr << "Usage: " << Syncify::program << " [-local=local] -remote=remote [-pattern=pattern] [-D]" << ios::NewLine;
42 >
43 >                return 1;
44 >        }
45 >
46 >        Syncify syncify(local, remote, pattern);
47          
48          return 0;
49   }
50  
51   extern "C"
52   {
53 <        void authenticate(const char* srv, const char* shr, char* wg, int wglen, char* un, int unlen, char* pw, int pwlen) {}
53 >        void authenticate(const char* srv, const char* shr, char* wg, int wglen, char* un, int unlen, char* pw, int pwlen)
54 >        {
55 >                static ext::Buffer user("Douglas Thrift"), password(::getpass("Password:"));
56 >
57 >                _foreach (ext::Buffer, atom, user)
58 >                        un[_index] = *atom;
59 >                _foreach (ext::Buffer, atom, password)
60 >                        pw[_index] = *atom;
61 >
62 >                un[user.GetSize() < size_t(unlen) ? user.GetSize() : unlen - 1] = '\0';
63 >                pw[password.GetSize() < size_t(pwlen) ? password.GetSize() : pwlen - 1] = '\0';
64 >        }
65 > }
66 >
67 > Syncify::Syncify(const ext::String& local, const ext::String& remote, const ext::String& pattern) : pattern(pattern), transfering(true), transferers(etl::BindAll(&Syncify::transfer, this))
68 > {
69 >        CheckError(::smbc_init(authenticate, debug ? 2 : 0));
70 >
71 >        transferers.Add(1);
72 >
73 >        syncify(local, remote);
74 >
75 >        transfering = false;
76 > }
77 >
78 > Syncify::~Syncify()
79 > {
80 >        transferers.Join();
81 >
82 >        api::Cout << ios::NewLine;
83 >
84 >        ::smbc_free_context(::smbc_set_context(NULL), 1);
85   }
86  
87   ext::String Syncify::program(api::GetExecutablePath().GetName());
88   bool Syncify::debug(false);
89 +
90 + void Syncify::syncify(const api::Path& local, const ext::String& remote)
91 + {
92 +        try
93 +        {
94 +                Matcher dots("^\\.{1,2}$");
95 +                ext::RedBlackSet<ext::String> directories;
96 +                int directory(CheckError(::smbc_opendir(remote.NullTerminate())));
97 +
98 +                for (::smbc_dirent* entity(::smbc_readdir(directory)); entity != NULL; entity = ::smbc_readdir(directory)) switch (entity->smbc_type)
99 +                {
100 +                case SMBC_FILE:
101 +                        if (entity->name == pattern)
102 +                        {
103 +                                api::Path path(local.GetChild(entity->name));
104 +
105 +                                if (!path.Exists())
106 +                                {
107 +                                        api::Cout << "+" << entity->name << ios::Flush;
108 +
109 +                                        ext::Buffer buffer(entity->name);
110 +
111 +                                        buffer.SetSize(buffer.GetSize() * 3);
112 +
113 +                                        ::smbc_urlencode(buffer.Begin(), entity->name, buffer.GetSize());
114 +
115 +                                        _synchronized (transfersLock)
116 +                                                transfers.push(Transfer(path.GetPath(), remote + "/" + ext::String(buffer)));
117 +                                }
118 +                                else
119 +                                        api::Cout << "-" << ios::Flush;
120 +                        }
121 +                        break;
122 +                case SMBC_DIR:
123 +                case SMBC_LINK:
124 +                        if (entity->name != dots)
125 +                                directories.Insert(entity->name);
126 +                }
127 +
128 +                ::smbc_closedir(directory);
129 +
130 +                _foreach (const ext::RedBlackSet<ext::String>, directory, directories)
131 +                        syncify(local.GetChild(*directory), remote + "/" + *directory);
132 +        }
133 +        catch (const Error& error) {}
134 + }
135 +
136 + int Syncify::transfer()
137 + {
138 +        _synchronized (transfersLock) while (transfering || !transfers.empty()) if (!transfers.empty())
139 +        {
140 +                Transfer transfer(transfers.front());
141 +
142 +                transfers.pop();
143 +
144 +                _desynchronized (transfersLock)
145 +                {
146 +                        {
147 +                                api::Path file(transfer.local);
148 +                                ext::Stack<ext::String> stack;
149 +
150 +                                for (api::Path path(file.GetParent()); !path.Exists(); path = path.GetParent())
151 +                                        stack.Push(path.GetPath());
152 +
153 +                                while (!stack.IsEmpty())
154 +                                {
155 +                                        try
156 +                                        {
157 +                                                api::Posix::CheckError(::mkdir(stack.Top().NullTerminate(), 0755));
158 +                                        }
159 +                                        catch (const api::Posix::Error&) {}
160 +
161 +                                        stack.Pop();
162 +                                }
163 +                        }
164 +
165 +                        try
166 +                        {
167 +                                SambaReader samba(transfer.remote);
168 +                                api::FileWriter file(transfer.local);
169 +
170 +                                ios::ReadToWrite(samba, file);
171 +                        }
172 +                        catch (const Error& error)
173 +                        {
174 +                                api::Cerr << error << ios::NewLine;
175 +                        }
176 +                }
177 +        }
178 +        else _desynchronized (transfersLock)
179 +        {
180 +                ::timespec wait = { 0, 1000000 };
181 +
182 +                ::nanosleep(&wait, NULL);
183 +        }
184 +
185 +        return 0;
186 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines