Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Group Policy Object Support
4 : * Copyright (C) Guenther Deschner 2006
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "system/filesys.h"
22 : #include "libsmb/libsmb.h"
23 : #include "../libgpo/gpo.h"
24 : #include "libgpo/gpo_proto.h"
25 : #include "lib/util/string_wrappers.h"
26 :
27 : struct sync_context {
28 : TALLOC_CTX *mem_ctx;
29 : struct cli_state *cli;
30 : char *remote_path;
31 : char *local_path;
32 : char *mask;
33 : uint16_t attribute;
34 : };
35 :
36 : static NTSTATUS gpo_sync_func(struct file_info *info,
37 : const char *mask,
38 : void *state);
39 :
40 0 : NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
41 : struct cli_state *cli,
42 : const char *nt_path,
43 : const char *unix_path)
44 : {
45 0 : NTSTATUS result;
46 0 : uint16_t fnum;
47 0 : int fd = -1;
48 0 : char *data = NULL;
49 0 : static int io_bufsize = 64512;
50 0 : int read_size = io_bufsize;
51 0 : off_t nread = 0;
52 :
53 0 : result = cli_open(cli, nt_path, O_RDONLY, DENY_NONE, &fnum);
54 0 : if (!NT_STATUS_IS_OK(result)) {
55 0 : goto out;
56 : }
57 :
58 0 : if ((fd = open(unix_path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
59 0 : result = map_nt_error_from_unix(errno);
60 0 : goto out;
61 : }
62 :
63 0 : if ((data = (char *)SMB_MALLOC(read_size)) == NULL) {
64 0 : result = NT_STATUS_NO_MEMORY;
65 0 : goto out;
66 : }
67 :
68 0 : while (1) {
69 0 : size_t n = 0;
70 :
71 0 : result = cli_read(cli, fnum, data, nread, read_size, &n);
72 0 : if (!NT_STATUS_IS_OK(result)) {
73 0 : goto out;
74 : }
75 :
76 0 : if (n == 0)
77 0 : break;
78 :
79 0 : if (write(fd, data, n) != n) {
80 0 : break;
81 : }
82 :
83 0 : nread += n;
84 : }
85 :
86 0 : result = NT_STATUS_OK;
87 :
88 0 : out:
89 0 : SAFE_FREE(data);
90 0 : if (fnum) {
91 0 : cli_close(cli, fnum);
92 : }
93 0 : if (fd != -1) {
94 0 : close(fd);
95 : }
96 :
97 0 : return result;
98 : }
99 :
100 : /****************************************************************
101 : copy dir
102 : ****************************************************************/
103 :
104 0 : static NTSTATUS gpo_copy_dir(const char *unix_path)
105 : {
106 0 : if ((mkdir(unix_path, 0644)) < 0 && errno != EEXIST) {
107 0 : return map_nt_error_from_unix(errno);
108 : }
109 :
110 0 : return NT_STATUS_OK;
111 : }
112 :
113 : /****************************************************************
114 : sync files
115 : ****************************************************************/
116 :
117 0 : static NTSTATUS gpo_sync_files(struct sync_context *ctx)
118 : {
119 0 : NTSTATUS status;
120 :
121 0 : DEBUG(3,("calling cli_list with mask: %s\n", ctx->mask));
122 :
123 0 : status = cli_list(ctx->cli, ctx->mask, ctx->attribute, gpo_sync_func,
124 : ctx);
125 0 : if (!NT_STATUS_IS_OK(status)) {
126 0 : DEBUG(1, ("listing [%s] failed with error: %s\n",
127 : ctx->mask, nt_errstr(status)));
128 0 : return status;
129 : }
130 :
131 0 : return status;
132 : }
133 :
134 : /****************************************************************
135 : synchronisation callback
136 : ****************************************************************/
137 :
138 0 : static NTSTATUS gpo_sync_func(struct file_info *info,
139 : const char *mask,
140 : void *state)
141 : {
142 0 : NTSTATUS result;
143 0 : struct sync_context *ctx;
144 0 : fstring nt_filename, unix_filename;
145 0 : fstring nt_dir, unix_dir;
146 0 : char *old_nt_dir, *old_unix_dir;
147 :
148 0 : ctx = (struct sync_context *)state;
149 :
150 0 : if (strequal(info->name, ".") || strequal(info->name, "..")) {
151 0 : return NT_STATUS_OK;
152 : }
153 :
154 0 : DEBUG(5,("gpo_sync_func: got mask: [%s], name: [%s]\n",
155 : mask, info->name));
156 :
157 0 : if (info->attr & FILE_ATTRIBUTE_DIRECTORY) {
158 :
159 0 : DEBUG(3,("got dir: [%s]\n", info->name));
160 :
161 0 : fstrcpy(nt_dir, ctx->remote_path);
162 0 : fstrcat(nt_dir, "\\");
163 0 : fstrcat(nt_dir, info->name);
164 :
165 0 : fstrcpy(unix_dir, ctx->local_path);
166 0 : fstrcat(unix_dir, "/");
167 0 : fstrcat(unix_dir, info->name);
168 :
169 0 : result = gpo_copy_dir(unix_dir);
170 0 : if (!NT_STATUS_IS_OK(result)) {
171 0 : DEBUG(1,("failed to copy dir: %s\n",
172 : nt_errstr(result)));
173 0 : return result;
174 : }
175 :
176 0 : old_nt_dir = ctx->remote_path;
177 0 : ctx->remote_path = talloc_strdup(ctx->mem_ctx, nt_dir);
178 :
179 0 : old_unix_dir = ctx->local_path;
180 0 : ctx->local_path = talloc_strdup(ctx->mem_ctx, unix_dir);
181 :
182 0 : ctx->mask = talloc_asprintf(ctx->mem_ctx,
183 : "%s\\*",
184 : nt_dir);
185 0 : if (!ctx->local_path || !ctx->mask || !ctx->remote_path) {
186 0 : DEBUG(0,("gpo_sync_func: ENOMEM\n"));
187 0 : return NT_STATUS_NO_MEMORY;
188 : }
189 0 : result = gpo_sync_files(ctx);
190 0 : if (!NT_STATUS_IS_OK(result)) {
191 0 : DEBUG(0,("could not sync files\n"));
192 0 : return result;
193 : }
194 :
195 0 : ctx->remote_path = old_nt_dir;
196 0 : ctx->local_path = old_unix_dir;
197 0 : return NT_STATUS_OK;
198 : }
199 :
200 0 : DEBUG(3,("got file: [%s]\n", info->name));
201 :
202 0 : fstrcpy(nt_filename, ctx->remote_path);
203 0 : fstrcat(nt_filename, "\\");
204 0 : fstrcat(nt_filename, info->name);
205 :
206 0 : fstrcpy(unix_filename, ctx->local_path);
207 0 : fstrcat(unix_filename, "/");
208 0 : fstrcat(unix_filename, info->name);
209 :
210 0 : result = gpo_copy_file(ctx->mem_ctx, ctx->cli,
211 : nt_filename, unix_filename);
212 0 : if (!NT_STATUS_IS_OK(result)) {
213 0 : DEBUG(1,("failed to copy file: %s\n",
214 : nt_errstr(result)));
215 : }
216 0 : return result;
217 : }
218 :
219 :
220 : /****************************************************************
221 : list a remote directory and download recursively
222 : ****************************************************************/
223 :
224 0 : NTSTATUS gpo_sync_directories(TALLOC_CTX *mem_ctx,
225 : struct cli_state *cli,
226 : const char *nt_path,
227 : const char *local_path)
228 : {
229 0 : struct sync_context ctx;
230 :
231 0 : ctx.mem_ctx = mem_ctx;
232 0 : ctx.cli = cli;
233 0 : ctx.remote_path = discard_const_p(char, nt_path);
234 0 : ctx.local_path = discard_const_p(char, local_path);
235 0 : ctx.attribute = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
236 :
237 0 : ctx.mask = talloc_asprintf(mem_ctx,
238 : "%s\\*",
239 : nt_path);
240 0 : if (!ctx.mask) {
241 0 : return NT_STATUS_NO_MEMORY;
242 : }
243 :
244 0 : return gpo_sync_files(&ctx);
245 : }
|