source: trunk/src/reglookup.c @ 170

Last change on this file since 170 was 170, checked in by tim, 14 years ago

merged Tobias Mueller's patch with some changes
updated version number

  • Property svn:keywords set to Id
File size: 17.5 KB
RevLine 
[30]1/*
[135]2 * A utility to read a Windows NT and later registry files.
[30]3 *
[170]4 * Copyright (C) 2005-2010 Timothy D. Morgan
5 * Copyright (C) 2010 Tobias Mueller (portions of '-i' code)
[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
[111]10 * the Free Software Foundation; version 3 of the License.
[30]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 170 2010-03-06 04:40:25Z 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>
[147]30#include "regfi.h"
31#include "void_stack.h"
[30]32
[40]33/* Globals, influenced by command line parameters */
[170]34bool print_value_mtime = false;
[40]35bool print_verbose = false;
36bool print_security = false;
[42]37bool print_header = true;
[40]38bool path_filter_enabled = false;
39bool type_filter_enabled = false;
40char* path_filter = NULL;
41int type_filter;
42char* registry_file = NULL;
43
[42]44/* Other globals */
[135]45REGFI_FILE* f;
[66]46
[40]47
[116]48/* XXX: A hack to share some functions with reglookup-recover.c.
[125]49 *      Should move these into a proper library at some point.
[111]50 */
51#include "common.c"
[61]52
[38]53
[159]54void printValue(REGFI_ITERATOR* iter, const REGFI_VK_REC* vk, char* prefix)
[41]55{
[159]56  REGFI_DATA* data;
[111]57  char* quoted_value = NULL;
58  char* quoted_name = NULL;
59  char* conv_error = NULL;
60  const char* str_type = NULL;
[170]61  char mtime[20];
62  time_t tmp_time[1];
63  struct tm* tmp_time_s = NULL;
[41]64
[162]65  if(vk->valuename == NULL)
66    quoted_name = quote_buffer(vk->valuename_raw, vk->name_length, 
67                               key_special_chars);
68  else
69    quoted_name = quote_string(vk->valuename, key_special_chars);
[111]70  if (quoted_name == NULL)
71  { /* Value names are NULL when we're looking at the "(default)" value.
72     * Currently we just return a 0-length string to try an eliminate
73     * ambiguity with a literal "(default)" value.  The data type of a line
74     * in the output allows one to differentiate between the parent key and
75     * this value.
76     */
77    quoted_name = malloc(1*sizeof(char));
78    if(quoted_name == NULL)
[143]79      bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Could not allocate sufficient memory.\n");
[111]80    quoted_name[0] = '\0';
81  }
[159]82 
83  data = regfi_iterator_fetch_data(iter, vk);
[41]84
[159]85  printMsgs(iter->f);
86  if(data != NULL)
[41]87  {
[159]88    quoted_value = data_to_ascii(data, &conv_error);
[138]89    if(quoted_value == NULL)
90    {
91      if(conv_error == NULL)
92        fprintf(stderr, "WARN: Could not quote value for '%s/%s'.  "
93                "Memory allocation failure likely.\n", prefix, quoted_name);
94      else
95        fprintf(stderr, "WARN: Could not quote value for '%s/%s'.  "
96                "Returned error: %s\n", prefix, quoted_name, conv_error);
97    }
[159]98    else if(conv_error != NULL)
99      fprintf(stderr, "WARN: While quoting value for '%s/%s', "
[138]100              "warning returned: %s\n", prefix, quoted_name, conv_error);
[159]101    regfi_free_data(data);
[138]102  }
[41]103
[170]104  if(print_value_mtime)
105  {
106    *tmp_time = regfi_nt2unix_time(&iter->cur_key->mtime);
107    tmp_time_s = gmtime(tmp_time);
108    strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
109  }
110  else
111    mtime[0] = '\0';
112
[111]113  str_type = regfi_type_val2str(vk->type);
114  if(print_security)
[41]115  {
[111]116    if(str_type == NULL)
[170]117      printf("%s/%s,0x%.8X,%s,%s,,,,\n", prefix, quoted_name,
118             vk->type, quoted_value, mtime);
[66]119    else
[170]120      printf("%s/%s,%s,%s,%s,,,,\n", prefix, quoted_name,
121             str_type, quoted_value, mtime);
[71]122  }
[111]123  else
124  {
125    if(str_type == NULL)
[170]126      printf("%s/%s,0x%.8X,%s,%s\n", prefix, quoted_name,
127             vk->type, quoted_value, mtime);
[111]128    else
[170]129      printf("%s/%s,%s,%s,%s\n", prefix, quoted_name,
130             str_type, quoted_value, mtime);
[111]131  }
[42]132
[111]133  if(quoted_value != NULL)
134    free(quoted_value);
135  if(quoted_name != NULL)
136    free(quoted_name);
137  if(conv_error != NULL)
138    free(conv_error);
[41]139}
140
141
[81]142char** splitPath(const char* s)
[30]143{
[81]144  char** ret_val;
[38]145  const char* cur = s;
[33]146  char* next = NULL;
[38]147  char* copy;
[168]148  uint32_t ret_cur = 0;
[38]149
[135]150  ret_val = (char**)malloc((REGFI_MAX_DEPTH+1+1)*sizeof(char**));
[81]151  if (ret_val == NULL)
[38]152    return NULL;
[81]153  ret_val[0] = NULL;
154
155  /* We return a well-formed, 0-length, path even when input is icky. */
[37]156  if (s == NULL)
[81]157    return ret_val;
[38]158 
159  while((next = strchr(cur, '/')) != NULL)
[33]160  {
[38]161    if ((next-cur) > 0)
162    {
163      copy = (char*)malloc((next-cur+1)*sizeof(char));
164      if(copy == NULL)
[143]165        bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Memory allocation problem.\n");
[38]166         
167      memcpy(copy, cur, next-cur);
168      copy[next-cur] = '\0';
[81]169      ret_val[ret_cur++] = copy;
[135]170      if(ret_cur < (REGFI_MAX_DEPTH+1+1))
[81]171        ret_val[ret_cur] = NULL;
172      else
[143]173        bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: Registry maximum depth exceeded.\n");
[38]174    }
175    cur = next+1;
[33]176  }
[81]177
178  /* Grab last element, if path doesn't end in '/'. */
[33]179  if(strlen(cur) > 0)
[38]180  {
181    copy = strdup(cur);
[81]182    ret_val[ret_cur++] = copy;
[135]183    if(ret_cur < (REGFI_MAX_DEPTH+1+1))
[81]184      ret_val[ret_cur] = NULL;
185    else
[143]186      bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: Registry maximum depth exceeded.\n");
[38]187  }
[33]188
189  return ret_val;
190}
191
[81]192
[83]193void freePath(char** path)
194{
[168]195  uint32_t i;
[83]196
197  if(path == NULL)
198    return;
199
200  for(i=0; path[i] != NULL; i++)
201    free(path[i]);
202
203  free(path);
204}
205
206
[81]207/* Returns a quoted path from an iterator's stack */
208char* iter2Path(REGFI_ITERATOR* i)
[33]209{
[81]210  const REGFI_ITER_POSITION* cur;
[161]211  const REGFI_NK_REC* tmp_key;
[168]212  uint32_t buf_left = 127;
213  uint32_t buf_len = buf_left+1;
214  uint32_t name_len = 0;
215  uint32_t grow_amt;
[81]216  char* buf;
[31]217  char* new_buf;
[66]218  char* name;
[31]219  void_stack_iterator* iter;
220 
221  buf = (char*)malloc((buf_len)*sizeof(char));
222  if (buf == NULL)
223    return NULL;
[54]224  buf[0] = '\0';
[30]225
[81]226  iter = void_stack_iterator_new(i->key_positions);
[31]227  if (iter == NULL)
[30]228  {
[31]229    free(buf);
230    return NULL;
[30]231  }
232
[33]233  /* skip root element */
[81]234  if(void_stack_size(i->key_positions) < 1)
235  {
236    buf[0] = '/';
237    buf[1] = '\0';
238    return buf;
239  }
[33]240  cur = void_stack_iterator_next(iter);
241
[81]242  do
[31]243  {
[81]244    cur = void_stack_iterator_next(iter);
245    if (cur == NULL)
[161]246      tmp_key = i->cur_key;
[81]247    else
[161]248      tmp_key = cur->nk;
[81]249
[161]250    if(tmp_key->keyname == NULL)
251      name = quote_buffer(i->cur_key->keyname_raw, i->cur_key->name_length,
252                          key_special_chars);
253    else
254      name = quote_string(tmp_key->keyname, key_special_chars);
255
[33]256    buf[buf_len-buf_left-1] = '/';
257    buf_left -= 1;
[66]258    name_len = strlen(name);
[31]259    if(name_len+1 > buf_left)
260    {
[168]261      grow_amt = (uint32_t)(buf_len/2);
[31]262      buf_len += name_len+1+grow_amt-buf_left;
263      if((new_buf = realloc(buf, buf_len)) == NULL)
264      {
[136]265        free(name);
[31]266        free(buf);
267        free(iter);
268        return NULL;
269      }
270      buf = new_buf;
271      buf_left = grow_amt + name_len + 1;
272    }
[66]273    strncpy(buf+(buf_len-buf_left-1), name, name_len);
[31]274    buf_left -= name_len;
275    buf[buf_len-buf_left-1] = '\0';
[66]276    free(name);
[81]277  } while(cur != NULL);
[30]278
[31]279  return buf;
280}
[30]281
[31]282
[137]283void printValueList(REGFI_ITERATOR* iter, char* prefix)
[32]284{
[150]285  REGFI_VK_REC* value;
[80]286
[137]287  value = regfi_iterator_first_value(iter);
[80]288  while(value != NULL)
[81]289  {
290    if(!type_filter_enabled || (value->type == type_filter))
[159]291      printValue(iter, value, prefix);
[150]292    regfi_free_value(value);
[137]293    value = regfi_iterator_next_value(iter);
[138]294    printMsgs(iter->f);
[81]295  }
[33]296}
297
[37]298
[137]299void printKey(REGFI_ITERATOR* iter, char* full_path)
[33]300{
[43]301  static char empty_str[1] = "";
[42]302  char* owner = NULL;
303  char* group = NULL;
304  char* sacl = NULL;
305  char* dacl = NULL;
[125]306  char* quoted_classname;
[42]307  char mtime[20];
308  time_t tmp_time[1];
309  struct tm* tmp_time_s = NULL;
[135]310  const REGFI_SK_REC* sk;
[137]311  const REGFI_NK_REC* k = regfi_iterator_cur_key(iter);
[160]312  REGFI_CLASSNAME* classname;
[42]313
[168]314  *tmp_time = regfi_nt2unix_time(&k->mtime);
[43]315  tmp_time_s = gmtime(tmp_time);
316  strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
317
[137]318  if(print_security && (sk=regfi_iterator_cur_sk(iter)))
[43]319  {
[109]320    owner = regfi_get_owner(sk->sec_desc);
321    group = regfi_get_group(sk->sec_desc);
322    sacl = regfi_get_sacl(sk->sec_desc);
323    dacl = regfi_get_dacl(sk->sec_desc);
[43]324    if(owner == NULL)
325      owner = empty_str;
326    if(group == NULL)
327      group = empty_str;
328    if(sacl == NULL)
329      sacl = empty_str;
330    if(dacl == NULL)
331      dacl = empty_str;
332
[160]333    classname = regfi_iterator_fetch_classname(iter, k);
334    printMsgs(iter->f);
335    if(classname != NULL)
[126]336    {
[160]337      if(classname->interpreted == NULL)
[126]338      {
[160]339        fprintf(stderr, "WARN: Could not convert class name"
340                " charset for key '%s'.  Quoting raw...\n", full_path);
341        quoted_classname = quote_buffer(classname->raw, classname->size,
342                                        key_special_chars);
[126]343      }
[160]344      else
345        quoted_classname = quote_string(classname->interpreted, 
346                                        key_special_chars);
347
348      if(quoted_classname == NULL)
[126]349      {
[160]350        fprintf(stderr, "ERROR: Could not quote classname"
351                " for key '%s' due to unknown error.\n", full_path);
352        quoted_classname = empty_str;
[126]353      }
354    }
[125]355    else
356      quoted_classname = empty_str;
[160]357    regfi_free_classname(classname);
[43]358
[138]359    printMsgs(iter->f);
[125]360    printf("%s,KEY,,%s,%s,%s,%s,%s,%s\n", full_path, mtime, 
361           owner, group, sacl, dacl, quoted_classname);
362
[43]363    if(owner != empty_str)
364      free(owner);
365    if(group != empty_str)
366      free(group);
367    if(sacl != empty_str)
368      free(sacl);
369    if(dacl != empty_str)
370      free(dacl);
[125]371    if(quoted_classname != empty_str)
372      free(quoted_classname);
[43]373  }
374  else
[66]375    printf("%s,KEY,,%s\n", full_path, mtime);
[43]376}
377
378
[81]379void printKeyTree(REGFI_ITERATOR* iter)
[43]380{
[135]381  const REGFI_NK_REC* root = NULL;
382  const REGFI_NK_REC* cur = NULL;
[150]383  REGFI_NK_REC* sub = NULL;
[43]384  char* path = NULL;
[78]385  int key_type = regfi_type_str2val("KEY");
[81]386  bool print_this = true;
387
388  root = cur = regfi_iterator_cur_key(iter);
389  sub = regfi_iterator_first_subkey(iter);
[138]390  printMsgs(iter->f);
[137]391
[81]392  if(root == NULL)
[143]393    bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: root cannot be NULL.\n");
[81]394 
395  do
[31]396  {
[81]397    if(print_this)
[54]398    {
[81]399      path = iter2Path(iter);
400      if(path == NULL)
[143]401        bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Could not construct iterator's path.\n");
[137]402
[81]403      if(!type_filter_enabled || (key_type == type_filter))
[109]404        printKey(iter, path);
[81]405      if(!type_filter_enabled || (key_type != type_filter))
406        printValueList(iter, path);
407     
408      free(path);
[54]409    }
[66]410   
[81]411    if(sub == NULL)
[31]412    {
[81]413      if(cur != root)
[31]414      {
[81]415        /* We're done with this sub-tree, going up and hitting other branches. */
416        if(!regfi_iterator_up(iter))
[137]417        {
[138]418          printMsgs(iter->f);
[143]419          bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator upward.\n");
[137]420        }
421
[81]422        cur = regfi_iterator_cur_key(iter);
423        if(cur == NULL)
[137]424        {
[138]425          printMsgs(iter->f);
[143]426          bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: unexpected NULL for key.\n");
[137]427        }
[150]428       
[81]429        sub = regfi_iterator_next_subkey(iter);
[66]430      }
[81]431      print_this = false;
[31]432    }
[81]433    else
434    { /* We have unexplored sub-keys. 
435       * Let's move down and print this first sub-tree out.
436       */
437      if(!regfi_iterator_down(iter))
[137]438      {
[138]439        printMsgs(iter->f);
[143]440        bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator downward.\n");
[137]441      }
[81]442
[150]443      cur = regfi_iterator_cur_key(iter);
444      regfi_free_key(sub);
[81]445      sub = regfi_iterator_first_subkey(iter);
446      print_this = true;
447    }
[138]448    printMsgs(iter->f);
[81]449  } while(!((cur == root) && (sub == NULL)));
450
[54]451  if(print_verbose)
[138]452    fprintf(stderr, "INFO: Finished printing key tree.\n");
[30]453}
454
[81]455
[140]456/* XXX: What if there is BOTH a value AND a key with that name??
457 *      What if there are multiple keys/values with the same name??
458 */
[33]459/*
[80]460 * Returns 0 if path was not found.
461 * Returns 1 if path was found as value.
462 * Returns 2 if path was found as key.
[33]463 * Returns less than 0 on other error.
464 */
[80]465int retrievePath(REGFI_ITERATOR* iter, char** path)
[33]466{
[150]467  REGFI_VK_REC* value;
[81]468  char* tmp_path_joined;
469  const char** tmp_path;
[168]470  uint32_t i;
[80]471 
472  if(path == NULL)
[33]473    return -1;
474
[80]475  /* One extra for any value at the end, and one more for NULL */
[135]476  tmp_path = (const char**)malloc(sizeof(const char**)*(REGFI_MAX_DEPTH+1+1));
[80]477  if(tmp_path == NULL)
[33]478    return -2;
479
[80]480  /* Strip any potential value name at end of path */
481  for(i=0; 
[136]482      (path[i] != NULL) && (path[i+1] != NULL) && (i < REGFI_MAX_DEPTH+1);
[80]483      i++)
[136]484  { tmp_path[i] = path[i]; }
[80]485  tmp_path[i] = NULL;
486
[54]487  if(print_verbose)
[138]488    fprintf(stderr, "INFO: Attempting to retrieve specified path: %s\n",
[54]489            path_filter);
490
[82]491  /* Special check for '/' path filter */
492  if(path[0] == NULL)
493  {
494    if(print_verbose)
[138]495      fprintf(stderr, "INFO: Found final path element as root key.\n");
[136]496    free(tmp_path);
[82]497    return 2;
498  }
499
[80]500  if(!regfi_iterator_walk_path(iter, tmp_path))
[33]501  {
[138]502    printMsgs(iter->f);
[80]503    free(tmp_path);
504    return 0;
[33]505  }
506
[80]507  if(regfi_iterator_find_value(iter, path[i]))
508  {
509    if(print_verbose)
[138]510      fprintf(stderr, "INFO: Found final path element as value.\n");
[33]511
[80]512    value = regfi_iterator_cur_value(iter);
[138]513    printMsgs(iter->f);
[81]514    tmp_path_joined = iter2Path(iter);
[54]515
[80]516    if((value == NULL) || (tmp_path_joined == NULL))
[143]517      bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Unexpected error before printValue.\n");
[54]518
[121]519    if(!type_filter_enabled || (value->type == type_filter))
[159]520      printValue(iter, value, tmp_path_joined);
[54]521
[150]522    regfi_free_value(value);
[80]523    free(tmp_path);
524    free(tmp_path_joined);
525    return 1;
[33]526  }
[80]527  else if(regfi_iterator_find_subkey(iter, path[i]))
[33]528  {
[138]529    printMsgs(iter->f);
[80]530    if(print_verbose)
[138]531      fprintf(stderr, "INFO: Found final path element as key.\n");
[82]532
533    if(!regfi_iterator_down(iter))
[137]534    {
[138]535      printMsgs(iter->f);
[143]536      bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: Unexpected error on traversing path filter key.\n");
[137]537    }
[82]538
[80]539    return 2;
[33]540  }
[138]541  printMsgs(iter->f);
[33]542
[54]543  if(print_verbose)
[138]544    fprintf(stderr, "INFO: Could not find last element of path.\n");
[54]545
[80]546  return 0;
[33]547}
548
549
[37]550static void usage(void)
551{
[61]552  fprintf(stderr, "Usage: reglookup [-v] [-s]"
[40]553          " [-p <PATH_FILTER>] [-t <TYPE_FILTER>]"
[39]554          " <REGISTRY_FILE>\n");
[111]555  fprintf(stderr, "Version: %s\n", REGLOOKUP_VERSION);
[39]556  fprintf(stderr, "Options:\n");
557  fprintf(stderr, "\t-v\t sets verbose mode.\n");
[47]558  fprintf(stderr, "\t-h\t enables header row. (default)\n");
559  fprintf(stderr, "\t-H\t disables header row.\n");
[44]560  fprintf(stderr, "\t-s\t enables security descriptor output.\n");
561  fprintf(stderr, "\t-S\t disables security descriptor output. (default)\n");
[40]562  fprintf(stderr, "\t-p\t restrict output to elements below this path.\n");
563  fprintf(stderr, "\t-t\t restrict results to this specific data type.\n");
[170]564  fprintf(stderr, "\t-i\t includes parent key modification times with child values.\n");
[37]565  fprintf(stderr, "\n");
566}
567
568
[30]569int main(int argc, char** argv)
570{
[80]571  char** path = NULL;
572  REGFI_ITERATOR* iter;
[33]573  int retr_path_ret;
[168]574  uint32_t argi, arge;
[31]575
[37]576  /* Process command line arguments */
[30]577  if(argc < 2)
578  {
[37]579    usage();
[143]580    bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: Requires at least one argument.\n");
[30]581  }
[37]582 
[44]583  arge = argc-1;
584  for(argi = 1; argi < arge; argi++)
[37]585  {
[40]586    if (strcmp("-p", argv[argi]) == 0)
[37]587    {
[44]588      if(++argi >= arge)
[37]589      {
590        usage();
[143]591        bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: '-p' option requires parameter.\n");
[37]592      }
[40]593      if((path_filter = strdup(argv[argi])) == NULL)
[143]594        bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Memory allocation problem.\n");
[38]595
[40]596      path_filter_enabled = true;
[37]597    }
598    else if (strcmp("-t", argv[argi]) == 0)
599    {
[44]600      if(++argi >= arge)
[37]601      {
602        usage();
[143]603        bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: '-t' option requires parameter.\n");
[37]604      }
[78]605      if((type_filter = regfi_type_str2val(argv[argi])) < 0)
[40]606      {
607        fprintf(stderr, "ERROR: Invalid type specified: %s.\n", argv[argi]);
[143]608        bailOut(REGLOOKUP_EXIT_USAGE, "");
[40]609      }
[37]610      type_filter_enabled = true;
611    }
[47]612    else if (strcmp("-h", argv[argi]) == 0)
613      print_header = true;
614    else if (strcmp("-H", argv[argi]) == 0)
615      print_header = false;
[37]616    else if (strcmp("-s", argv[argi]) == 0)
617      print_security = true;
[44]618    else if (strcmp("-S", argv[argi]) == 0)
619      print_security = false;
[37]620    else if (strcmp("-v", argv[argi]) == 0)
621      print_verbose = true;
[170]622    else if (strcmp("-i", argv[argi]) == 0)
623      print_value_mtime = true;
[44]624    else
[37]625    {
[38]626      usage();
[37]627      fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
[143]628      bailOut(REGLOOKUP_EXIT_USAGE, "");
[37]629    }
630  }
[44]631  if((registry_file = strdup(argv[argi])) == NULL)
[143]632    bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Memory allocation problem.\n");
[30]633
[110]634  f = regfi_open(registry_file);
[37]635  if(f == NULL)
636  {
637    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
[143]638    bailOut(REGLOOKUP_EXIT_NOINPUT, "");
[37]639  }
[38]640
[138]641  if(print_verbose)
642    regfi_set_message_mask(f, REGFI_MSG_INFO|REGFI_MSG_WARN|REGFI_MSG_ERROR);
643
[159]644  /* XXX: add command line option to choose output encoding */
[161]645  iter = regfi_iterator_new(f, REGFI_ENCODING_ASCII);
[80]646  if(iter == NULL)
[158]647  {
648    printMsgs(f);
[143]649    bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Couldn't create registry iterator.\n");
[158]650  }
[30]651
[81]652  if(print_header)
653  {
654    if(print_security)
[125]655      printf("PATH,TYPE,VALUE,MTIME,OWNER,GROUP,SACL,DACL,CLASS\n");
[81]656    else
657      printf("PATH,TYPE,VALUE,MTIME\n");
658  }
659
[80]660  if(path_filter_enabled && path_filter != NULL)
661    path = splitPath(path_filter);
[81]662
[80]663  if(path != NULL)
[33]664  {
[80]665    retr_path_ret = retrievePath(iter, path);
[138]666    printMsgs(iter->f);
[83]667    freePath(path);
668
[80]669    if(retr_path_ret == 0)
[141]670      fprintf(stderr, "WARN: Specified path '%s' not found.\n", path_filter);
[80]671    else if (retr_path_ret == 2)
[81]672      printKeyTree(iter);
[93]673    else if(retr_path_ret < 0)
674    {
675      fprintf(stderr, "ERROR: retrievePath() returned %d.\n", 
676              retr_path_ret);
[143]677      bailOut(REGLOOKUP_EXIT_DATAERR,
678              "ERROR: Unknown error occurred in retrieving path.\n");
[93]679    }
[33]680  }
[37]681  else
[81]682    printKeyTree(iter);
[31]683
[80]684  regfi_iterator_free(iter);
[78]685  regfi_close(f);
[30]686
687  return 0;
688}
Note: See TracBrowser for help on using the repository browser.