"Fossies" - the Fresh Open Source Software Archive 
Member "encfs-1.9.5/encfs/encfsctl.cpp" (27 Apr 2018, 22751 Bytes) of package /linux/misc/encfs-1.9.5.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "encfsctl.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.9.4_vs_1.9.5.
1 /*****************************************************************************
2 * Author: Valient Gough <vgough@pobox.com>
3 *
4 *****************************************************************************
5 * Copyright (c) 2004, Valient Gough
6 *
7 * This program is free software; you can distribute it and/or modify it under
8 * the terms of the GNU General Public License (GPL), as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 */
17
18 #include <fcntl.h>
19 #include <getopt.h>
20 #include <iostream>
21 #include <limits.h>
22 #include <memory>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <string>
27 #include <sys/stat.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <vector>
31
32 #define NO_DES
33 #include <openssl/ssl.h>
34
35 #include "Cipher.h"
36 #include "CipherKey.h"
37 #include "Context.h"
38 #include "DirNode.h"
39 #include "Error.h"
40 #include "FSConfig.h"
41 #include "FileNode.h"
42 #include "FileUtils.h"
43 #include "Interface.h"
44 #include "autosprintf.h"
45 #include "config.h"
46 #include "i18n.h"
47 #include "intl/gettext.h"
48
49 #ifndef PATH_MAX
50 #define PATH_MAX 4096
51 #endif
52
53 using namespace std;
54 using gnu::autosprintf;
55 using namespace encfs;
56
57 static int showInfo(int argc, char **argv);
58 static int showVersion(int argc, char **argv);
59 static int chpasswd(int argc, char **argv);
60 static int chpasswdAutomaticly(int argc, char **argv);
61 static int ckpasswdAutomaticly(int argc, char **argv);
62 static int cmd_ls(int argc, char **argv);
63 static int cmd_decode(int argc, char **argv);
64 static int cmd_encode(int argc, char **argv);
65 static int cmd_showcruft(int argc, char **argv);
66 static int cmd_cat(int argc, char **argv);
67 static int cmd_export(int argc, char **argv);
68 static int cmd_showKey(int argc, char **argv);
69
70 struct CommandOpts {
71 const char *name;
72 int minOptions;
73 int maxOptions;
74 int (*func)(int argc, char **argv);
75 const char *argStr;
76 const char *usageStr;
77 } commands[] = {
78 {"info", 1, 1, showInfo, "(root dir)",
79 // xgroup(usage)
80 gettext_noop(" -- show information (Default command)")},
81 {"showKey", 1, 1, cmd_showKey, "(root dir)",
82 // xgroup(usage)
83 gettext_noop(" -- show key")},
84 {"passwd", 1, 1, chpasswd, "(root dir)",
85 // xgroup(usage)
86 gettext_noop(" -- change password for volume")},
87 {"autopasswd", 1, 1, chpasswdAutomaticly, "(root dir)",
88 // xgroup(usage)
89 gettext_noop(" -- change password for volume, taking password"
90 " from standard input.\n\tNo prompts are issued.")},
91 {"autocheckpasswd", 1, 1, ckpasswdAutomaticly, "(root dir)",
92 // xgroup(usage)
93 gettext_noop(" -- check password for volume, taking password"
94 " from standard input.\n\tNo prompts are issued.")},
95 {"ls", 1, 2, cmd_ls, 0, 0},
96 {"showcruft", 1, 1, cmd_showcruft, "(root dir)",
97 // xgroup(usage)
98 gettext_noop(" -- show undecodable filenames in the volume")},
99 {"cat", 2, 4, cmd_cat, "[--extpass=prog] [--reverse] (root dir) path",
100 // xgroup(usage)
101 gettext_noop(" -- decodes the file and cats it to standard out")},
102 {"decode", 1, 100, cmd_decode,
103 "[--extpass=prog] (root dir) [encoded-name ...]",
104 // xgroup(usage)
105 gettext_noop(" -- decodes name and prints plaintext version")},
106 {"encode", 1, 100, cmd_encode,
107 "[--extpass=prog] (root dir) [plaintext-name ...]",
108 // xgroup(usage)
109 gettext_noop(" -- encodes a filename and print result")},
110 {"export", 2, 2, cmd_export, "(root dir) path",
111 // xgroup(usage)
112 gettext_noop(" -- decrypts a volume and writes results to path")},
113 {"--version", 0, 0, showVersion, "",
114 // xgroup(usage)
115 gettext_noop(" -- print version number and exit")},
116 {0, 0, 0, 0, 0, 0}};
117
118 auto ctx = std::make_shared<EncFS_Context>();
119
120 static void usage(const char *name) {
121 cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n"
122 << _("Usage:\n")
123 // displays usage commands, eg "./encfs (root dir) ..."
124 // xgroup(usage)
125 << autosprintf(
126 _("%s (root dir)\n"
127 " -- displays information about the filesystem, or \n"),
128 name);
129
130 int offset = 0;
131 while (commands[offset].name != 0) {
132 if (commands[offset].argStr != 0) {
133 cerr << "encfsctl " << commands[offset].name << " "
134 << commands[offset].argStr << "\n"
135 << gettext(commands[offset].usageStr) << "\n";
136 }
137 ++offset;
138 }
139
140 cerr << "\n"
141 // xgroup(usage)
142 << autosprintf(_("Example: \n%s info ~/.crypt\n"), name) << "\n";
143 }
144
145 static bool checkDir(string &rootDir) {
146 if (!isDirectory(rootDir.c_str())) {
147 cerr << autosprintf(_("directory %s does not exist.\n"), rootDir.c_str());
148 return false;
149 }
150 if (rootDir[rootDir.length() - 1] != '/') rootDir.append("/");
151
152 return true;
153 }
154
155 static int showVersion(int argc, char **argv) {
156 (void)argc;
157 (void)argv;
158 // xgroup(usage)
159 cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n";
160
161 return EXIT_SUCCESS;
162 }
163
164 static int showInfo(int argc, char **argv) {
165 (void)argc;
166 string rootDir = argv[1];
167 if (!checkDir(rootDir)) return EXIT_FAILURE;
168
169 std::shared_ptr<EncFSConfig> config(new EncFSConfig);
170 ConfigType type = readConfig(rootDir, config.get(), "");
171
172 // show information stored in config..
173 switch (type) {
174 case Config_None:
175 // xgroup(diag)
176 cout << _("Unable to load or parse config file\n");
177 return EXIT_FAILURE;
178 case Config_Prehistoric:
179 // xgroup(diag)
180 cout << _(
181 "A really old EncFS filesystem was found. \n"
182 "It is not supported in this EncFS build.\n");
183 return EXIT_FAILURE;
184 case Config_V3:
185 // xgroup(diag)
186 cout << "\n"
187 << autosprintf(_("Version 3 configuration; "
188 "created by %s\n"),
189 config->creator.c_str());
190 break;
191 case Config_V4:
192 // xgroup(diag)
193 cout << "\n"
194 << autosprintf(_("Version 4 configuration; "
195 "created by %s\n"),
196 config->creator.c_str());
197 break;
198 case Config_V5:
199 // xgroup(diag)
200 cout << "\n"
201 << autosprintf(_("Version 5 configuration; "
202 "created by %s (revision %i)\n"),
203 config->creator.c_str(), config->subVersion);
204 break;
205 case Config_V6:
206 // xgroup(diag)
207 cout << "\n"
208 << autosprintf(_("Version 6 configuration; "
209 "created by %s (revision %i)\n"),
210 config->creator.c_str(), config->subVersion);
211 break;
212 }
213
214 showFSInfo(config.get());
215
216 return EXIT_SUCCESS;
217 }
218
219 static RootPtr initRootInfo(int &argc, char **&argv) {
220 RootPtr result;
221 std::shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
222 opts->createIfNotFound = false;
223 opts->checkKey = false;
224
225 static struct option long_options[] = {{"extpass", 1, 0, 'p'}, {"reverse", 0, nullptr, 'r'}, {0, 0, 0, 0}};
226
227 for (;;) {
228 int option_index = 0;
229
230 int res = getopt_long(argc, argv, "", long_options, &option_index);
231 if (res == -1) break;
232
233 switch (res) {
234 case 'p':
235 opts->passwordProgram.assign(optarg);
236 break;
237 case 'r':
238 opts->reverseEncryption = true;
239 break;
240 default:
241 RLOG(WARNING) << "getopt error: " << res;
242 break;
243 }
244 }
245
246 argc -= optind;
247 argv += optind;
248
249 if (argc == 0) {
250 cerr << _("Incorrect number of arguments") << "\n";
251 } else {
252 opts->rootDir = string(argv[0]);
253
254 --argc;
255 ++argv;
256
257 ctx->publicFilesystem = opts->ownerCreate;
258 if (checkDir(opts->rootDir)) result = initFS(ctx.get(), opts);
259
260 if (!result)
261 cerr << _("Unable to initialize encrypted filesystem - check path.\n");
262 }
263
264 return result;
265 }
266
267 static RootPtr initRootInfo(const char *crootDir) {
268 string rootDir(crootDir);
269 RootPtr result;
270
271 if (checkDir(rootDir)) {
272 std::shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
273 opts->rootDir = rootDir;
274 opts->createIfNotFound = false;
275 opts->checkKey = false;
276
277 ctx->publicFilesystem = opts->ownerCreate;
278 result = initFS(ctx.get(), opts);
279 }
280
281 if (!result)
282 cerr << _("Unable to initialize encrypted filesystem - check path.\n");
283
284 return result;
285 }
286
287 static int cmd_showKey(int argc, char **argv) {
288 (void)argc;
289 RootPtr rootInfo = initRootInfo(argv[1]);
290
291 if (!rootInfo)
292 return EXIT_FAILURE;
293 else {
294 // encode with itself
295 string b64Key = rootInfo->cipher->encodeAsString(rootInfo->volumeKey,
296 rootInfo->volumeKey);
297
298 cout << b64Key << "\n";
299
300 return EXIT_SUCCESS;
301 }
302 }
303
304 static int cmd_decode(int argc, char **argv) {
305 RootPtr rootInfo = initRootInfo(argc, argv);
306 if (!rootInfo) return EXIT_FAILURE;
307
308 if (argc > 0) {
309 for (int i = 0; i < argc; ++i) {
310 string name = rootInfo->root->plainPath(argv[i]);
311 cout << name << "\n";
312 }
313 } else {
314 char buf[PATH_MAX + 1];
315 while (cin.getline(buf, PATH_MAX)) {
316 cout << rootInfo->root->plainPath(buf) << "\n";
317 }
318 }
319 return EXIT_SUCCESS;
320 }
321
322 static int cmd_encode(int argc, char **argv) {
323 RootPtr rootInfo = initRootInfo(argc, argv);
324 if (!rootInfo) return EXIT_FAILURE;
325
326 if (argc > 0) {
327 for (int i = 0; i < argc; ++i) {
328 string name = rootInfo->root->cipherPathWithoutRoot(argv[i]);
329 cout << name << "\n";
330 }
331 } else {
332 char buf[PATH_MAX + 1];
333 while (cin.getline(buf, PATH_MAX)) {
334 cout << rootInfo->root->cipherPathWithoutRoot(buf) << "\n";
335 }
336 }
337 return EXIT_SUCCESS;
338 }
339
340 static int cmd_ls(int argc, char **argv) {
341 (void)argc;
342
343 RootPtr rootInfo = initRootInfo(argv[1]);
344
345 if (!rootInfo) return EXIT_FAILURE;
346
347 // show files in directory
348 {
349 DirTraverse dt = rootInfo->root->openDir("/");
350 if (dt.valid()) {
351 for (string name = dt.nextPlaintextName(); !name.empty();
352 name = dt.nextPlaintextName()) {
353 std::shared_ptr<FileNode> fnode =
354 rootInfo->root->lookupNode(name.c_str(), "encfsctl-ls");
355 struct stat stbuf;
356 fnode->getAttr(&stbuf);
357
358 struct tm stm;
359 localtime_r(&stbuf.st_mtime, &stm);
360 stm.tm_year += 1900;
361 // TODO: when I add "%s" to the end and name.c_str(), I get a
362 // seg fault from within strlen. Why ???
363 printf("%11i %4i-%02i-%02i %02i:%02i:%02i %s\n", int(stbuf.st_size),
364 int(stm.tm_year), int(stm.tm_mon), int(stm.tm_mday),
365 int(stm.tm_hour), int(stm.tm_min), int(stm.tm_sec),
366 name.c_str());
367 }
368 }
369 }
370
371 return EXIT_SUCCESS;
372 }
373
374 // apply an operation to every block in the file
375 template <typename T>
376 int processContents(const std::shared_ptr<EncFS_Root> &rootInfo,
377 const char *path, T &op) {
378 int errCode = 0;
379 std::shared_ptr<FileNode> node;
380
381 try {
382 node = rootInfo->root->openNode(path, "encfsctl", O_RDONLY, &errCode);
383 }
384 catch(...) {}
385
386 if (!node) {
387 // try treating filename as an enciphered path
388 string plainName = rootInfo->root->plainPath(path);
389 if (plainName.length() > 0) {
390 node = rootInfo->root->lookupNode(plainName.c_str(), "encfsctl");
391 }
392 if (node) {
393 errCode = node->open(O_RDONLY);
394 if (errCode < 0) node.reset();
395 }
396 }
397
398 if (!node) {
399 cerr << "unable to open " << path << "\n";
400 return errCode;
401 } else {
402 unsigned char buf[512];
403 int blocks = (node->getSize() + sizeof(buf) - 1) / sizeof(buf);
404 // read all the data in blocks
405 for (int i = 0; i < blocks; ++i) {
406 int bytes = node->read(i * sizeof(buf), buf, sizeof(buf));
407 int res = op(buf, bytes);
408 if (res < 0) return res;
409 }
410 }
411 return 0;
412 }
413
414 class WriteOutput {
415 int _fd;
416
417 public:
418 WriteOutput(int fd) { _fd = fd; }
419 ~WriteOutput() { close(_fd); }
420
421 int operator()(const void *buf, int count) {
422 return (int)write(_fd, buf, count);
423 }
424 };
425
426 static int cmd_cat(int argc, char **argv) {
427 RootPtr rootInfo = initRootInfo(argc, argv);
428
429 if (!rootInfo) return EXIT_FAILURE;
430
431 const char *path = argv[0];
432 // If user provides a leading slash, in reverse mode, it will be converted
433 // to "+" by plainpath, and will fail to decode... Workaround below then...
434 if (path[0] == '/') {
435 path++;
436 }
437 WriteOutput output(STDOUT_FILENO);
438 int errCode = processContents(rootInfo, path, output);
439
440 return errCode;
441 }
442
443 static int copyLink(const struct stat &stBuf,
444 const std::shared_ptr<EncFS_Root> &rootInfo,
445 const string &cpath, const string &destName) {
446 std::vector<char> buf(stBuf.st_size + 1, '\0');
447 int res = ::readlink(cpath.c_str(), buf.data(), stBuf.st_size);
448 if (res == -1) {
449 cerr << "unable to readlink of " << cpath << "\n";
450 return EXIT_FAILURE;
451 }
452
453 buf[res] = '\0';
454 string decodedLink = rootInfo->root->plainPath(buf.data());
455
456 res = ::symlink(decodedLink.c_str(), destName.c_str());
457 if (res == -1) {
458 cerr << "unable to create symlink for " << cpath << " to " << decodedLink
459 << "\n";
460 }
461
462 return EXIT_SUCCESS;
463 }
464
465 static int copyContents(const std::shared_ptr<EncFS_Root> &rootInfo,
466 const char *encfsName, const char *targetName) {
467 std::shared_ptr<FileNode> node =
468 rootInfo->root->lookupNode(encfsName, "encfsctl");
469
470 if (!node) {
471 cerr << "unable to open " << encfsName << "\n";
472 return EXIT_FAILURE;
473 } else {
474 struct stat st;
475
476 if (node->getAttr(&st) != 0) return EXIT_FAILURE;
477
478 if ((st.st_mode & S_IFMT) == S_IFLNK) {
479 string d = rootInfo->root->cipherPath(encfsName);
480 char linkContents[PATH_MAX + 2];
481
482 if (readlink(d.c_str(), linkContents, PATH_MAX + 1) <= 0) {
483 cerr << "unable to read link " << encfsName << "\n";
484 return EXIT_FAILURE;
485 }
486 if (symlink(rootInfo->root->plainPath(linkContents).c_str(),
487 targetName) != 0) {
488 cerr << "unable to create symlink " << targetName << "\n";
489 return EXIT_FAILURE;
490 }
491 } else {
492 int outfd = creat(targetName, st.st_mode);
493
494 WriteOutput output(outfd);
495 processContents(rootInfo, encfsName, output);
496 }
497 }
498 return EXIT_SUCCESS;
499 }
500
501 static bool endsWith(const string &str, char ch) {
502 if (str.empty())
503 return false;
504 else
505 return str[str.length() - 1] == ch;
506 }
507
508 static int traverseDirs(const std::shared_ptr<EncFS_Root> &rootInfo,
509 string volumeDir, string destDir) {
510 if (!endsWith(volumeDir, '/')) volumeDir.append("/");
511 if (!endsWith(destDir, '/')) destDir.append("/");
512
513 // Lookup directory node so we can create a destination directory
514 // with the same permissions
515 {
516 struct stat st;
517 std::shared_ptr<FileNode> dirNode =
518 rootInfo->root->lookupNode(volumeDir.c_str(), "encfsctl");
519 if (dirNode->getAttr(&st)) return EXIT_FAILURE;
520
521 mkdir(destDir.c_str(), st.st_mode);
522 }
523
524 // show files in directory
525 DirTraverse dt = rootInfo->root->openDir(volumeDir.c_str());
526 if (dt.valid()) {
527 for (string name = dt.nextPlaintextName(); !name.empty();
528 name = dt.nextPlaintextName()) {
529 // Recurse to subdirectories
530 if (name != "." && name != "..") {
531 string plainPath = volumeDir + name;
532 string cpath = rootInfo->root->cipherPath(plainPath.c_str());
533 string destName = destDir + name;
534
535 int r = EXIT_SUCCESS;
536 struct stat stBuf;
537 if (!lstat(cpath.c_str(), &stBuf)) {
538 if (S_ISDIR(stBuf.st_mode)) {
539 traverseDirs(rootInfo, (plainPath + '/').c_str(), destName + '/');
540 } else if (S_ISLNK(stBuf.st_mode)) {
541 r = copyLink(stBuf, rootInfo, cpath, destName);
542 } else {
543 r = copyContents(rootInfo, plainPath.c_str(), destName.c_str());
544 }
545 } else {
546 r = EXIT_FAILURE;
547 }
548
549 if (r != EXIT_SUCCESS) return r;
550 }
551 }
552 }
553 return EXIT_SUCCESS;
554 }
555
556 static int cmd_export(int argc, char **argv) {
557 (void)argc;
558
559 RootPtr rootInfo = initRootInfo(argv[1]);
560
561 if (!rootInfo) return EXIT_FAILURE;
562
563 string destDir = argv[2];
564 // if the dir doesn't exist, then create it (with user permission)
565 if (!checkDir(destDir) && !userAllowMkdir(destDir.c_str(), 0700))
566 return EXIT_FAILURE;
567
568 return traverseDirs(rootInfo, "/", destDir);
569 }
570
571 int showcruft(const std::shared_ptr<EncFS_Root> &rootInfo,
572 const char *dirName) {
573 int found = 0;
574 DirTraverse dt = rootInfo->root->openDir(dirName);
575 if (dt.valid()) {
576 bool showedDir = false;
577 for (string name = dt.nextInvalid(); !name.empty();
578 name = dt.nextInvalid()) {
579 string cpath = rootInfo->root->cipherPath(dirName);
580 cpath += '/';
581 cpath += name;
582
583 if (!showedDir) {
584 // just before showing a list of files in a directory
585 cout << autosprintf(_("In directory %s: \n"), dirName);
586 showedDir = true;
587 }
588 ++found;
589 cout << cpath << "\n";
590 }
591
592 // now go back and look for directories to recurse into..
593 dt = rootInfo->root->openDir(dirName);
594 if (dt.valid()) {
595 for (string name = dt.nextPlaintextName(); !name.empty();
596 name = dt.nextPlaintextName()) {
597 if (name == "." || name == "..") continue;
598
599 string plainPath = dirName;
600 plainPath += '/';
601 plainPath += name;
602
603 string cpath = rootInfo->root->cipherPath(plainPath.c_str());
604
605 if (isDirectory(cpath.c_str()))
606 found += showcruft(rootInfo, plainPath.c_str());
607 }
608 }
609 }
610
611 return found;
612 }
613
614 /*
615 iterate recursively through the filesystem and print out names of files
616 which have filenames which cannot be decoded with the given key..
617 */
618 static int cmd_showcruft(int argc, char **argv) {
619 (void)argc;
620
621 RootPtr rootInfo = initRootInfo(argv[1]);
622
623 if (!rootInfo) return EXIT_FAILURE;
624
625 int filesFound = showcruft(rootInfo, "/");
626
627 // TODO: the singular version should say "Found an invalid file", but all the
628 // translations
629 // depend upon this broken singular form, so it isn't easy to change.
630 cerr << autosprintf(ngettext("Found %i invalid file.",
631 "Found %i invalid files.", filesFound),
632 filesFound)
633 << "\n";
634
635 return EXIT_SUCCESS;
636 }
637
638 static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc,
639 char **argv) {
640 (void)argc;
641 string rootDir = argv[1];
642 if (!checkDir(rootDir)) return EXIT_FAILURE;
643
644 EncFSConfig *config = new EncFSConfig;
645 ConfigType cfgType = readConfig(rootDir, config, "");
646
647 if (cfgType == Config_None) {
648 cout << _("Unable to load or parse config file\n");
649 return EXIT_FAILURE;
650 }
651
652 // instanciate proper cipher
653 std::shared_ptr<Cipher> cipher =
654 Cipher::New(config->cipherIface, config->keySize);
655 if (!cipher) {
656 cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
657 config->cipherIface.name().c_str());
658 return EXIT_FAILURE;
659 }
660
661 // ask for existing password
662 cout << _("Enter current Encfs password\n");
663 if (annotate) cerr << "$PROMPT$ passwd" << endl;
664 CipherKey userKey = config->getUserKey(useStdin);
665 if (!userKey) return EXIT_FAILURE;
666
667 // decode volume key using user key -- at this point we detect an incorrect
668 // password if the key checksum does not match (causing readKey to fail).
669 CipherKey volumeKey = cipher->readKey(config->getKeyData(), userKey);
670
671 if (!volumeKey) {
672 cout << _("Invalid password\n");
673 return EXIT_FAILURE;
674 }
675
676 if (checkOnly) {
677 cout << _("Password is correct\n");
678 return EXIT_SUCCESS;
679 }
680
681 // Now, get New user key..
682 userKey.reset();
683 cout << _("Enter new Encfs password\n");
684 // reinitialize salt and iteration count
685 config->kdfIterations = 0; // generate new
686
687 if (useStdin) {
688 if (annotate) cerr << "$PROMPT$ new_passwd" << endl;
689 userKey = config->getUserKey(true);
690 } else
691 userKey = config->getNewUserKey();
692
693 // re-encode the volume key using the new user key and write it out..
694 int result = EXIT_FAILURE;
695 if (userKey) {
696 int encodedKeySize = cipher->encodedKeySize();
697 unsigned char *keyBuf = new unsigned char[encodedKeySize];
698
699 // encode volume key with new user key
700 cipher->writeKey(volumeKey, keyBuf, userKey);
701 userKey.reset();
702
703 config->assignKeyData(keyBuf, encodedKeySize);
704 delete[] keyBuf;
705
706 if (saveConfig(cfgType, rootDir, config, "")) {
707 // password modified -- changes volume key of filesystem..
708 cout << _("Volume Key successfully updated.\n");
709 result = EXIT_SUCCESS;
710 } else {
711 cout << _("Error saving modified config file.\n");
712 }
713 } else {
714 cout << _("Error creating key\n");
715 }
716
717 volumeKey.reset();
718
719 return result;
720 }
721
722 static int chpasswd(int argc, char **argv) {
723 return do_chpasswd(false, false, false, argc, argv);
724 }
725
726 static int chpasswdAutomaticly(int argc, char **argv) {
727 return do_chpasswd(true, false, false, argc, argv);
728 }
729
730 static int ckpasswdAutomaticly(int argc, char **argv) {
731 return do_chpasswd(true, false, true, argc, argv);
732 }
733
734 int main(int argc, char **argv) {
735 START_EASYLOGGINGPP(argc, argv);
736 encfs::initLogging();
737
738 #if defined(ENABLE_NLS) && defined(LOCALEDIR)
739 setlocale(LC_ALL, "");
740 bindtextdomain(PACKAGE, LOCALEDIR);
741 textdomain(PACKAGE);
742 #endif
743
744 SSL_load_error_strings();
745 SSL_library_init();
746
747 if (argc < 2) {
748 usage(argv[0]);
749 return EXIT_FAILURE;
750 }
751
752 // Skip over uninteresting args.
753 while (argc > 2 && *argv[1] == '-') {
754 VLOG(1) << "skipping arg " << argv[1];
755 argc--;
756 argv[1] = argv[0];
757 argv++;
758 }
759
760 if (argc == 2 && !(*argv[1] == '-' && *(argv[1] + 1) == '-')) {
761 // default command when only 1 argument given -- treat the argument as
762 // a directory..
763 return showInfo(argc, argv);
764 } else {
765 // find the specified command
766 int offset = 0;
767 while (commands[offset].name != 0) {
768 if (!strcmp(argv[1], commands[offset].name)) break;
769 ++offset;
770 }
771
772 if (commands[offset].name == 0) {
773 cerr << autosprintf(_("invalid command: \"%s\""), argv[1]) << "\n";
774 } else {
775 if ((argc - 2 < commands[offset].minOptions) ||
776 (argc - 2 > commands[offset].maxOptions)) {
777 cerr << autosprintf(
778 _("Incorrect number of arguments for command \"%s\""),
779 argv[1])
780 << "\n";
781 } else
782 return (*commands[offset].func)(argc - 1, argv + 1);
783 }
784 }
785
786 return EXIT_FAILURE;
787 }