--- Syncify/Syncify.cpp 2005/04/04 07:33:57 436 +++ Syncify/Syncify.cpp 2005/04/17 05:45:40 444 @@ -5,6 +5,7 @@ // $Id$ #include "Syncify.hpp" +#include "SambaReader.hpp" #include #include @@ -51,50 +52,135 @@ extern "C" { void authenticate(const char* srv, const char* shr, char* wg, int wglen, char* un, int unlen, char* pw, int pwlen) { - static ext::String user("Douglas Thrift"), password(::getpass("Password:")); + static ext::Buffer user("Douglas Thrift"), password(::getpass("Password:")); - ::snprintf(un, unlen, "%s", user.NullTerminate()); - ::snprintf(pw, pwlen, "%s", password.NullTerminate()); + _foreach (ext::Buffer, atom, user) + un[_index] = *atom; + _foreach (ext::Buffer, atom, password) + pw[_index] = *atom; + + un[user.GetSize() < size_t(unlen) ? user.GetSize() : unlen - 1] = '\0'; + pw[password.GetSize() < size_t(pwlen) ? password.GetSize() : pwlen - 1] = '\0'; } } -Syncify::Syncify(const ext::String& local, const ext::String& remote, const ext::String& pattern) : pattern(pattern) +Syncify::Syncify(const ext::String& local, const ext::String& remote, const ext::String& pattern) : pattern(pattern), transfering(true), transferers(etl::BindAll(&Syncify::transfer, this)) { CheckError(::smbc_init(authenticate, debug ? 2 : 0)); + transferers.Add(1); + syncify(local, remote); + + transfering = false; } Syncify::~Syncify() { + transferers.Join(); + + api::Cout << ios::NewLine; + ::smbc_free_context(::smbc_set_context(NULL), 1); } ext::String Syncify::program(api::GetExecutablePath().GetName()); bool Syncify::debug(false); -void Syncify::syncify(const ext::String& local, const ext::String& remote) +void Syncify::syncify(const api::Path& local, const ext::String& remote) { - Matcher dots("^\\.{1,2}$"); - ext::RedBlackSet directories; - int directory(CheckError(::smbc_opendir(remote.NullTerminate()))); + try + { + Matcher dots("^\\.{1,2}$"); + ext::RedBlackSet directories; + int directory(CheckError(::smbc_opendir(remote.NullTerminate()))); + + for (::smbc_dirent* entity(::smbc_readdir(directory)); entity != NULL; entity = ::smbc_readdir(directory)) switch (entity->smbc_type) + { + case SMBC_FILE: + if (entity->name == pattern) + { + api::Path path(local.GetChild(entity->name)); + + if (!path.Exists()) + { + api::Cout << "+" << entity->name << ios::Flush; + + ext::Buffer buffer(entity->name); + + buffer.SetSize(buffer.GetSize() * 3); + + ::smbc_urlencode(buffer.Begin(), entity->name, buffer.GetSize()); + + _synchronized (transfersLock) + transfers.push(Transfer(path.GetPath(), remote + "/" + ext::String(buffer))); + } + else + api::Cout << "-" << ios::Flush; + } + break; + case SMBC_DIR: + case SMBC_LINK: + if (entity->name != dots) + directories.Insert(entity->name); + } + + ::smbc_closedir(directory); - for (::smbc_dirent* entity(::smbc_readdir(directory)); entity != NULL; entity = ::smbc_readdir(directory)) switch (entity->smbc_type) + _foreach (const ext::RedBlackSet, directory, directories) + syncify(local.GetChild(*directory), remote + "/" + *directory); + } + catch (const Error& error) {} +} + +int Syncify::transfer() +{ + _synchronized (transfersLock) while (transfering || !transfers.empty()) if (!transfers.empty()) { - case SMBC_FILE: - if (entity->name == pattern) + Transfer transfer(transfers.front()); + + transfers.pop(); + + _desynchronized (transfersLock) { - api::Cout << entity->name << ios::NewLine; + { + api::Path file(transfer.local); + ext::Stack stack; + + for (api::Path path(file.GetParent()); !path.Exists(); path = path.GetParent()) + stack.Push(path.GetPath()); + + while (!stack.IsEmpty()) + { + try + { + api::Posix::CheckError(::mkdir(stack.Top().NullTerminate(), 0755)); + } + catch (const api::Posix::Error&) {} + + stack.Pop(); + } + } + + try + { + SambaReader samba(transfer.remote); + api::FileWriter file(transfer.local); + + ios::ReadToWrite(samba, file); + } + catch (const Error& error) + { + api::Cerr << error << ios::NewLine; + } } - break; - case SMBC_DIR: - case SMBC_LINK: - if (entity->name != dots) - directories.Insert(entity->name); } + else _desynchronized (transfersLock) + { + ::timespec wait = { 0, 1000000 }; - ::smbc_closedir(directory); + ::nanosleep(&wait, NULL); + } - _foreach (const ext::RedBlackSet, directory, directories) - syncify(local + "/" + *directory, remote + "/" + *directory); + return 0; }