ucommon  7.0.0
About: GNU uCommon C++ is a portable and optimized class framework for writing C++ applications that need to use threads and support concurrent synchronization, and that use sockets, XML parsing, object serialization, thread-optimized string and data structure classes, etc..
  Fossies Dox: ucommon-7.0.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

mdsum.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This file is part of GNU uCommon C++.
5 //
6 // GNU uCommon C++ is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published
8 // by the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // GNU uCommon C++ 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 Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18 
19 #include <ucommon/secure.h>
20 #include <sys/stat.h>
21 
22 using namespace ucommon;
23 
24 static shell::flagopt helpflag('h',"--help", _TEXT("display this list"));
25 static shell::flagopt althelp('?', NULL, NULL);
26 static shell::stringopt hash('d', "--digest", _TEXT("digest method (md5)"), "method", "md5");
27 static shell::flagopt recursive('R', "--recursive", _TEXT("recursive directory scan"));
28 static shell::flagopt altrecursive('r', NULL, NULL);
29 static shell::flagopt hidden('s', "--hidden", _TEXT("show hidden files"));
30 
31 static int exit_code = 0;
32 static const char *argv0 = "md";
33 static digest_t md;
34 
35 static void result(const char *path, int code)
36 {
37  const char *err = _TEXT("i/o error");
38 
39  switch(code) {
40  case EACCES:
41  case EPERM:
42  err = _TEXT("permission denied");
43  break;
44  case EROFS:
45  err = _TEXT("read-only file system");
46  break;
47  case ENODEV:
48  case ENOENT:
49  err = _TEXT("no such file or directory");
50  break;
51  case ENOTDIR:
52  err = _TEXT("not a directory");
53  break;
54  case ENOTEMPTY:
55  err = _TEXT("directory not empty");
56  break;
57  case ENOSPC:
58  err = _TEXT("no space left on device");
59  break;
60  case EBADF:
61  case ENAMETOOLONG:
62  err = _TEXT("bad file path");
63  break;
64  case EBUSY:
65  case EINPROGRESS:
66  err = _TEXT("file or directory busy");
67  break;
68  case EINTR:
69  err = _TEXT("operation interupted");
70  break;
71  case EISDIR:
72  err = _TEXT("is a directory");
73  break;
74 #ifdef ELOOP
75  case ELOOP:
76  err = _TEXT("too many sym links");
77  break;
78 #endif
79  }
80 
81  if(!code) {
82  if(!path)
83  path="-";
84  secure::string sum = *md;
85  shell::printf("%s %s\n", *sum, path);
86  return;
87  }
88 
89  if(path)
90  shell::printf("%s: %s: %s\n", argv0, path, err);
91  else
92  shell::errexit(1, "*** %s: %s\n", argv0, err);
93 
94  exit_code = 1;
95 }
96 
97 static void digest(const char *path = NULL)
98 {
99  fsys_t fs;
100  fsys::fileinfo_t ino;
101  uint8_t buffer[1024];
102 
103  if(path) {
104  int err = fsys::info(path, &ino);
105 
106  if(err) {
107  result(path, err);
108  return;
109  }
110 
111  if(fsys::is_sys(&ino)) {
112  result(path, EBADF);
113  return;
114  }
115 
116  fs.open(path, fsys::STREAM);
117  }
118  else
119  fs.assign(shell::input());
120 
121  if(!is(fs)) {
122  result(path, fs.err());
123  return;
124  }
125 
126  for(;;) {
127  ssize_t size = fs.read(buffer, sizeof(buffer));
128  if(size < 1)
129  break;
130  md.put(buffer, size);
131  }
132 
133  fs.close();
134  result(path, fs.err());
135  md.reset();
136 }
137 
138 static void scan(String path, bool top = true)
139 {
140  char filename[128];
141  string_t filepath;
142  dir_t dir(path);
143 
144  while(is(dir) && dir.read(filename, sizeof(filename))) {
145  if(*filename == '.' && (filename[1] == '.' || !filename[1]))
146  continue;
147 
148  if(*filename == '.' && !is(hidden))
149  continue;
150 
151  filepath = str(path) + str("/") + str(filename);
152  if(fsys::is_dir(filepath)) {
153  if(is(recursive) || is(altrecursive))
154  scan(filepath, false);
155  else
156  result(filepath, EISDIR);
157  }
158  else
159  digest(filepath);
160  }
161 }
162 
163 int main(int argc, char **argv)
164 {
165  shell::bind("mdsum");
166  shell args(argc, argv);
167  argv0 = args.argv0();
168  unsigned count = 0;
169 
170  argv0 = args.argv0();
171 
172  if(is(helpflag) || is(althelp)) {
173  printf("%s\n", _TEXT("Usage: mdsum [options] path..."));
174  printf("%s\n\n", _TEXT("Compute digests for files"));
175  printf("%s\n", _TEXT("Options:"));
176  shell::help();
177  printf("\n%s\n", _TEXT("Report bugs to dyfet@gnu.org"));
178  return 0;
179  }
180 
181  secure::init();
182  if(!Digest::has(*hash))
183  shell::errexit(2, "*** %s: %s: %s\n",
184  argv0, *hash, _TEXT("unkown or unsupported digest method"));
185 
186  md = *hash;
187 
188  // we can symlink md as md5, etc, to set alternate default digest names
189  if(!is(hash) && Digest::has(argv0))
190  md = argv0;
191 
192  if(!args())
193  digest();
194  else while(count < args()) {
195  if(fsys::is_dir(args[count]))
196  scan(str(args[count++]));
197  else
198  digest(args[count++]);
199  }
200 
201  return exit_code;
202 }
203 
altrecursive
static shell::flagopt altrecursive('r', NULL, NULL)
ucommon::fsys::fileinfo_t
struct stat fileinfo_t
Definition: fsys.h:147
ucommon::shell::bind
static void bind(const char *name)
Definition: shell.cpp:2113
ucommon::fsys::read
ssize_t read(void *buffer, size_t count)
Definition: fsys.cpp:750
ucommon
Definition: access.cpp:23
ucommon::stringref
Definition: typeref.h:656
main
int main(int argc, char **argv)
Definition: mdsum.cpp:163
althelp
static shell::flagopt althelp('?', NULL, NULL)
scan
static void scan(String path, bool top=true)
Definition: mdsum.cpp:138
ucommon::fsys::err
int err(void) const
Definition: fsys.h:557
ucommon::String
Definition: string.h:78
result
static void result(const char *path, int code)
Definition: mdsum.cpp:35
ucommon::secure::init
static bool init(void)
Definition: secure.cpp:37
ucommon::Digest::has
static bool has(const char *name)
Definition: digest.cpp:69
ucommon::Digest::reset
void reset(void)
Definition: digest.cpp:88
ucommon::shell::input
static fd_t input(void)
Definition: shell.h:869
ucommon::shell::errexit
static void static void errexit(int exitcode, const char *format=NULL,...) __PRINTF(2
Definition: shell.cpp:828
ucommon::fsys::is_sys
static bool is_sys(struct stat *inode)
Definition: fsys.h:653
ucommon::fsys::close
int close(void)
Definition: fsys.cpp:820
ucommon::fsys::info
int info(fileinfo_t *buffer)
hidden
static shell::flagopt hidden('s', "--hidden", _TEXT("show hidden files"))
ucommon::shell
Definition: shell.h:59
ucommon::fsys::assign
void assign(fd_t descriptor)
Definition: fsys.h:491
digest
static void digest(const char *path=NULL)
Definition: mdsum.cpp:97
secure.h
helpflag
static shell::flagopt helpflag('h',"--help", _TEXT("display this list"))
ucommon::dir
Definition: fsys.h:743
ucommon::str
String str(Socket &so, size_t size)
Definition: socket.cpp:3507
ucommon::fsys::is_dir
static bool is_dir(const char *path)
Definition: fsys.cpp:1500
buffer
static uint8_t buffer[65536]
Definition: zerofill.cpp:27
hash
static shell::stringopt hash('d', "--digest", _TEXT("digest method (md5)"), "method", "md5")
ucommon::fsys::STREAM
Definition: fsys.h:169
ucommon::dir::read
ssize_t read(char *buffer, size_t count)
Definition: fsys.cpp:736
ucommon::fsys
Definition: fsys.h:125
ucommon::fsys::open
void open(const char *path, access_t access)
Definition: fsys.cpp:919
ucommon::shell::argv0
const char * argv0() const
Definition: shell.h:664
argv0
static const char * argv0
Definition: mdsum.cpp:32
md
static digest_t md
Definition: mdsum.cpp:33
recursive
static shell::flagopt recursive('R', "--recursive", _TEXT("recursive directory scan"))
ucommon::shell::stringopt
Definition: shell.h:295
ucommon::Digest::put
bool put(const void *memory, size_t size)
Definition: digest.cpp:79
ucommon::shell::flagopt
Definition: shell.h:234
ucommon::Digest
Definition: secure.h:509
ucommon::shell::help
static void help(void)
Definition: shell.cpp:408
ucommon::shell::printf
static size_t printf(const char *format,...) __PRINTF(1
Definition: shell.cpp:874
exit_code
static int exit_code
Definition: mdsum.cpp:31
ucommon::is
bool is(T &object)
Definition: generics.h:292
ucommon::_TEXT
const char * _TEXT(const char *s)
Definition: shell.h:911