8019d4ff612d5526e4db5666335359b92e4371a7
[samba.git] / source3 / utils / net_printing.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Local printing tdb migration interface
5
6    Copyright (C) Guenther Deschner 2010
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 "system/filesys.h"
24 #include "utils/net.h"
25 #include "librpc/gen_ndr/ndr_ntprinting.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
27 #include "rpc_client/cli_spoolss.h"
28 #include "../libcli/security/security.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35
36 static void dump_form(TALLOC_CTX *mem_ctx,
37                       const char *key_name,
38                       unsigned char *data,
39                       size_t length)
40 {
41         enum ndr_err_code ndr_err;
42         DATA_BLOB blob;
43         char *s;
44         struct ntprinting_form r;
45
46         printf("found form: %s\n", key_name);
47
48         blob = data_blob_const(data, length);
49
50         ZERO_STRUCT(r);
51
52         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
53                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
54         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
55                 d_fprintf(stderr, _("form pull failed: %s\n"),
56                           ndr_errstr(ndr_err));
57                 return;
58         }
59
60         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
61         if (s) {
62                 printf("%s\n", s);
63         }
64 }
65
66 static void dump_driver(TALLOC_CTX *mem_ctx,
67                         const char *key_name,
68                         unsigned char *data,
69                         size_t length)
70 {
71         enum ndr_err_code ndr_err;
72         DATA_BLOB blob;
73         char *s;
74         struct ntprinting_driver r;
75
76         printf("found driver: %s\n", key_name);
77
78         blob = data_blob_const(data, length);
79
80         ZERO_STRUCT(r);
81
82         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
83                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
84         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
85                 d_fprintf(stderr, _("driver pull failed: %s\n"),
86                           ndr_errstr(ndr_err));
87                 return;
88         }
89
90         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
91         if (s) {
92                 printf("%s\n", s);
93         }
94 }
95
96 static void dump_printer(TALLOC_CTX *mem_ctx,
97                          const char *key_name,
98                          unsigned char *data,
99                          size_t length)
100 {
101         enum ndr_err_code ndr_err;
102         DATA_BLOB blob;
103         char *s;
104         struct ntprinting_printer r;
105
106         printf("found printer: %s\n", key_name);
107
108         blob = data_blob_const(data, length);
109
110         ZERO_STRUCT(r);
111
112         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
113                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
114         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
115                 d_fprintf(stderr, _("printer pull failed: %s\n"),
116                           ndr_errstr(ndr_err));
117                 return;
118         }
119
120         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
121         if (s) {
122                 printf("%s\n", s);
123         }
124 }
125
126 static void dump_sd(TALLOC_CTX *mem_ctx,
127                     const char *key_name,
128                     unsigned char *data,
129                     size_t length)
130 {
131         enum ndr_err_code ndr_err;
132         DATA_BLOB blob;
133         char *s;
134         struct sec_desc_buf r;
135
136         printf("found security descriptor: %s\n", key_name);
137
138         blob = data_blob_const(data, length);
139
140         ZERO_STRUCT(r);
141
142         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
143                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
144         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
145                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
146                           ndr_errstr(ndr_err));
147                 return;
148         }
149
150         s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
151         if (s) {
152                 printf("%s\n", s);
153         }
154 }
155
156
157 static int net_printing_dump(struct net_context *c, int argc,
158                              const char **argv)
159 {
160         int ret = -1;
161         TALLOC_CTX *ctx = talloc_stackframe();
162         TDB_CONTEXT *tdb;
163         TDB_DATA kbuf, newkey, dbuf;
164
165         if (argc < 1 || c->display_usage) {
166                 d_fprintf(stderr, "%s\nnet printing dump <file.tdb>\n",
167                           _("Usage:"));
168                 goto done;
169         }
170
171         tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
172         if (!tdb) {
173                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
174                 goto done;
175         }
176
177         for (kbuf = tdb_firstkey(tdb);
178              kbuf.dptr;
179              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
180         {
181                 dbuf = tdb_fetch(tdb, kbuf);
182                 if (!dbuf.dptr) {
183                         continue;
184                 }
185
186                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
187                         dump_form(ctx, (const char *)kbuf.dptr+strlen(FORMS_PREFIX), dbuf.dptr, dbuf.dsize);
188                         SAFE_FREE(dbuf.dptr);
189                         continue;
190                 }
191
192                 if (strncmp((const char *)kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
193                         dump_driver(ctx, (const char *)kbuf.dptr+strlen(DRIVERS_PREFIX), dbuf.dptr, dbuf.dsize);
194                         SAFE_FREE(dbuf.dptr);
195                         continue;
196                 }
197
198                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
199                         dump_printer(ctx, (const char *)kbuf.dptr+strlen(PRINTERS_PREFIX), dbuf.dptr, dbuf.dsize);
200                         SAFE_FREE(dbuf.dptr);
201                         continue;
202                 }
203
204                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
205                         dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
206                         SAFE_FREE(dbuf.dptr);
207                         continue;
208                 }
209
210         }
211
212         ret = 0;
213
214  done:
215         talloc_free(ctx);
216         return ret;
217 }
218
219 static NTSTATUS migrate_form(TALLOC_CTX *mem_ctx,
220                          struct rpc_pipe_client *pipe_hnd,
221                          const char *key_name,
222                          unsigned char *data,
223                          size_t length)
224 {
225         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
226         struct policy_handle hnd;
227         enum ndr_err_code ndr_err;
228         struct ntprinting_form r;
229         union spoolss_AddFormInfo f;
230         struct spoolss_AddFormInfo1 f1;
231         DATA_BLOB blob;
232         NTSTATUS status;
233         WERROR result;
234
235         blob = data_blob_const(data, length);
236
237         ZERO_STRUCT(r);
238
239         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
240                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
241         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
242                 d_fprintf(stderr, _("form pull failed: %s\n"),
243                           ndr_errstr(ndr_err));
244                 return NT_STATUS_NO_MEMORY;
245         }
246
247         /* Don't migrate builtin forms */
248         if (r.flag == SPOOLSS_FORM_BUILTIN) {
249                 return NT_STATUS_OK;
250         }
251
252         d_printf(_("Migrating Form: %s\n"), key_name);
253
254         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
255                                                mem_ctx,
256                                                pipe_hnd->srv_name_slash,
257                                                MAXIMUM_ALLOWED_ACCESS,
258                                                &hnd);
259         if (!W_ERROR_IS_OK(result)) {
260                 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
261                                   pipe_hnd->srv_name_slash, win_errstr(result));
262                 return werror_to_ntstatus(result);
263         }
264
265         f1.form_name = key_name;
266         f1.flags = r.flag;
267
268         f1.size.width = r.width;
269         f1.size.height = r.length;
270
271         f1.area.top = r.top;
272         f1.area.right = r.right;
273         f1.area.bottom = r.bottom;
274         f1.area.left = r.left;
275
276         f.info1 = &f1;
277
278         status = dcerpc_spoolss_AddForm(b,
279                                         mem_ctx,
280                                         &hnd,
281                                         1,
282                                         f,
283                                         &result);
284         if (!NT_STATUS_IS_OK(status)) {
285                 d_printf(_("\tAddForm(%s) refused -- %s.\n"),
286                         f.info1->form_name, nt_errstr(status));
287         } else if (!W_ERROR_IS_OK(result)) {
288                 d_printf(_("\tAddForm(%s) refused -- %s.\n"),
289                         f.info1->form_name, win_errstr(result));
290                 status = werror_to_ntstatus(result);
291         }
292
293         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
294
295         return status;
296 }
297
298 static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx,
299                                struct rpc_pipe_client *pipe_hnd,
300                                const char *key_name,
301                                unsigned char *data,
302                                size_t length)
303 {
304         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
305         enum ndr_err_code ndr_err;
306         struct ntprinting_driver r;
307         struct spoolss_AddDriverInfoCtr d;
308         struct spoolss_AddDriverInfo3 d3;
309         struct spoolss_StringArray a;
310         DATA_BLOB blob;
311         NTSTATUS status;
312         WERROR result;
313
314         blob = data_blob_const(data, length);
315
316         ZERO_STRUCT(r);
317
318         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
319                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
320         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
321                 d_fprintf(stderr, _("driver pull failed: %s\n"),
322                           ndr_errstr(ndr_err));
323                 return NT_STATUS_NO_MEMORY;
324         }
325
326         d_printf(_("Migrating Printer Driver: %s\n"), key_name);
327
328         ZERO_STRUCT(d3);
329         ZERO_STRUCT(a);
330
331         a.string = r.dependent_files;
332
333         d3.architecture = r.environment;
334         d3.config_file = r.configfile;
335         d3.data_file = r.datafile;
336         d3.default_datatype = r.defaultdatatype;
337         d3.dependent_files = &a;
338         d3.driver_path = r.driverpath;
339         d3.help_file = r.helpfile;
340         d3.monitor_name = r.monitorname;
341         d3.driver_name = r.name;
342         d3.version = r.version;
343
344         d.info.info3 = &d3;
345         d.level = 3;
346
347         status = dcerpc_spoolss_AddPrinterDriver(b,
348                                                  mem_ctx,
349                                                  NULL,
350                                                  &d,
351                                                  &result);
352         if (!NT_STATUS_IS_OK(status)) {
353                 d_printf(_("\tAddDriver driver: [%s] refused -- %s.\n"),
354                         d3.driver_name, nt_errstr(status));
355         } else if (!W_ERROR_IS_OK(result)) {
356                 d_printf(_("\tAddDriver driver: [%s] refused -- %s.\n"),
357                         d3.driver_name, win_errstr(result));
358                 status = werror_to_ntstatus(result);
359         }
360
361         return status;
362 }
363
364 static NTSTATUS migrate_printer(TALLOC_CTX *mem_ctx,
365                                 struct rpc_pipe_client *pipe_hnd,
366                                 const char *key_name,
367                                 unsigned char *data,
368                                 size_t length)
369 {
370         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
371         struct policy_handle hnd;
372         enum ndr_err_code ndr_err;
373         struct ntprinting_printer r;
374         struct spoolss_SetPrinterInfo2 info2;
375         struct spoolss_DeviceMode dm;
376         struct spoolss_SetPrinterInfoCtr info_ctr;
377         struct spoolss_DevmodeContainer devmode_ctr;
378         struct sec_desc_buf secdesc_ctr;
379         DATA_BLOB blob;
380         NTSTATUS status;
381         WERROR result;
382         int j;
383
384         if (strequal(key_name, "printers")) {
385                 return NT_STATUS_OK;
386         }
387
388         blob = data_blob_const(data, length);
389
390         ZERO_STRUCT(r);
391
392         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
393                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
394         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
395                 d_fprintf(stderr, _("printer pull failed: %s\n"),
396                           ndr_errstr(ndr_err));
397                 return NT_STATUS_NO_MEMORY;
398         }
399
400         d_printf(_("Migrating Printer: %s\n"), key_name);
401
402         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
403                                                mem_ctx,
404                                                key_name,
405                                                MAXIMUM_ALLOWED_ACCESS,
406                                                &hnd);
407         if (!W_ERROR_IS_OK(result)) {
408                 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
409                                   key_name, win_errstr(result));
410                 return werror_to_ntstatus(result);
411         }
412
413         /* Create printer info level 2 */
414         ZERO_STRUCT(info2);
415         ZERO_STRUCT(devmode_ctr);
416         ZERO_STRUCT(secdesc_ctr);
417
418         info2.attributes = r.info.attributes;
419         info2.averageppm = r.info.averageppm;
420         info2.cjobs = r.info.cjobs;
421         info2.comment = r.info.comment;
422         info2.datatype = r.info.datatype;
423         info2.defaultpriority = r.info.default_priority;
424         info2.drivername = r.info.drivername;
425         info2.location = r.info.location;
426         info2.parameters = r.info.parameters;
427         info2.portname = r.info.portname;
428         info2.printername = r.info.printername;
429         info2.printprocessor = r.info.printprocessor;
430         info2.priority = r.info.priority;
431         info2.sepfile = r.info.sepfile;
432         info2.sharename = r.info.sharename;
433         info2.starttime = r.info.starttime;
434         info2.status = r.info.status;
435         info2.untiltime = r.info.untiltime;
436
437         /* Create Device Mode */
438         if (r.devmode != NULL) {
439                 ZERO_STRUCT(dm);
440
441                 dm.bitsperpel              = r.devmode->bitsperpel;
442                 dm.collate                 = r.devmode->collate;
443                 dm.color                   = r.devmode->color;
444                 dm.copies                  = r.devmode->copies;
445                 dm.defaultsource           = r.devmode->defaultsource;
446                 dm.devicename              = r.devmode->devicename;
447                 dm.displayflags            = r.devmode->displayflags;
448                 dm.displayfrequency        = r.devmode->displayfrequency;
449                 dm.dithertype              = r.devmode->dithertype;
450                 dm.driverversion           = r.devmode->driverversion;
451                 dm.duplex                  = r.devmode->duplex;
452                 dm.fields                  = r.devmode->fields;
453                 dm.formname                = r.devmode->formname;
454                 dm.icmintent               = r.devmode->icmintent;
455                 dm.icmmethod               = r.devmode->icmmethod;
456                 dm.logpixels               = r.devmode->logpixels;
457                 dm.mediatype               = r.devmode->mediatype;
458                 dm.orientation             = r.devmode->orientation;
459                 dm.panningheight           = r.devmode->pelsheight;
460                 dm.panningwidth            = r.devmode->panningwidth;
461                 dm.paperlength             = r.devmode->paperlength;
462                 dm.papersize               = r.devmode->papersize;
463                 dm.paperwidth              = r.devmode->paperwidth;
464                 dm.pelsheight              = r.devmode->pelsheight;
465                 dm.pelswidth               = r.devmode->pelswidth;
466                 dm.printquality            = r.devmode->printquality;
467                 dm.scale                   = r.devmode->scale;
468                 dm.specversion             = r.devmode->specversion;
469                 dm.ttoption                = r.devmode->ttoption;
470                 dm.yresolution             = r.devmode->yresolution;
471
472                 if (r.devmode->nt_dev_private != NULL) {
473                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
474                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
475                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
476                 }
477
478                 devmode_ctr.devmode = &dm;
479
480                 info2.devmode_ptr = 1;
481         }
482
483         info_ctr.info.info2 = &info2;
484         info_ctr.level = 2;
485
486         status = dcerpc_spoolss_SetPrinter(b,
487                                            mem_ctx,
488                                            &hnd,
489                                            &info_ctr,
490                                            &devmode_ctr,
491                                            &secdesc_ctr,
492                                            0, /* command */
493                                            &result);
494         if (!NT_STATUS_IS_OK(status)) {
495                 d_printf(_("\tSetPrinter(%s) level 2 refused -- %s.\n"),
496                         key_name, nt_errstr(status));
497                 goto done;
498         } else if (!W_ERROR_IS_OK(result)) {
499                 d_printf(_("\tSetPrinter(%s) level 2 refused -- %s.\n"),
500                         key_name, win_errstr(result));
501                 status = werror_to_ntstatus(result);
502                 goto done;
503         }
504
505         /* migrate printerdata */
506         for (j = 0; j < r.count; j++) {
507                 char *valuename;
508                 char *keyname;
509
510                 if (r.printer_data[j].type == REG_NONE) {
511                         continue;
512                 }
513
514                 keyname = CONST_DISCARD(char *, r.printer_data[j].name);
515                 valuename = strchr(keyname, '\\');
516                 if (valuename == NULL) {
517                         continue;
518                 } else {
519                         valuename[0] = '\0';
520                         valuename++;
521                 }
522
523                 printf("          data: %s\\%s\n", keyname, valuename);
524
525                 status = dcerpc_spoolss_SetPrinterDataEx(b,
526                                                          mem_ctx,
527                                                          &hnd,
528                                                          keyname,
529                                                          valuename,
530                                                          r.printer_data[j].type,
531                                                          r.printer_data[j].data.data,
532                                                          r.printer_data[j].data.length,
533                                                          &result);
534                 if (!NT_STATUS_IS_OK(status)) {
535                         d_printf(_("\tSetPrinterDataEx: printer [%s], keyname [%s], valuename [%s] refused -- %s.\n"),
536                                 key_name, keyname, valuename, nt_errstr(status));
537                         break;
538                 } else if (!W_ERROR_IS_OK(result)) {
539                         d_printf(_("\tSetPrinterDataEx: printer [%s], keyname [%s], valuename [%s] refused -- %s.\n"),
540                                 key_name, keyname, valuename, win_errstr(result));
541                         status = werror_to_ntstatus(result);
542                         break;
543                 }
544         }
545
546  done:
547         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
548
549         return status;
550 }
551
552 static NTSTATUS migrate_secdesc(TALLOC_CTX *mem_ctx,
553                                 struct rpc_pipe_client *pipe_hnd,
554                                 const char *key_name,
555                                 unsigned char *data,
556                                 size_t length)
557 {
558         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
559         struct policy_handle hnd;
560         enum ndr_err_code ndr_err;
561         struct sec_desc_buf secdesc_ctr;
562         struct spoolss_SetPrinterInfo3 info3;
563         struct spoolss_SetPrinterInfoCtr info_ctr;
564         struct spoolss_DevmodeContainer devmode_ctr;
565         DATA_BLOB blob;
566         NTSTATUS status;
567         WERROR result;
568
569         if (strequal(key_name, "printers")) {
570                 return NT_STATUS_OK;
571         }
572
573         blob = data_blob_const(data, length);
574
575         ZERO_STRUCT(secdesc_ctr);
576
577         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
578                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
579         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
580                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
581                           ndr_errstr(ndr_err));
582                 return NT_STATUS_NO_MEMORY;
583         }
584
585         d_printf(_("Migrating Security Descriptor: %s\n"), key_name);
586
587         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
588                                                mem_ctx,
589                                                key_name,
590                                                MAXIMUM_ALLOWED_ACCESS,
591                                                &hnd);
592         if (!W_ERROR_IS_OK(result)) {
593                 d_fprintf(stderr, _("\tOpenPrinter(%s) failed: %s\n"),
594                                   key_name, win_errstr(result));
595                 return werror_to_ntstatus(result);
596         }
597
598         ZERO_STRUCT(devmode_ctr);
599
600         info3.sec_desc_ptr = 1;
601
602         info_ctr.info.info3 = &info3;
603         info_ctr.level = 3;
604
605         status = dcerpc_spoolss_SetPrinter(b,
606                                            mem_ctx,
607                                            &hnd,
608                                            &info_ctr,
609                                            &devmode_ctr,
610                                            &secdesc_ctr,
611                                            0, /* command */
612                                            &result);
613         if (!NT_STATUS_IS_OK(status)) {
614                 d_printf(_("\tSetPrinter(%s) level 3 refused -- %s.\n"),
615                         key_name, nt_errstr(status));
616         } else if (!W_ERROR_IS_OK(result)) {
617                 d_printf(_("\tSetPrinter(%s) level 3 refused -- %s.\n"),
618                         key_name, win_errstr(result));
619                 status = werror_to_ntstatus(result);
620         }
621
622         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
623
624         return status;
625 }
626
627 static NTSTATUS printing_migrate_internal(struct net_context *c,
628                                           const struct dom_sid *domain_sid,
629                                           const char *domain_name,
630                                           struct cli_state *cli,
631                                           struct rpc_pipe_client *pipe_hnd,
632                                           TALLOC_CTX *mem_ctx,
633                                           int argc,
634                                           const char **argv)
635 {
636         TALLOC_CTX *tmp_ctx;
637         TDB_CONTEXT *tdb;
638         TDB_DATA kbuf, newkey, dbuf;
639         NTSTATUS status;
640
641         tmp_ctx = talloc_new(mem_ctx);
642         if (tmp_ctx == NULL) {
643                 return NT_STATUS_NO_MEMORY;
644         }
645
646         tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
647         if (tdb == NULL) {
648                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
649                 status = NT_STATUS_NO_SUCH_FILE;
650                 goto done;
651         }
652
653         for (kbuf = tdb_firstkey(tdb);
654              kbuf.dptr;
655              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
656         {
657                 dbuf = tdb_fetch(tdb, kbuf);
658                 if (!dbuf.dptr) {
659                         continue;
660                 }
661
662                 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
663                         migrate_form(tmp_ctx,
664                                      pipe_hnd,
665                                      (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
666                                      dbuf.dptr,
667                                      dbuf.dsize);
668                         SAFE_FREE(dbuf.dptr);
669                         continue;
670                 }
671
672                 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
673                         migrate_driver(tmp_ctx,
674                                        pipe_hnd,
675                                        (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
676                                        dbuf.dptr,
677                                        dbuf.dsize);
678                         SAFE_FREE(dbuf.dptr);
679                         continue;
680                 }
681
682                 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
683                         migrate_printer(tmp_ctx,
684                                         pipe_hnd,
685                                         (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
686                                         dbuf.dptr,
687                                         dbuf.dsize);
688                         SAFE_FREE(dbuf.dptr);
689                         continue;
690                 }
691
692                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
693                         migrate_secdesc(tmp_ctx,
694                                         pipe_hnd,
695                                         (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
696                                         dbuf.dptr,
697                                         dbuf.dsize);
698                         SAFE_FREE(dbuf.dptr);
699                         continue;
700                 }
701
702         }
703
704         status = NT_STATUS_OK;
705
706  done:
707         talloc_free(tmp_ctx);
708         return status;
709 }
710
711 static int net_printing_migrate(struct net_context *c,
712                                 int argc,
713                                 const char **argv)
714 {
715         if (argc < 1 || c->display_usage) {
716                 d_printf(  "%s\n"
717                            "net printing migrate <file.tdb>\n"
718                            "    %s\n",
719                          _("Usage:"),
720                          _("Migrate tdb printing files to new storage"));
721                 return 0;
722         }
723
724         return run_rpc_command(c,
725                                NULL,
726                                &ndr_table_spoolss.syntax_id,
727                                0,
728                                printing_migrate_internal,
729                                argc,
730                                argv);
731 }
732 /**
733  * 'net printing' entrypoint.
734  * @param argc  Standard main() style argc.
735  * @param argv  Standard main() style argv. Initial components are already
736  *              stripped.
737  **/
738
739 int net_printing(struct net_context *c, int argc, const char **argv)
740 {
741         int ret = -1;
742
743         struct functable func[] = {
744                 {
745                         "dump",
746                         net_printing_dump,
747                         NET_TRANSPORT_LOCAL,
748                         N_("Dump printer databases"),
749                         N_("net printing dump\n"
750                            "    Dump tdb printing file")
751                 },
752
753                 {
754                         "migrate",
755                         net_printing_migrate,
756                         NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
757                         N_("Migrate printer databases"),
758                         N_("net printing migrate\n"
759                            "    Migrate tdb printing files to new storage")
760                 },
761
762         { NULL, NULL, 0, NULL, NULL }
763         };
764
765         ret = net_run_function(c, argc, argv, "net printing", func);
766
767         return ret;
768 }