r23779: Change from v2 or later to v3 or later.
[kai/samba-autobuild/.git] / source / libgpo / gpo_filesync.c
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, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22
23 struct sync_context {
24         TALLOC_CTX *mem_ctx;
25         struct cli_state *cli;
26         char *remote_path;
27         char *local_path;
28         pstring mask;
29         uint16 attribute;
30 };
31
32 static void gpo_sync_func(const char *mnt,
33                            file_info *info,
34                            const char *mask,
35                            void *state);
36
37 NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
38                        struct cli_state *cli,
39                        const char *nt_path,
40                        const char *unix_path)
41 {
42         NTSTATUS result;
43         int fnum;
44         int fd = 0;
45         char *data = NULL;
46         static int io_bufsize = 64512;
47         int read_size = io_bufsize;
48         off_t start = 0;
49         off_t nread = 0;
50
51         if ((fnum = cli_open(cli, nt_path, O_RDONLY, DENY_NONE)) == -1) {
52                 result = NT_STATUS_NO_SUCH_FILE;
53                 goto out;
54         }
55
56         if ((fd = sys_open(unix_path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
57                 result = map_nt_error_from_unix(errno);
58                 goto out;
59         }
60          
61         if ((data = (char *)SMB_MALLOC(read_size)) == NULL) {
62                 result = NT_STATUS_NO_MEMORY;
63                 goto out;
64         }
65
66         while (1) {
67
68                 int n = cli_read(cli, fnum, data, nread + start, read_size);
69
70                 if (n <= 0)
71                         break;
72
73                 if (write(fd, data, n) != n) {
74                         break;
75                 }
76
77                 nread += n;
78         }
79
80         result = NT_STATUS_OK;
81
82  out:
83         SAFE_FREE(data);
84         if (fnum) {
85                 cli_close(cli, fnum);
86         }
87         if (fd) {
88                 close(fd);
89         }
90
91         return result;
92 }
93
94 /****************************************************************
95  copy dir
96 ****************************************************************/
97
98 static NTSTATUS gpo_copy_dir(const char *unix_path)
99 {
100         if ((mkdir(unix_path, 0644)) < 0 && errno != EEXIST) {
101                 return NT_STATUS_ACCESS_DENIED;
102         }
103
104         return NT_STATUS_OK;
105 }
106
107 /****************************************************************
108  sync files
109 ****************************************************************/
110
111 static BOOL gpo_sync_files(struct sync_context *ctx)
112 {
113         DEBUG(3,("calling cli_list with mask: %s\n", ctx->mask));
114
115         if (cli_list(ctx->cli, ctx->mask, ctx->attribute, gpo_sync_func, ctx) == -1) {
116                 DEBUG(1,("listing [%s] failed with error: %s\n", 
117                         ctx->mask, cli_errstr(ctx->cli)));
118                 return False;
119         }
120
121         return True;
122 }
123
124 /****************************************************************
125  syncronisation call back
126 ****************************************************************/
127
128 static void gpo_sync_func(const char *mnt,
129                           file_info *info,
130                           const char *mask,
131                           void *state)
132 {
133         NTSTATUS result;
134         struct sync_context *ctx;
135         fstring nt_filename, unix_filename;
136         fstring nt_dir, unix_dir;
137         char *old_nt_dir, *old_unix_dir;
138
139         ctx = (struct sync_context *)state;
140
141         if (strequal(info->name, ".") || strequal(info->name, "..")) {
142                 return;
143         }
144
145         DEBUG(5,("gpo_sync_func: got mask: [%s], name: [%s]\n", 
146                 mask, info->name));
147
148         if (info->mode & aDIR) {
149
150                 DEBUG(3,("got dir: [%s]\n", info->name));
151
152                 fstrcpy(nt_dir, ctx->remote_path);
153                 fstrcat(nt_dir, "\\");
154                 fstrcat(nt_dir, info->name);
155
156                 fstrcpy(unix_dir, ctx->local_path);
157                 fstrcat(unix_dir, "/");
158                 fstrcat(unix_dir, info->name);
159
160                 result = gpo_copy_dir(unix_dir);
161                 if (!NT_STATUS_IS_OK(result)) {
162                         DEBUG(1,("failed to copy dir: %s\n", nt_errstr(result)));
163                 }
164
165                 old_nt_dir = ctx->remote_path;
166                 ctx->remote_path = nt_dir;
167                 
168                 old_unix_dir = ctx->local_path;
169                 ctx->local_path = talloc_strdup(ctx->mem_ctx, unix_dir);
170
171                 pstrcpy(ctx->mask, nt_dir);
172                 pstrcat(ctx->mask, "\\*");
173
174                 if (!gpo_sync_files(ctx)) {
175                         DEBUG(0,("could not sync files\n"));
176                 }
177
178                 ctx->remote_path = old_nt_dir;
179                 ctx->local_path = old_unix_dir;
180                 return;
181         }
182
183         DEBUG(3,("got file: [%s]\n", info->name));
184
185         fstrcpy(nt_filename, ctx->remote_path);
186         fstrcat(nt_filename, "\\");
187         fstrcat(nt_filename, info->name);
188
189         fstrcpy(unix_filename, ctx->local_path);
190         fstrcat(unix_filename, "/");
191         fstrcat(unix_filename, info->name);
192
193         result = gpo_copy_file(ctx->mem_ctx, ctx->cli, nt_filename, unix_filename);
194         if (!NT_STATUS_IS_OK(result)) {
195                 DEBUG(1,("failed to copy file: %s\n", nt_errstr(result)));
196         }
197 }
198
199
200 /****************************************************************
201  list a remote directory and download recursivly
202 ****************************************************************/
203
204 NTSTATUS gpo_sync_directories(TALLOC_CTX *mem_ctx, 
205                               struct cli_state *cli, 
206                               const char *nt_path, 
207                               const char *local_path)
208 {
209         struct sync_context ctx;
210
211         ctx.mem_ctx     = mem_ctx;
212         ctx.cli         = cli;
213         ctx.remote_path = CONST_DISCARD(char *, nt_path);
214         ctx.local_path  = CONST_DISCARD(char *, local_path);
215         ctx.attribute   = (aSYSTEM | aHIDDEN | aDIR);
216
217         pstrcpy(ctx.mask, nt_path);
218         pstrcat(ctx.mask, "\\*");
219
220         if (!gpo_sync_files(&ctx)) {
221                 return NT_STATUS_NO_SUCH_FILE;
222         }
223
224         return NT_STATUS_OK;
225 }