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

# User Rev Content
1 douglas 435 // Syncify
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7     #include "Syncify.hpp"
8 douglas 440 #include "SambaReader.hpp"
9 douglas 435
10     #include <menes-api/exename.hpp>
11     #include <menes-app/simple.hpp>
12    
13 douglas 436 #include <stdio.h>
14    
15 douglas 435 int Main(const app::Options& options)
16     {
17 douglas 436 ext::String local("."), remote, pattern("^.*$");
18 douglas 435
19     _foreach (const app::ArgumentList, arg, app::GetArguments())
20     {
21 douglas 436 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 douglas 435 Syncify::debug = true;
31     else
32     {
33 douglas 436 api::Cerr << "Usage: " << Syncify::program << " [-local=local] -remote=remote [-pattern=pattern] [-D]" << ios::NewLine;
34 douglas 435
35     return 1;
36     }
37     }
38    
39 douglas 436 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 douglas 435
48     return 0;
49     }
50    
51     extern "C"
52     {
53 douglas 436 void authenticate(const char* srv, const char* shr, char* wg, int wglen, char* un, int unlen, char* pw, int pwlen)
54     {
55 douglas 438 static ext::Buffer user("Douglas Thrift"), password(::getpass("Password:"));
56 douglas 436
57 douglas 438 _foreach (ext::Buffer, atom, user)
58 douglas 437 un[_index] = *atom;
59 douglas 438 _foreach (ext::Buffer, atom, password)
60 douglas 437 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 douglas 436 }
65 douglas 435 }
66    
67 douglas 444 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 douglas 436 {
69     CheckError(::smbc_init(authenticate, debug ? 2 : 0));
70    
71 douglas 444 transferers.Add(1);
72    
73 douglas 436 syncify(local, remote);
74 douglas 444
75     transfering = false;
76 douglas 436 }
77    
78     Syncify::~Syncify()
79     {
80 douglas 444 transferers.Join();
81    
82     api::Cout << ios::NewLine;
83    
84 douglas 436 ::smbc_free_context(::smbc_set_context(NULL), 1);
85     }
86    
87 douglas 435 ext::String Syncify::program(api::GetExecutablePath().GetName());
88     bool Syncify::debug(false);
89 douglas 436
90 douglas 440 void Syncify::syncify(const api::Path& local, const ext::String& remote)
91 douglas 436 {
92 douglas 437 try
93     {
94     Matcher dots("^\\.{1,2}$");
95     ext::RedBlackSet<ext::String> directories;
96     int directory(CheckError(::smbc_opendir(remote.NullTerminate())));
97 douglas 436
98 douglas 437 for (::smbc_dirent* entity(::smbc_readdir(directory)); entity != NULL; entity = ::smbc_readdir(directory)) switch (entity->smbc_type)
99 douglas 436 {
100 douglas 437 case SMBC_FILE:
101     if (entity->name == pattern)
102     {
103 douglas 440 api::Path path(local.GetChild(entity->name));
104    
105     if (!path.Exists())
106     {
107 douglas 444 api::Cout << "+" << entity->name << ios::Flush;
108 douglas 440
109 douglas 444 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 douglas 440 }
118 douglas 444 else
119     api::Cout << "-" << ios::Flush;
120 douglas 437 }
121     break;
122     case SMBC_DIR:
123     case SMBC_LINK:
124     if (entity->name != dots)
125     directories.Insert(entity->name);
126 douglas 436 }
127    
128 douglas 437 ::smbc_closedir(directory);
129 douglas 436
130 douglas 437 _foreach (const ext::RedBlackSet<ext::String>, directory, directories)
131 douglas 440 syncify(local.GetChild(*directory), remote + "/" + *directory);
132 douglas 437 }
133 douglas 444 catch (const Error& error) {}
134     }
135    
136     int Syncify::transfer()
137     {
138     _synchronized (transfersLock) while (transfering || !transfers.empty()) if (!transfers.empty())
139 douglas 437 {
140 douglas 444 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 douglas 437 }
178 douglas 444 else _desynchronized (transfersLock)
179     {
180     ::timespec wait = { 0, 1000000 };
181    
182     ::nanosleep(&wait, NULL);
183     }
184    
185     return 0;
186 douglas 436 }

Properties

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