PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/samba-3.6.6/source3/registry/reg_parse.c

#
C | 960 lines | 883 code | 42 blank | 35 comment | 50 complexity | eb4ba3842a8d60fbdf51ce8a03b99eae MD5 | raw file
Possible License(s): GPL-3.0, Apache-2.0, BSD-3-Clause
  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. * @brief Parser for dot.reg files
  21. * @file reg_parse.c
  22. * @author Gregor Beck <gb@sernet.de>
  23. * @date Jun 2010
  24. *
  25. */
  26. #include "includes.h"
  27. #include "system/filesys.h"
  28. #include "cbuf.h"
  29. #include "srprs.h"
  30. #include "reg_parse_internal.h"
  31. #include "reg_parse.h"
  32. #include "reg_format.h"
  33. #include <stdio.h>
  34. #include <unistd.h>
  35. #include <wchar.h>
  36. #include <talloc.h>
  37. #include <stdbool.h>
  38. #include <string.h>
  39. #include <sys/types.h>
  40. #include <regex.h>
  41. #include <assert.h>
  42. #include <stdint.h>
  43. enum reg_parse_state {
  44. STATE_DEFAULT,
  45. STATE_KEY_OPEN,
  46. STATE_VAL_HEX_CONT,
  47. STATE_VAL_SZ_CONT
  48. };
  49. struct reg_parse {
  50. struct reg_format_callback reg_format_callback;
  51. cbuf* key;
  52. cbuf* valname;
  53. uint32_t valtype;
  54. cbuf* valblob;
  55. cbuf* tmp;
  56. struct reg_parse_callback call;
  57. int ret;
  58. int linenum;
  59. enum reg_parse_state state;
  60. struct reg_parse_options* opt;
  61. smb_iconv_t str2UTF16;
  62. unsigned flags;
  63. };
  64. /**
  65. * @defgroup action Action
  66. * @{
  67. */
  68. static bool act_key(struct reg_parse* p, cbuf* keyname, bool del)
  69. {
  70. const char* name = cbuf_gets(keyname, 0);
  71. cbuf_swap(p->key, keyname);
  72. assert(p->state == STATE_DEFAULT || p->state == STATE_KEY_OPEN);
  73. p->state = del ? STATE_DEFAULT : STATE_KEY_OPEN;
  74. assert(p->call.key);
  75. p->ret = p->call.key(p->call.data, &name, 1, del);
  76. return p->ret >= 0;
  77. }
  78. static bool value_callback(struct reg_parse* p)
  79. {
  80. const char* name = cbuf_gets(p->valname,0);
  81. const uint8_t* val = (const uint8_t*)cbuf_gets(p->valblob,0);
  82. size_t len = cbuf_getpos(p->valblob);
  83. assert(p->call.val);
  84. p->ret = p->call.val(p->call.data, name, p->valtype, val, len);
  85. return p->ret >= 0;
  86. }
  87. static bool act_val_hex(struct reg_parse* p, cbuf* value, bool cont)
  88. {
  89. cbuf_swap(p->valblob, value);
  90. assert((p->state == STATE_KEY_OPEN) || (p->state == STATE_VAL_HEX_CONT));
  91. if (cont) {
  92. p->state = STATE_VAL_HEX_CONT;
  93. } else {
  94. p->state = STATE_KEY_OPEN;
  95. switch (p->valtype) {
  96. case REG_EXPAND_SZ:
  97. case REG_MULTI_SZ:
  98. if (p->str2UTF16 != NULL) {
  99. char* dst = NULL;
  100. const char* src = cbuf_gets(p->valblob, 0);
  101. const size_t slen = cbuf_getpos(p->valblob);
  102. size_t dlen = iconvert_talloc(p,
  103. p->str2UTF16,
  104. src, slen,
  105. &dst);
  106. if (dlen != -1) {
  107. cbuf_swapptr(p->valblob, &dst, dlen);
  108. } else {
  109. DEBUG(0, ("iconvert_talloc failed\n"));
  110. }
  111. talloc_free(dst);
  112. }
  113. default:
  114. break;
  115. }
  116. return value_callback(p);
  117. }
  118. return true;
  119. }
  120. static bool act_val_dw(struct reg_parse* p, uint32_t val)
  121. {
  122. assert(p->valtype == REG_DWORD);
  123. assert(p->state == STATE_KEY_OPEN);
  124. cbuf_clear(p->valblob);
  125. if (cbuf_putdw(p->valblob, val) < 0) {
  126. return false;
  127. }
  128. return value_callback(p);
  129. }
  130. static bool act_val_sz(struct reg_parse* p, cbuf* value, bool cont)
  131. {
  132. cbuf_swap(p->valblob, value);
  133. assert(p->valtype == REG_SZ);
  134. assert((p->state == STATE_KEY_OPEN) || (p->state == STATE_VAL_SZ_CONT));
  135. if (cont) {
  136. p->state = STATE_VAL_SZ_CONT;
  137. } else {
  138. char* dst = NULL;
  139. size_t dlen;
  140. const char* src = cbuf_gets(p->valblob, 0);
  141. p->state = STATE_KEY_OPEN;
  142. if (convert_string_talloc(p->valblob, CH_UNIX, CH_UTF16LE,
  143. src, strlen(src)+1,
  144. &dst, &dlen, true))
  145. {
  146. cbuf_swapptr(p->valblob, &dst, dlen);
  147. } else {
  148. DEBUG(0, ("convert_string_talloc failed: >%s<\n"
  149. "use it as is\t", src));
  150. }
  151. talloc_free(dst);
  152. return value_callback(p);
  153. }
  154. return true;
  155. }
  156. static bool act_val_del(struct reg_parse* p)
  157. {
  158. const char* name = cbuf_gets(p->valname, 0);
  159. assert(p->call.val_del);
  160. p->ret = p->call.val_del(p->call.data, name);
  161. return p->ret >= 0;
  162. }
  163. static bool act_comment (struct reg_parse* p, const char* txt)
  164. {
  165. assert(p->call.comment);
  166. p->ret = p->call.comment(p->call.data, txt);
  167. return p->ret >= 0;
  168. }
  169. /**@}*/
  170. static int nop(void* data)
  171. {
  172. return 0;
  173. }
  174. struct reg_parse* reg_parse_new(const void* ctx,
  175. struct reg_parse_callback cb,
  176. const char* str_enc, unsigned flags)
  177. {
  178. struct reg_parse* s = talloc_zero(ctx, struct reg_parse);
  179. if (s == NULL)
  180. return NULL;
  181. s->key = cbuf_new(s);
  182. s->valname = cbuf_new(s);
  183. s->valblob = cbuf_new(s);
  184. s->tmp = cbuf_new(s);
  185. if ( (s->tmp == NULL) || (s->valblob == NULL)
  186. || (s->valname == NULL) || (s->key == NULL) )
  187. {
  188. goto fail;
  189. }
  190. s->reg_format_callback.writeline = (reg_format_callback_writeline_t)&reg_parse_line;
  191. s->reg_format_callback.data = s;
  192. s->valtype = 0;
  193. if (cb.key == NULL) {
  194. cb.key = (reg_parse_callback_key_t)&nop;
  195. }
  196. if (cb.val == NULL) {
  197. cb.val = (reg_parse_callback_val_t)&nop;
  198. }
  199. if (cb.val_del == NULL) {
  200. cb.val_del = (reg_parse_callback_val_del_t)&nop;
  201. }
  202. if (cb.comment == NULL) {
  203. cb.comment = (reg_parse_callback_comment_t)&nop;
  204. }
  205. s->call = cb;
  206. s->linenum = 0;
  207. s->state = STATE_DEFAULT;
  208. s->flags = flags;
  209. if (str_enc && !set_iconv(&s->str2UTF16, "UTF-16LE", str_enc)) {
  210. DEBUG(0, ("reg_parse_new: failed to set encoding: %s",
  211. str_enc));
  212. goto fail;
  213. }
  214. assert(&s->reg_format_callback == (struct reg_format_callback*)s);
  215. return s;
  216. fail:
  217. talloc_free(s);
  218. return NULL;
  219. }
  220. /**
  221. * @defgroup parse Parser Primitive
  222. * @ingroup internal
  223. * @{
  224. */
  225. static bool srprs_key(const char** ptr, cbuf* key, bool* del)
  226. {
  227. const char* pos = *ptr;
  228. const char* closing_bracket_pos = NULL;
  229. size_t closing_bracket_idx = 0;
  230. if (!srprs_skipws(&pos) || !srprs_char(&pos, '[')) {
  231. return false;
  232. }
  233. *del = srprs_char(&pos, '-');
  234. cbuf_clear(key);
  235. while (true) {
  236. while (srprs_charsetinv(&pos, "]\\", key))
  237. ;
  238. switch (*pos) {
  239. case ']':
  240. closing_bracket_idx = cbuf_getpos(key);
  241. closing_bracket_pos = pos;
  242. cbuf_putc(key, ']');
  243. pos++;
  244. break;
  245. case '\\':
  246. cbuf_putc(key, '\\');
  247. /* n++; */
  248. /* cbuf_puts(subkeyidx, cbuf_getpos(key), sizeof(size_t)) */
  249. while (srprs_char(&pos,'\\'))
  250. ;
  251. break;
  252. case '\0':
  253. if (closing_bracket_pos == NULL) {
  254. return false;
  255. }
  256. /* remove trailing backslash (if any) */
  257. if (*(closing_bracket_pos-1)=='\\') {
  258. closing_bracket_idx--;
  259. }
  260. cbuf_setpos(key, closing_bracket_idx);
  261. *ptr = closing_bracket_pos+1;
  262. return true;
  263. default:
  264. assert(false);
  265. }
  266. }
  267. }
  268. static bool srprs_val_name(const char** ptr, cbuf* name)
  269. {
  270. const char* pos = *ptr;
  271. const size_t spos = cbuf_getpos(name);
  272. if ( !srprs_skipws(&pos) ) {
  273. goto fail;
  274. }
  275. if ( srprs_char(&pos, '@') ) {
  276. cbuf_puts(name, "", -1);
  277. }
  278. else if (!srprs_quoted_string(&pos, name, NULL)) {
  279. goto fail;
  280. }
  281. if (!srprs_skipws(&pos) || !srprs_char(&pos, '=')) {
  282. goto fail;
  283. }
  284. *ptr = pos;
  285. return true;
  286. fail:
  287. cbuf_setpos(name, spos);
  288. return false;
  289. }
  290. static bool srprs_val_dword(const char** ptr, uint32_t* type, uint32_t* val)
  291. {
  292. const char* pos = *ptr;
  293. if (!srprs_str(&pos, "dword:", -1)) {
  294. return false;
  295. }
  296. if (!srprs_hex(&pos, 8, val)) {
  297. return false;
  298. }
  299. *type = REG_DWORD;
  300. *ptr = pos;
  301. return true;
  302. }
  303. static bool srprs_val_sz(const char** ptr, uint32_t* type, cbuf* val, bool* cont)
  304. {
  305. if (!srprs_quoted_string(ptr, val, cont)) {
  306. return false;
  307. }
  308. *type = REG_SZ;
  309. return true;
  310. }
  311. static bool srprs_nl_no_eos(const char** ptr, cbuf* str, bool eof)
  312. {
  313. const char* pos = *ptr;
  314. const size_t spos = cbuf_getpos(str);
  315. if( srprs_nl(&pos, str) && (eof || *pos != '\0')) {
  316. *ptr = pos;
  317. return true;
  318. }
  319. cbuf_setpos(str, spos);
  320. return false;
  321. }
  322. static bool srprs_eol_cont(const char** ptr, bool* cont)
  323. {
  324. const char* pos = *ptr;
  325. bool bs = srprs_char(&pos, '\\');
  326. if (!srprs_eol(&pos, NULL)) {
  327. return false;
  328. }
  329. *cont = bs;
  330. *ptr = pos;
  331. return true;
  332. }
  333. /* matches the empty string, for zero length lists */
  334. static bool srprs_val_hex_values(const char** ptr, cbuf* val, bool* cont)
  335. {
  336. const char* pos = *ptr;
  337. unsigned u;
  338. do {
  339. if (!srprs_skipws(&pos) || !srprs_hex(&pos, 2, &u) || !srprs_skipws(&pos)) {
  340. break;
  341. }
  342. cbuf_putc(val, (char)u);
  343. } while(srprs_char(&pos, ','));
  344. *ptr = pos;
  345. if (srprs_skipws(&pos) && srprs_eol_cont(&pos, cont)) {
  346. *ptr = pos;
  347. }
  348. return true;
  349. }
  350. static bool srprs_val_hex(const char** ptr, uint32_t* ptype, cbuf* val,
  351. bool* cont)
  352. {
  353. const char* pos = *ptr;
  354. uint32_t type;
  355. if (!srprs_str(&pos, "hex", -1)) {
  356. return false;
  357. }
  358. if (srprs_char(&pos, ':')) {
  359. type = REG_BINARY;
  360. }
  361. else if (!srprs_char(&pos, '(') ||
  362. !srprs_hex(&pos, 8, &type) ||
  363. !srprs_char(&pos,')') ||
  364. !srprs_char(&pos, ':'))
  365. {
  366. return false;
  367. }
  368. if (!srprs_val_hex_values(&pos, val, cont)) {
  369. return false;
  370. }
  371. *ptype = type;
  372. *ptr = pos;
  373. return true;
  374. }
  375. static bool srprs_comment(const char** ptr, cbuf* str)
  376. {
  377. return srprs_char(ptr, ';') && srprs_line(ptr, str);
  378. }
  379. /**@}*/
  380. int reg_parse_set_options(struct reg_parse* parser, const char* options)
  381. {
  382. static const char* DEFAULT ="enc=unix,flags=0";
  383. int ret = 0;
  384. char *key, *val;
  385. void* ctx = talloc_new(parser);
  386. if (options == NULL) {
  387. options = DEFAULT;
  388. }
  389. while (srprs_option(&options, ctx, &key, &val)) {
  390. if ((strcmp(key, "enc") == 0) || (strcmp(key, "strenc") == 0)) {
  391. } else if ((strcmp(key, "flags") == 0) && (val != NULL)) {
  392. char* end = NULL;
  393. if (val != NULL) {
  394. parser->flags = strtol(val, &end, 0);
  395. }
  396. if ((end==NULL) || (*end != '\0')) {
  397. DEBUG(0, ("Invalid flags format: %s\n",
  398. val ? val : "<NULL>"));
  399. ret = -1;
  400. }
  401. }
  402. /* else if (strcmp(key, "hive") == 0) { */
  403. /* if (strcmp(val, "short") == 0) { */
  404. /* f->hive_fmt = REG_FMT_SHORT_HIVES; */
  405. /* } else if (strcmp(val, "long") == 0) { */
  406. /* f->hive_fmt = REG_FMT_LONG_HIVES; */
  407. /* } else if (strcmp(val, "preserve") == 0) { */
  408. /* f->hive_fmt = REG_FMT_PRESERVE_HIVES; */
  409. /* } else { */
  410. /* DEBUG(0, ("Invalid hive format: %s\n", val)); */
  411. /* ret = -1; */
  412. /* } */
  413. /* } */
  414. }
  415. talloc_free(ctx);
  416. return ret;
  417. }
  418. int reg_parse_line(struct reg_parse* parser, const char* line)
  419. {
  420. const char* pos;
  421. bool del=false;
  422. cbuf* tmp=cbuf_clear(parser->tmp);
  423. bool cb_ok = true;
  424. bool cont = true;
  425. if (!line) {
  426. return -4;
  427. }
  428. parser->linenum++;
  429. pos = line;
  430. switch (parser->state) {
  431. case STATE_VAL_HEX_CONT:
  432. if (srprs_val_hex_values(&pos, parser->valblob, &cont)) {
  433. cb_ok = act_val_hex(parser, parser->valblob, cont);
  434. }
  435. goto done;
  436. case STATE_VAL_SZ_CONT:
  437. if (srprs_quoted_string(&pos, parser->valblob, &cont)) {
  438. cb_ok = act_val_sz(parser, parser->valblob, cont);
  439. }
  440. goto done;
  441. default:
  442. cont = false;
  443. }
  444. if ( !srprs_skipws(&pos) ) {
  445. return -4;
  446. }
  447. /* empty line ?*/
  448. if ( srprs_eol(&pos, NULL) ) {
  449. return 0;
  450. }
  451. /* key line ?*/
  452. else if (srprs_key(&pos, tmp, &del)) {
  453. cb_ok = act_key(parser, tmp, del);
  454. }
  455. /* comment line ? */
  456. else if (srprs_comment(&pos, tmp)) {
  457. cb_ok = act_comment(parser, cbuf_gets(tmp, 0));
  458. }
  459. /* head line */
  460. else if ((parser->linenum == 1) && srprs_line(&pos, tmp) ) {
  461. /* cb_ok = act_head(parser, cbuf_gets(tmp, 0)); */
  462. }
  463. /* value line ?*/
  464. else if (srprs_val_name(&pos, tmp)) {
  465. uint32_t dw;
  466. cbuf_swap(parser->valname, tmp);
  467. cbuf_clear(tmp);
  468. if (parser->state != STATE_KEY_OPEN) {
  469. DEBUG(0, ("value \"%s\" without a key at line: %i",
  470. cbuf_gets(parser->valname, 0), parser->linenum));
  471. return -3;
  472. }
  473. if (!srprs_skipws(&pos)) {
  474. return -4;
  475. }
  476. if (srprs_char(&pos, '-')) {
  477. cb_ok = act_val_del(parser);
  478. }
  479. else if (srprs_val_dword(&pos, &parser->valtype, &dw)) {
  480. cb_ok = act_val_dw(parser, dw);
  481. }
  482. else if (srprs_val_sz(&pos, &parser->valtype, tmp, &cont)) {
  483. cb_ok = act_val_sz(parser, tmp, cont);
  484. }
  485. else if (srprs_val_hex(&pos, &parser->valtype, tmp, &cont)){
  486. cb_ok = act_val_hex(parser, tmp, cont);
  487. }
  488. else {
  489. DEBUG(0, ("value \"%s\" parse error"
  490. "at line: %i pos: %li : %s",
  491. cbuf_gets(parser->valname, 0), parser->linenum,
  492. (long int)(pos-line), pos));
  493. return -3;
  494. }
  495. }
  496. else {
  497. DEBUG(0, ("unrecognized line %i : %s\n", parser->linenum, line));
  498. return -3;
  499. }
  500. done:
  501. if (!cb_ok)
  502. return -2;
  503. if (!srprs_skipws(&pos) || !srprs_eol(&pos, NULL)) {
  504. DEBUG(0, ("trailing garbage at line: %i pos: %li : %s\n",
  505. parser->linenum, (long int)(pos-line), pos));
  506. return -1;
  507. }
  508. return 0;
  509. }
  510. /******************************************************************************/
  511. /**
  512. * @addtogroup misc
  513. * @{
  514. */
  515. static bool lookslike_utf16(const char* line, size_t len, bool* little_endian)
  516. {
  517. static const uint16_t M_LE = 0xFF80;
  518. static const uint16_t M_BE = 0x80FF;
  519. uint16_t mask;
  520. bool le;
  521. size_t l = MIN(len/2, 64);
  522. uint16_t* u = (uint16_t*)line;
  523. int i;
  524. assert(len >= 2);
  525. if ( u[0] & M_LE ) {
  526. le = true;
  527. mask = M_LE;
  528. } else if ( u[0] & M_BE ) {
  529. le = false;
  530. mask = M_BE;
  531. } else {
  532. return false;
  533. }
  534. for (i=1; i<l; i++) {
  535. if ( u[i] & mask ) {
  536. return false;
  537. }
  538. }
  539. *little_endian = le;
  540. return true;
  541. }
  542. static bool lookslike_dos(const char* line, size_t len)
  543. {
  544. int i;
  545. for (i=0; i<len; i++) {
  546. if ( (line[i] == '\0') || (line[i] & 0x80) ) {
  547. return false;
  548. }
  549. if ( (line[i] == '\r') && (i+1 < len) && (line[i+1] == '\n') ) {
  550. return true;
  551. }
  552. }
  553. return false;
  554. }
  555. static bool guess_charset(const char** ptr,
  556. size_t* len,
  557. const char** file_enc,
  558. const char** str_enc)
  559. {
  560. const char* charset = NULL;
  561. const char* pos = *ptr;
  562. if (*len < 4) {
  563. return false;
  564. }
  565. if (srprs_bom(&pos, &charset, NULL)) {
  566. *len -= (pos - *ptr);
  567. *ptr = pos;
  568. if (*file_enc == NULL) {
  569. *file_enc = charset;
  570. }
  571. else if( strcmp(*file_enc, charset) != 0 ) {
  572. DEBUG(0, ("file encoding forced to %s\n",
  573. *file_enc));
  574. }
  575. }
  576. else if (*file_enc == NULL) {
  577. bool le;
  578. if (lookslike_utf16(*ptr, *len, &le)) {
  579. *file_enc = le ? "UTF-16LE" : "UTF-16BE";
  580. }
  581. else if (lookslike_dos(*ptr, *len)) {
  582. *file_enc = "dos";
  583. }
  584. else {
  585. *file_enc = "unix";
  586. }
  587. }
  588. if ((str_enc != NULL) && (*str_enc == NULL)) {
  589. *str_enc = ( strncmp(*ptr, "REGEDIT4", 8) == 0)
  590. ? *file_enc
  591. : "UTF-16LE";
  592. }
  593. return true;
  594. }
  595. /**@}*/
  596. struct reg_parse_fd_opt {
  597. const char* file_enc;
  598. const char* str_enc;
  599. unsigned flags;
  600. int fail_level;
  601. };
  602. static struct reg_parse_fd_opt
  603. reg_parse_fd_opt(void* mem_ctx, const char* options)
  604. {
  605. struct reg_parse_fd_opt ret = {
  606. .file_enc = NULL,
  607. .str_enc = NULL,
  608. .flags = 0,
  609. };
  610. void* ctx = talloc_new(mem_ctx);
  611. char *key, *val;
  612. if (options == NULL) {
  613. goto done;
  614. }
  615. while (srprs_option(&options, ctx, &key, &val)) {
  616. if (strcmp(key, "enc") == 0) {
  617. ret.file_enc = talloc_steal(mem_ctx, val);
  618. ret.str_enc = ret.file_enc;
  619. } else if (strcmp(key, "strenc") == 0) {
  620. ret.str_enc = talloc_steal(mem_ctx, val);
  621. } else if (strcmp(key, "fileenc") == 0) {
  622. ret.file_enc = talloc_steal(mem_ctx, val);
  623. } else if ((strcmp(key, "flags") == 0) && (val != NULL)) {
  624. char* end = NULL;
  625. if (val != NULL) {
  626. ret.flags = strtol(val, &end, 0);
  627. }
  628. if ((end==NULL) || (*end != '\0')) {
  629. DEBUG(0, ("Invalid format \"%s\": %s\n",
  630. key, val ? val : "<NULL>"));
  631. }
  632. } else if ((strcmp(key, "fail") == 0) && (val != NULL)) {
  633. char* end = NULL;
  634. if (val != NULL) {
  635. ret.fail_level = -strtol(val, &end, 0);
  636. }
  637. if ((end==NULL) || (*end != '\0')) {
  638. DEBUG(0, ("Invalid format \"%s\": %s\n",
  639. key, val ? val : "<NULL>"));
  640. }
  641. }
  642. }
  643. done:
  644. talloc_free(ctx);
  645. return ret;
  646. }
  647. static void
  648. handle_iconv_errno(int err, const char* obuf, size_t linenum,
  649. smb_iconv_t cd, const char** iptr, size_t* ilen,
  650. char** optr, size_t *olen)
  651. {
  652. const char *pos = obuf;
  653. const char *ptr = obuf;
  654. switch(err) {
  655. case EINVAL:
  656. /* DEBUG(0, ("Incomplete multibyte sequence\n")); */
  657. case E2BIG:
  658. return;
  659. case EILSEQ:
  660. break;
  661. default:
  662. assert(false);
  663. }
  664. **optr = '\0';
  665. while (srprs_line(&ptr, NULL) && srprs_nl(&ptr, NULL)) {
  666. pos = ptr;
  667. linenum++;
  668. }
  669. if (pos == *optr) {
  670. pos = MAX(obuf, *optr-60);
  671. }
  672. DEBUG(0, ("Illegal multibyte sequence at line %lu: %s",
  673. (long unsigned)(linenum+1), pos));
  674. assert((*ilen) > 0);
  675. do {
  676. size_t il = 1;
  677. DEBUGADD(0, ("<%02x>", (unsigned char)**iptr));
  678. if ((*olen) > 0) {
  679. *(*optr)++ = '\?';
  680. (*iptr)++;
  681. /* Todo: parametrize, e.g. skip: *optr++ = *iptr++; */
  682. (*ilen)--;
  683. }
  684. if (smb_iconv(cd, iptr, &il, optr, olen) != (size_t)-1 || (errno != EILSEQ)) {
  685. if(il == 0)
  686. (*ilen)-- ;
  687. break;
  688. }
  689. }
  690. while ((*ilen > 0) && (*olen > 0));
  691. DEBUGADD(0, ("\n"));
  692. }
  693. int reg_parse_fd(int fd, const struct reg_parse_callback* cb, const char* opts)
  694. {
  695. void* mem_ctx = talloc_stackframe();
  696. cbuf* line = cbuf_new(mem_ctx);
  697. smb_iconv_t cd = (smb_iconv_t)-1;
  698. struct reg_parse* parser = NULL;
  699. char buf_raw[1024];
  700. char buf_unix[1025];
  701. ssize_t nread;
  702. size_t nconv;
  703. const char* pos;
  704. const char* iptr;
  705. char* optr;
  706. size_t ilen;
  707. size_t olen;
  708. int ret = -1;
  709. bool eof = false;
  710. size_t linenum = 0;
  711. struct reg_parse_fd_opt opt = reg_parse_fd_opt(mem_ctx, opts);
  712. if (cb == NULL) {
  713. DEBUG(0,("reg_parse_fd: NULL callback\n"));
  714. goto done;
  715. }
  716. nread = read(fd, buf_raw, sizeof(buf_raw));
  717. if (nread < 0) {
  718. DEBUG(0, ("reg_parse_fd: read failed: %s\n", strerror(errno)));
  719. ret = nread;
  720. goto done;
  721. }
  722. iptr = &buf_raw[0];
  723. ilen = nread;
  724. if (!guess_charset(&iptr, &ilen,
  725. &opt.file_enc, &opt.str_enc))
  726. {
  727. DEBUG(0, ("reg_parse_fd: failed to guess encoding\n"));
  728. goto done;
  729. }
  730. DEBUG(10, ("reg_parse_fd: encoding file: %s str: %s\n",
  731. opt.file_enc, opt.str_enc));
  732. if (!set_iconv(&cd, "unix", opt.file_enc)) {
  733. DEBUG(0, ("reg_parse_fd: failed to set file encoding %s\n",
  734. opt.file_enc));
  735. goto done;
  736. }
  737. parser = reg_parse_new(mem_ctx, *cb, opt.str_enc, opt.flags);
  738. optr = &buf_unix[0];
  739. while (!eof) {
  740. olen = sizeof(buf_unix) - (optr - buf_unix) - 1 ;
  741. while ( olen > 0 ) {
  742. memmove(buf_raw, iptr, ilen);
  743. nread = read(fd, buf_raw + ilen, sizeof(buf_raw) - ilen);
  744. if (nread < 0) {
  745. DEBUG(0, ("reg_parse_fd: read failed: %s\n", strerror(errno)));
  746. ret = nread;
  747. goto done;
  748. }
  749. iptr = buf_raw;
  750. ilen += nread;
  751. if (ilen == 0) {
  752. smb_iconv(cd, NULL, NULL, &optr, &olen);
  753. eof = true;
  754. break;
  755. }
  756. nconv = smb_iconv(cd, &iptr, &ilen, &optr, &olen);
  757. if (nconv == (size_t)-1) {
  758. handle_iconv_errno(errno, buf_unix, linenum,
  759. cd, &iptr, &ilen,
  760. &optr, &olen);
  761. break;
  762. }
  763. }
  764. /* process_lines: */
  765. *optr = '\0';
  766. pos = &buf_unix[0];
  767. while ( srprs_line(&pos, line) && srprs_nl_no_eos(&pos, line, eof)) {
  768. linenum ++;
  769. ret = reg_parse_line(parser, cbuf_gets(line, 0));
  770. if (ret < opt.fail_level) {
  771. goto done;
  772. }
  773. cbuf_clear(line);
  774. }
  775. memmove(buf_unix, pos, optr - pos);
  776. optr -= (pos - buf_unix);
  777. }
  778. ret = 0;
  779. done:
  780. set_iconv(&cd, NULL, NULL);
  781. talloc_free(mem_ctx);
  782. return ret;
  783. }
  784. int reg_parse_file(const char* fname, const struct reg_parse_callback* cb,
  785. const char* opt)
  786. {
  787. int ret = -1;
  788. int fd;
  789. fd = open(fname, O_RDONLY);
  790. if (fd < 0) {
  791. DEBUG(0, ("reg_parse_file: open failed: %s\n", strerror(errno)));
  792. return -1;
  793. }
  794. ret = reg_parse_fd(fd, cb, opt);
  795. close(fd);
  796. return ret;
  797. }
  798. /* static struct registry_key *find_regkey_by_hnd(pipes_struct *p, */
  799. /* struct policy_handle *hnd) */
  800. /* { */
  801. /* struct registry_key *regkey = NULL; */
  802. /* if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) { */
  803. /* DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: ")); */
  804. /* return NULL; */
  805. /* } */
  806. /* return regkey; */
  807. /* } */