Line data Source code
1 : /*
2 : * Samba Unix/Linux SMB client library
3 : *
4 : * Copyright (C) Gregor Beck 2010
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 : /**
21 : * @brief Format dot.reg files
22 : * @file reg_format.c
23 : * @author Gregor Beck <gb@sernet.de>
24 : * @date Sep 2010
25 : */
26 :
27 : #include "includes.h"
28 : #include "reg_format.h"
29 : #include "reg_parse.h"
30 : #include "reg_parse_internal.h"
31 : #include "cbuf.h"
32 : #include "srprs.h"
33 : #include "registry.h"
34 : #include "registry/reg_objects.h"
35 : #include <assert.h>
36 :
37 0 : static void cstr_unescape(char* val)
38 : {
39 0 : all_string_sub(val, "\\r", "\r", 0);
40 0 : all_string_sub(val, "\\n", "\n", 0);
41 0 : all_string_sub(val, "\\t", "\t", 0);
42 0 : all_string_sub(val, "\\\\", "\\", 0);
43 0 : }
44 :
45 : /******************************************************************************/
46 :
47 : /**
48 : * Print value assign to stream.
49 : *
50 : * @param[out] ost outstream
51 : * @param[in] name string
52 : *
53 : * @return number of bytes written, -1 on error
54 : * @see srprs_val_name
55 : */
56 2288 : static int cbuf_print_value_assign(cbuf* ost, const char* name) {
57 2288 : size_t ret = 0;
58 0 : int n;
59 2288 : if (*name == '\0') {
60 0 : n = cbuf_putc(ost, '@');
61 : } else {
62 2288 : n = cbuf_print_quoted_string(ost, name);
63 : }
64 2288 : if (n < 0) {
65 0 : return n;
66 : }
67 2288 : ret += n;
68 :
69 2288 : n = cbuf_putc(ost, '=');
70 2288 : if (n < 0) {
71 0 : return n;
72 : }
73 2288 : ret += n;
74 :
75 2288 : return ret;
76 : }
77 :
78 : enum fmt_hive {
79 : FMT_HIVE_PRESERVE=0,
80 : FMT_HIVE_SHORT,
81 : FMT_HIVE_LONG
82 : };
83 :
84 :
85 : struct fmt_key {
86 : enum fmt_hive hive_fmt;
87 : enum fmt_case hive_case;
88 : enum fmt_case key_case;
89 : const char* sep;
90 : };
91 :
92 :
93 : static int
94 740 : cbuf_print_hive(cbuf* ost, const char* hive, int len, const struct fmt_key* fmt)
95 : {
96 740 : if (fmt->hive_fmt != FMT_HIVE_PRESERVE) {
97 0 : const struct hive_info* hinfo = hive_info(hive);
98 0 : if (hinfo == NULL) {
99 0 : DEBUG(0, ("Unknown hive %*s\n", len, hive));
100 : } else {
101 0 : switch(fmt->hive_fmt) {
102 0 : case FMT_HIVE_SHORT:
103 0 : hive = hinfo->short_name;
104 0 : len = hinfo->short_name_len;
105 0 : break;
106 0 : case FMT_HIVE_LONG:
107 0 : hive = hinfo->long_name;
108 0 : len = hinfo->long_name_len;
109 0 : break;
110 0 : default:
111 0 : DEBUG(0, ("Unsupported hive format %d\n",
112 : (int)fmt->hive_fmt));
113 0 : return -1;
114 : }
115 : }
116 : }
117 :
118 740 : return cbuf_puts_case(ost, hive, len, fmt->hive_case);
119 : }
120 :
121 : static int
122 740 : cbuf_print_keyname(cbuf* ost, const char* key[], int n, const struct fmt_key* fmt)
123 : {
124 0 : int r;
125 740 : size_t ret = 0;
126 740 : size_t pos = cbuf_getpos(ost);
127 740 : bool hive = true;
128 :
129 1480 : for (; n>0; key++, n--) {
130 740 : const char* start = *key;
131 4504 : while(*start != '\0') {
132 3764 : const char* end = start;
133 33328 : while(*end != '\\' && *end != '\0') {
134 29564 : end++;
135 : }
136 :
137 3764 : if (hive) {
138 740 : r = cbuf_print_hive(ost, start, end-start, fmt);
139 740 : if (r < 0) {
140 0 : goto fail;
141 : }
142 :
143 740 : ret += r;
144 740 : hive = false;
145 : } else {
146 3024 : r = cbuf_puts(ost, fmt->sep, -1);
147 3024 : if (r < 0) {
148 0 : goto fail;
149 : }
150 3024 : ret += r;
151 :
152 3024 : r = cbuf_puts_case(ost, start, end-start, fmt->key_case);
153 3024 : if (r < 0) {
154 0 : goto fail;
155 : }
156 3024 : ret += r;
157 : }
158 :
159 6788 : while(*end == '\\') {
160 3024 : end++;
161 : }
162 3764 : start = end;
163 : }
164 : }
165 740 : return ret;
166 0 : fail:
167 0 : cbuf_setpos(ost, pos);
168 0 : return r;
169 : }
170 : /**@}*/
171 :
172 : /**
173 : * @defgroup reg_format Format dot.reg file.
174 : * @{
175 : */
176 :
177 : struct reg_format
178 : {
179 : struct reg_parse_callback reg_parse_callback;
180 : struct reg_format_callback call;
181 : unsigned flags;
182 : smb_iconv_t fromUTF16;
183 : const char* sep;
184 : };
185 :
186 0 : int reg_format_value_delete(struct reg_format* f, const char* name)
187 : {
188 0 : int ret;
189 0 : cbuf* line = cbuf_new(f);
190 :
191 0 : ret = cbuf_print_value_assign(line, name);
192 0 : if (ret < 0) {
193 0 : goto done;
194 : }
195 :
196 0 : ret = cbuf_putc(line, '-');
197 0 : if (ret < 0 ) {
198 0 : goto done;
199 : }
200 :
201 0 : ret = f->call.writeline(f->call.data, cbuf_gets(line, 0));
202 0 : done:
203 0 : talloc_free(line);
204 0 : return ret;
205 : }
206 :
207 : /* Todo: write hex if str contains CR or LF */
208 : static int
209 2282 : reg_format_value_sz(struct reg_format* f, const char* name, const char* str)
210 : {
211 0 : int ret;
212 2282 : cbuf* line = cbuf_new(f);
213 :
214 2282 : ret = cbuf_print_value_assign(line, name);
215 2282 : if (ret < 0) {
216 0 : goto done;
217 : }
218 :
219 2282 : ret = cbuf_print_quoted_string(line, str);
220 2282 : if (ret < 0) {
221 0 : goto done;
222 : }
223 :
224 2282 : ret = f->call.writeline(f->call.data, cbuf_gets(line, 0));
225 :
226 2282 : done:
227 2282 : talloc_free(line);
228 2282 : return ret;
229 : }
230 :
231 6 : static int reg_format_value_dw(struct reg_format* f, const char* name, uint32_t dw)
232 : {
233 0 : int ret;
234 6 : cbuf* line = cbuf_new(f);
235 :
236 6 : ret = cbuf_print_value_assign(line, name);
237 6 : if (ret < 0) {
238 0 : goto done;
239 : }
240 :
241 6 : ret = cbuf_printf(line, "dword:%08x", dw);
242 6 : if (ret < 0) {
243 0 : goto done;
244 : }
245 :
246 6 : ret = f->call.writeline(f->call.data, cbuf_gets(line, 0));
247 6 : done:
248 6 : talloc_free(line);
249 6 : return ret;
250 : }
251 :
252 0 : static int reg_format_value_hex(struct reg_format* f, const char* name, uint32_t type,
253 : const void* data, size_t len)
254 : {
255 0 : int n;
256 0 : int cpl=0;
257 0 : int ret=0;
258 0 : const unsigned char* ptr;
259 :
260 0 : cbuf* line = cbuf_new(f);
261 :
262 0 : n = cbuf_print_value_assign(line, name);
263 0 : if (n < 0) {
264 0 : ret = n;
265 0 : goto done;
266 : }
267 :
268 0 : cpl += n;
269 :
270 0 : if (type==REG_BINARY && !(f->flags & REG_FMT_HEX_BIN)) {
271 0 : n=cbuf_puts(line, "hex:", -1);
272 : } else {
273 0 : n=cbuf_printf(line, "hex(%x):", type);
274 : }
275 0 : if (n < 0) {
276 0 : ret = n;
277 0 : goto done;
278 : }
279 :
280 0 : cpl += n;
281 :
282 0 : for (ptr=(const unsigned char *)data; len>1; len--,ptr++) {
283 0 : n = cbuf_printf(line, "%02x,", (unsigned)(*ptr));
284 0 : if (n < 0) {
285 0 : return n;
286 : }
287 0 : cpl += n;
288 :
289 0 : if ( cpl > 76 ) {
290 0 : n = cbuf_putc(line, '\\');
291 0 : if (n< 0) {
292 0 : return n;
293 : }
294 :
295 0 : n = f->call.writeline(f->call.data, cbuf_gets(line,0));
296 0 : if (n < 0) {
297 0 : ret = n;
298 0 : goto done;
299 : }
300 0 : ret += n;
301 :
302 0 : cbuf_clear(line);
303 0 : cpl = cbuf_puts(line, " ", -1);
304 0 : if (cpl < 0) {
305 0 : ret = cpl;
306 0 : goto done;
307 : }
308 : }
309 : }
310 :
311 0 : if ( len > 0 ) {
312 0 : n = cbuf_printf(line, "%02x", (unsigned)(*ptr));
313 0 : if (n < 0) {
314 0 : ret = n;
315 0 : goto done;
316 : }
317 0 : cpl += n;
318 : }
319 :
320 0 : n = f->call.writeline(f->call.data, cbuf_gets(line,0));
321 0 : if (n < 0) {
322 0 : ret = n;
323 0 : goto done;
324 : }
325 0 : ret += n;
326 0 : done:
327 0 : talloc_free(line);
328 0 : return ret;
329 : }
330 :
331 2282 : static bool is_zero_terminated_ucs2(const uint8_t* data, size_t len) {
332 2282 : const size_t idx = len/sizeof(smb_ucs2_t);
333 2282 : const smb_ucs2_t *str = (const smb_ucs2_t*)data;
334 :
335 2282 : if ((len % sizeof(smb_ucs2_t)) != 0) {
336 0 : return false;
337 : }
338 :
339 2282 : if (idx == 0) {
340 0 : return false;
341 : }
342 :
343 2282 : return (str[idx-1] == 0);
344 : }
345 :
346 2288 : int reg_format_value(struct reg_format* f, const char* name, uint32_t type,
347 : const uint8_t* data, size_t len)
348 : {
349 2288 : int ret = 0;
350 2288 : void* mem_ctx = talloc_new(f);
351 :
352 2288 : switch (type) {
353 2282 : case REG_SZ:
354 2282 : if (!(f->flags & REG_FMT_HEX_SZ)
355 2282 : && is_zero_terminated_ucs2(data, len))
356 : {
357 2282 : char* str = NULL;
358 0 : size_t dlen;
359 2282 : if (pull_ucs2_talloc(mem_ctx, &str, (const smb_ucs2_t*)data, &dlen)) {
360 2282 : ret = reg_format_value_sz(f, name, str);
361 2282 : goto done;
362 : } else {
363 0 : DEBUG(0, ("reg_format_value %s: "
364 : "pull_ucs2_talloc failed"
365 : ", try to write hex\n", name));
366 : }
367 : }
368 0 : break;
369 :
370 6 : case REG_DWORD:
371 6 : if (!(f->flags & REG_FMT_HEX_SZ) && (len == sizeof(uint32_t))) {
372 6 : uint32_t dw = IVAL(data,0);
373 6 : ret = reg_format_value_dw(f, name, dw);
374 6 : goto done;
375 : }
376 0 : break;
377 :
378 0 : case REG_MULTI_SZ:
379 : case REG_EXPAND_SZ:
380 0 : if (f->fromUTF16 && (f->fromUTF16 != ((smb_iconv_t)-1))) {
381 0 : char* str = NULL;
382 0 : size_t dlen = iconvert_talloc(mem_ctx, f->fromUTF16,
383 : (const char*)data, len, &str);
384 0 : if (dlen != -1) {
385 0 : ret = reg_format_value_hex(f, name, type, str, dlen);
386 0 : goto done;
387 : } else {
388 0 : DEBUG(0, ("reg_format_value %s: "
389 : "iconvert_talloc failed"
390 : ", try to write hex\n", name));
391 : }
392 : }
393 0 : break;
394 0 : default:
395 0 : break;
396 : }
397 :
398 0 : ret = reg_format_value_hex(f, name, type, data, len);
399 2288 : done:
400 2288 : talloc_free(mem_ctx);
401 2288 : return ret;
402 : }
403 :
404 :
405 42 : int reg_format_comment(struct reg_format* f, const char* txt)
406 : {
407 0 : int ret;
408 42 : cbuf* line = cbuf_new(f);
409 :
410 42 : ret = cbuf_putc(line,';');
411 42 : if (ret<0) {
412 0 : goto done;
413 : }
414 :
415 42 : ret = cbuf_puts(line, txt, -1);
416 42 : if (ret < 0) {
417 0 : goto done;
418 : }
419 :
420 42 : ret = f->call.writeline(f->call.data, cbuf_gets(line, 0));
421 42 : done:
422 42 : talloc_free(line);
423 42 : return ret;
424 : }
425 :
426 :
427 : /******************************************************************************/
428 :
429 :
430 :
431 14 : struct reg_format* reg_format_new(const void* talloc_ctx,
432 : struct reg_format_callback cb,
433 : const char* str_enc, unsigned flags,
434 : const char* sep)
435 : {
436 0 : static const struct reg_parse_callback reg_parse_callback_default = {
437 : .key = (reg_parse_callback_key_t)®_format_key,
438 : .val = (reg_parse_callback_val_t)®_format_value,
439 : .val_del = (reg_parse_callback_val_del_t)®_format_value_delete,
440 : .comment = (reg_parse_callback_comment_t)®_format_comment,
441 : };
442 :
443 14 : struct reg_format* f = talloc_zero(talloc_ctx, struct reg_format);
444 14 : if (f == NULL) {
445 0 : return NULL;
446 : }
447 :
448 14 : f->reg_parse_callback = reg_parse_callback_default;
449 14 : f->reg_parse_callback.data = f;
450 :
451 14 : f->call = cb;
452 14 : f->flags = flags;
453 14 : f->sep = sep;
454 :
455 14 : if (str_enc && !set_iconv(&f->fromUTF16, str_enc, "UTF-16LE")) {
456 0 : DEBUG(0, ("reg_format_new: failed to set encoding: %s\n",
457 : str_enc));
458 0 : goto fail;
459 : }
460 :
461 : assert(&f->reg_parse_callback == (struct reg_parse_callback*)f);
462 14 : return f;
463 0 : fail:
464 0 : talloc_free(f);
465 0 : return NULL;
466 : }
467 :
468 0 : int reg_format_set_options(struct reg_format* fmt, const char* options)
469 : {
470 0 : static const char* DEFAULT ="enc=unix,flags=0,sep=\\";
471 :
472 0 : int ret = 0;
473 0 : char *key, *val;
474 0 : void* ctx = talloc_new(fmt);
475 :
476 0 : if (options == NULL) {
477 0 : options = DEFAULT;
478 : }
479 :
480 0 : while (srprs_option(&options, ctx, &key, &val)) {
481 0 : if ((strcmp(key, "enc") == 0) || (strcmp(key, "strenc") == 0)) {
482 0 : if (!set_iconv(&fmt->fromUTF16, val, "UTF-16LE")) {
483 0 : DEBUG(0, ("Failed to set encoding: %s\n", val));
484 0 : ret = -1;
485 : }
486 0 : } else if ((strcmp(key, "flags") == 0) && (val != NULL)) {
487 0 : char* end = NULL;
488 0 : if (val != NULL) {
489 0 : fmt->flags = strtol(val, &end, 0);
490 : }
491 0 : if ((end==NULL) || (*end != '\0')) {
492 0 : DEBUG(0, ("Invalid flags format: %s\n",
493 : val ? val : "<NULL>"));
494 0 : ret = -1;
495 : }
496 0 : } else if ((strcmp(key, "sep") == 0) && (val != NULL)) {
497 0 : cstr_unescape(val);
498 0 : fmt->sep = talloc_steal(fmt, val);
499 : }
500 :
501 : /* else if (strcmp(key, "hive") == 0) { */
502 : /* if (strcmp(val, "short") == 0) { */
503 : /* f->hive_fmt = REG_FMT_SHORT_HIVES; */
504 : /* } else if (strcmp(val, "long") == 0) { */
505 : /* f->hive_fmt = REG_FMT_LONG_HIVES; */
506 : /* } else if (strcmp(val, "preserve") == 0) { */
507 : /* f->hive_fmt = REG_FMT_PRESERVE_HIVES; */
508 : /* } else { */
509 : /* DEBUG(0, ("Invalid hive format: %s\n", val)); */
510 : /* ret = -1; */
511 : /* } */
512 : /* } */
513 : }
514 0 : talloc_free(ctx);
515 0 : return ret;
516 : }
517 :
518 740 : int reg_format_key(struct reg_format* f, const char* key[], size_t n, bool del)
519 : {
520 0 : int ret, r;
521 740 : cbuf* line = cbuf_new(f);
522 740 : struct fmt_key key_fmt = {
523 740 : .key_case = (f->flags >> 4) & 0x0F,
524 740 : .hive_case = (f->flags >> 8) & 0x0F,
525 740 : .hive_fmt = (f->flags >> 12) & 0x0F,
526 740 : .sep = f->sep,
527 : };
528 :
529 740 : ret = cbuf_putc(line, '[');
530 740 : if (ret < 0) {
531 0 : goto done;
532 : }
533 :
534 740 : if (del) {
535 0 : ret = cbuf_putc(line, '-');
536 0 : if (ret < 0) {
537 0 : goto done;
538 : }
539 : }
540 :
541 740 : ret = cbuf_print_keyname(line, key, n, &key_fmt);
542 740 : if (ret < 0) {
543 0 : goto done;
544 : }
545 :
546 740 : ret = cbuf_putc(line, ']');
547 740 : if (ret < 0) {
548 0 : goto done;
549 : }
550 :
551 740 : ret = f->call.writeline(f->call.data, "");
552 740 : if (ret < 0) {
553 0 : goto done;
554 : }
555 :
556 740 : r = f->call.writeline(f->call.data, cbuf_gets(line, 0));
557 740 : if (r < 0) {
558 0 : ret = r;
559 0 : goto done;
560 : }
561 740 : ret += r;
562 :
563 740 : done:
564 740 : talloc_free(line);
565 740 : return ret;
566 : }
567 :
568 :
569 724 : int reg_format_registry_key(struct reg_format* f, struct registry_key* key,
570 : bool del)
571 : {
572 0 : const char *knames[1];
573 724 : knames[0] = key->key->name;
574 724 : return reg_format_key(f, knames, 1, del);
575 : }
576 :
577 2196 : int reg_format_registry_value(struct reg_format* f, const char* name,
578 : struct registry_value* val)
579 : {
580 4392 : return reg_format_value(f, name, val->type,
581 2196 : val->data.data, val->data.length);
582 : }
583 :
584 92 : int reg_format_regval_blob(struct reg_format* f, const char* name,
585 : struct regval_blob* val)
586 : {
587 :
588 92 : return reg_format_value(f,
589 0 : name ? name : regval_name(val),
590 : regval_type(val),
591 92 : regval_data_p(val),
592 92 : regval_size(val));
593 : }
594 :
595 : /**@}*/
596 :
597 :
598 : struct reg_format_file
599 : {
600 : FILE* file;
601 : const char* encoding;
602 : smb_iconv_t fromUnix;
603 : char* nl;
604 : size_t nl_len;
605 : };
606 :
607 :
608 14 : static int reg_format_file_close(struct reg_format* fmt)
609 : {
610 14 : struct reg_format_file* fmt_ctx
611 : = (struct reg_format_file*) fmt->call.data;
612 14 : int ret = 0;
613 14 : FILE* file = fmt_ctx->file;
614 :
615 14 : if (fmt_ctx->encoding) {
616 0 : char buf[32];
617 14 : snprintf(buf, sizeof(buf), "coding: %s", fmt_ctx->encoding);
618 14 : reg_format_comment(fmt, "Local Variables:");
619 14 : reg_format_comment(fmt, buf);
620 14 : reg_format_comment(fmt, "End:");
621 : }
622 :
623 14 : if (file != NULL) {
624 14 : ret = fclose(file);
625 : }
626 :
627 14 : return ret;
628 : }
629 :
630 3824 : static int reg_format_file_writeline(void* ptr, const char* line)
631 : {
632 0 : size_t size;
633 3824 : char* dst=NULL;
634 3824 : struct reg_format_file* fmt_ctx = (struct reg_format_file*)ptr;
635 0 : int ret, r;
636 :
637 3824 : size = iconvert_talloc(ptr, fmt_ctx->fromUnix, line, strlen(line), &dst);
638 3824 : if (size == -1 ) {
639 0 : DEBUG(0, ("reg_format_file_writeline: iconvert_talloc failed >%s<\n", line));
640 0 : return -1;
641 : }
642 :
643 3824 : ret = fwrite(dst, 1, size, fmt_ctx->file);
644 3824 : if (ret < 0) {
645 0 : goto done;
646 : }
647 :
648 3824 : r = fwrite(fmt_ctx->nl, 1, fmt_ctx->nl_len, fmt_ctx->file);
649 3824 : ret = (r < 0) ? r : ret + r;
650 :
651 3824 : done:
652 3824 : talloc_free(dst);
653 3824 : return ret;
654 : }
655 :
656 : struct reg_format_file_opt {
657 : const char* head;
658 : const char* nl;
659 : const char* enc;
660 : bool bom;
661 : const char* str_enc;
662 : unsigned flags;
663 : const char* sep;
664 : };
665 :
666 14 : static struct reg_format_file_opt reg_format_file_opt(void* mem_ctx, const char* opt)
667 : {
668 0 : static const struct reg_format_file_opt REG4 = {
669 : .head = "REGEDIT4",
670 : .nl = "\r\n",
671 : .enc = "dos",
672 : .str_enc = "dos",
673 : .bom = false,
674 : .flags = (FMT_HIVE_LONG << 12),
675 : .sep = "\\",
676 : };
677 :
678 0 : static const struct reg_format_file_opt REG5 = {
679 : .head = "Windows Registry Editor Version 5.00",
680 : .nl = "\r\n",
681 : .enc = "UTF-16LE",
682 : .str_enc = "UTF-16LE",
683 : .bom = true,
684 : .flags = (FMT_HIVE_LONG << 12),
685 : .sep = "\\",
686 : };
687 :
688 14 : struct reg_format_file_opt ret = {
689 14 : .head = REG5.head,
690 : .nl = "\n",
691 : .enc = "unix",
692 : .bom = false,
693 : .str_enc = "UTF-16LE",
694 : .flags = 0,
695 : .sep = "\\",
696 : };
697 :
698 14 : void* tmp_ctx = talloc_new(mem_ctx);
699 :
700 0 : char *key, *val;
701 :
702 14 : if (opt == NULL) {
703 14 : goto done;
704 : }
705 :
706 0 : while(srprs_option(&opt, tmp_ctx, &key, &val)) {
707 0 : if (strcmp(key, "enc") == 0) {
708 0 : ret.enc = talloc_steal(mem_ctx, val);
709 0 : ret.str_enc = ret.enc;
710 0 : } else if (strcmp(key, "strenc") == 0) {
711 0 : ret.str_enc = talloc_steal(mem_ctx, val);
712 0 : } else if (strcmp(key, "fileenc") == 0) {
713 0 : ret.enc = talloc_steal(mem_ctx, val);
714 0 : } else if ((strcmp(key, "flags") == 0) && (val != NULL)) {
715 0 : char* end = NULL;
716 0 : if (val != NULL) {
717 0 : ret.flags = strtol(val, &end, 0);
718 : }
719 0 : if ((end==NULL) || (*end != '\0')) {
720 0 : DEBUG(0, ("Invalid flags format: %s\n",
721 : val ? val : "<NULL>"));
722 : }
723 0 : } else if ((strcmp(key, "sep") == 0) && (val != NULL)) {
724 0 : cstr_unescape(val);
725 0 : ret.sep = talloc_steal(mem_ctx, val);
726 0 : } else if (strcmp(key, "head") == 0) {
727 0 : cstr_unescape(val);
728 0 : ret.head = talloc_steal(mem_ctx, val);
729 0 : } else if (strcmp(key, "nl") == 0) {
730 0 : cstr_unescape(val);
731 0 : ret.nl = talloc_steal(mem_ctx, val);
732 0 : } else if (strcmp(key, "bom") == 0) {
733 0 : if (val == NULL) {
734 0 : ret.bom = true;
735 : } else {
736 0 : ret.bom = atoi(val);
737 : }
738 0 : } else if (strcmp(key, "regedit4") == 0) {
739 0 : ret = REG4;
740 0 : } else if (strcmp(key, "regedit5") == 0) {
741 0 : ret = REG5;
742 : }
743 : }
744 0 : done:
745 14 : talloc_free(tmp_ctx);
746 14 : return ret;
747 : }
748 :
749 :
750 14 : struct reg_format* reg_format_file(const void* talloc_ctx,
751 : const char* filename,
752 : const char* options)
753 : {
754 0 : struct reg_format_file* fmt_ctx;
755 0 : struct reg_format* fmt;
756 0 : int ret;
757 0 : struct reg_format_file_opt opt;
758 :
759 14 : struct reg_format_callback reg_format_cb = {
760 : .writeline = ®_format_file_writeline
761 : };
762 :
763 14 : fmt_ctx = talloc_zero(talloc_ctx, struct reg_format_file);
764 14 : if (fmt_ctx == NULL) {
765 0 : errno = ENOMEM;
766 0 : return NULL;
767 : }
768 :
769 14 : opt = reg_format_file_opt(fmt_ctx, options);
770 :
771 14 : reg_format_cb.data = fmt_ctx;
772 :
773 14 : fmt = reg_format_new(talloc_ctx, reg_format_cb,
774 : opt.str_enc, opt.flags, opt.sep);
775 14 : if (fmt == NULL) {
776 0 : errno = ENOMEM;
777 0 : talloc_free(fmt_ctx);
778 0 : return NULL;
779 : }
780 :
781 14 : talloc_steal(fmt, fmt_ctx);
782 :
783 14 : if (!set_iconv(&fmt->fromUTF16, opt.str_enc, "UTF-16LE")) { /* HACK */
784 0 : DEBUG(0, ("reg_format_file: failed to set string encoding %s\n",
785 : opt.str_enc));
786 0 : goto fail;
787 : }
788 :
789 14 : if (!set_iconv(&fmt_ctx->fromUnix, opt.enc, "unix")) {
790 0 : DEBUG(0, ("reg_format_file: failed to set file encoding %s\n",
791 : opt.enc));
792 0 : goto fail;
793 : }
794 14 : fmt_ctx->encoding = talloc_strdup(fmt_ctx, smbreg_get_charset(opt.enc));
795 :
796 14 : fmt_ctx->file = fopen(filename, "w");
797 14 : if (fmt_ctx->file == NULL) {
798 0 : DEBUG(0, ("reg_format_file: fopen failed: %s\n", strerror(errno)));
799 0 : goto fail;
800 : }
801 :
802 14 : if (setvbuf(fmt_ctx->file, NULL, _IOFBF, 64000) < 0) {
803 0 : DEBUG(0, ("reg_format_file: setvbuf failed: %s\n", strerror(errno)));
804 : }
805 :
806 14 : talloc_set_destructor(fmt, reg_format_file_close);
807 :
808 14 : fmt_ctx->nl_len = iconvert_talloc(fmt, fmt_ctx->fromUnix, opt.nl, strlen(opt.nl), &fmt_ctx->nl);
809 14 : if (fmt_ctx->nl_len == -1) {
810 0 : DEBUG(0, ("iconvert_talloc failed\n"));
811 0 : goto fail;
812 : }
813 :
814 14 : if (opt.bom) {
815 0 : ret = write_bom(fmt_ctx->file, opt.enc, -1);
816 0 : if (ret < 0) {
817 0 : goto fail;
818 : }
819 : }
820 :
821 14 : ret = fmt->call.writeline(fmt->call.data, opt.head);
822 14 : if (ret < 0) {
823 0 : goto fail;
824 : }
825 :
826 14 : return fmt;
827 0 : fail:
828 0 : talloc_free(fmt);
829 0 : return NULL;
830 : }
|