source: trunk/src/reglookup.c @ 55

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

fixed a type filtering bug, and a verbosity print order bug

  • Property svn:keywords set to Id
File size: 19.4 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 55 2005-09-05 01:41:26Z 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    ascii_max = sizeof(char)*len;
149    ascii = malloc(ascii_max+4);
150    if(ascii == NULL)
151      return NULL;
152   
153    /* XXX: This has to be fixed. It has to be UNICODE */
154    uni_to_ascii(datap, ascii, len, ascii_max);
[42]155    cur_quoted = quote_string((char*)ascii, special_chars);
156    free(ascii);
157    return (unsigned char*)cur_quoted;
[41]158    break;
159
160  case REG_EXPAND_SZ:
161    ascii_max = sizeof(char)*len;
162    ascii = malloc(ascii_max+2);
163    if(ascii == NULL)
164      return NULL;
165
166    uni_to_ascii(datap, ascii, len, ascii_max);
[42]167    cur_quoted = quote_string((char*)ascii, special_chars);
168    free(ascii);
169    return (unsigned char*)cur_quoted;
[41]170    break;
171
172  case REG_DWORD:
173    ascii_max = sizeof(char)*10;
174    ascii = malloc(ascii_max+1);
175    if(ascii == NULL)
176      return NULL;
177
178    if (*(int *)datap == 0)
179      snprintf((char*)ascii, ascii_max, "0");
180    else
181      snprintf((char*)ascii, ascii_max, "0x%x", *(int *)datap);
182    return ascii;
183    break;
184
[42]185  /* XXX: this MULTI_SZ parser is pretty inefficient.  Should be
[54]186   *      redone with fewer malloc calls and better string concatenation.
[42]187   */
[41]188  case REG_MULTI_SZ:
189    ascii_max = sizeof(char)*len*4;
190    cur_str_max = sizeof(char)*len+1;
191    cur_str = malloc(cur_str_max);
192    cur_ascii = malloc(cur_str_max);
193    ascii = malloc(ascii_max+4);
[42]194    if(ascii == NULL || cur_str == NULL || cur_ascii == NULL)
[41]195      return NULL;
196
197    /* Reads until it reaches 4 consecutive NULLs,
198     * which is two nulls in unicode, or until it reaches len, or until we
199     * run out of buffer.  The latter should never happen, but we shouldn't
200     * trust our file to have the right lengths/delimiters.
201     */
202    asciip = ascii;
203    num_nulls = 0;
204    str_rem = ascii_max;
205    cur_str_rem = cur_str_max;
206    cur_str_len = 0;
207
208    for(i=0; (i < len) && str_rem > 0; i++)
209    {
210      *(cur_str+cur_str_len) = *(datap+i);
211      if(*(cur_str+cur_str_len) == 0)
212        num_nulls++;
213      else
214        num_nulls = 0;
215      cur_str_len++;
216
217      if(num_nulls == 2)
218      {
219        uni_to_ascii(cur_str, cur_ascii, cur_str_max, 0);
[42]220        cur_quoted = quote_string((char*)cur_ascii, ",|\"\\");
[41]221        alen = snprintf((char*)asciip, str_rem, "%s", cur_quoted);
222        asciip += alen;
223        str_rem -= alen;
224        free(cur_quoted);
225
226        if(*(datap+i+1) == 0 && *(datap+i+2) == 0)
227          break;
228        else
229        {
230          alen = snprintf((char*)asciip, str_rem, "%c", '|');
231          asciip += alen;
232          str_rem -= alen;
233          memset(cur_str, 0, cur_str_max);
234          cur_str_len = 0;
235          num_nulls = 0;
236          /* To eliminate leading nulls in subsequent strings. */
237          i++;
238        }
239      }
240    }
241    *asciip = 0;
[42]242    free(cur_str);
243    free(cur_ascii);
[41]244    return ascii;
245    break;
246
[42]247  /* XXX: Dont know what to do with these yet, just print as binary... */
248  case REG_RESOURCE_LIST:
249  case REG_FULL_RESOURCE_DESCRIPTOR:
250  case REG_RESOURCE_REQUIREMENTS_LIST:
251
252  case REG_BINARY:
253    return (unsigned char*)quote_buffer(datap, len, special_chars);
254    break;
255
[41]256  default:
257    return NULL;
258    break;
259  } 
260
261  return NULL;
262}
263
264
[33]265void_stack* path2Stack(const char* s)
[30]266{
[38]267  void_stack* ret_val;
268  void_stack* rev_ret = void_stack_new(1024);
269  const char* cur = s;
[33]270  char* next = NULL;
[38]271  char* copy;
272
273  if (rev_ret == NULL)
274    return NULL;
[37]275  if (s == NULL)
[38]276    return rev_ret;
277 
278  while((next = strchr(cur, '/')) != NULL)
[33]279  {
[38]280    if ((next-cur) > 0)
281    {
282      copy = (char*)malloc((next-cur+1)*sizeof(char));
283      if(copy == NULL)
284        bailOut(2, "ERROR: Memory allocation problem.\n");
285         
286      memcpy(copy, cur, next-cur);
287      copy[next-cur] = '\0';
288      void_stack_push(rev_ret, copy);
289    }
290    cur = next+1;
[33]291  }
292  if(strlen(cur) > 0)
[38]293  {
294    copy = strdup(cur);
295    void_stack_push(rev_ret, copy);
296  }
[33]297
[38]298  ret_val = void_stack_copy_reverse(rev_ret);
299  void_stack_destroy(rev_ret);
300
[33]301  return ret_val;
302}
303
304
305char* stack2Path(void_stack* nk_stack)
306{
307  const REGF_NK_REC* cur;
[37]308  uint32 buf_left = 127;
309  uint32 buf_len = buf_left+1;
310  uint32 name_len = 0;
311  uint32 grow_amt;
[31]312  char* buf; 
313  char* new_buf;
314  void_stack_iterator* iter;
315 
316  buf = (char*)malloc((buf_len)*sizeof(char));
317  if (buf == NULL)
318    return NULL;
[54]319  buf[0] = '\0';
[30]320
[31]321  iter = void_stack_iterator_new(nk_stack);
322  if (iter == NULL)
[30]323  {
[31]324    free(buf);
325    return NULL;
[30]326  }
327
[33]328  /* skip root element */
329  cur = void_stack_iterator_next(iter);
330
[31]331  while((cur = void_stack_iterator_next(iter)) != NULL)
332  {
[33]333    buf[buf_len-buf_left-1] = '/';
334    buf_left -= 1;
[31]335    name_len = strlen(cur->keyname);
336    if(name_len+1 > buf_left)
337    {
[37]338      grow_amt = (uint32)(buf_len/2);
[31]339      buf_len += name_len+1+grow_amt-buf_left;
340      if((new_buf = realloc(buf, buf_len)) == NULL)
341      {
342        free(buf);
343        free(iter);
344        return NULL;
345      }
346      buf = new_buf;
347      buf_left = grow_amt + name_len + 1;
348    }
349    strncpy(buf+(buf_len-buf_left-1), cur->keyname, name_len);
350    buf_left -= name_len;
351    buf[buf_len-buf_left-1] = '\0';
352  }
[30]353
[31]354  return buf;
355}
[30]356
[31]357
[33]358void printValue(REGF_VK_REC* vk, char* prefix)
[31]359{
[41]360  uint32 size;
361  uint8 tmp_buf[4];
[42]362  unsigned char* quoted_value;
363  char* quoted_prefix;
364  char* quoted_name;
[41]365
[43]366  /* Thanks Microsoft for making this process so straight-forward!!! */
367  size = (vk->data_size & ~VK_DATA_IN_OFFSET);
368  if(vk->data_size & VK_DATA_IN_OFFSET)
[41]369  {
[43]370    tmp_buf[0] = (uint8)((vk->data_off >> 3) & 0xFF);
371    tmp_buf[1] = (uint8)((vk->data_off >> 2) & 0xFF);
372    tmp_buf[2] = (uint8)((vk->data_off >> 1) & 0xFF);
373    tmp_buf[3] = (uint8)(vk->data_off & 0xFF);
374    if(size > 4)
375      size = 4;
376    quoted_value = data_to_ascii(tmp_buf, 4, vk->type);
377  }
378  else
379  {
380    /* XXX: This is a safety hack.  No data fields have yet been found
381     * larger, but length limits are probably better got from fields
382     * in the registry itself, within reason.
383     */
384    if(size > 16384)
[41]385    {
[43]386      fprintf(stderr, "WARNING: key size %d larger than "
387              "16384, truncating...\n", size);
388      size = 16384;
[41]389    }
[43]390    quoted_value = data_to_ascii(vk->data, vk->data_size, vk->type);
391  }
392 
393  /* XXX: Sometimes value names can be NULL in registry.  Need to
394   *      figure out why and when, and generate the appropriate output
395   *      for that condition.
396   */
397  quoted_prefix = quote_string(prefix, special_chars);
398  quoted_name = quote_string(vk->valuename, special_chars);
399 
400  if(print_security)
[42]401    printf("%s/%s,%s,%s,,,,,\n", quoted_prefix, quoted_name,
[41]402           regfio_type_val2str(vk->type), quoted_value);
[43]403  else
404    printf("%s/%s,%s,%s,\n", quoted_prefix, quoted_name,
405           regfio_type_val2str(vk->type), quoted_value);
406 
407  if(quoted_value != NULL)
408    free(quoted_value);
409  if(quoted_prefix != NULL)
410    free(quoted_prefix);
411  if(quoted_name != NULL)
412    free(quoted_name);
[32]413}
414
415
[33]416void printValueList(REGF_NK_REC* nk, char* prefix)
[32]417{
[37]418  uint32 i;
[33]419 
420  for(i=0; i < nk->num_values; i++)
[43]421    if(!type_filter_enabled || (nk->values[i].type == type_filter))
422      printValue(&nk->values[i], prefix);
[33]423}
424
[37]425
[43]426void printKey(REGF_NK_REC* k, char* full_path)
[33]427{
[43]428  static char empty_str[1] = "";
[42]429  char* owner = NULL;
430  char* group = NULL;
431  char* sacl = NULL;
432  char* dacl = NULL;
433  char mtime[20];
434  time_t tmp_time[1];
435  struct tm* tmp_time_s = NULL;
436
[43]437  *tmp_time = nt_time_to_unix(&k->mtime);
438  tmp_time_s = gmtime(tmp_time);
439  strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
440
441  if(print_security)
442  {
[53]443    owner = regfio_get_owner(k->sec_desc->sec_desc);
444    group = regfio_get_group(k->sec_desc->sec_desc);
445    sacl = regfio_get_sacl(k->sec_desc->sec_desc);
446    dacl = regfio_get_dacl(k->sec_desc->sec_desc);
[43]447    if(owner == NULL)
448      owner = empty_str;
449    if(group == NULL)
450      group = empty_str;
451    if(sacl == NULL)
452      sacl = empty_str;
453    if(dacl == NULL)
454      dacl = empty_str;
455
456    printf("%s,KEY,,%s,%s,%s,%s,%s\n", full_path, mtime, 
457           owner, group, sacl, dacl);
458
459    if(owner != empty_str)
460      free(owner);
461    if(group != empty_str)
462      free(group);
463    if(sacl != empty_str)
464      free(sacl);
465    if(dacl != empty_str)
466      free(dacl);
467  }
468  else
469    printf("%s,KEY,,%s\n", full_path, mtime);
470}
471
472
[54]473/* XXX: this function is awful.  Needs to be re-designed. */
[43]474void printKeyTree(REGF_FILE* f, void_stack* nk_stack, char* prefix)
475{
[52]476  REGF_NK_REC* cur = NULL;
477  REGF_NK_REC* sub = NULL;
[43]478  char* path = NULL;
479  char* val_path = NULL;
[41]480  int key_type = regfio_type_str2val("KEY");
[43]481 
[32]482  if((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
[31]483  {
[33]484    cur->subkey_index = 0;
485    path = stack2Path(nk_stack);
[43]486
[54]487    if(print_verbose)
488    {
489      if(prefix[0] == '\0')
490        fprintf(stderr, "VERBOSE: Printing key tree under path: /\n");
491      else
492        fprintf(stderr, "VERBOSE: Printing key tree under path: %s\n",
493                prefix);
494    }
495
[43]496    val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
497    sprintf(val_path, "%s%s", prefix, path);
[54]498    if(val_path[0] == '\0')
499    {
500      val_path[0] = '/';
501      val_path[1] = '\0';
502    }
503
[43]504    if(!type_filter_enabled || (key_type == type_filter))
505      printKey(cur, val_path);
[40]506    if(!type_filter_enabled || (key_type != type_filter))
[43]507      printValueList(cur, val_path);
508    if(val_path != NULL)
509      free(val_path);
[32]510    while((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
[31]511    {
[32]512      if((sub = regfio_fetch_subkey(f, cur)) != NULL)
[31]513      {
[33]514        sub->subkey_index = 0;
[32]515        void_stack_push(nk_stack, sub);
[33]516        path = stack2Path(nk_stack);
[32]517        if(path != NULL)
518        {
[33]519          val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
520          sprintf(val_path, "%s%s", prefix, path);
[40]521          if(!type_filter_enabled || (key_type == type_filter))
[43]522            printKey(sub, val_path);
[40]523          if(!type_filter_enabled || (key_type != type_filter))
524            printValueList(sub, val_path);
[42]525          if(val_path != NULL)
526            free(val_path);
[32]527        }
[31]528      }
[32]529      else
530      {
531        cur = void_stack_pop(nk_stack);
532        /* XXX: This is just a shallow free.  Need to write deep free
533         * routines to replace the Samba code for this.
534         */ 
[39]535        if(cur != NULL)
536          free(cur);
[32]537      }
[31]538    }
539  }
[54]540  if(print_verbose)
541    fprintf(stderr, "VERBOSE: Finished printing key tree.\n");
[30]542}
543
544
[33]545/*
546 * Returns 0 if path was found.
547 * Returns 1 if path was not found.
548 * Returns less than 0 on other error.
549 */
550int retrievePath(REGF_FILE* f, void_stack* nk_stack,
551                 void_stack* path_stack)
552{
[52]553  REGF_NK_REC* sub = NULL; 
554  REGF_NK_REC* cur = NULL;
[33]555  void_stack* sub_nk_stack;
556  char* prefix;
[52]557  uint32 prefix_len;
[33]558  char* cur_str = NULL;
[53]559  char* path = NULL;
[33]560  bool found_cur = true;
[37]561  uint32 i;
562  uint16 path_depth;
[33]563  if(path_stack == NULL)
564    return -1;
565
566  path_depth = void_stack_size(path_stack);
567  if(path_depth < 1)
568    return -2;
569
570  if(void_stack_size(nk_stack) < 1)
571    return -3;
572  cur = (REGF_NK_REC*)void_stack_cur(nk_stack);
573
[54]574  if(print_verbose)
575    fprintf(stderr, "VERBOSE: Beginning retrieval of specified path: %s\n", 
576            path_filter);
577
[33]578  while(void_stack_size(path_stack) > 1)
579  {
580    /* Search key records only */
581    cur_str = (char*)void_stack_pop(path_stack);
582
583    found_cur = false;
584    while(!found_cur &&
585          (sub = regfio_fetch_subkey(f, cur)) != NULL)
586    {
587      if(strcasecmp(sub->keyname, cur_str) == 0)
588      {
589        cur = sub;
590        void_stack_push(nk_stack, sub);
591        found_cur = true;
592      }
593    }
[54]594    if(print_verbose && !found_cur)
595      fprintf(stderr, "VERBOSE: Could not find KEY '%s' in specified path.\n", 
596              cur_str);
597
[39]598    free(cur_str);
[33]599    if(!found_cur)
[37]600      return 1;
[33]601  }
602
603  /* Last round, search value and key records */
604  cur_str = (char*)void_stack_pop(path_stack);
605
[54]606  if(print_verbose)
607    fprintf(stderr, "VERBOSE: Searching values for last component"
608                    " of specified path.\n");
609
[33]610  for(i=0; (i < cur->num_values); i++)
611  {
[48]612    /* XXX: Not sure when/why this can be NULL, but it's happened. */
613    if(sub->values[i].valuename != NULL 
614       && strcasecmp(sub->values[i].valuename, cur_str) == 0)
[33]615    {
[53]616      path = stack2Path(nk_stack);
[54]617
618      if(print_verbose)
619        fprintf(stderr, "VERBOSE: Found final path element as value.\n");
620
[55]621      if(!type_filter_enabled || (&sub->values[i].type == type_filter))
622        printValue(&sub->values[i], path);
623      if(path != NULL)
624        free(path);
625
[33]626      return 0;
627    }
628  }
629
[54]630  if(print_verbose)
631    fprintf(stderr, "VERBOSE: Searching keys for last component"
632                    " of specified path.\n");
633
[33]634  while((sub = regfio_fetch_subkey(f, cur)) != NULL)
635  {
636    if(strcasecmp(sub->keyname, cur_str) == 0)
637    {
638      sub_nk_stack = void_stack_new(1024);
639      void_stack_push(sub_nk_stack, sub);
640      prefix = stack2Path(nk_stack);
[52]641      prefix_len = strlen(prefix);
642      prefix = realloc(prefix, prefix_len+strlen(sub->keyname)+2);
643      if(prefix == NULL)
644        return -1;
645      strcat(prefix, "/");
646      strcat(prefix, sub->keyname);
[54]647
648      if(print_verbose)
649        fprintf(stderr, "VERBOSE: Found final path element as key.\n");
650
[33]651      printKeyTree(f, sub_nk_stack, prefix);
[54]652
[33]653      return 0;
654    }
655  }
656
[54]657  if(print_verbose)
658    fprintf(stderr, "VERBOSE: Could not find last element of path.\n");
659
[33]660  return 1;
661}
662
663
[37]664static void usage(void)
665{
[39]666  fprintf(stderr, "Usage: readreg [-v] [-s]"
[40]667          " [-p <PATH_FILTER>] [-t <TYPE_FILTER>]"
[39]668          " <REGISTRY_FILE>\n");
[37]669  /* XXX: replace version string with Subversion property? */
[53]670  fprintf(stderr, "Version: 0.2.1\n");
[39]671  fprintf(stderr, "Options:\n");
672  fprintf(stderr, "\t-v\t sets verbose mode.\n");
[47]673  fprintf(stderr, "\t-h\t enables header row. (default)\n");
674  fprintf(stderr, "\t-H\t disables header row.\n");
[44]675  fprintf(stderr, "\t-s\t enables security descriptor output.\n");
676  fprintf(stderr, "\t-S\t disables security descriptor output. (default)\n");
[40]677  fprintf(stderr, "\t-p\t restrict output to elements below this path.\n");
678  fprintf(stderr, "\t-t\t restrict results to this specific data type.\n");
[37]679  fprintf(stderr, "\n");
680}
681
682
[30]683int main(int argc, char** argv)
684{
[31]685  void_stack* nk_stack;
[33]686  void_stack* path_stack;
[31]687  REGF_FILE* f;
688  REGF_NK_REC* root;
[33]689  int retr_path_ret;
[44]690  uint32 argi, arge;
[31]691
[37]692  /* Process command line arguments */
[30]693  if(argc < 2)
694  {
[37]695    usage();
[44]696    bailOut(1, "ERROR: Requires at least one argument.\n");
[30]697  }
[37]698 
[44]699  arge = argc-1;
700  for(argi = 1; argi < arge; argi++)
[37]701  {
[40]702    if (strcmp("-p", argv[argi]) == 0)
[37]703    {
[44]704      if(++argi >= arge)
[37]705      {
706        usage();
[40]707        bailOut(1, "ERROR: '-p' option requires parameter.\n");
[37]708      }
[40]709      if((path_filter = strdup(argv[argi])) == NULL)
[38]710        bailOut(2, "ERROR: Memory allocation problem.\n");
711
[40]712      path_filter_enabled = true;
[37]713    }
714    else if (strcmp("-t", argv[argi]) == 0)
715    {
[44]716      if(++argi >= arge)
[37]717      {
718        usage();
[38]719        bailOut(1, "ERROR: '-t' option requires parameter.\n");
[37]720      }
[41]721      if((type_filter = regfio_type_str2val(argv[argi])) == 0)
[40]722      {
723        fprintf(stderr, "ERROR: Invalid type specified: %s.\n", argv[argi]);
724        bailOut(1, "");
725      }
[38]726
[37]727      type_filter_enabled = true;
728    }
[47]729    else if (strcmp("-h", argv[argi]) == 0)
730      print_header = true;
731    else if (strcmp("-H", argv[argi]) == 0)
732      print_header = false;
[37]733    else if (strcmp("-s", argv[argi]) == 0)
734      print_security = true;
[44]735    else if (strcmp("-S", argv[argi]) == 0)
736      print_security = false;
[37]737    else if (strcmp("-v", argv[argi]) == 0)
738      print_verbose = true;
[44]739    else
[37]740    {
[38]741      usage();
[37]742      fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
[38]743      bailOut(1, "");
[37]744    }
745  }
[44]746  if((registry_file = strdup(argv[argi])) == NULL)
747    bailOut(2, "ERROR: Memory allocation problem.\n");
[30]748
[37]749  f = regfio_open(registry_file);
750  if(f == NULL)
751  {
752    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
[38]753    bailOut(3, "");
[37]754  }
[38]755
[31]756  root = regfio_rootkey(f);
[37]757  nk_stack = void_stack_new(1024);
[30]758
[31]759  if(void_stack_push(nk_stack, root))
[33]760  {
[42]761    if(print_header)
[43]762    {
763      if(print_security)
764        printf("PATH,TYPE,VALUE,MTIME,OWNER,GROUP,SACL,DACL\n");
765      else
766        printf("PATH,TYPE,VALUE,MTIME\n");
767    }
[42]768
[40]769    path_stack = path2Stack(path_filter);
[33]770    if(void_stack_size(path_stack) < 1)
771      printKeyTree(f, nk_stack, "");
772    else
773    {
[37]774      retr_path_ret = retrievePath(f, nk_stack, path_stack);
[33]775      if(retr_path_ret == 1)
[37]776        fprintf(stderr, "WARNING: specified path not found.\n");
[33]777      else if(retr_path_ret != 0)
[38]778        bailOut(4, "ERROR:\n");
[33]779    }
780  }
[37]781  else
[38]782    bailOut(2, "ERROR: Memory allocation problem.\n");
[31]783
[38]784  void_stack_destroy_deep(nk_stack);
[30]785  regfio_close(f);
786
787  return 0;
788}
Note: See TracBrowser for help on using the repository browser.