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 436 by douglas, 2005-04-04T00:33:57-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>
# Line 51 | Line 52 | 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::String user("Douglas Thrift"), password(::getpass("Password:"));
55 >                static ext::Buffer user("Douglas Thrift"), password(::getpass("Password:"));
56  
57 <                ::snprintf(un, unlen, "%s", user.NullTerminate());
58 <                ::snprintf(pw, pwlen, "%s", password.NullTerminate());
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)
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 ext::String& local, const ext::String& remote)
90 > void Syncify::syncify(const api::Path& local, const ext::String& remote)
91   {
92 <        Matcher dots("^\\.{1,2}$");
93 <        ext::RedBlackSet<ext::String> directories;
94 <        int directory(CheckError(::smbc_opendir(remote.NullTerminate())));
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 <        for (::smbc_dirent* entity(::smbc_readdir(directory)); entity != NULL; entity = ::smbc_readdir(directory)) switch (entity->smbc_type)
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 <        case SMBC_FILE:
141 <                if (entity->name == pattern)
140 >                Transfer transfer(transfers.front());
141 >
142 >                transfers.pop();
143 >
144 >                _desynchronized (transfersLock)
145                  {
146 <                        api::Cout << entity->name << ios::NewLine;
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                  }
89                break;
90        case SMBC_DIR:
91        case SMBC_LINK:
92                if (entity->name != dots)
93                        directories.Insert(entity->name);
177          }
178 +        else _desynchronized (transfersLock)
179 +        {
180 +                ::timespec wait = { 0, 1000000 };
181  
182 <        ::smbc_closedir(directory);
182 >                ::nanosleep(&wait, NULL);
183 >        }
184  
185 <        _foreach (const ext::RedBlackSet<ext::String>, directory, directories)
99 <                syncify(local + "/" + *directory, remote + "/" + *directory);
185 >        return 0;
186   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines