source: trunk/src/reglookup.c @ 49

Last change on this file since 49 was 48, checked in by tim, 19 years ago

fixed segfault when valuenames are NULL

  • Property svn:keywords set to Id
File size: 21.2 KB
RevLine 
[30]1/*
[42]2 * A utility to read a Windows NT/2K/XP/2K3 registry file, using
3 * Gerald Carter''s regfio interface.
[30]4 *
5 * Copyright (C) 2005 Timothy D. Morgan
[42]6 * Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
[30]7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
20 *
21 * $Id: reglookup.c 48 2005-08-06 22:05:18Z tim $
22 */
23
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
[33]28#include <strings.h>
[42]29#include <time.h>
[30]30#include "../include/regfio.h"
[31]31#include "../include/void_stack.h"
[30]32
[40]33/* Globals, influenced by command line parameters */
34bool print_verbose = false;
35bool print_security = false;
[42]36bool print_header = true;
[40]37bool path_filter_enabled = false;
38bool type_filter_enabled = false;
39char* path_filter = NULL;
40int type_filter;
41char* registry_file = NULL;
42
[42]43/* Other globals */
44const char* special_chars = ",\"\\";
[40]45
[38]46void bailOut(int code, char* message)
47{
48  fprintf(stderr, message);
49  exit(code);
50}
51
52
[41]53/* Returns a newly malloc()ed string which contains original buffer,
54 * except for non-printable or special characters are quoted in hex
55 * with the syntax '\xQQ' where QQ is the hex ascii value of the quoted
56 * character.  A null terminator is added, as only ascii, not binary,
57 * is returned.
58 */
59static char* quote_buffer(const unsigned char* str, 
[44]60                          unsigned int len, const char* special)
[41]61{
62  unsigned int i;
63  unsigned int num_written=0;
64  unsigned int out_len = sizeof(char)*len+1;
65  char* ret_val = malloc(out_len);
66
67  if(ret_val == NULL)
68    return NULL;
69
70  for(i=0; i<len; i++)
71  {
72    if(str[i] < 32 || str[i] > 126 || strchr(special, str[i]) != NULL)
73    {
74      out_len += 3;
75      /* XXX: may not be the most efficient way of getting enough memory. */
76      ret_val = realloc(ret_val, out_len);
77      if(ret_val == NULL)
78        break;
79      num_written += snprintf(ret_val+num_written, (out_len)-num_written,
80                              "\\x%.2X", str[i]);
81    }
82    else
83      ret_val[num_written++] = str[i];
84  }
85  ret_val[num_written] = '\0';
86
87  return ret_val;
88}
89
90
91/* Returns a newly malloc()ed string which contains original string,
92 * except for non-printable or special characters are quoted in hex
93 * with the syntax '\xQQ' where QQ is the hex ascii value of the quoted
94 * character.
95 */
[44]96static char* quote_string(const char* str, const char* special)
[41]97{
[42]98  unsigned int len;
[41]99
[42]100  if(str == NULL)
101    return NULL;
102
103  len = strlen(str);
104  return quote_buffer((const unsigned char*)str, len, special);
[41]105}
106
107
108/*
109 * Convert from UniCode to Ascii ... Does not take into account other lang
110 * Restrict by ascii_max if > 0
111 */
112static int uni_to_ascii(unsigned char *uni, unsigned char *ascii, 
113                        int ascii_max, int uni_max)
114{
115  int i = 0; 
116
117  while (i < ascii_max && (uni[i*2] || uni[i*2+1]))
118  {
119    if (uni_max > 0 && (i*2) >= uni_max) break;
120    ascii[i] = uni[i*2];
121    i++;
122  }
123  ascii[i] = '\0';
124
125  return i;
126}
127
128
129/*
130 * Convert a data value to a string for display
131 */
132static unsigned char* data_to_ascii(unsigned char *datap, int len, int type)
133{
134  unsigned char *asciip;
135  unsigned int i;
136  unsigned short num_nulls;
137  unsigned char* ascii;
138  unsigned char* cur_str;
139  unsigned char* cur_ascii;
140  char* cur_quoted;
141  unsigned int cur_str_len;
142  unsigned int ascii_max, cur_str_max;
143  unsigned int str_rem, cur_str_rem, alen;
144
145  switch (type) 
146  {
147  case REG_SZ:
148    if (print_verbose)
149      fprintf(stderr, "Len: %d\n", len);
150   
151    ascii_max = sizeof(char)*len;
152    ascii = malloc(ascii_max+4);
153    if(ascii == NULL)
154      return NULL;
155   
156    /* XXX: This has to be fixed. It has to be UNICODE */
157    uni_to_ascii(datap, ascii, len, ascii_max);
[42]158    cur_quoted = quote_string((char*)ascii, special_chars);
159    free(ascii);
160    return (unsigned char*)cur_quoted;
[41]161    break;
162
163  case REG_EXPAND_SZ:
164    ascii_max = sizeof(char)*len;
165    ascii = malloc(ascii_max+2);
166    if(ascii == NULL)
167      return NULL;
168
169    uni_to_ascii(datap, ascii, len, ascii_max);
[42]170    cur_quoted = quote_string((char*)ascii, special_chars);
171    free(ascii);
172    return (unsigned char*)cur_quoted;
[41]173    break;
174
175  case REG_DWORD:
176    ascii_max = sizeof(char)*10;
177    ascii = malloc(ascii_max+1);
178    if(ascii == NULL)
179      return NULL;
180
181    if (*(int *)datap == 0)
182      snprintf((char*)ascii, ascii_max, "0");
183    else
184      snprintf((char*)ascii, ascii_max, "0x%x", *(int *)datap);
185    return ascii;
186    break;
187
[42]188  /* XXX: this MULTI_SZ parser is pretty inefficient.  Should be
189   *      redone with fewer malloc and better string concatenation.
190   */
[41]191  case REG_MULTI_SZ:
192    ascii_max = sizeof(char)*len*4;
193    cur_str_max = sizeof(char)*len+1;
194    cur_str = malloc(cur_str_max);
195    cur_ascii = malloc(cur_str_max);
196    ascii = malloc(ascii_max+4);
[42]197    if(ascii == NULL || cur_str == NULL || cur_ascii == NULL)
[41]198      return NULL;
199
200    /* Reads until it reaches 4 consecutive NULLs,
201     * which is two nulls in unicode, or until it reaches len, or until we
202     * run out of buffer.  The latter should never happen, but we shouldn't
203     * trust our file to have the right lengths/delimiters.
204     */
205    asciip = ascii;
206    num_nulls = 0;
207    str_rem = ascii_max;
208    cur_str_rem = cur_str_max;
209    cur_str_len = 0;
210
211    for(i=0; (i < len) && str_rem > 0; i++)
212    {
213      *(cur_str+cur_str_len) = *(datap+i);
214      if(*(cur_str+cur_str_len) == 0)
215        num_nulls++;
216      else
217        num_nulls = 0;
218      cur_str_len++;
219
220      if(num_nulls == 2)
221      {
222        uni_to_ascii(cur_str, cur_ascii, cur_str_max, 0);
[42]223        cur_quoted = quote_string((char*)cur_ascii, ",|\"\\");
[41]224        alen = snprintf((char*)asciip, str_rem, "%s", cur_quoted);
225        asciip += alen;
226        str_rem -= alen;
227        free(cur_quoted);
228
229        if(*(datap+i+1) == 0 && *(datap+i+2) == 0)
230          break;
231        else
232        {
233          alen = snprintf((char*)asciip, str_rem, "%c", '|');
234          asciip += alen;
235          str_rem -= alen;
236          memset(cur_str, 0, cur_str_max);
237          cur_str_len = 0;
238          num_nulls = 0;
239          /* To eliminate leading nulls in subsequent strings. */
240          i++;
241        }
242      }
243    }
244    *asciip = 0;
[42]245    free(cur_str);
246    free(cur_ascii);
[41]247    return ascii;
248    break;
249
[42]250  /* XXX: Dont know what to do with these yet, just print as binary... */
251  case REG_RESOURCE_LIST:
252  case REG_FULL_RESOURCE_DESCRIPTOR:
253  case REG_RESOURCE_REQUIREMENTS_LIST:
254
255  case REG_BINARY:
256    return (unsigned char*)quote_buffer(datap, len, special_chars);
257    break;
258
[41]259  default:
260    return NULL;
261    break;
262  } 
263
264  return NULL;
265}
266
267
[42]268/* Security descriptor print functions  */
[43]269/* XXX: these functions should be moved out into regfio library */
[42]270const char* ace_type2str(uint8 type)
271{
272  static const char* map[7] 
273    = {"ALLOW", "DENY", "AUDIT", "ALARM", 
274       "ALLOW CPD", "OBJ ALLOW", "OBJ DENY"};
275  if(type < 7)
276    return map[type];
277  else
278    return "UNKNOWN";
279}
280
281
282char* ace_flags2str(uint8 flags)
283{
284  char* flg_output = malloc(21*sizeof(char));
285  int some = 0;
286
287  if(flg_output == NULL)
288    return NULL;
289
290  flg_output[0] = '\0';
291  if (!flags)
292    return flg_output;
293
294  if (flags & 0x01) {
295    if (some) strcat(flg_output, " ");
296    some = 1;
297    strcat(flg_output, "OI");
298  }
299  if (flags & 0x02) {
300    if (some) strcat(flg_output, " ");
301    some = 1;
302    strcat(flg_output, "CI");
303  }
304  if (flags & 0x04) {
305    if (some) strcat(flg_output, " ");
306    some = 1;
307    strcat(flg_output, "NP");
308  }
309  if (flags & 0x08) {
310    if (some) strcat(flg_output, " ");
311    some = 1;
312    strcat(flg_output, "IO");
313  }
314  if (flags & 0x10) {
315    if (some) strcat(flg_output, " ");
316    some = 1;
317    strcat(flg_output, "IA");
318  }
319  if (flags == 0xF) {
320    if (some) strcat(flg_output, " ");
321    some = 1;
322    strcat(flg_output, "VI");
323  }
324
325  return flg_output;
326}
327
328
329char* ace_perms2str(uint32 perms)
330{
331  char* ret_val = malloc(9*sizeof(char));
[43]332  sprintf(ret_val, "%.8X", perms);
[42]333
334  return ret_val;
335}
336
337
338char* sid2str(DOM_SID* sid)
339{
340  uint32 i, size = MAXSUBAUTHS*11 + 24;
341  uint32 left = size;
342  uint8 comps = sid->num_auths;
343  char* ret_val = malloc(size);
344 
345  if(ret_val == NULL)
346    return NULL;
347
348  if(comps > MAXSUBAUTHS)
349    comps = MAXSUBAUTHS;
350
351  left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
352
353  for (i = 0; i < comps; i++) 
354    left -= snprintf(ret_val+(size-left), left, "-%u", sid->sub_auths[i]);
355
356  return ret_val;
357}
358
359
360char* get_acl(SEC_ACL* acl)
361{
362  uint32 i, extra, size = 0;
363  const char* type_str;
364  char* flags_str;
365  char* perms_str;
366  char* sid_str;
367  char* ret_val = NULL;
368  char* ace_delim = "";
369  char field_delim = ':';
370
371  for (i = 0; i < acl->num_aces; i++)
372  {
373    /* XXX: check for NULL */
374    sid_str = sid2str(&acl->ace[i].trustee);
375    type_str = ace_type2str(acl->ace[i].type);
376    perms_str = ace_perms2str(acl->ace[i].info.mask);
377    flags_str = ace_flags2str(acl->ace[i].flags);
378
379    /* XXX: this is slow */
380    extra = strlen(sid_str) + strlen(type_str) 
[43]381          + strlen(perms_str) + strlen(flags_str)+5;
382    ret_val = realloc(ret_val, size+extra);
[42]383    if(ret_val == NULL)
384      return NULL;
[43]385    size += snprintf(ret_val+size, extra, "%s%s%c%s%c%s%c%s",
386                     ace_delim,sid_str,
387                     field_delim,type_str,
388                     field_delim,perms_str,
389                     field_delim,flags_str);
[42]390    ace_delim = "|";
391    free(sid_str);
392    free(perms_str);
393    free(flags_str);
394  }
395
396  return ret_val;
397}
398
399
400char* get_sacl(SEC_DESC *sec_desc)
401{
402  if (sec_desc->sacl)
403    return get_acl(sec_desc->sacl);
404  else
[43]405    return NULL;
[42]406}
407
408
409char* get_dacl(SEC_DESC *sec_desc)
410{
411  if (sec_desc->dacl)
412    return get_acl(sec_desc->dacl);
413  else
[43]414    return NULL;
[42]415}
416
417
418char* get_owner(SEC_DESC *sec_desc)
419{
420  return sid2str(sec_desc->owner_sid);
421}
422
423
424char* get_group(SEC_DESC *sec_desc)
425{
426  return sid2str(sec_desc->grp_sid);
427}
428
429
[33]430void_stack* path2Stack(const char* s)
[30]431{
[38]432  void_stack* ret_val;
433  void_stack* rev_ret = void_stack_new(1024);
434  const char* cur = s;
[33]435  char* next = NULL;
[38]436  char* copy;
437
438  if (rev_ret == NULL)
439    return NULL;
[37]440  if (s == NULL)
[38]441    return rev_ret;
442 
443  while((next = strchr(cur, '/')) != NULL)
[33]444  {
[38]445    if ((next-cur) > 0)
446    {
447      copy = (char*)malloc((next-cur+1)*sizeof(char));
448      if(copy == NULL)
449        bailOut(2, "ERROR: Memory allocation problem.\n");
450         
451      memcpy(copy, cur, next-cur);
452      copy[next-cur] = '\0';
453      void_stack_push(rev_ret, copy);
454    }
455    cur = next+1;
[33]456  }
457  if(strlen(cur) > 0)
[38]458  {
459    copy = strdup(cur);
460    void_stack_push(rev_ret, copy);
461  }
[33]462
[38]463  ret_val = void_stack_copy_reverse(rev_ret);
464  void_stack_destroy(rev_ret);
465
[33]466  return ret_val;
467}
468
469
470char* stack2Path(void_stack* nk_stack)
471{
472  const REGF_NK_REC* cur;
[37]473  uint32 buf_left = 127;
474  uint32 buf_len = buf_left+1;
475  uint32 name_len = 0;
476  uint32 grow_amt;
[31]477  char* buf; 
478  char* new_buf;
479  void_stack_iterator* iter;
480 
481  buf = (char*)malloc((buf_len)*sizeof(char));
482  if (buf == NULL)
483    return NULL;
[43]484  buf[0] = '/';
485  buf[1] = '\0';
[30]486
[31]487  iter = void_stack_iterator_new(nk_stack);
488  if (iter == NULL)
[30]489  {
[31]490    free(buf);
491    return NULL;
[30]492  }
493
[33]494  /* skip root element */
495  cur = void_stack_iterator_next(iter);
496
[31]497  while((cur = void_stack_iterator_next(iter)) != NULL)
498  {
[33]499    buf[buf_len-buf_left-1] = '/';
500    buf_left -= 1;
[31]501    name_len = strlen(cur->keyname);
502    if(name_len+1 > buf_left)
503    {
[37]504      grow_amt = (uint32)(buf_len/2);
[31]505      buf_len += name_len+1+grow_amt-buf_left;
506      if((new_buf = realloc(buf, buf_len)) == NULL)
507      {
508        free(buf);
509        free(iter);
510        return NULL;
511      }
512      buf = new_buf;
513      buf_left = grow_amt + name_len + 1;
514    }
515    strncpy(buf+(buf_len-buf_left-1), cur->keyname, name_len);
516    buf_left -= name_len;
517    buf[buf_len-buf_left-1] = '\0';
518  }
[30]519
[31]520  return buf;
521}
[30]522
[31]523
[33]524void printValue(REGF_VK_REC* vk, char* prefix)
[31]525{
[41]526  uint32 size;
527  uint8 tmp_buf[4];
[42]528  unsigned char* quoted_value;
529  char* quoted_prefix;
530  char* quoted_name;
[41]531
[43]532  /* Thanks Microsoft for making this process so straight-forward!!! */
533  size = (vk->data_size & ~VK_DATA_IN_OFFSET);
534  if(vk->data_size & VK_DATA_IN_OFFSET)
[41]535  {
[43]536    tmp_buf[0] = (uint8)((vk->data_off >> 3) & 0xFF);
537    tmp_buf[1] = (uint8)((vk->data_off >> 2) & 0xFF);
538    tmp_buf[2] = (uint8)((vk->data_off >> 1) & 0xFF);
539    tmp_buf[3] = (uint8)(vk->data_off & 0xFF);
540    if(size > 4)
541      size = 4;
542    quoted_value = data_to_ascii(tmp_buf, 4, vk->type);
543  }
544  else
545  {
546    /* XXX: This is a safety hack.  No data fields have yet been found
547     * larger, but length limits are probably better got from fields
548     * in the registry itself, within reason.
549     */
550    if(size > 16384)
[41]551    {
[43]552      fprintf(stderr, "WARNING: key size %d larger than "
553              "16384, truncating...\n", size);
554      size = 16384;
[41]555    }
[43]556    quoted_value = data_to_ascii(vk->data, vk->data_size, vk->type);
557  }
558 
559  /* XXX: Sometimes value names can be NULL in registry.  Need to
560   *      figure out why and when, and generate the appropriate output
561   *      for that condition.
562   */
563  quoted_prefix = quote_string(prefix, special_chars);
564  quoted_name = quote_string(vk->valuename, special_chars);
565 
566  if(print_security)
[42]567    printf("%s/%s,%s,%s,,,,,\n", quoted_prefix, quoted_name,
[41]568           regfio_type_val2str(vk->type), quoted_value);
[43]569  else
570    printf("%s/%s,%s,%s,\n", quoted_prefix, quoted_name,
571           regfio_type_val2str(vk->type), quoted_value);
572 
573  if(quoted_value != NULL)
574    free(quoted_value);
575  if(quoted_prefix != NULL)
576    free(quoted_prefix);
577  if(quoted_name != NULL)
578    free(quoted_name);
[32]579}
580
581
[33]582void printValueList(REGF_NK_REC* nk, char* prefix)
[32]583{
[37]584  uint32 i;
[33]585 
586  for(i=0; i < nk->num_values; i++)
[43]587    if(!type_filter_enabled || (nk->values[i].type == type_filter))
588      printValue(&nk->values[i], prefix);
[33]589}
590
[37]591
[43]592void printKey(REGF_NK_REC* k, char* full_path)
[33]593{
[43]594  static char empty_str[1] = "";
[42]595  char* owner = NULL;
596  char* group = NULL;
597  char* sacl = NULL;
598  char* dacl = NULL;
599  char mtime[20];
600  time_t tmp_time[1];
601  struct tm* tmp_time_s = NULL;
602
[43]603  *tmp_time = nt_time_to_unix(&k->mtime);
604  tmp_time_s = gmtime(tmp_time);
605  strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
606
607  if(print_security)
608  {
609    owner = get_owner(k->sec_desc->sec_desc);
610    group = get_group(k->sec_desc->sec_desc);
611    sacl = get_sacl(k->sec_desc->sec_desc);
612    dacl = get_dacl(k->sec_desc->sec_desc);
613    if(owner == NULL)
614      owner = empty_str;
615    if(group == NULL)
616      group = empty_str;
617    if(sacl == NULL)
618      sacl = empty_str;
619    if(dacl == NULL)
620      dacl = empty_str;
621
622    printf("%s,KEY,,%s,%s,%s,%s,%s\n", full_path, mtime, 
623           owner, group, sacl, dacl);
624
625    if(owner != empty_str)
626      free(owner);
627    if(group != empty_str)
628      free(group);
629    if(sacl != empty_str)
630      free(sacl);
631    if(dacl != empty_str)
632      free(dacl);
633  }
634  else
635    printf("%s,KEY,,%s\n", full_path, mtime);
636}
637
638
639/* XXX: this function is god-awful.  Needs to be re-designed. */
640void printKeyTree(REGF_FILE* f, void_stack* nk_stack, char* prefix)
641{
642  REGF_NK_REC* cur;
643  REGF_NK_REC* sub;
644  char* path = NULL;
645  char* val_path = NULL;
646
[41]647  int key_type = regfio_type_str2val("KEY");
[43]648 
[32]649  if((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
[31]650  {
[33]651    cur->subkey_index = 0;
652    path = stack2Path(nk_stack);
653   
[43]654
655    val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
656    sprintf(val_path, "%s%s", prefix, path);
657    if(!type_filter_enabled || (key_type == type_filter))
658      printKey(cur, val_path);
659
[40]660    if(!type_filter_enabled || (key_type != type_filter))
[43]661      printValueList(cur, val_path);
662    if(val_path != NULL)
663      free(val_path);
[32]664    while((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
[31]665    {
[32]666      if((sub = regfio_fetch_subkey(f, cur)) != NULL)
[31]667      {
[33]668        sub->subkey_index = 0;
[32]669        void_stack_push(nk_stack, sub);
[33]670        path = stack2Path(nk_stack);
[32]671        if(path != NULL)
672        {
[33]673          val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
674          sprintf(val_path, "%s%s", prefix, path);
[40]675          if(!type_filter_enabled || (key_type == type_filter))
[43]676            printKey(sub, val_path);
[40]677          if(!type_filter_enabled || (key_type != type_filter))
678            printValueList(sub, val_path);
[42]679          if(val_path != NULL)
680            free(val_path);
[32]681        }
[31]682      }
[32]683      else
684      {
685        cur = void_stack_pop(nk_stack);
686        /* XXX: This is just a shallow free.  Need to write deep free
687         * routines to replace the Samba code for this.
688         */ 
[39]689        if(cur != NULL)
690          free(cur);
[32]691      }
[31]692    }
693  }
[30]694}
695
696
[33]697/*
698 * Returns 0 if path was found.
699 * Returns 1 if path was not found.
700 * Returns less than 0 on other error.
701 */
702int retrievePath(REGF_FILE* f, void_stack* nk_stack,
703                 void_stack* path_stack)
704{
705  REGF_NK_REC* sub; 
706  REGF_NK_REC* cur;
707  void_stack* sub_nk_stack;
708  char* prefix;
709  char* cur_str = NULL;
710  bool found_cur = true;
[37]711  uint32 i;
712  uint16 path_depth;
[33]713  if(path_stack == NULL)
714    return -1;
715
716  path_depth = void_stack_size(path_stack);
717  if(path_depth < 1)
718    return -2;
719
720  if(void_stack_size(nk_stack) < 1)
721    return -3;
722  cur = (REGF_NK_REC*)void_stack_cur(nk_stack);
723
724  while(void_stack_size(path_stack) > 1)
725  {
726    /* Search key records only */
727    cur_str = (char*)void_stack_pop(path_stack);
728
729    found_cur = false;
730    while(!found_cur &&
731          (sub = regfio_fetch_subkey(f, cur)) != NULL)
732    {
733      if(strcasecmp(sub->keyname, cur_str) == 0)
734      {
735        cur = sub;
736        void_stack_push(nk_stack, sub);
737        found_cur = true;
738      }
739    }
[39]740    free(cur_str);
[33]741
742    if(!found_cur)
[37]743      return 1;
[33]744  }
745
746  /* Last round, search value and key records */
747  cur_str = (char*)void_stack_pop(path_stack);
748
749  for(i=0; (i < cur->num_values); i++)
750  {
[48]751    /* XXX: Not sure when/why this can be NULL, but it's happened. */
752    if(sub->values[i].valuename != NULL 
753       && strcasecmp(sub->values[i].valuename, cur_str) == 0)
[33]754    {
[43]755      /* XXX: fix mem leak with stack2Path return value */
[33]756      printValue(&sub->values[i], stack2Path(nk_stack));
757      return 0;
758    }
759  }
760
761  while((sub = regfio_fetch_subkey(f, cur)) != NULL)
762  {
763    if(strcasecmp(sub->keyname, cur_str) == 0)
764    {
765      sub_nk_stack = void_stack_new(1024);
766      void_stack_push(sub_nk_stack, sub);
767      void_stack_push(nk_stack, sub);
768      prefix = stack2Path(nk_stack);
769      printKeyTree(f, sub_nk_stack, prefix);
770      return 0;
771    }
772  }
773
774  return 1;
775}
776
777
[37]778static void usage(void)
779{
[39]780  fprintf(stderr, "Usage: readreg [-v] [-s]"
[40]781          " [-p <PATH_FILTER>] [-t <TYPE_FILTER>]"
[39]782          " <REGISTRY_FILE>\n");
[37]783  /* XXX: replace version string with Subversion property? */
784  fprintf(stderr, "Version: 0.2\n");
[39]785  fprintf(stderr, "Options:\n");
786  fprintf(stderr, "\t-v\t sets verbose mode.\n");
[47]787  fprintf(stderr, "\t-h\t enables header row. (default)\n");
788  fprintf(stderr, "\t-H\t disables header row.\n");
[44]789  fprintf(stderr, "\t-s\t enables security descriptor output.\n");
790  fprintf(stderr, "\t-S\t disables security descriptor output. (default)\n");
[40]791  fprintf(stderr, "\t-p\t restrict output to elements below this path.\n");
792  fprintf(stderr, "\t-t\t restrict results to this specific data type.\n");
[37]793  fprintf(stderr, "\n");
794}
795
796
[30]797int main(int argc, char** argv)
798{
[31]799  void_stack* nk_stack;
[33]800  void_stack* path_stack;
[31]801  REGF_FILE* f;
802  REGF_NK_REC* root;
[33]803  int retr_path_ret;
[44]804  uint32 argi, arge;
[31]805
[37]806  /* Process command line arguments */
[30]807  if(argc < 2)
808  {
[37]809    usage();
[44]810    bailOut(1, "ERROR: Requires at least one argument.\n");
[30]811  }
[37]812 
[44]813  arge = argc-1;
814  for(argi = 1; argi < arge; argi++)
[37]815  {
[40]816    if (strcmp("-p", argv[argi]) == 0)
[37]817    {
[44]818      if(++argi >= arge)
[37]819      {
820        usage();
[40]821        bailOut(1, "ERROR: '-p' option requires parameter.\n");
[37]822      }
[40]823      if((path_filter = strdup(argv[argi])) == NULL)
[38]824        bailOut(2, "ERROR: Memory allocation problem.\n");
825
[40]826      path_filter_enabled = true;
[37]827    }
828    else if (strcmp("-t", argv[argi]) == 0)
829    {
[44]830      if(++argi >= arge)
[37]831      {
832        usage();
[38]833        bailOut(1, "ERROR: '-t' option requires parameter.\n");
[37]834      }
[41]835      if((type_filter = regfio_type_str2val(argv[argi])) == 0)
[40]836      {
837        fprintf(stderr, "ERROR: Invalid type specified: %s.\n", argv[argi]);
838        bailOut(1, "");
839      }
[38]840
[37]841      type_filter_enabled = true;
842    }
[47]843    else if (strcmp("-h", argv[argi]) == 0)
844      print_header = true;
845    else if (strcmp("-H", argv[argi]) == 0)
846      print_header = false;
[37]847    else if (strcmp("-s", argv[argi]) == 0)
848      print_security = true;
[44]849    else if (strcmp("-S", argv[argi]) == 0)
850      print_security = false;
[37]851    else if (strcmp("-v", argv[argi]) == 0)
852      print_verbose = true;
[44]853    else
[37]854    {
[38]855      usage();
[37]856      fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
[38]857      bailOut(1, "");
[37]858    }
859  }
[44]860  if((registry_file = strdup(argv[argi])) == NULL)
861    bailOut(2, "ERROR: Memory allocation problem.\n");
[30]862
[37]863  f = regfio_open(registry_file);
864  if(f == NULL)
865  {
866    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
[38]867    bailOut(3, "");
[37]868  }
[38]869
[31]870  root = regfio_rootkey(f);
[37]871  nk_stack = void_stack_new(1024);
[30]872
[31]873  if(void_stack_push(nk_stack, root))
[33]874  {
[42]875    if(print_header)
[43]876    {
877      if(print_security)
878        printf("PATH,TYPE,VALUE,MTIME,OWNER,GROUP,SACL,DACL\n");
879      else
880        printf("PATH,TYPE,VALUE,MTIME\n");
881    }
[42]882
[40]883    path_stack = path2Stack(path_filter);
[33]884    if(void_stack_size(path_stack) < 1)
885      printKeyTree(f, nk_stack, "");
886    else
887    {
[37]888      retr_path_ret = retrievePath(f, nk_stack, path_stack);
[33]889      if(retr_path_ret == 1)
[37]890        fprintf(stderr, "WARNING: specified path not found.\n");
[33]891      else if(retr_path_ret != 0)
[38]892        bailOut(4, "ERROR:\n");
[33]893    }
894  }
[37]895  else
[38]896    bailOut(2, "ERROR: Memory allocation problem.\n");
[31]897
[38]898  void_stack_destroy_deep(nk_stack);
[30]899  regfio_close(f);
900
901  return 0;
902}
Note: See TracBrowser for help on using the repository browser.