ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/Syncify/Syncify.cpp
Revision: 444
Committed: 2005-04-16T22:45:40-07:00 (20 years, 2 months ago) by douglas
File size: 4218 byte(s)
Log Message:
Fux0r!

File Contents

# Content
1 // Syncify
2 //
3 // Douglas Thrift
4 //
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 ext::String local("."), remote, pattern("^.*$");
18
19 _foreach (const app::ArgumentList, arg, app::GetArguments())
20 {
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 << " [-local=local] -remote=remote [-pattern=pattern] [-D]" << ios::NewLine;
34
35 return 1;
36 }
37 }
38
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)
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 }

Properties

Name Value
svn:eol-style native
svn:keywords Id