Panda3D
check_md5.cxx
1 // Filename: check_md5.cxx
2 // Created by:
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pandabase.h"
16 #include "pystub.h"
17 #include "hashVal.h"
18 #include "filename.h"
19 #include "panda_getopt.h"
20 #include "preprocess_argv.h"
21 
22 bool output_decimal = false;
23 bool suppress_filename = false;
24 pofstream binary_output;
25 
26 void
27 usage() {
28  cerr <<
29  "\n"
30  "Usage:\n\n"
31  "check_md5 [-q] [-d] [-b filename] [-i \"input string\"] [file1 file2 ...]\n"
32  "check_md5 -h\n\n";
33 }
34 
35 void
36 help() {
37  usage();
38  cerr <<
39  "This program outputs the MD5 hash of one or more files (or of a string\n"
40  "passed on the command line with -i).\n\n"
41 
42  "An MD5 hash is a 128-bit value. The output is presented as a 32-digit\n"
43  "hexadecimal string by default, but with -d, it is presented as four\n"
44  "big-endian unsigned 32-bit decimal integers. Normally the filename\n"
45  "of each file is printed along with the hash; -q suppresses this.\n\n"
46 
47  "To write the 16 bytes (per input file) of the output directly to a\n"
48  "binary file, use -b with the name of the file to receive the output.\n";
49 }
50 
51 void
52 output_hash(const string &filename, const HashVal &hash) {
53  if (!suppress_filename && !filename.empty()) {
54  cout << filename << " ";
55  }
56  if (output_decimal) {
57  hash.output_dec(cout);
58  } else {
59  hash.output_hex(cout);
60  }
61  cout << "\n";
62 
63  // Also output to the binary_output file if it is open. No sweat if
64  // it's not.
65  hash.output_binary(binary_output);
66 }
67 
68 
69 int
70 main(int argc, char **argv) {
71  // A call to pystub() to force libpystub.so to be linked in.
72  pystub();
73 
74  extern char *optarg;
75  extern int optind;
76  const char *optstr = "i:db:qh";
77 
78  bool got_input_string = false;
79  string input_string;
80  Filename binary_output_filename;
81 
82  preprocess_argv(argc, argv);
83  int flag = getopt(argc, argv, optstr);
84 
85  while (flag != EOF) {
86  switch (flag) {
87  case 'i':
88  got_input_string = true;
89  input_string = optarg;
90  break;
91 
92  case 'd':
93  output_decimal = true;
94  break;
95 
96  case 'b':
97  binary_output_filename = Filename::binary_filename(string(optarg));
98  break;
99 
100  case 'q':
101  suppress_filename = true;
102  break;
103 
104  case 'h':
105  help();
106  exit(1);
107 
108  default:
109  exit(1);
110  }
111  flag = getopt(argc, argv, optstr);
112  }
113 
114  argc -= (optind-1);
115  argv += (optind-1);
116 
117  if (argc < 2 && !got_input_string) {
118  usage();
119  exit(1);
120  }
121 
122  if (!binary_output_filename.empty()) {
123  if (!binary_output_filename.open_write(binary_output)) {
124  cerr << "Unable to open " << binary_output_filename << ".\n";
125  exit(1);
126  }
127  }
128 
129  if (got_input_string) {
130  HashVal hash;
131  hash.hash_string(input_string);
132  output_hash("", hash);
133  }
134 
135  bool okflag = true;
136 
137  for (int i = 1; i < argc; i++) {
138  Filename source_file = Filename::from_os_specific(argv[i]);
139 
140  if (!source_file.exists()) {
141  cerr << source_file << " not found!\n";
142  okflag = false;
143  } else {
144  HashVal hash;
145  if (!hash.hash_file(source_file)) {
146  cerr << "Unable to read " << source_file << "\n";
147  okflag = false;
148  } else {
149  output_hash(source_file.get_basename(), hash);
150  }
151  }
152  }
153 
154  if (!okflag) {
155  exit(1);
156  }
157 
158  return 0;
159 }
void output_binary(ostream &out) const
Outputs the HashVal as a binary stream of bytes in order.
Definition: hashVal.cxx:85
string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:436
bool open_write(ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:2045
Stores a 128-bit value that represents the hashed contents (typically MD5) of a file or buffer...
Definition: hashVal.h:32
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
void output_hex(ostream &out) const
Outputs the HashVal as a 32-digit hexadecimal number.
Definition: hashVal.cxx:31
void output_dec(ostream &out) const
Outputs the HashVal as four unsigned decimal integers.
Definition: hashVal.I:125
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1356
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).
Definition: filename.cxx:332