s3:registry: extract the reg_cachehook prototypes into their own header.
[Samba/gebeck_regimport.git] / source3 / utils / net_printing.c
blobc7a262433eff5c2f20a6100b82aba76e1c9362e0
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Local printing tdb migration interface
6 Copyright (C) Guenther Deschner 2010
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.
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.
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/>.
22 #include "includes.h"
23 #include "utils/net.h"
24 #include "librpc/gen_ndr/ndr_ntprinting.h"
25 #include "librpc/gen_ndr/cli_spoolss.h"
26 #include "rpc_client/cli_spoolss.h"
28 #define FORMS_PREFIX "FORMS/"
29 #define DRIVERS_PREFIX "DRIVERS/"
30 #define PRINTERS_PREFIX "PRINTERS/"
31 #define SECDESC_PREFIX "SECDESC/"
33 static void dump_form(TALLOC_CTX *mem_ctx,
34 const char *key_name,
35 unsigned char *data,
36 size_t length)
38 enum ndr_err_code ndr_err;
39 DATA_BLOB blob;
40 char *s;
41 struct ntprinting_form r;
43 printf("found form: %s\n", key_name);
45 blob = data_blob_const(data, length);
47 ZERO_STRUCT(r);
49 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
50 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
51 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
52 d_fprintf(stderr, _("form pull failed: %s\n"),
53 ndr_errstr(ndr_err));
54 return;
57 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
58 if (s) {
59 printf("%s\n", s);
63 static void dump_driver(TALLOC_CTX *mem_ctx,
64 const char *key_name,
65 unsigned char *data,
66 size_t length)
68 enum ndr_err_code ndr_err;
69 DATA_BLOB blob;
70 char *s;
71 struct ntprinting_driver r;
73 printf("found driver: %s\n", key_name);
75 blob = data_blob_const(data, length);
77 ZERO_STRUCT(r);
79 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
80 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
81 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
82 d_fprintf(stderr, _("driver pull failed: %s\n"),
83 ndr_errstr(ndr_err));
84 return;
87 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
88 if (s) {
89 printf("%s\n", s);
93 static void dump_printer(TALLOC_CTX *mem_ctx,
94 const char *key_name,
95 unsigned char *data,
96 size_t length)
98 enum ndr_err_code ndr_err;
99 DATA_BLOB blob;
100 char *s;
101 struct ntprinting_printer r;
103 printf("found printer: %s\n", key_name);
105 blob = data_blob_const(data, length);
107 ZERO_STRUCT(r);
109 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
110 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
111 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
112 d_fprintf(stderr, _("printer pull failed: %s\n"),
113 ndr_errstr(ndr_err));
114 return;
117 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
118 if (s) {
119 printf("%s\n", s);
123 static void dump_sd(TALLOC_CTX *mem_ctx,
124 const char *key_name,
125 unsigned char *data,
126 size_t length)
128 enum ndr_err_code ndr_err;
129 DATA_BLOB blob;
130 char *s;
131 struct sec_desc_buf r;
133 printf("found security descriptor: %s\n", key_name);
135 blob = data_blob_const(data, length);
137 ZERO_STRUCT(r);
139 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
140 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
141 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
142 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
143 ndr_errstr(ndr_err));
144 return;
147 s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
148 if (s) {
149 printf("%s\n", s);
154 static int net_printing_dump(struct net_context *c, int argc,
155 const char **argv)
157 int ret = -1;
158 TALLOC_CTX *ctx = talloc_stackframe();
159 TDB_CONTEXT *tdb;
160 TDB_DATA kbuf, newkey, dbuf;
162 if (argc < 1 || c->display_usage) {
163 d_fprintf(stderr, "%s\nnet printing dump <file.tdb>\n",
164 _("Usage:"));
165 goto done;
168 tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
169 if (!tdb) {
170 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
171 goto done;
174 for (kbuf = tdb_firstkey(tdb);
175 kbuf.dptr;
176 newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
178 dbuf = tdb_fetch(tdb, kbuf);
179 if (!dbuf.dptr) {
180 continue;
183 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
184 dump_form(ctx, (const char *)kbuf.dptr+strlen(FORMS_PREFIX), dbuf.dptr, dbuf.dsize);
185 SAFE_FREE(dbuf.dptr);
186 continue;
189 if (strncmp((const char *)kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
190 dump_driver(ctx, (const char *)kbuf.dptr+strlen(DRIVERS_PREFIX), dbuf.dptr, dbuf.dsize);
191 SAFE_FREE(dbuf.dptr);
192 continue;
195 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
196 dump_printer(ctx, (const char *)kbuf.dptr+strlen(PRINTERS_PREFIX), dbuf.dptr, dbuf.dsize);
197 SAFE_FREE(dbuf.dptr);
198 continue;
201 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
202 dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
203 SAFE_FREE(dbuf.dptr);
204 continue;
209 ret = 0;
211 done:
212 talloc_free(ctx);
213 return ret;
216 static NTSTATUS migrate_form(TALLOC_CTX *mem_ctx,
217 struct rpc_pipe_client *pipe_hnd,
218 const char *key_name,
219 unsigned char *data,
220 size_t length)
222 struct policy_handle hnd;
223 enum ndr_err_code ndr_err;
224 struct ntprinting_form r;
225 union spoolss_AddFormInfo f;
226 struct spoolss_AddFormInfo1 f1;
227 DATA_BLOB blob;
228 NTSTATUS status;
229 WERROR result;
231 blob = data_blob_const(data, length);
233 ZERO_STRUCT(r);
235 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
236 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
237 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
238 d_fprintf(stderr, _("form pull failed: %s\n"),
239 ndr_errstr(ndr_err));
240 return NT_STATUS_NO_MEMORY;
243 /* Don't migrate builtin forms */
244 if (r.flag == SPOOLSS_FORM_BUILTIN) {
245 return NT_STATUS_OK;
248 d_printf(_("Migrating Form: %s\n"), key_name);
250 result = rpccli_spoolss_openprinter_ex(pipe_hnd,
251 mem_ctx,
252 pipe_hnd->srv_name_slash,
253 MAXIMUM_ALLOWED_ACCESS,
254 &hnd);
255 if (!W_ERROR_IS_OK(result)) {
256 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
257 pipe_hnd->srv_name_slash, win_errstr(result));
258 return werror_to_ntstatus(result);
261 f1.form_name = key_name;
262 f1.flags = r.flag;
264 f1.size.width = r.width;
265 f1.size.height = r.length;
267 f1.area.top = r.top;
268 f1.area.right = r.right;
269 f1.area.bottom = r.bottom;
270 f1.area.left = r.left;
272 f.info1 = &f1;
274 status = rpccli_spoolss_AddForm(pipe_hnd,
275 mem_ctx,
276 &hnd,
279 &result);
280 if (!NT_STATUS_IS_OK(status)) {
281 d_printf(_("\tAddForm(%s) refused -- %s.\n"),
282 f.info1->form_name, nt_errstr(status));
285 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
287 return status;
290 static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx,
291 struct rpc_pipe_client *pipe_hnd,
292 const char *key_name,
293 unsigned char *data,
294 size_t length)
296 enum ndr_err_code ndr_err;
297 struct ntprinting_driver r;
298 struct spoolss_AddDriverInfoCtr d;
299 struct spoolss_AddDriverInfo3 d3;
300 struct spoolss_StringArray a;
301 DATA_BLOB blob;
302 NTSTATUS status;
303 WERROR result;
305 blob = data_blob_const(data, length);
307 ZERO_STRUCT(r);
309 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
310 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
311 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
312 d_fprintf(stderr, _("driver pull failed: %s\n"),
313 ndr_errstr(ndr_err));
314 return NT_STATUS_NO_MEMORY;
317 d_printf(_("Migrating Printer Driver: %s\n"), key_name);
319 ZERO_STRUCT(d3);
320 ZERO_STRUCT(a);
322 a.string = r.dependent_files;
324 d3.architecture = r.environment;
325 d3.config_file = r.configfile;
326 d3.data_file = r.datafile;
327 d3.default_datatype = r.defaultdatatype;
328 d3.dependent_files = &a;
329 d3.driver_path = r.driverpath;
330 d3.help_file = r.helpfile;
331 d3.monitor_name = r.monitorname;
332 d3.driver_name = r.name;
333 d3.version = r.version;
335 d.info.info3 = &d3;
336 d.level = 3;
338 status = rpccli_spoolss_AddPrinterDriver(pipe_hnd,
339 mem_ctx,
340 NULL,
342 &result);
343 if (!NT_STATUS_IS_OK(status)) {
344 d_printf(_("\tAddDriver driver: [%s] refused -- %s.\n"),
345 d3.driver_name, nt_errstr(status));
348 return status;
351 static NTSTATUS migrate_printer(TALLOC_CTX *mem_ctx,
352 struct rpc_pipe_client *pipe_hnd,
353 const char *key_name,
354 unsigned char *data,
355 size_t length)
357 struct policy_handle hnd;
358 enum ndr_err_code ndr_err;
359 struct ntprinting_printer r;
360 struct spoolss_SetPrinterInfo2 info2;
361 struct spoolss_DeviceMode dm;
362 struct spoolss_SetPrinterInfoCtr info_ctr;
363 struct spoolss_DevmodeContainer devmode_ctr;
364 struct sec_desc_buf secdesc_ctr;
365 DATA_BLOB blob;
366 NTSTATUS status;
367 WERROR result;
368 int j;
370 if (strequal(key_name, "printers")) {
371 return NT_STATUS_OK;
374 blob = data_blob_const(data, length);
376 ZERO_STRUCT(r);
378 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
379 (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
380 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
381 d_fprintf(stderr, _("printer pull failed: %s\n"),
382 ndr_errstr(ndr_err));
383 return NT_STATUS_NO_MEMORY;
386 d_printf(_("Migrating Printer: %s\n"), key_name);
388 result = rpccli_spoolss_openprinter_ex(pipe_hnd,
389 mem_ctx,
390 key_name,
391 MAXIMUM_ALLOWED_ACCESS,
392 &hnd);
393 if (!W_ERROR_IS_OK(result)) {
394 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
395 key_name, win_errstr(result));
396 return werror_to_ntstatus(result);
399 /* Create printer info level 2 */
400 ZERO_STRUCT(info2);
401 ZERO_STRUCT(devmode_ctr);
402 ZERO_STRUCT(secdesc_ctr);
404 info2.attributes = r.info.attributes;
405 info2.averageppm = r.info.averageppm;
406 info2.cjobs = r.info.cjobs;
407 info2.comment = r.info.comment;
408 info2.datatype = r.info.datatype;
409 info2.defaultpriority = r.info.default_priority;
410 info2.drivername = r.info.drivername;
411 info2.location = r.info.location;
412 info2.parameters = r.info.parameters;
413 info2.portname = r.info.portname;
414 info2.printername = r.info.printername;
415 info2.printprocessor = r.info.printprocessor;
416 info2.priority = r.info.priority;
417 info2.sepfile = r.info.sepfile;
418 info2.sharename = r.info.sharename;
419 info2.starttime = r.info.starttime;
420 info2.status = r.info.status;
421 info2.untiltime = r.info.untiltime;
423 /* Create Device Mode */
424 if (r.devmode != NULL) {
425 ZERO_STRUCT(dm);
427 dm.bitsperpel = r.devmode->bitsperpel;
428 dm.collate = r.devmode->collate;
429 dm.color = r.devmode->color;
430 dm.copies = r.devmode->copies;
431 dm.defaultsource = r.devmode->defaultsource;
432 dm.devicename = r.devmode->devicename;
433 dm.displayflags = r.devmode->displayflags;
434 dm.displayfrequency = r.devmode->displayfrequency;
435 dm.dithertype = r.devmode->dithertype;
436 dm.driverversion = r.devmode->driverversion;
437 dm.duplex = r.devmode->duplex;
438 dm.fields = r.devmode->fields;
439 dm.formname = r.devmode->formname;
440 dm.icmintent = r.devmode->icmintent;
441 dm.icmmethod = r.devmode->icmmethod;
442 dm.logpixels = r.devmode->logpixels;
443 dm.mediatype = r.devmode->mediatype;
444 dm.orientation = r.devmode->orientation;
445 dm.panningheight = r.devmode->pelsheight;
446 dm.panningwidth = r.devmode->panningwidth;
447 dm.paperlength = r.devmode->paperlength;
448 dm.papersize = r.devmode->papersize;
449 dm.paperwidth = r.devmode->paperwidth;
450 dm.pelsheight = r.devmode->pelsheight;
451 dm.pelswidth = r.devmode->pelswidth;
452 dm.printquality = r.devmode->printquality;
453 dm.scale = r.devmode->scale;
454 dm.specversion = r.devmode->specversion;
455 dm.ttoption = r.devmode->ttoption;
456 dm.yresolution = r.devmode->yresolution;
458 if (r.devmode->nt_dev_private != NULL) {
459 dm.driverextra_data.data = r.devmode->nt_dev_private->data;
460 dm.driverextra_data.length = r.devmode->nt_dev_private->length;
461 dm.__driverextra_length = r.devmode->nt_dev_private->length;
464 devmode_ctr.devmode = &dm;
466 info2.devmode_ptr = 1;
469 info_ctr.info.info2 = &info2;
470 info_ctr.level = 2;
472 status = rpccli_spoolss_SetPrinter(pipe_hnd,
473 mem_ctx,
474 &hnd,
475 &info_ctr,
476 &devmode_ctr,
477 &secdesc_ctr,
478 0, /* command */
479 &result);
480 if (!NT_STATUS_IS_OK(status)) {
481 d_printf(_("\tSetPrinter(%s) level 2 refused -- %s.\n"),
482 key_name, nt_errstr(status));
483 goto done;
486 /* migrate printerdata */
487 for (j = 0; j < r.count; j++) {
488 char *valuename;
489 char *keyname;
491 if (r.printer_data[j].type == REG_NONE) {
492 continue;
495 keyname = CONST_DISCARD(char *, r.printer_data[j].name);
496 valuename = strchr(keyname, '\\');
497 if (valuename == NULL) {
498 continue;
499 } else {
500 valuename[0] = '\0';
501 valuename++;
504 printf(" data: %s\\%s\n", keyname, valuename);
506 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd,
507 mem_ctx,
508 &hnd,
509 keyname,
510 valuename,
511 r.printer_data[j].type,
512 r.printer_data[j].data.data,
513 r.printer_data[j].data.length,
514 &result);
515 if (!NT_STATUS_IS_OK(status)) {
516 d_printf(_("\tSetPrinterDataEx: printer [%s], keyname [%s], valuename [%s] refused -- %s.\n"),
517 key_name, keyname, valuename, nt_errstr(status));
518 break;
522 done:
523 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
525 return status;
528 static NTSTATUS migrate_secdesc(TALLOC_CTX *mem_ctx,
529 struct rpc_pipe_client *pipe_hnd,
530 const char *key_name,
531 unsigned char *data,
532 size_t length)
534 struct policy_handle hnd;
535 enum ndr_err_code ndr_err;
536 struct sec_desc_buf secdesc_ctr;
537 struct spoolss_SetPrinterInfo3 info3;
538 struct spoolss_SetPrinterInfoCtr info_ctr;
539 struct spoolss_DevmodeContainer devmode_ctr;
540 DATA_BLOB blob;
541 NTSTATUS status;
542 WERROR result;
544 if (strequal(key_name, "printers")) {
545 return NT_STATUS_OK;
548 blob = data_blob_const(data, length);
550 ZERO_STRUCT(secdesc_ctr);
552 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
553 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
554 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
555 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
556 ndr_errstr(ndr_err));
557 return NT_STATUS_NO_MEMORY;
560 d_printf(_("Migrating Security Descriptor: %s\n"), key_name);
562 result = rpccli_spoolss_openprinter_ex(pipe_hnd,
563 mem_ctx,
564 key_name,
565 MAXIMUM_ALLOWED_ACCESS,
566 &hnd);
567 if (!W_ERROR_IS_OK(result)) {
568 d_fprintf(stderr, _("\tOpenPrinter(%s) failed: %s\n"),
569 key_name, win_errstr(result));
570 return werror_to_ntstatus(result);
573 ZERO_STRUCT(devmode_ctr);
575 info3.sec_desc_ptr = 1;
577 info_ctr.info.info3 = &info3;
578 info_ctr.level = 3;
580 status = rpccli_spoolss_SetPrinter(pipe_hnd,
581 mem_ctx,
582 &hnd,
583 &info_ctr,
584 &devmode_ctr,
585 &secdesc_ctr,
586 0, /* command */
587 &result);
588 if (!NT_STATUS_IS_OK(status)) {
589 d_printf(_("\tSetPrinter(%s) level 3 refused -- %s.\n"),
590 key_name, nt_errstr(status));
593 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
595 return status;
598 static NTSTATUS printing_migrate_internal(struct net_context *c,
599 const struct dom_sid *domain_sid,
600 const char *domain_name,
601 struct cli_state *cli,
602 struct rpc_pipe_client *pipe_hnd,
603 TALLOC_CTX *mem_ctx,
604 int argc,
605 const char **argv)
607 TALLOC_CTX *tmp_ctx;
608 TDB_CONTEXT *tdb;
609 TDB_DATA kbuf, newkey, dbuf;
610 NTSTATUS status;
612 tmp_ctx = talloc_new(mem_ctx);
613 if (tmp_ctx == NULL) {
614 return NT_STATUS_NO_MEMORY;
617 tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
618 if (tdb == NULL) {
619 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
620 status = NT_STATUS_NO_SUCH_FILE;
621 goto done;
624 for (kbuf = tdb_firstkey(tdb);
625 kbuf.dptr;
626 newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
628 dbuf = tdb_fetch(tdb, kbuf);
629 if (!dbuf.dptr) {
630 continue;
633 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
634 migrate_form(tmp_ctx,
635 pipe_hnd,
636 (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
637 dbuf.dptr,
638 dbuf.dsize);
639 SAFE_FREE(dbuf.dptr);
640 continue;
643 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
644 migrate_driver(tmp_ctx,
645 pipe_hnd,
646 (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
647 dbuf.dptr,
648 dbuf.dsize);
649 SAFE_FREE(dbuf.dptr);
650 continue;
653 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
654 migrate_printer(tmp_ctx,
655 pipe_hnd,
656 (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
657 dbuf.dptr,
658 dbuf.dsize);
659 SAFE_FREE(dbuf.dptr);
660 continue;
663 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
664 migrate_secdesc(tmp_ctx,
665 pipe_hnd,
666 (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
667 dbuf.dptr,
668 dbuf.dsize);
669 SAFE_FREE(dbuf.dptr);
670 continue;
675 status = NT_STATUS_OK;
677 done:
678 talloc_free(tmp_ctx);
679 return status;
682 static int net_printing_migrate(struct net_context *c,
683 int argc,
684 const char **argv)
686 if (argc < 1 || c->display_usage) {
687 d_printf( "%s\n"
688 "net printing migrate <file.tdb>\n"
689 " %s\n",
690 _("Usage:"),
691 _("Migrate tdb printing files to new storage"));
692 return 0;
695 return run_rpc_command(c,
696 NULL,
697 &ndr_table_spoolss.syntax_id,
699 printing_migrate_internal,
700 argc,
701 argv);
704 * 'net printing' entrypoint.
705 * @param argc Standard main() style argc.
706 * @param argv Standard main() style argv. Initial components are already
707 * stripped.
710 int net_printing(struct net_context *c, int argc, const char **argv)
712 int ret = -1;
714 struct functable func[] = {
716 "dump",
717 net_printing_dump,
718 NET_TRANSPORT_LOCAL,
719 N_("Dump eventlog"),
720 N_("net printing dump\n"
721 " Dump tdb printing file")
725 "migrate",
726 net_printing_migrate,
727 NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
728 N_("Migrate printer databases"),
729 N_("net printing migrate\n"
730 " Migrate tdb printing files to new storage")
733 { NULL, NULL, 0, NULL, NULL }
736 ret = net_run_function(c, argc, argv, "net printing", func);
738 return ret;