LCOV - code coverage report
Current view: top level - source3/registry - reg_format.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 189 421 44.9 %
Date: 2024-04-21 15:09:00 Functions: 17 21 81.0 %

          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)&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          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 = &reg_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             : }

Generated by: LCOV version 1.14