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