r24667: Finally merge the registry improvements that Wilco Baan Hofman and I have
[sfrench/samba-autobuild/.git] / source4 / lib / registry / tools / regdiff.c
1 /* 
2    Unix SMB/CIFS implementation.
3    simple registry frontend
4    
5    Copyright (C) Jelmer Vernooij 2004-2007
6    Copyright (C) Wilco Baan Hofman 2006
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/registry/registry.h"
24 #include "lib/events/events.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "lib/registry/tools/common.h"
27
28 enum reg_backend { REG_UNKNOWN, REG_LOCAL, REG_REMOTE, REG_NULL };
29
30 static struct registry_context *open_backend(poptContext pc, enum reg_backend backend, const char *remote_host)
31 {
32         WERROR error;
33         struct registry_context *ctx;
34         
35         switch (backend) {
36         case REG_UNKNOWN:
37                 poptPrintUsage(pc, stderr, 0);
38                 return NULL;
39         case REG_LOCAL:
40                 error = reg_open_samba(NULL, &ctx, NULL, cmdline_credentials);
41                 break;
42         case REG_REMOTE:
43                 error = reg_open_remote(&ctx, NULL, cmdline_credentials, remote_host, NULL);
44                 break;
45         case REG_NULL:
46                 error = reg_open_local(NULL, &ctx, NULL, cmdline_credentials);
47                 break;
48         }
49
50         if (!W_ERROR_IS_OK(error)) {
51                 fprintf(stderr, "Error: %s\n", win_errstr(error));
52                 return NULL;
53         }
54
55         return ctx;
56 }
57
58 int main(int argc, const char **argv)
59 {
60         int opt;
61         poptContext pc;
62         char *outputfile = NULL;
63         enum reg_backend backend1 = REG_UNKNOWN, backend2 = REG_UNKNOWN;
64         const char *remote1 = NULL, *remote2 = NULL;
65         struct registry_context *h1 = NULL, *h2 = NULL;
66         WERROR error;
67         struct poptOption long_options[] = {
68                 POPT_AUTOHELP
69                 {"output", 'o', POPT_ARG_STRING, &outputfile, 0, "output file to use", NULL },
70                 {"null", 'n', POPT_ARG_NONE, NULL, 'n', "Diff from NULL", NULL },
71                 {"remote", 'R', POPT_ARG_STRING, NULL, 'R', "Connect to remote server" , NULL },
72                 {"local", 'L', POPT_ARG_NONE, NULL, 'L', "Open local registry", NULL },
73                 POPT_COMMON_SAMBA
74                 POPT_COMMON_CREDENTIALS
75                 POPT_COMMON_VERSION
76                 { NULL }
77         };
78         TALLOC_CTX *ctx;
79         void *callback_data;
80         struct reg_diff_callbacks *callbacks;
81
82         ctx = talloc_init("regdiff");
83
84         pc = poptGetContext(argv[0], argc, argv, long_options,0);
85
86         while((opt = poptGetNextOpt(pc)) != -1) {
87                 error = WERR_OK;
88                 switch(opt)     {
89                 case 'L':
90                         if (backend1 == REG_UNKNOWN)
91                                 backend1 = REG_LOCAL;
92                         else if (backend2 == REG_UNKNOWN)
93                                 backend2 = REG_LOCAL;
94                         break;
95                 case 'n':
96                         if (backend1 == REG_UNKNOWN)
97                                 backend1 = REG_NULL;
98                         else if (backend2 == REG_UNKNOWN)
99                                 backend2 = REG_NULL;
100                         break;
101                 case 'R':
102                         if (backend1 == REG_UNKNOWN) {
103                                 backend1 = REG_REMOTE;
104                                 remote1 = poptGetOptArg(pc);
105                         } else if (backend2 == REG_UNKNOWN) {
106                                 backend2 = REG_REMOTE;
107                                 remote2 = poptGetOptArg(pc);
108                         }
109                         break;
110                 }
111
112         }
113
114         h1 = open_backend(pc, backend1, remote1);
115         if (h1 == NULL)
116                 return 1;
117
118         h2 = open_backend(pc, backend2, remote2);
119         if (h2 == NULL)
120                 return 1;
121
122         poptFreeContext(pc);
123
124         error = reg_dotreg_diff_save(ctx, outputfile, &callbacks, &callback_data);
125         if (!W_ERROR_IS_OK(error)) {
126                 fprintf(stderr, "Problem saving registry diff to '%s': %s\n", outputfile, win_errstr(error));
127                 return -1;
128         }
129
130         error = reg_generate_diff(h1, h2, callbacks, callback_data);
131         if (!W_ERROR_IS_OK(error)) {
132                 fprintf(stderr, "Unable to generate diff between keys: %s\n", win_errstr(error));
133                 return -1;
134         }
135
136         return 0;
137 }