Annotation of truecrypt/linux/cli/cli.c, revision 1.1.1.3

1.1       root        1: /* 
1.1.1.3 ! root        2: Copyright (c) 2004-2006 TrueCrypt Foundation. All rights reserved. 
1.1       root        3: 
                      4: Covered by TrueCrypt License 2.0 the full text of which is contained in the file
                      5: License.txt included in TrueCrypt binary and source code distribution archives. 
                      6: */
                      7: 
                      8: #define _LARGEFILE_SOURCE      1
                      9: #define _FILE_OFFSET_BITS      64
                     10: 
                     11: #include <getopt.h>
                     12: #include <inttypes.h>
                     13: #include <stdarg.h>
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
1.1.1.3 ! root       16: #include <strings.h>
1.1       root       17: #include <sys/mman.h>
                     18: #include <sys/stat.h>
1.1.1.3 ! root       19: #include <sys/time.h>
1.1       root       20: #include <sys/types.h>
                     21: #include <sys/wait.h>
1.1.1.3 ! root       22: #include <fcntl.h>
1.1       root       23: #include <termios.h>
                     24: #include <time.h>
                     25: #include <unistd.h>
                     26: #include <utime.h>
                     27: 
                     28: #include "Tcdefs.h"
                     29: #include "Keyfiles.h"
1.1.1.3 ! root       30: #include "Fat.h"
        !            31: #include "Format.h"
        !            32: #include "Progress.h"
        !            33: #include "Random.h"
1.1       root       34: #include "Volumes.h"
                     35: #include "Tests.h"
                     36: #include "Dm-target.h"
                     37: 
                     38: #define MAX_VOLUMES    256
                     39: #define MAX_MINOR 256
                     40: 
                     41: #undef MAX_PATH
                     42: #define MAX_PATH 260
                     43: #define MAX_PATH_STR "259"
                     44: 
                     45: #define TC_MAP_DEV "/dev/mapper/truecrypt"
                     46: #define LOOP_DEV "/dev/loop"
                     47: 
                     48: #define error(fmt, args...) fprintf (stderr, "truecrypt: " fmt, ## args)
                     49: 
                     50: typedef struct
                     51: {
                     52:        int DeviceNumber;
                     53:        int DeviceMajor;
                     54:        int DeviceMinor;
                     55:        uint64_t VolumeSize;
                     56:        char VolumePath[MAX_PATH];
                     57:        int EA;
1.1.1.2   root       58:        int Mode;
1.1       root       59:        BOOL Hidden;
                     60:        uint64_t ReadOnlyStart;
                     61:        uint64_t ReadOnlyEnd;
                     62:        uint64_t ModTime;
                     63:        uint64_t AcTime;
                     64:        int Flags;
                     65: } MountListEntry;
                     66: 
                     67: static MountListEntry MountList[MAX_VOLUMES];
                     68: static BOOL MountListValid = FALSE;
                     69: 
1.1.1.3 ! root       70: static BOOL DisplayKeys = FALSE;
1.1       root       71: static BOOL DisplayPassword = FALSE;
1.1.1.3 ! root       72: static BOOL DisplayProgress = TRUE;
        !            73: static BOOL UserMount = FALSE;
1.1       root       74: static char *Filesystem = NULL;
                     75: static char *MountOpts = NULL;
                     76: static int PasswordEntryTries = 3;
                     77: static Password CmdPassword;
                     78: static Password CmdPassword2;
                     79: static BOOL CmdPasswordValid = FALSE;
                     80: static BOOL CmdPassword2Valid = FALSE;
                     81: static int UseDeviceNumber = -1;
                     82: static BOOL ProtectHidden = FALSE;
                     83: static BOOL ReadOnly = FALSE;
                     84: static BOOL UpdateTime = FALSE;
                     85: static int Verbose = 0;
                     86: 
                     87: static BOOL    IsTerminal = FALSE;
                     88: static struct termios TerminalAttributes;
                     89: static Password password;
                     90: static KeyFile *FirstKeyFile;
                     91: static KeyFile *FirstProtVolKeyFile;
1.1.1.3 ! root       92: static KeyFile *FirstNewKeyFile;
        !            93: 
        !            94: static uid_t RealUserId;
        !            95: static gid_t RealGroupId;
1.1       root       96: 
1.1.1.3 ! root       97: static unsigned __int64 VolumeSize;
        !            98: static unsigned int ClusterSize = 0;
        !            99: static int EA;
        !           100: static int EAMode;
        !           101: static int HashAlgorithm;
        !           102: static char *Filesystem;
        !           103: static int VolumeType = -1;
        !           104: static BOOL Quick;
1.1       root      105: 
                    106: static void SecurityCleanup ()
                    107: {
                    108:        burn (&password, sizeof (password));
                    109:        burn (&CmdPassword, sizeof (CmdPassword));
                    110:        burn (&CmdPassword2, sizeof (CmdPassword2));
                    111: }
                    112: 
                    113: 
                    114: static void OnSignal (int signal)
                    115: {
                    116:        SecurityCleanup ();
                    117: 
                    118:        if (IsTerminal)
                    119:        {
                    120:                tcsetattr (0, TCSANOW, &TerminalAttributes);
                    121:                puts ("");
                    122:        }
                    123: 
                    124:        _exit (1);
                    125: }
                    126: 
                    127: 
                    128: static void OnExit ()
                    129: {
                    130:        SecurityCleanup ();
                    131: }
                    132: 
                    133: 
1.1.1.3 ! root      134: BOOL CheckAdminPrivileges ()
        !           135: {
        !           136:        char *env;
        !           137: 
        !           138:        if (getuid () != 0 && geteuid () != 0)
        !           139:        {
        !           140:                error ("Administrator (root) privileges required\n");
        !           141:                return FALSE;
        !           142:        }
        !           143: 
        !           144:        if (getuid () != 0)
        !           145:        {
        !           146:                // Impersonate root to support executing of commands like mount
        !           147:                setuid (0);
        !           148: 
        !           149:                // Allow execution of system binaries only
        !           150:                setenv ("PATH", "/usr/sbin:/sbin:/usr/bin:/bin", 1);
        !           151:        }
        !           152: 
        !           153:        return TRUE;
        !           154: }
        !           155: 
        !           156: 
        !           157: void DropEffectiveUserId ()
        !           158: {
        !           159:        setuid (getuid ());
        !           160: }
        !           161: 
        !           162: 
        !           163: BOOL LockMemory ()
        !           164: {
        !           165:        // Lock process memory
        !           166:        if (mlockall (MCL_FUTURE) != 0)
        !           167:        {
        !           168:                perror ("Cannot prevent memory swapping: mlockall");
        !           169:                return FALSE;
        !           170:        }
        !           171: 
        !           172:        return TRUE;
        !           173: }
        !           174: 
        !           175: 
1.1       root      176: static BOOL WaitChild (BOOL quiet, char *execName)
                    177: {
                    178:        int status;
                    179:        if (wait (&status) == -1)
                    180:        {
                    181:                perror ("wait");
                    182:                return FALSE;
                    183:        }
                    184: 
                    185:        if (!WIFEXITED (status)
                    186:                || (WIFEXITED (status) && WEXITSTATUS (status)))
                    187:        {
                    188:                if (!quiet && Verbose >= 3)
                    189:                        error ("Error: %s returned %d\n", execName, WEXITSTATUS (status));
                    190:                return FALSE;
                    191:        }
                    192: 
                    193:        return TRUE;
                    194: }
                    195: 
                    196: 
                    197: BOOL Execute (BOOL quiet, char *execName, ...)
                    198: {
                    199:        int pid;
                    200:        va_list vl;
                    201:        va_start (vl, execName);
                    202: 
                    203:        pid = fork ();
                    204:        if (pid == -1)
                    205:        {
                    206:                perror ("fork");
                    207:                goto err;
                    208:        }
                    209:        else if (pid == 0)
                    210:        {
                    211:                char *args[32];
                    212:                int i = 1;
                    213: 
                    214:                SecurityCleanup ();
                    215: 
                    216:                if (Verbose >= 3)
                    217:                        printf ("Executing %s", execName);
                    218: 
                    219:                args[0] = execName;
                    220:                while (i < 32 && (args[i] = (va_arg (vl, char *))))
                    221:                {
                    222:                        if (Verbose >= 3)
                    223:                                printf (" %s", args[i]);
                    224:                        i++;
                    225:                }
                    226: 
                    227:                if (Verbose >= 3)
                    228:                        puts ("");
                    229: 
                    230:                if (quiet)
                    231:                {
                    232:                        // >/dev/null is safer than >&-
                    233:                        int i = open ("/dev/null", 0);
                    234:                        if (i == -1)
                    235:                        {
                    236:                                perror ("open /dev/null");
                    237:                                _exit (1);
                    238:                        }
                    239: 
                    240:                        dup2 (i, STDOUT_FILENO);
                    241:                        dup2 (i, STDERR_FILENO);
                    242:                }
                    243: 
                    244:                execvp (execName, args);
                    245: 
                    246:                fprintf (stderr, "%s ", execName);
                    247:                perror ("execlp");
                    248:                _exit (1);
                    249:        }
                    250: 
                    251:        if (!WaitChild (quiet, execName))
                    252:                goto err;
                    253: 
                    254:        va_end (vl);
                    255:        return TRUE;
                    256: err:
                    257:        va_end (vl);
                    258:        return FALSE;
                    259: }
                    260: 
                    261: 
                    262: static BOOL IsFile (char *path)
                    263: {
                    264:        struct stat st;
                    265:        if (stat (path, &st) != 0)
                    266:                return FALSE;
                    267: 
                    268:        return S_ISREG (st.st_mode);
                    269: }
                    270: 
                    271: 
                    272: static BOOL IsBlockDevice (char *path)
                    273: {
                    274:        struct stat st;
                    275:        if (stat (path, &st) != 0)
                    276:                return FALSE;
                    277: 
                    278:        return S_ISBLK (st.st_mode);
                    279: }
                    280: 
                    281: 
                    282: static BOOL RestoreFileTime (char *path, time_t modTime, time_t acTime)
                    283: {
                    284:        struct utimbuf t;
                    285: 
                    286:        t.actime = acTime;
                    287:        t.modtime = modTime;
                    288: 
                    289:        return utime (path, &t) != 0;
                    290: }
                    291: 
                    292: 
                    293: static BOOL LoadKernelModule ()
                    294: {
                    295:        char s[2048];   
                    296:        FILE *m;
                    297:        
                    298:        m = fopen ("/proc/modules", "r");
                    299:        if (m == NULL)
                    300:        {
                    301:                perror ("fopen /proc/modules");
                    302:                return FALSE;
                    303:        }
                    304: 
                    305:        while (fgets (s, sizeof (s), m))
                    306:        {
                    307:                if (strstr (s, "truecrypt ") == s)
                    308:                {
                    309:                        fclose (m);
                    310:                        return TRUE;
                    311:                }
                    312:        }
                    313: 
                    314:        fclose (m);
                    315: 
                    316:        if (!Execute (FALSE, "modprobe", "truecrypt", NULL))
                    317:        {
                    318:                error ("Failed to load TrueCrypt kernel module\n");
                    319:                return FALSE;
                    320:        }
                    321:        return TRUE;
                    322: }
                    323: 
                    324: 
                    325: static BOOL UnloadKernelModule (BOOL quiet)
                    326: {
                    327:        // rmmod is used instead of modprobe to prevent unload of dependencies
                    328:        return Execute (quiet, "rmmod", "truecrypt", NULL);
                    329: }
                    330: 
                    331: 
                    332: static BOOL CheckKernelModuleVersion (BOOL wait)
                    333: {
                    334:        FILE *p;
                    335:        int pfd[2];
                    336:        int pid, res;
                    337:        int i, dummy;
                    338:        char s[2048];
                    339:        int ver1 = 0, ver2 = 0, ver3 = 0;
                    340:        int tries = 10;
                    341: 
                    342:        do
                    343:        {
                    344:                pipe (pfd);
                    345:                pid = fork ();
                    346: 
                    347:                if (pid == -1)
                    348:                {
                    349:                        perror ("fork");
                    350:                        return FALSE;
                    351:                }
                    352:                else if (pid == 0)
                    353:                {
                    354:                        SecurityCleanup ();
                    355: 
                    356:                        dup2 (pfd[1], STDOUT_FILENO);
                    357:                        close (pfd[0]);
                    358:                        close (STDERR_FILENO);
                    359: 
                    360:                        execlp ("dmsetup", "dmsetup", "targets", NULL);
                    361: 
                    362:                        perror ("execlp dmsetup");
                    363:                        _exit (1);
                    364:                }
                    365: 
                    366:                close (pfd[1]);
                    367:                p = fdopen (pfd[0], "r");
                    368:                if (p == NULL)
                    369:                {
                    370:                        perror ("fdopen");
                    371:                        return FALSE;
                    372:                }
                    373: 
                    374:                while (fgets (s, sizeof (s), p))
                    375:                {
                    376:                        char name[32];
                    377: 
                    378:                        if (sscanf (s, "%31s v%d.%d.%d", &name, &ver1, &ver2, &ver3) == 4
                    379:                                && strcmp (name, "truecrypt") == 0)
                    380:                        {
                    381:                                fclose (p);
                    382:                                WaitChild (FALSE, "dmsetup");
                    383: 
                    384:                                if (ver1 == VERSION_NUM1 && ver2 == VERSION_NUM2 && ver3 == VERSION_NUM3)
                    385:                                        return TRUE;
                    386: 
                    387:                                error ("Incorrect version of kernel module loaded - version %s required\n", VERSION_STRING);
                    388:                                UnloadKernelModule (TRUE);
                    389:                                return FALSE;
                    390:                        }
                    391:                }
                    392: 
                    393:                fclose (p);
                    394:                WaitChild (FALSE, "dmsetup");
                    395: 
                    396:                // Target registration may take some time
                    397:                if (wait)
                    398:                        usleep (100 * 1000);
                    399:                else
                    400:                        break;
                    401: 
                    402:        } while (tries--);
                    403: 
                    404:        error ("Kernel module not loaded\n");
                    405:        return FALSE;
                    406: }
                    407: 
                    408: 
                    409: static BOOL GetMountList ()
                    410: {
                    411:        FILE *p;
                    412:        int pfd[2];
                    413:        int pid, res;
                    414:        int i, dummy;
                    415: 
                    416:        if (MountListValid)
                    417:                return TRUE;
                    418: 
                    419:        MountList[0].DeviceNumber = -1;
                    420: 
                    421:        pipe (pfd);
                    422:        pid = fork ();
                    423: 
                    424:        if (pid == -1)
                    425:        {
                    426:                perror ("fork");
                    427:                goto err;
                    428:        }
                    429:        else if (pid == 0)
                    430:        {
                    431:                SecurityCleanup ();
                    432: 
                    433:                dup2 (pfd[1], STDOUT_FILENO);
                    434:                close (pfd[0]);
                    435:                close (STDERR_FILENO);
                    436: 
                    437:                execlp ("dmsetup", "dmsetup", "table", NULL);
                    438: 
                    439:                perror ("execlp dmsetup");
                    440:                _exit (1);
                    441:        }
                    442: 
                    443:        close (pfd[1]);
                    444:        p = fdopen (pfd[0], "r");
                    445:        if (p == NULL)
                    446:        {
                    447:                perror ("fdopen");
                    448:                goto err;
                    449:        }
                    450: 
                    451:        for (i = 0; i < MAX_VOLUMES; i++)
                    452:        {
1.1.1.2   root      453:                int n = 0;
1.1       root      454:                char s[2048];
                    455:                MountListEntry *e = &MountList[i];
                    456: 
                    457:                if (!fgets (s, sizeof (s), p))
                    458:                        break;
                    459: 
1.1.1.2   root      460:                if (sscanf (s, "truecrypt%d: 0 %lld truecrypt %d %d 0 0 %d:%d %lld %lld %lld %lld %lld %d %n",
1.1       root      461:                        &e->DeviceNumber,
                    462:                        &e->VolumeSize,
                    463:                        &e->EA,
1.1.1.2   root      464:                        &e->Mode,
1.1       root      465:                        &e->DeviceMajor,
                    466:                        &e->DeviceMinor,
                    467:                        &e->Hidden,
                    468:                        &e->ReadOnlyStart,
                    469:                        &e->ReadOnlyEnd,
                    470:                        &e->ModTime,
                    471:                        &e->AcTime,
                    472:                        &e->Flags,
1.1.1.2   root      473:                        &n) >= 12 && n > 0)
1.1       root      474:                {
1.1.1.2   root      475:                        int l;
                    476:                        strncpy (e->VolumePath, s + n, sizeof (e->VolumePath));
                    477:                        l = strlen (s + n);
                    478:                        if (l > 0)
                    479:                                e->VolumePath[l - 1] = 0;
                    480: 
1.1       root      481:                        e->Hidden = e->Hidden == 1 ? FALSE : TRUE;
                    482:                        e->VolumeSize *= SECTOR_SIZE;
                    483:                }
                    484:                else
                    485:                        i--;
                    486:        }
                    487: 
                    488:        MountList[i].DeviceNumber = -1;
                    489: 
                    490:        fclose (p);
                    491:        if (!WaitChild (TRUE, "dmsetup"))
                    492:                goto err;
                    493: 
                    494:        MountListValid = TRUE;
                    495:        return TRUE;
                    496: 
                    497: err:
                    498:        MountList[0].DeviceNumber = -1;
                    499:        return FALSE;
                    500: }
                    501: 
                    502: 
                    503: static BOOL IsVolumeMounted (char *volumePath)
                    504: {
                    505:        int i;
                    506:        if (!GetMountList ())
                    507:                return FALSE;
                    508: 
                    509:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                    510:                if (strcmp (volumePath, MountList[i].VolumePath) == 0)
                    511:                        return TRUE;
                    512: 
                    513:        return FALSE;
                    514: }
                    515: 
                    516: 
                    517: static int GetFreeMapDevice ()
                    518: {
                    519:        FILE *p;
                    520:        char cmd[128];
                    521:        int n;
                    522: 
                    523:        if (!GetMountList ())
                    524:                return -1;
                    525: 
                    526:        for (n = 0; n < MAX_MINOR; n++)
                    527:        {
                    528:                int j = 0;
                    529:                while (MountList[j].DeviceNumber != -1)
                    530:                {
                    531:                        if (MountList[j].DeviceNumber == n)
                    532:                                break;
                    533:                        j++;
                    534:                }
                    535: 
                    536:                if (MountList[j].DeviceNumber == -1)
                    537:                        return n;
                    538:        }
                    539: 
                    540:        return -1;
                    541: }
                    542: 
                    543: 
                    544: static BOOL DeleteLoopDevice (int loopDeviceNo)
                    545: {
                    546:        char dev[32];
                    547:        BOOL r;
                    548: 
                    549:        sprintf (dev, LOOP_DEV "%d", loopDeviceNo);
                    550:        if (!IsBlockDevice (dev))
                    551:                sprintf (dev, LOOP_DEV "/%d", loopDeviceNo);
                    552: 
                    553:        r = Execute (FALSE, "losetup", "-d", dev, NULL);
                    554: 
                    555:        if (r && Verbose > 1)
                    556:                printf ("Detached %s\n", dev);
                    557: 
                    558:        return r;
                    559: }
                    560: 
                    561: 
1.1.1.3 ! root      562: static int AskSelection (int defaultChoice, int min, int max)
        !           563: {
        !           564:        int c;
        !           565:        char s[3];
        !           566: 
        !           567:        while (1)
        !           568:        {
        !           569:                printf ("Select [%d]: ", defaultChoice);
        !           570: 
        !           571:                if (fgets (s, sizeof (s), stdin) && sscanf (s, "%d", &c) == 1)
        !           572:                {
        !           573:                        if (c < min || c > max)
        !           574:                                continue;
        !           575: 
        !           576:                        puts ("");
        !           577:                        return c;
        !           578:                }
        !           579: 
        !           580:                puts ("");
        !           581:                return defaultChoice;
        !           582:        }
        !           583: }
        !           584: 
        !           585: 
        !           586: static char *AskString (char *prompt, char *buf, int maxSize)
        !           587: {
        !           588:        printf ("%s: ", prompt);
        !           589: 
        !           590:        if (fgets (buf, maxSize, stdin))
        !           591:        {
        !           592:                char *lf = strchr (buf, '\n');
        !           593:                if (lf)
        !           594:                        lf[0] = 0;
        !           595: 
        !           596:                return buf;
        !           597:        }
        !           598: 
        !           599:        return NULL;
        !           600: }
        !           601: 
        !           602: 
        !           603: static void AskPassword (char *prompt, char *volumePath, Password *password)
        !           604: {
        !           605:        struct termios noEcho;
        !           606: 
        !           607:        if (tcgetattr (0, &TerminalAttributes) == 0)
        !           608:        {
        !           609:                noEcho = TerminalAttributes;
        !           610: 
        !           611:                if (!DisplayPassword)
        !           612:                {
        !           613:                        noEcho.c_lflag &= ~ECHO;
        !           614:                        if (tcsetattr (0, TCSANOW, &noEcho) != 0)
        !           615:                                error ("Failed to turn terminal echo off\n");
        !           616:                }
        !           617: 
        !           618:                printf (prompt, volumePath);
        !           619:        }
        !           620: 
        !           621:        if (fgets ((char *)password->Text, sizeof (password->Text), stdin))
        !           622:        {
        !           623:                char *newl = strchr ((char *)password->Text, '\n');
        !           624:                if (newl) newl[0] = 0;
        !           625: 
        !           626:                password->Length = strlen ((char *)password->Text);
        !           627:        }
        !           628:        else
        !           629:                password->Length = 0;
        !           630: 
        !           631:        if (IsTerminal && !DisplayPassword)
        !           632:        {
        !           633:                tcsetattr (0, TCSANOW, &TerminalAttributes);
        !           634:                puts ("");
        !           635:        }
        !           636: }
        !           637: 
        !           638: 
        !           639: static char *AskVolumePath (char *volumePath, char *prompt)
        !           640: {
        !           641:        static char path[MAX_PATH];
        !           642: 
        !           643:        // Volume path
        !           644:        while (!volumePath || !volumePath[0])
        !           645:        {
        !           646:                volumePath = AskString (prompt, path, sizeof (path));
        !           647:        }
        !           648: 
        !           649:        return volumePath;
        !           650: }
        !           651: 
        !           652: 
        !           653: static BOOL OpenVolume (char *volumePath, char *prompt, char *promptArg, BOOL secondaryPassword, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime)
1.1       root      654: {
                    655:        char header[SECTOR_SIZE];
                    656:        uint64_t r;
                    657:        FILE *f = NULL;
                    658:        struct stat volumeStat;
1.1.1.3 ! root      659:        int tries = PasswordEntryTries;
        !           660:        char msg[128];
        !           661:        BOOL ret = FALSE;
1.1       root      662: 
                    663:        if (stat (volumePath, &volumeStat) != 0)
                    664:        {
1.1.1.3 ! root      665:                perror ("Cannot read volume's modification and access time");
1.1       root      666:                volumeStat.st_ctime = 0;
                    667:                goto err;
                    668:        }
                    669: 
1.1.1.2   root      670:        f = fopen (volumePath, "rb");
1.1       root      671:        if (!f)
                    672:        {
                    673:                perror ("Cannot open volume");
                    674:                goto err;
                    675:        }
                    676: 
1.1.1.3 ! root      677:        do
1.1       root      678:        {
1.1.1.3 ! root      679:                Password *pw = &password;
1.1       root      680: 
1.1.1.3 ! root      681:                if (!secondaryPassword && !CmdPasswordValid || (secondaryPassword && !CmdPassword2Valid))
        !           682:                        AskPassword (prompt, promptArg, &password);
        !           683:                else
        !           684:                        pw = secondaryPassword ? &CmdPassword2 : &CmdPassword;
1.1       root      685: 
1.1.1.3 ! root      686:                if ((!secondaryPassword
        !           687:                                && FirstKeyFile
        !           688:                                && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
        !           689:                        || (secondaryPassword 
        !           690:                                && FirstProtVolKeyFile
        !           691:                                && !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime)))
        !           692:                {
        !           693:                        error ("Error while processing keyfiles\n");
        !           694:                        goto err;
        !           695:                }
1.1       root      696: 
1.1.1.3 ! root      697:                // Normal header
        !           698:                fseek (f, 0, SEEK_SET);
        !           699:                if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
1.1       root      700:                {
                    701:                        perror ("Cannot read volume header");
                    702:                        goto err;
                    703:                }
                    704: 
1.1.1.3 ! root      705:                if (fseek (f, 0, SEEK_END) == -1)
1.1       root      706:                {
1.1.1.3 ! root      707:                        perror ("Cannot determine volume size");
1.1       root      708:                        goto err;
                    709:                }
                    710: 
1.1.1.3 ! root      711:                r = VolumeReadHeader (header, pw, cryptoInfo);
1.1       root      712: 
1.1.1.3 ! root      713:                if (r == 0)
        !           714:                {
        !           715:                        *totalSectors = ftello (f) / SECTOR_SIZE - 1;
        !           716:                        *startSector = 1;
        !           717:                        ret = TRUE;
        !           718:                        break;
        !           719:                }
1.1.1.2   root      720: 
1.1.1.3 ! root      721:                if (r == ERR_PASSWORD_WRONG)
        !           722:                {
        !           723:                        // Hidden header
        !           724:                        if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1
        !           725:                                || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
        !           726:                        {
        !           727:                                perror ("Cannot read volume header");
        !           728:                                goto err;
        !           729:                        }
        !           730: 
        !           731:                        r = VolumeReadHeader (header, pw, cryptoInfo);
        !           732: 
        !           733:                        if (r == 0)
        !           734:                        {
        !           735:                                *startSector = (ftello (f) 
        !           736:                                        + SECTOR_SIZE * 2 
        !           737:                                        - (*cryptoInfo)->hiddenVolumeSize 
        !           738:                                        - HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE;
        !           739: 
        !           740:                                *totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE;
        !           741:                                ret = TRUE;
        !           742:                                break;
        !           743:                        }
        !           744:                        
        !           745:                        if (r == ERR_PASSWORD_WRONG)
        !           746:                        {
        !           747:                                if (IsTerminal)
        !           748:                                {
        !           749:                                        puts ("Incorrect password or not a TrueCrypt volume.");
        !           750:                                        continue;
        !           751:                                }
        !           752:                                else
        !           753:                                {
        !           754:                                        error ("Incorrect password or not a TrueCrypt volume.\n");
        !           755:                                        goto err;
        !           756:                                }
        !           757:                        }
        !           758:                }
1.1.1.2   root      759: 
1.1.1.3 ! root      760:                // Report errors
1.1.1.2   root      761:                switch (r)
                    762:                {
                    763:                case ERR_NEW_VERSION_REQUIRED:
1.1.1.3 ! root      764:                        strcpy (msg, "A newer version of TrueCrypt is required to open this volume."); 
1.1.1.2   root      765:                        break;
                    766: 
                    767:                default:
                    768:                        sprintf (msg, "Volume cannot be opened: Error %d", r);
                    769:                        break;
                    770:                }
                    771: 
                    772:                if (IsTerminal)
                    773:                        printf ("%s\n", msg);
                    774:                else
                    775:                        error ("%s\n", msg);
                    776: 
                    777:                goto err;
1.1.1.3 ! root      778: 
        !           779:        } while (IsTerminal
        !           780:                && --tries > 0
        !           781:                && ((!secondaryPassword && !CmdPasswordValid)
        !           782:                        || (secondaryPassword && !CmdPassword2Valid)));
1.1       root      783: 
                    784:        fclose (f);
                    785: 
                    786:        if (!UpdateTime)
                    787:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
                    788: 
                    789:        *modTime = volumeStat.st_mtime;
                    790:        *acTime = volumeStat.st_atime;
1.1.1.3 ! root      791: 
        !           792:        return ret;
1.1       root      793: 
                    794: err:
                    795:        *cryptoInfo = NULL;
                    796: 
                    797:        if (f)
                    798:                fclose (f);
                    799: 
                    800:        if (volumeStat.st_ctime != 0 && !UpdateTime)
                    801:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
                    802: 
1.1.1.3 ! root      803:        *totalSectors = 0;
1.1       root      804:        return FALSE;
                    805: }
                    806: 
                    807: 
1.1.1.2   root      808: static char *EscapeSpaces (char *string)
                    809: {
                    810:        static char escapedString[MAX_PATH * 2];
                    811:        char *e = escapedString;
                    812:        char c;
                    813: 
                    814:        if (strlen (string) > MAX_PATH)
                    815:                return NULL;
                    816: 
                    817:        while ((c = *string++))
                    818:        {
                    819:                if (c == ' ')
                    820:                        *e++ = '\\';
                    821: 
                    822:                *e++ = c;
                    823:        }
                    824: 
                    825:        return escapedString;
                    826: }
                    827: 
                    828: 
1.1       root      829: static BOOL MountVolume (char *volumePath, char *mountPoint)
                    830: {
                    831:        char hostDevice[MAX_PATH];
                    832:        char mapDevice[MAX_PATH];
                    833:        int loopDevNo = -1;
                    834:        PCRYPTO_INFO ci = NULL;
                    835:        uint64_t startSector, totalSectors;
                    836:        uint64_t readOnlyStartSector = 0, readOnlySectors = 0;
                    837:        int pfd[2];
                    838:        int pid, res, devNo;
                    839:        time_t modTime, acTime;
                    840:        FILE *f, *w;
                    841:        int flags;
                    842:        int i;
                    843:        int tries = PasswordEntryTries;
                    844: 
1.1.1.3 ! root      845: #if DEBUG
1.1       root      846:        if (!AutoTestAlgorithms ())
                    847:        {
                    848:                error ("Self-tests of algorithms FAILED!\n");
                    849:                return FALSE;
                    850:        }
1.1.1.3 ! root      851: #endif
1.1       root      852: 
                    853:        if (IsVolumeMounted (volumePath))
                    854:        {
1.1.1.3 ! root      855:                error ("Volume already mapped\n");
1.1       root      856:                return FALSE;
                    857:        }
                    858: 
1.1.1.3 ! root      859:        if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE,
        !           860:                &ci, &startSector, &totalSectors, &modTime, &acTime))
        !           861:                goto err;
1.1       root      862: 
                    863:        if (totalSectors == 0)
1.1.1.3 ! root      864:        {
        !           865:                error ("Illegal volume size (0 bytes).\n");
1.1       root      866:                goto err;
1.1.1.3 ! root      867:        }
1.1       root      868: 
                    869:        // Hidden volume protection
                    870:        if (ProtectHidden)
                    871:        {
                    872:                PCRYPTO_INFO ciH = NULL;
                    873:                uint64_t startSectorH, totalSectorsH;
                    874: 
1.1.1.3 ! root      875:                if (OpenVolume (volumePath, "Enter hidden volume password: ", "", TRUE,
        !           876:                        &ciH, &startSectorH, &totalSectorsH, &modTime, &acTime))
1.1       root      877:                {
1.1.1.3 ! root      878:                        readOnlyStartSector = startSectorH;
        !           879:                        readOnlySectors = startSectorH + totalSectorsH;
        !           880:                }
1.1       root      881:                
                    882:                if (ciH)
                    883:                        crypto_close (ciH);
                    884: 
                    885:                if (readOnlySectors == 0)
                    886:                        goto err;
                    887:        }
                    888: 
                    889:        // Headers decrypted
                    890: 
                    891:        // Loopback
                    892:        if (IsFile (volumePath))
                    893:        {
                    894:                int i;
                    895: 
                    896:                for (i = 0; i < MAX_MINOR; i++)
                    897:                {
                    898:                        snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i);
                    899: 
                    900:                        if (!IsBlockDevice (hostDevice))
                    901:                        {
                    902:                                snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i);
                    903:                                if (!IsBlockDevice (hostDevice))
                    904:                                        continue;
                    905:                        }
                    906: 
                    907:                        if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
                    908:                                break;
                    909:                }
                    910: 
                    911:                if (i >= MAX_MINOR)
                    912:                {
                    913:                        error ("No free loopback device available for file-hosted volume\n");
                    914:                        goto err;
                    915:                }
                    916: 
                    917:                loopDevNo = i;
                    918: 
                    919:                if (Verbose > 1)
                    920:                        printf ("Attached %s to %s\n", volumePath, hostDevice);
                    921: 
                    922:        }
                    923:        else
                    924:                strncpy (hostDevice, volumePath, sizeof (hostDevice));
                    925: 
                    926:        // Load kernel module
                    927:        if (!LoadKernelModule ())
                    928:                goto err;
                    929: 
                    930:        if (!CheckKernelModuleVersion (TRUE))
                    931:                goto err;
                    932: 
                    933:        // dmsetup
                    934:        devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber;
                    935:        if (devNo == -1)
                    936:        {
                    937:                error ("Maximum number of volumes mounted\n");
                    938:                goto err;
                    939:        }
                    940: 
                    941:        sprintf (mapDevice, "truecrypt%d", devNo);
                    942: 
                    943:        pipe (pfd);
                    944:        pid = fork ();
                    945: 
                    946:        if (pid == -1)
                    947:        {
                    948:                perror ("fork");
                    949:                goto err;
                    950:        }
                    951:        else if (pid == 0)
                    952:        {
                    953:                SecurityCleanup ();
                    954: 
                    955:                close (pfd[1]);
                    956:                dup2 (pfd[0], STDIN_FILENO);
                    957: 
                    958:                execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL);
                    959: 
                    960:                perror ("execlp dmsetup");
                    961:                _exit (1);
                    962:        }
                    963: 
                    964:        close (pfd[0]);
                    965:        w = fdopen (pfd[1], "a");
                    966:        if (w == NULL)
                    967:        {
                    968:                perror ("fdopen");
                    969:                goto err;
                    970:        }
                    971: 
1.1.1.2   root      972:        fprintf (w, "0 %lld truecrypt %d %d ", totalSectors, ci->ea, ci->mode);
1.1       root      973: 
                    974:        for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++)
                    975:                fprintf (w, "%02x", ci->master_key[i]);
                    976: 
                    977:        fprintf (w, " ");
                    978: 
                    979:        for (i = 0; i < (int)sizeof (ci->iv); i++)
                    980:                fprintf (w, "%02x", ci->iv[i]);
                    981: 
                    982:        flags = 0;
                    983: 
                    984:        if (ReadOnly)
                    985:                flags |= FLAG_READ_ONLY;
                    986:        else if (ProtectHidden)
                    987:                flags |= FLAG_HIDDEN_VOLUME_PROTECTION;
                    988: 
                    989:        fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n",
                    990:                hostDevice,
                    991:                startSector,
                    992:                readOnlyStartSector,
                    993:                readOnlySectors,
                    994:                (uint64_t) modTime,
                    995:                (uint64_t) acTime,
                    996:                flags,
1.1.1.2   root      997:                EscapeSpaces (volumePath));
1.1       root      998: 
                    999:        fclose (w);
                   1000: 
                   1001:        if (!WaitChild (FALSE, "dmsetup"))
                   1002:        {
                   1003:                Execute (TRUE, "dmsetup", "remove", mapDevice, NULL);
                   1004:                goto err;
                   1005:        }
                   1006: 
                   1007:        sprintf (mapDevice, TC_MAP_DEV "%d", devNo);
                   1008: 
                   1009:        if (Verbose >= 1)
                   1010:                printf ("Mapped %s as %s\n", volumePath, mapDevice);
                   1011: 
                   1012:        // Mount
                   1013:        if (mountPoint)
                   1014:        {
                   1015:                char fstype[64], opts[128];
                   1016: 
                   1017:                strcpy (fstype, "-t");
                   1018:                if (Filesystem)
                   1019:                        strncat (fstype, Filesystem, sizeof (fstype) - 3);
                   1020:                else
                   1021:                        strcat (fstype, "auto");
                   1022: 
                   1023:                strcpy (opts, ReadOnly ? "-oro" : "-orw");
                   1024:                if (MountOpts)
                   1025:                {
                   1026:                        strcat (opts, ",");
                   1027:                        strncat (opts, MountOpts, sizeof (opts) - 6);
                   1028:                }
                   1029: 
1.1.1.3 ! root     1030:                if (UserMount)
        !          1031:                {
        !          1032:                        // Set default uid and gid
        !          1033:                        char s[64];
        !          1034:                        sprintf (s, ",uid=%d,gid=%d", RealUserId, RealGroupId);
        !          1035:                        strcat (opts, s);
        !          1036:                }
        !          1037: 
1.1       root     1038:                if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL))
                   1039:                {
                   1040:                        error ("Mount failed\n");
                   1041:                        loopDevNo = -1;
                   1042:                        goto err;
                   1043:                }
                   1044: 
                   1045:                if (Verbose >= 1)
                   1046:                        printf ("Mounted %s at %s\n", mapDevice, mountPoint);
                   1047:        }
                   1048: 
                   1049:        crypto_close (ci);
                   1050: 
                   1051:        return TRUE;
                   1052: 
                   1053: err:
                   1054:        if (ci)
                   1055:                crypto_close (ci);
                   1056: 
                   1057:        if (loopDevNo != -1)
                   1058:                DeleteLoopDevice (loopDevNo);
                   1059: 
                   1060:        UnloadKernelModule (TRUE);
                   1061: 
                   1062:        return FALSE;
                   1063: }
                   1064: 
                   1065: 
1.1.1.3 ! root     1066: int RandGetBytesAvailable ()
1.1       root     1067: {
1.1.1.3 ! root     1068:        int n = -1;
        !          1069:        FILE *f = fopen ("/proc/sys/kernel/random/entropy_avail", "r");
        !          1070:        
        !          1071:        if (f == NULL)
        !          1072:                return -1;
1.1       root     1073: 
1.1.1.3 ! root     1074:        if (fscanf (f, "%d", &n) == 1)
        !          1075:                n /= 8;
1.1       root     1076: 
1.1.1.3 ! root     1077:        fclose (f);
        !          1078:        return n;
        !          1079: }
        !          1080: 
        !          1081: 
        !          1082: void RandBytesFillRequired (int randReq)
        !          1083: {
        !          1084:        int n;
        !          1085: 
        !          1086:        if (RandGetBytesAvailable () < randReq)
        !          1087:        {
        !          1088:                printf ("There is not enough entropy available in the kernel random pool. Please move\n"
        !          1089:                        "the mouse randomly and/or press random keys. Both the mouse and keyboard must\n"
        !          1090:                        "be physically connected to the computer where TrueCrypt is running. Disk\n"
        !          1091:                        "activity (read/write) can also be used to fill the kernel random pool.\n\n");
        !          1092: 
        !          1093:                while ((n = RandGetBytesAvailable()) < randReq)
        !          1094:                {
        !          1095:                        if (n < 0)
        !          1096:                        {
        !          1097:                                printf ("WARNING: Number of random bytes available could not be determined.\n"
        !          1098:                                        "If the volume creation does not start, try moving the mouse or pressing keys\n"
        !          1099:                                        "to increase the random pool entropy.\n");
        !          1100:                                break;
        !          1101:                        }
        !          1102: 
        !          1103:                        printf ("\rRandom bytes available: %d%%", n * 100 / (randReq));
        !          1104:                        fflush (stdout);
        !          1105:                        usleep (200 * 1000);
        !          1106:                }
        !          1107: 
        !          1108:                if (n > 0)
        !          1109:                        printf ("\rRandom bytes available: 100%%\n\n");
        !          1110:        }
        !          1111: }
        !          1112: 
        !          1113: 
        !          1114: BOOL RandpeekBytes (unsigned char *buf , int len)
        !          1115: {
        !          1116:        int f = open ("/dev/urandom", 0);
        !          1117: 
        !          1118:        if (f == -1)
        !          1119:        {
        !          1120:                perror ("Cannot open /dev/urandom");
        !          1121:                return FALSE;
        !          1122:        }
        !          1123: 
        !          1124:        if (read (f, buf, len) != len)
        !          1125:        {
        !          1126:                perror ("Read from /dev/urandom failed");
        !          1127:                return FALSE;
        !          1128:        }
        !          1129: 
        !          1130:        close (f);
        !          1131:        return TRUE;
        !          1132: }
        !          1133: 
        !          1134: 
        !          1135: BOOL RandgetBytes (unsigned char *buf , int len, BOOL forceSlowPoll)
        !          1136: {
        !          1137:        char m[128];
        !          1138:        int f = open ("/dev/random", 0);
        !          1139:        int r;
        !          1140: 
        !          1141:        if (f == -1)
        !          1142:        {
        !          1143:                perror ("Cannot open /dev/random");
        !          1144:                return FALSE;
        !          1145:        }
        !          1146: 
        !          1147:        while ((r = read (f, buf++, 1)) == 1 && --len);
        !          1148: 
        !          1149:        if (r == -1)
        !          1150:        {
        !          1151:                perror ("Read from /dev/random failed");
        !          1152:                close (f);
        !          1153:                return FALSE;
        !          1154:        }
        !          1155: 
        !          1156:        if (len > 0)
        !          1157:        {
        !          1158:                perror ("Cannot read enough bytes from /dev/random");
        !          1159:                close (f);
        !          1160:                return FALSE;
        !          1161:        }
        !          1162: 
        !          1163:        close (f);
        !          1164:        return TRUE;
        !          1165: }
        !          1166: 
        !          1167: 
        !          1168: void HexDump (unsigned __int8 *data, unsigned int length)
        !          1169: {
        !          1170:        while (length--)
        !          1171:                printf ("%02x", (unsigned int) *data++);
        !          1172: }
        !          1173: 
        !          1174: 
        !          1175: double GetTime ()
        !          1176: {
        !          1177:        struct timeval tv;
        !          1178:        gettimeofday (&tv, NULL);
        !          1179: 
        !          1180:        return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
        !          1181: }
        !          1182: 
        !          1183: 
        !          1184: static __int64 TotalSectors, StartSector;
        !          1185: static double StartTime;
        !          1186: static double LastUpdateTime;
        !          1187: 
        !          1188: 
        !          1189: void InitProgressBar (__int64 totalSectors)
        !          1190: {
        !          1191:        LastUpdateTime = 0;
        !          1192:        StartTime = GetTime ();
        !          1193:        TotalSectors = totalSectors;
        !          1194: }
        !          1195: 
        !          1196: 
        !          1197: BOOL UpdateProgressBar (__int64 sector)
        !          1198: {
        !          1199:        unsigned __int64 s = sector - StartSector;
        !          1200:        double t = GetTime ();
        !          1201:        double elapsed = t - StartTime;
        !          1202:        unsigned __int64 bytesDone = (s + 1) * SECTOR_SIZE;
        !          1203:        unsigned __int64 bytesPerSec = bytesDone / (1 + elapsed);
        !          1204:        int timeRemain = (int)((TotalSectors  - s) / ((s + 1)/(elapsed + 1) + 1));
        !          1205: 
        !          1206:        if (DisplayProgress && IsTerminal && t - LastUpdateTime > 0.2)
        !          1207:        {
        !          1208:                printf ("\rDone: %.2f MB  Speed: %.2f MB/s  Left: %d:%02d:%02d  "
        !          1209:                        , (double)bytesDone / 1024 / 1024
        !          1210:                        , (double)bytesPerSec / 1024 / 1024
        !          1211:                        , timeRemain / 3600
        !          1212:                        , (timeRemain % 3600) / 60
        !          1213:                        , (timeRemain % 3600) % 60);
        !          1214: 
        !          1215:                fflush (stdout);
        !          1216:                LastUpdateTime = t;
        !          1217:        }
        !          1218: }
        !          1219: 
        !          1220: 
        !          1221: static BOOL ParseSize (char *string, uint64_t *size)
        !          1222: {
        !          1223:        if (sscanf (string, "%lld", size) == 1)
        !          1224:        {
        !          1225:                if (strchr (string, 'k') || strchr (string, 'K'))
        !          1226:                        *size *= 1024;
        !          1227:                else if (strchr (string, 'M'))
        !          1228:                        *size *= 1024 * 1024;
        !          1229:                else if (strchr (string, 'G'))
        !          1230:                        *size *= 1024 * 1024 * 1024;
        !          1231: 
        !          1232:                *size &= ~0x1FF;
        !          1233: 
        !          1234:                return TRUE;
        !          1235:        }
        !          1236:        return FALSE;
        !          1237: }
        !          1238: 
        !          1239: 
        !          1240: static BOOL CreateVolume (char *hostPath)
        !          1241: {
        !          1242:        PCRYPTO_INFO ci;
        !          1243:        char header[HEADER_SIZE];
        !          1244:        char path[MAX_PATH];
        !          1245:        char str[128];
        !          1246:        FILE *f;
        !          1247:        fatparams ft;
        !          1248:        Password *pw = &password;
        !          1249:        unsigned __int64 startSector, totalSectors, hostSize;
        !          1250:        BOOL hiddenVolume;
        !          1251:        int randReq;
        !          1252:        int i, r = 0;
        !          1253: 
        !          1254:        DropEffectiveUserId ();
        !          1255: 
        !          1256:        // Volume type
        !          1257:        switch (VolumeType)
        !          1258:        {
        !          1259:        case VOLUME_TYPE_NORMAL:
        !          1260:                hiddenVolume = FALSE;
        !          1261:                break;
        !          1262: 
        !          1263:        case VOLUME_TYPE_HIDDEN:
        !          1264:                hiddenVolume = TRUE;
        !          1265:                Quick = TRUE;
        !          1266:                break;
        !          1267: 
        !          1268:        default:
        !          1269:                puts ("Volume type:\n 1) Normal\n 2) Hidden");
        !          1270:                hiddenVolume = AskSelection (1, 1, 2) == 2;
        !          1271:                break;
        !          1272:        }
        !          1273: 
        !          1274:        // Host file or device
        !          1275:        hostPath = AskVolumePath (hostPath, hiddenVolume ? "Enter volume path" : "Enter file or device name for new volume");
        !          1276: 
        !          1277:        if (hiddenVolume)
        !          1278:        {
        !          1279:                if (!IsFile (hostPath) && !IsBlockDevice (hostPath))
        !          1280:                {
        !          1281:                        error ("File or device %s does not exist. Hidden volume cannot be created.\n", hostPath);
        !          1282:                        return FALSE;
        !          1283:                }
        !          1284:                f = fopen (hostPath, "r+b");
        !          1285:        }
        !          1286:        else if (IsFile (hostPath))
        !          1287:        {
        !          1288:                error ("File %s already exists.\n", hostPath);
        !          1289:                return FALSE;
        !          1290:        }
        !          1291:        else
        !          1292:        {
        !          1293:                f = fopen (hostPath, "wb");
        !          1294:        }
        !          1295: 
        !          1296:        if (!f)
        !          1297:        {
        !          1298:                perror ("Cannot open file or device");
        !          1299:                return FALSE;
        !          1300:        }
        !          1301: 
        !          1302:        EAMode = LRW;
        !          1303: 
        !          1304:        // Filesystem
        !          1305:        if (!Filesystem)
        !          1306:        {
        !          1307:                puts ("Filesystem:\n 1) FAT\n 2) None");
        !          1308:                Filesystem = AskSelection (1, 1, 2) == 1 ? "FAT" : "None";
        !          1309:        }
        !          1310: 
        !          1311:        // Host file/device size
        !          1312:        if (fseek (f, 0, SEEK_END) == -1 || (hostSize = ftello (f)) == (unsigned __int64)-1)
        !          1313:        {
        !          1314:                perror ("Cannot determine host file/device size");
        !          1315:                goto err;
        !          1316:        }
        !          1317: 
        !          1318:        // Volume size
        !          1319:        if (IsBlockDevice (hostPath) && !hiddenVolume)
        !          1320:        {
        !          1321:                if (VolumeSize != 0)
        !          1322:                {
        !          1323:                        error ("Volume size cannot be changed for device-hosted volumes.\n");
        !          1324:                        goto err;
        !          1325:                }
        !          1326: 
        !          1327:                VolumeSize = hostSize;
        !          1328:        }
        !          1329:        else if (VolumeSize == 0)
        !          1330:        {
        !          1331:                while (!AskString ("Enter volume size (bytes - size/sizeK/sizeM/sizeG)", str, sizeof (str))
        !          1332:                        || !ParseSize (str, &VolumeSize)
        !          1333:                        || VolumeSize == 0);
        !          1334:                puts ("");
        !          1335:        }
        !          1336: 
        !          1337:        if (hiddenVolume && VolumeSize > hostSize - MIN_VOLUME_SIZE )
        !          1338:        {
        !          1339:                error ("Outer volume too small for the size specified.\n");
        !          1340:                goto err;
        !          1341:        }
        !          1342: 
        !          1343:        if (strcasecmp ("FAT", Filesystem) == 0)
        !          1344:        {
        !          1345:                if (VolumeSize < MIN_VOLUME_SIZE || VolumeSize > MAX_FAT_VOLUME_SIZE)
        !          1346:                {
        !          1347:                        error ("Specified volume size cannot be used with FAT filesystem.\n");
        !          1348:                        goto err;
        !          1349:                }
        !          1350:        }
        !          1351: 
        !          1352:        // Hash algorithm
        !          1353:        if (HashAlgorithm == 0)
        !          1354:        {
        !          1355:                puts ("Hash algorithm:");
        !          1356: 
        !          1357:                for (i = 1; i <= LAST_PRF_ID; i++)
        !          1358:                        printf ("%2d) %s\n", i, HashGetName (i));
        !          1359: 
        !          1360:                HashAlgorithm = AskSelection (1, 1, LAST_PRF_ID);
        !          1361:        }
        !          1362: 
        !          1363:        // Encryption algorithm
        !          1364:        if (EA == 0)
        !          1365:        {
        !          1366:                int max = 0;
        !          1367: ea:
        !          1368:                puts ("Encryption algorithm:");
        !          1369: 
        !          1370:                for (i = EAGetFirst (); i != 0; i = EAGetNext (i))
        !          1371:                {
        !          1372:                        if (EAGetFirstMode (i) == LRW)
        !          1373:                        {
        !          1374:                                printf ("%2d) %s\n", i, EAGetName (str, i));
        !          1375:                                max = i;
        !          1376:                        }
        !          1377:                }
        !          1378: 
        !          1379:                EA = AskSelection (1, EAGetFirst (), max);
        !          1380: 
        !          1381:                if (CipherGetBlockSize (EAGetFirstCipher (EA)) == 8
        !          1382:                        && VolumeSize > WARN_VOL_SIZE_BLOCK64)
        !          1383:                {
        !          1384:                        char s[3];
        !          1385: 
        !          1386:                        AskString ("WARNING: You have selected a 64-bit block cipher. Due to security reasons,\n"
        !          1387:                                "for this volume size, it is strongly recommended to select a 128-bit block cipher\n"
        !          1388:                                "(for example, AES, Serpent, or Twofish) instead.\n\n"
        !          1389:                                "Continue? [y/N]", s, sizeof (s));
        !          1390:                        puts ("");
        !          1391: 
        !          1392:                        if (strcmp (s, "y") && strcmp (s, "Y"))
        !          1393:                                goto ea;
        !          1394:                }
        !          1395:        }
        !          1396: 
        !          1397:        randReq = EAGetKeySize (EA) * 2 + DISK_IV_SIZE * 2 + PKCS5_SALT_SIZE;
        !          1398: 
        !          1399:        // Password
        !          1400:        if (!CmdPasswordValid)
        !          1401:        {
        !          1402:                while (1)
        !          1403:                {
        !          1404:                        AskPassword ("Enter password for new volume '%s': ", hostPath, &password);
        !          1405:                        if (!DisplayPassword)
        !          1406:                        {
        !          1407:                                Password pv;
        !          1408:                                AskPassword ("Re-enter password%s", ": ", &pv);
        !          1409:                                if (password.Length != pv.Length || memcmp (password.Text, pv.Text, pv.Length))
        !          1410:                                {
        !          1411:                                        puts ("Passwords do not match.\n");
        !          1412:                                        continue;
        !          1413:                                }
        !          1414:                        }
        !          1415:                        break;
        !          1416:                }
        !          1417:                puts ("");
        !          1418:        }
        !          1419:        else
        !          1420:                pw = &CmdPassword;
        !          1421: 
        !          1422:        if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
        !          1423:        {
        !          1424:                error ("Error while processing keyfiles\n");
        !          1425:                goto err;
        !          1426:        }
        !          1427: 
        !          1428:        RandBytesFillRequired (randReq);
        !          1429: 
        !          1430:        // Create volume header
        !          1431:        r = VolumeWriteHeader (header,
        !          1432:                EA,
        !          1433:                EAMode,
        !          1434:                pw,
        !          1435:                HashAlgorithm,
        !          1436:                0,
        !          1437:                0,
        !          1438:                &ci,
        !          1439:                hiddenVolume ? VolumeSize : 0,
        !          1440:                FALSE);
        !          1441:        
        !          1442:        if (r == ERR_CIPHER_INIT_WEAK_KEY)
        !          1443:        {
        !          1444:                error ("A weak or a potentially weak key has been generated. Please try again.\n");
        !          1445:                goto err;
        !          1446:        }
        !          1447: 
        !          1448:        if (r != 0)
        !          1449:        {
        !          1450:                error ("Volume header creation failed.\n");
        !          1451:                goto err;
        !          1452:        }
        !          1453: 
        !          1454:        totalSectors = VolumeSize / SECTOR_SIZE;
        !          1455:        ci->hiddenVolumeOffset = hostSize - VolumeSize - HIDDEN_VOL_HEADER_OFFSET;
        !          1456:        startSector = !hiddenVolume ? 1 : (ci->hiddenVolumeOffset / SECTOR_SIZE);
        !          1457: 
        !          1458:        if (DisplayKeys)
        !          1459:        {
        !          1460:                printf ("Master Key: ");
        !          1461:                HexDump (ci->master_key, EAGetKeySize (ci->ea));
        !          1462:                printf ("\nSecondary Key: ");
        !          1463:                HexDump (ci->iv, sizeof (ci->iv));
        !          1464:                puts ("\n");
        !          1465:        }
        !          1466: 
        !          1467:        // Write header
        !          1468:        if (hiddenVolume)
        !          1469:        {
        !          1470:                if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
        !          1471:                {
        !          1472:                        perror ("Cannot seek to hidden volume header location");
        !          1473:                        goto err;
        !          1474:                }
        !          1475:        }
        !          1476:        else
        !          1477:        {
        !          1478:                if (fseek (f, 0, SEEK_SET) == -1)
        !          1479:                {
        !          1480:                        perror ("Cannot seek to volume header location");
        !          1481:                        goto err;
        !          1482:                }
        !          1483:        }
        !          1484: 
        !          1485:        if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
        !          1486:        {
        !          1487:                perror ("Cannot write volume header");
        !          1488:                goto err;
        !          1489:        }
        !          1490: 
        !          1491:        InitProgressBar (totalSectors - 1);
        !          1492:        StartSector = startSector;
        !          1493: 
        !          1494:        if (Quick && !hiddenVolume && IsFile (hostPath))
        !          1495:                Quick = FALSE;
        !          1496: 
        !          1497:        if (strcasecmp ("FAT", Filesystem) == 0)
        !          1498:        {
        !          1499:                if (hiddenVolume)
        !          1500:                {
        !          1501:                        if (fseeko (f, startSector * SECTOR_SIZE, SEEK_SET) == -1)
        !          1502:                        {
        !          1503:                                perror ("Cannot seek to hidden volume data area");
        !          1504:                                goto err;
        !          1505:                        }
        !          1506:                }
        !          1507: 
        !          1508:                ft.num_sectors = (unsigned int) totalSectors - 1;
        !          1509:                ft.cluster_size = ClusterSize;
        !          1510:                memcpy (ft.volume_name, "NO NAME    ", 11);
        !          1511:                GetFatParams (&ft); 
        !          1512:                r = FormatFat (startSector, &ft, f, ci, Quick);
        !          1513:        }
        !          1514:        else if (!hiddenVolume)
        !          1515:        {
        !          1516:                r = FormatNoFs (startSector, totalSectors - 1, f, ci, Quick);
        !          1517:        }
        !          1518: 
        !          1519:        if (r == ERR_OS_ERROR)
        !          1520:        {
        !          1521:                perror ("Volume creation failed");
        !          1522:                goto err;
        !          1523:        }
        !          1524: 
        !          1525:        if (DisplayProgress && IsTerminal)
        !          1526:                puts ("\nVolume created.");
        !          1527: 
        !          1528:        crypto_close (ci);
        !          1529:        fclose (f);
        !          1530:        return TRUE;
        !          1531: 
        !          1532: err:
        !          1533:        fclose (f);
        !          1534:        return FALSE;
        !          1535: }
        !          1536: 
        !          1537: 
        !          1538: static BOOL ChangePassword (char *volumePath)
        !          1539: {
        !          1540:        char header[HEADER_SIZE];
        !          1541:        char path[MAX_PATH];
        !          1542:        Password *pw = &password;
        !          1543:        PCRYPTO_INFO ci = NULL, ci2 = NULL;
        !          1544:        uint64_t startSector, totalSectors;
        !          1545:        time_t modTime = 0, acTime;
        !          1546:        int wipePass, ret = TRUE;
        !          1547:        int fd, r;
        !          1548:        FILE *f;
        !          1549: 
        !          1550:        // Volume path
        !          1551:        volumePath = AskVolumePath (volumePath, "Enter volume path");
        !          1552: 
        !          1553:        // Open volume
        !          1554:        if (!OpenVolume (volumePath, "Enter current password for '%s': ", volumePath, FALSE,
        !          1555:                        &ci, &startSector, &totalSectors, &modTime, &acTime))
        !          1556:                return FALSE;
        !          1557: 
        !          1558:        // New password and/or keyfile(s)
        !          1559:        if (!CmdPassword2Valid)
        !          1560:        {
        !          1561:                while (1)
        !          1562:                {
        !          1563:                        AskPassword ("Enter new password for '%s': ", volumePath, &password);
        !          1564:                        if (!DisplayPassword)
        !          1565:                        {
        !          1566:                                Password pv;
        !          1567:                                AskPassword ("Re-enter new password%s", ": ", &pv);
        !          1568:                                if (password.Length != pv.Length || memcmp (password.Text, pv.Text, pv.Length))
        !          1569:                                {
        !          1570:                                        puts ("Passwords do not match.\n");
        !          1571:                                        continue;
        !          1572:                                }
        !          1573:                        }
        !          1574:                        break;
        !          1575:                }
        !          1576: 
        !          1577:                puts ("");
        !          1578:        }
        !          1579:        else
        !          1580:                pw = &CmdPassword2;
        !          1581: 
        !          1582:        if (FirstNewKeyFile && !KeyFilesApply (pw, FirstNewKeyFile, !UpdateTime))
        !          1583:        {
        !          1584:                error ("Error while processing new keyfiles\n");
        !          1585:                return FALSE;
        !          1586:        }
        !          1587: 
        !          1588:        fd = open (volumePath, O_RDWR | O_SYNC);
        !          1589:        if (fd == -1)
        !          1590:        {
        !          1591:                perror ("Cannot open file or device");
        !          1592:                return FALSE;
        !          1593:        }
        !          1594:        f = fdopen (fd, "r+b");
        !          1595: 
        !          1596:        // Write a new volume header
        !          1597:        for (wipePass = 0; wipePass < DISK_WIPE_PASSES; wipePass++)
        !          1598:        {
        !          1599:                BOOL wipeMode = wipePass < DISK_WIPE_PASSES - 1;
        !          1600: 
        !          1601:                if (!wipeMode)
        !          1602:                {
        !          1603:                        if (Verbose) puts ("\n");
        !          1604:                        RandBytesFillRequired (PKCS5_SALT_SIZE);
        !          1605:                }
        !          1606: 
        !          1607:                r = VolumeWriteHeader (header,
        !          1608:                        ci->ea,
        !          1609:                        ci->mode,
        !          1610:                        pw,
        !          1611:                        HashAlgorithm == 0 ? ci->pkcs5 : HashAlgorithm,
        !          1612:                        (char *)ci->master_key,
        !          1613:                        ci->volume_creation_time,
        !          1614:                        &ci2,
        !          1615:                        ci->hiddenVolumeSize,
        !          1616:                        wipeMode);
        !          1617: 
        !          1618:                if (r == ERR_CIPHER_INIT_WEAK_KEY)
        !          1619:                {
        !          1620:                        ret = FALSE;
        !          1621:                        error ("A weak or a potentially weak key has been generated. Please try again.\n");
        !          1622:                        goto err;
        !          1623:                }
        !          1624: 
        !          1625:                if (r != 0)
        !          1626:                {
        !          1627:                        error ("Volume header creation failed.\n");
        !          1628:                        ret = FALSE;
        !          1629:                        goto err;
        !          1630:                }
        !          1631: 
        !          1632:                crypto_close (ci2);
        !          1633:                ci2 = NULL;
        !          1634: 
        !          1635:                if (ci->hiddenVolumeSize)
        !          1636:                {
        !          1637:                        if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
        !          1638:                        {
        !          1639:                                perror ("Cannot seek to hidden volume header location");
        !          1640:                                ret = FALSE;
        !          1641:                                goto err;
        !          1642:                        }
        !          1643:                }
        !          1644:                else
        !          1645:                {
        !          1646:                        if (fseek (f, 0, SEEK_SET) == -1)
        !          1647:                        {
        !          1648:                                perror ("Cannot seek to volume header location");
        !          1649:                                ret = FALSE;
        !          1650:                                goto err;
        !          1651:                        }
        !          1652:                }
        !          1653: 
        !          1654:                if (Verbose)
        !          1655:                {
        !          1656:                        printf ("\rWriting header (pass %d)", wipePass);
        !          1657:                        fflush (stdout);
        !          1658:                }
        !          1659: 
        !          1660:                if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
        !          1661:                {
        !          1662:                        perror ("Cannot write volume header");
        !          1663:                        ret = FALSE;
        !          1664:                        goto err;
        !          1665:                }
        !          1666: 
        !          1667:                fflush (f);
        !          1668:                fdatasync (fd);
        !          1669:        }
        !          1670: 
        !          1671:        printf ("%sPassword and/or keyfile(s) changed.\n", Verbose ? "\n" : "");
        !          1672: 
        !          1673: err:
        !          1674:        crypto_close (ci);
        !          1675:        close (fd);
        !          1676: 
        !          1677:        if (!UpdateTime && modTime != 0)
        !          1678:                RestoreFileTime (volumePath, modTime, acTime);
        !          1679: 
        !          1680:        return ret;
        !          1681: }
        !          1682: 
        !          1683: 
        !          1684: static BOOL BackupVolumeHeaders (char *backupFile, char *volumePath)
        !          1685: {
        !          1686:        char path[MAX_PATH];
        !          1687:        char header[HEADER_SIZE * 2];
        !          1688:        FILE *f = NULL, *fb = NULL;
        !          1689:        struct stat volumeStat;
        !          1690:        int ret = FALSE;
        !          1691: 
        !          1692:        DropEffectiveUserId ();
        !          1693: 
        !          1694:        // Volume path
        !          1695:        volumePath = AskVolumePath (volumePath, "Enter volume path");
        !          1696:        
        !          1697:        if (strcmp (backupFile, volumePath) == 0)
        !          1698:        {
        !          1699:                error ("Volume path identical to backup file\n");
        !          1700:                goto err;
        !          1701:        }
        !          1702: 
        !          1703:        volumeStat.st_mtime = 0;
        !          1704:        if (IsFile (volumePath) && stat (volumePath, &volumeStat) != 0)
        !          1705:        {
        !          1706:                perror ("Cannot read volume's modification and access time");
        !          1707:                volumeStat.st_mtime = 0;
        !          1708:                ret = FALSE;
        !          1709:                goto err;
        !          1710:        }
        !          1711: 
        !          1712:        // Volume
        !          1713:        f = fopen (volumePath, "rb");
        !          1714:        if (!f)
        !          1715:        {
        !          1716:                perror ("Cannot open volume");
        !          1717:                goto err;
        !          1718:        }
        !          1719: 
        !          1720:        if (fread (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
        !          1721:        {
        !          1722:                perror ("Cannot read volume header");
        !          1723:                goto err;
        !          1724:        }
        !          1725:        
        !          1726:        if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
        !          1727:        {
        !          1728:                perror ("Cannot seek to hidden volume header location");
        !          1729:                goto err;
        !          1730:        }
        !          1731: 
        !          1732:        if (fread (header + HEADER_SIZE, 1, HEADER_SIZE, f) != HEADER_SIZE)
        !          1733:        {
        !          1734:                perror ("Cannot read hidden volume header");
        !          1735:                goto err;
        !          1736:        }
        !          1737: 
        !          1738:        // Backup file
        !          1739:        fb = fopen (backupFile, "wb");
        !          1740:        if (!fb)
        !          1741:        {
        !          1742:                perror ("Cannot open backup file");
        !          1743:                goto err;
        !          1744:        }
        !          1745: 
        !          1746:        if (fwrite (header, 1, HEADER_SIZE * 2, fb) != HEADER_SIZE * 2)
        !          1747:        {
        !          1748:                perror ("Cannot write backup file");
        !          1749:                goto err;
        !          1750:        }
        !          1751: 
        !          1752:        ret = TRUE;
        !          1753: 
        !          1754: err:
        !          1755:        if (f)
        !          1756:                fclose (f);
        !          1757:        if (f)
        !          1758:                fclose (fb);
        !          1759: 
        !          1760:        if (!UpdateTime && volumeStat.st_mtime != 0)
        !          1761:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
        !          1762: 
        !          1763:        return ret;
        !          1764: }
        !          1765: 
        !          1766: 
        !          1767: static BOOL RestoreVolumeHeader (char *backupFile, char *volumePath)
        !          1768: {
        !          1769:        char path[MAX_PATH];
        !          1770:        char header[HEADER_SIZE];
        !          1771:        FILE *f = NULL, *fb = NULL;
        !          1772:        struct stat volumeStat;
        !          1773:        int ret = FALSE;
        !          1774:        BOOL hiddenVolume;
        !          1775: 
        !          1776:        DropEffectiveUserId ();
        !          1777: 
        !          1778:        // Backup file
        !          1779:        fb = fopen (backupFile, "rb");
        !          1780:        if (!fb)
        !          1781:        {
        !          1782:                perror ("Cannot open backup file");
        !          1783:                goto err;
        !          1784:        }
        !          1785: 
        !          1786:        // Volume path
        !          1787:        volumePath = AskVolumePath (volumePath, "Enter volume path");
        !          1788: 
        !          1789:        if (strcmp (backupFile, volumePath) == 0)
        !          1790:        {
        !          1791:                error ("Volume path identical to backup file\n");
        !          1792:                goto err;
        !          1793:        }
        !          1794: 
        !          1795:        // Volume type
        !          1796:        switch (VolumeType)
        !          1797:        {
        !          1798:        case VOLUME_TYPE_NORMAL:
        !          1799:                hiddenVolume = FALSE;
        !          1800:                break;
        !          1801: 
        !          1802:        case VOLUME_TYPE_HIDDEN:
        !          1803:                hiddenVolume = TRUE;
        !          1804:                Quick = TRUE;
        !          1805:                break;
        !          1806: 
        !          1807:        default:
        !          1808:                puts ("Restore headear of:\n 1) Normal/Outer Volume\n 2) Hidden Volume");
        !          1809:                hiddenVolume = AskSelection (1, 1, 2) == 2;
        !          1810:                break;
        !          1811:        }
        !          1812: 
        !          1813:        volumeStat.st_mtime = 0;
        !          1814:        if (IsFile (volumePath) && stat (volumePath, &volumeStat) != 0)
        !          1815:        {
        !          1816:                perror ("Cannot read volume's modification and access time");
        !          1817:                volumeStat.st_mtime = 0;
        !          1818:                goto err;
        !          1819:        }
        !          1820: 
        !          1821:        f = fopen (volumePath, "r+b");
        !          1822:        if (!f)
        !          1823:        {
        !          1824:                perror ("Cannot open volume");
        !          1825:                goto err;
        !          1826:        }
        !          1827: 
        !          1828:        if (hiddenVolume)
        !          1829:        {
        !          1830: 
        !          1831:                if (fseek (fb, HEADER_SIZE, SEEK_SET) == -1)
        !          1832:                {
        !          1833:                        perror ("Cannot seek to hidden volume header location in backup file");
        !          1834:                        goto err;
        !          1835:                }
        !          1836: 
        !          1837:                if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
        !          1838:                {
        !          1839:                        perror ("Cannot seek to hidden volume header location");
        !          1840:                        goto err;
        !          1841:                }
        !          1842:        }
        !          1843: 
        !          1844:        if (fread (header, 1, HEADER_SIZE, fb) != HEADER_SIZE)
        !          1845:        {
        !          1846:                perror ("Cannot read backup file");
        !          1847:                goto err;
        !          1848:        }
        !          1849: 
        !          1850:        if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
        !          1851:        {
        !          1852:                perror ("Cannot write volume header");
        !          1853:                goto err;
        !          1854:        }
        !          1855: 
        !          1856:        ret = TRUE;
        !          1857: 
        !          1858: err:
        !          1859:        if (f)
        !          1860:                fclose (f);
        !          1861:        if (f)
        !          1862:                fclose (fb);
        !          1863: 
        !          1864:        if (!UpdateTime && volumeStat.st_mtime != 0)
        !          1865:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
        !          1866: 
        !          1867:        return ret;
        !          1868: }
        !          1869: 
        !          1870: 
        !          1871: static BOOL CreateKeyfile (char *path)
        !          1872: {
        !          1873:        uint8_t keyFile[MAX_PASSWORD];
        !          1874:        FILE *f;
        !          1875: 
        !          1876:        DropEffectiveUserId ();
        !          1877: 
        !          1878:        RandBytesFillRequired (sizeof (keyFile));
        !          1879:        if (!RandgetBytes (keyFile, sizeof (keyFile), FALSE))
        !          1880:                return FALSE;
        !          1881: 
        !          1882:        f = fopen (path, "wb");
        !          1883:        if (!f)
        !          1884:        {
        !          1885:                perror ("Cannot open file");
        !          1886:                return FALSE;
        !          1887:        }
        !          1888: 
        !          1889:        if (fwrite (keyFile, 1, sizeof (keyFile), f) != sizeof (keyFile))
        !          1890:        {
        !          1891:                perror ("Cannot write file");
        !          1892:                fclose (f);
        !          1893:                return FALSE;
        !          1894:        }
        !          1895: 
        !          1896:        fclose (f);
        !          1897:        puts ("Keyfile created.");
        !          1898:        return TRUE;
        !          1899: }
        !          1900: 
        !          1901: 
        !          1902: static time_t WindowsFileTime2UnixTime (uint64_t wTime)
        !          1903: {
        !          1904:        return (time_t) (wTime / 1000LL / 1000 / 10 - 134774LL * 24 * 3600);
        !          1905: }
        !          1906: 
        !          1907: 
        !          1908: static BOOL DumpVolumeProperties (char *volumePath)
        !          1909: {
        !          1910:        uint64_t startSector, totalSectors;
        !          1911:        time_t modTime = 0, acTime;
        !          1912:        PCRYPTO_INFO ci = NULL;
        !          1913:        BOOL ret = FALSE;
        !          1914:        char eaName[256], timeBuf[256], timeBuf2[256];
        !          1915:        int keySize;
        !          1916:        time_t volCTime, headerMTime;
        !          1917: 
        !          1918:        volumePath = AskVolumePath (volumePath, "Enter volume path");
        !          1919: 
        !          1920:        if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE,
        !          1921:                &ci, &startSector, &totalSectors, &modTime, &acTime))
        !          1922:                goto err;
        !          1923: 
        !          1924:        EAGetName (eaName, ci->ea);
        !          1925: 
        !          1926:        keySize = EAGetKeySize (ci->ea);        
        !          1927:        if (strcmp (eaName, "Triple DES") == 0)
        !          1928:                keySize -= 3; // Compensate for parity bytes
        !          1929: 
        !          1930:        volCTime = WindowsFileTime2UnixTime (ci->volume_creation_time);
        !          1931:        headerMTime = WindowsFileTime2UnixTime (ci->header_creation_time);
        !          1932: 
        !          1933:        printf ("%sVolume properties:\n"
        !          1934:                " Location: %s\n"
        !          1935:                " Size: %lld bytes\n"
        !          1936:                " Type: %s\n"
        !          1937:                " Encryption algorithm: %s\n"
        !          1938:                " Key size: %d bits\n"
        !          1939:                " Block size: %d bits\n"
        !          1940:                " Mode of operation: %s\n"
        !          1941:                " PKCS-5 PRF: %s\n"
        !          1942:                " PKCS-5 iteration count: %d\n"
        !          1943:                " Volume created: %s"
        !          1944:                " Header modified: %s"
        !          1945:                ,
        !          1946:                CmdPasswordValid ? "" : "\n",
        !          1947:                volumePath,
        !          1948:                totalSectors * SECTOR_SIZE,
        !          1949:                ci->hiddenVolumeSize == 0 ? "Normal" : "Hidden",
        !          1950:                eaName,
        !          1951:                keySize * 8,
        !          1952:                CipherGetBlockSize (EAGetFirstCipher(ci->ea)) * 8,
        !          1953:                EAGetModeName (ci->ea, ci->mode, TRUE),
        !          1954:                get_pkcs5_prf_name (ci->pkcs5),
        !          1955:                ci->noIterations,
        !          1956:                ctime_r (&volCTime, timeBuf),
        !          1957:                ctime_r (&headerMTime, timeBuf2)
        !          1958:                );
        !          1959: 
        !          1960:        ret = TRUE;
        !          1961: err:
        !          1962:        if (ci != NULL)
        !          1963:                crypto_close (ci);
        !          1964: 
        !          1965:        if (!UpdateTime && modTime != 0)
        !          1966:                RestoreFileTime (volumePath, modTime, acTime);
        !          1967: 
        !          1968:        return ret;
        !          1969: }
        !          1970: 
        !          1971: 
        !          1972: static void DumpVersion (FILE *f)
        !          1973: {
        !          1974:        fprintf (f, 
        !          1975: "truecrypt %s\n\n"
        !          1976: "Copyright (C) 2004-2006 TrueCrypt Foundation. All Rights Reserved.\n\
        !          1977: Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\
        !          1978: Copyright (C) 2004 TrueCrypt Team. All Rights Reserved.\n\
        !          1979: Copyright (C) 1999-2005 Dr. Brian Gladman. All Rights Reserved.\n\
        !          1980: Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\
        !          1981: Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n"
        !          1982:        , VERSION_STRING);
        !          1983: }
        !          1984: 
        !          1985: 
        !          1986: static void DumpUsage (FILE *f)
        !          1987: {
        !          1988:        fprintf (f,
        !          1989: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
        !          1990: "   or: truecrypt [OPTIONS] -c | --create | -C | --change [VOLUME_PATH]\n"
        !          1991: "   or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
        !          1992: "   or: truecrypt [OPTIONS] --backup-headers | --restore-header FILE [VOLUME]\n"
        !          1993: "   or: truecrypt [OPTIONS] --properties [VOLUME_PATH]\n"
        !          1994: "   or: truecrypt --keyfile-create FILE\n"
        !          1995: "   or: truecrypt -h | --help | --test | -V | --version\n"
        !          1996: "\nCommands:\n"
        !          1997: " VOLUME_PATH                         Map volume\n"
        !          1998: " VOLUME_PATH MOUNT_DIRECTORY         Map and mount volume\n"
        !          1999: "     --backup-headers FILE [VOLUME]  Backup headers of VOLUME to FILE\n"
        !          2000: " -c, --create [VOLUME_PATH]          Create a new volume\n"
        !          2001: " -C, --change [VOLUME_PATH]          Change password/keyfile(s)\n"
        !          2002: " -d, --dismount [MAPPED_VOLUME]      Dismount and unmap volume\n"
        !          2003: " -h, --help                          Display detailed help\n"
        !          2004: "     --keyfile-create FILE           Create a new keyfile\n"
        !          2005: " -l, --list [MAPPED_VOLUME]          List mapped volumes\n"
        !          2006: "     --properties [VOLUME_PATH]      Display properties of volume\n"
        !          2007: "     --restore-headers FILE [VOLUME] Restore header of VOLUME from FILE\n"
        !          2008: "     --test                          Test algorithms\n"
        !          2009: " -V, --version                       Display version information\n"
        !          2010: "\nOptions:\n"
        !          2011: "     --cluster SIZE                  Cluster size\n"
        !          2012: "     --display-keys                  Display encryption keys\n"
        !          2013: "     --display-password              Display password while typing\n"
        !          2014: "     --disable-progress              Disable progress display\n"
        !          2015: "     --encryption EA                 Encryption algorithm\n"
        !          2016: "     --filesystem TYPE               Filesystem type to mount\n"
        !          2017: "     --hash HASH                     Hash algorithm\n"
        !          2018: " -k, --keyfile FILE|DIR              Keyfile for volume\n"
        !          2019: "     --keyfile-add FILE|DIR          New keyfile for volume\n"
        !          2020: " -K, --keyfile-protected FILE|DIR    Keyfile for protected volume\n"
        !          2021: " -M, --mount-options OPTIONS         Mount options\n"
        !          2022: " -N, --device-number NUMBER          Map volume as device number\n"
        !          2023: " -p, --password PASSWORD             Password for volume\n"
        !          2024: "     --password-tries NUMBER         Password entry tries\n"
        !          2025: " -P, --protect-hidden                Protect hidden volume\n"
        !          2026: "     --quick                         Use quick format\n"
        !          2027: "     --update-time                   Do not preserve timestamps\n"
        !          2028: " -r, --read-only                     Map/Mount read-only\n"
        !          2029: "     --size SIZE                     Volume size\n"
        !          2030: "     --type TYPE                     Volume type\n"
        !          2031: " -u, --user-mount                    Set default user and group ID on mount\n"
        !          2032: " -v, --verbose                       Verbose output\n"
        !          2033: "\n MAPPED_VOLUME = DEVICE_NUMBER | DEVICE_NAME | MOUNT_POINT | VOLUME_PATH\n"
        !          2034: "For a detailed help use --help or see truecrypt(1) man page.\n"
        !          2035: );
1.1       root     2036: }
                   2037: 
                   2038: static void DumpHelp ()
                   2039: {
                   2040:        fprintf (stdout,
                   2041: "Manages encrypted TrueCrypt volumes, which can be mapped as virtual block\n"
                   2042: "devices and used as any other standard block device. All data being read\n"
                   2043: "from a mapped TrueCrypt volume is transparently decrypted and all data being\n"
                   2044: "written to it is transparently encrypted.\n"
                   2045: "\n"
                   2046: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
1.1.1.3 ! root     2047: "   or: truecrypt [OPTIONS] -c | --create | -C | --change [VOLUME_PATH]\n"
1.1       root     2048: "   or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
1.1.1.3 ! root     2049: "   or: truecrypt [OPTIONS] --backup-headers | --restore-header FILE [VOLUME]\n"
        !          2050: "   or: truecrypt [OPTIONS] --properties [VOLUME_PATH]\n"
        !          2051: "   or: truecrypt --keyfile-create FILE\n"
1.1       root     2052: "   or: truecrypt -h | --help | --test | -V | --version\n"
                   2053: "\n"
                   2054: "Options:\n"
                   2055: "\n"
                   2056: "VOLUME_PATH [MOUNT_DIRECTORY]\n"
                   2057: " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n"
                   2058: " /dev/mapper/truecryptN. N is the first available device number if not\n"
1.1.1.3 ! root     2059: " otherwise specified with -N. To map a hidden volume, specify its password\n"
        !          2060: " and/or keyfiles (the outer volume cannot be mapped at the same time).\n"
        !          2061: " Filesystem of the mapped volume is mounted at MOUNT_DIRECTORY if specified.\n"
        !          2062: " See also options --display-password, --filesystem, -k, -M, -p, -P,\n"
        !          2063: " --password-tries, -r, -u, --update-time.\n"
        !          2064: "\n"
        !          2065: "--backup-headers BACKUP_FILE [VOLUME_PATH]\n"
        !          2066: " Backup headers of a volume specified by VOLUME_PATH to a file BACKUP_FILE.\n"
        !          2067: " Volume path is requested from user if not specified on command line. Both\n"
        !          2068: " normal/outer and hidden volume headers are stored in the backup file even\n"
        !          2069: " if there is no hidden volume within the volume (to preserve plausible\n"
        !          2070: " deniability). When restoring the volume header, it is possible to select\n"
        !          2071: " which header is to be restored. Note that this command drops effective user\n"
        !          2072: " ID. See also --restore-header.\n"
        !          2073: "\n"
        !          2074: "-c, --create [VOLUME_PATH]\n"
        !          2075: " Create a new volume. Most options are requested from user if not specified\n"
        !          2076: " on command line. Hidden volume can be created only in an existing file or\n"
        !          2077: " device. Size of the hidden volume should not exceed the free space of the\n"
        !          2078: " filesystem on the outer volume. Hidden volume protection (see option -P)\n"
        !          2079: " should be used to update the outer volume contents after the hidden volume\n"
        !          2080: " is created. Note that this command drops effective user ID.\n"
        !          2081: " See also options --cluster, --disable-progress, --display-keys,\n"
        !          2082: " --encryption, -k, --filesystem, --hash, -p, --quick, --size, --type. Note\n"
        !          2083: " that passing some of the options may affect plausible deniability. See option\n"
        !          2084: " -p for more information.\n"
        !          2085: "\n"
        !          2086: "-C, --change [VOLUME_PATH]\n"
        !          2087: " Change a password and/or keyfile(s) of a volume. Volume path and passwords are\n"
        !          2088: " requested from user if not specified on command line. PKCS-5 PRF HMAC hash\n"
        !          2089: " algorithm can be changed with option --hash. See also options -k,\n"
        !          2090: " --keyfile-add, -p, -v.\n"
1.1       root     2091: "\n"
                   2092: "-d, --dismount [MAPPED_VOLUME]\n"
                   2093: " Dismount and unmap mapped volumes. If MAPPED_VOLUME is not specified, all\n"
                   2094: " volumes are dismounted and unmapped. See below for a description of\n"
                   2095: " MAPPED_VOLUME.\n"
                   2096: "\n"
1.1.1.3 ! root     2097: "-h, --help\n"
        !          2098: " Display help information.\n"
        !          2099: "\n"
1.1       root     2100: "-l, --list [MAPPED_VOLUME]\n"
                   2101: " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n"
                   2102: " volumes are listed. By default, the list contains only volume path and mapped\n"
                   2103: " device name pairs. A more detailed list can be enabled by verbose output\n"
                   2104: " option (-v). See below for a description of MAPPED_VOLUME.\n"
                   2105: "\n"
1.1.1.3 ! root     2106: "--keyfile-create FILE\n"
        !          2107: " Create a new keyfile using the random number generator. FILE argument specifies\n"
        !          2108: " the output file. Note that this command drops effective user ID.\n"
        !          2109: "\n"
        !          2110: "--properties [VOLUME_PATH]\n"
        !          2111: " Display properties of a volume specified by VOLUME_PATH.\n"
        !          2112: "\n"
        !          2113: "--restore-header BACKUP_FILE [VOLUME_PATH]\n"
        !          2114: " Restore header of a volume specified by VOLUME_PATH from a file BACKUP_FILE.\n"
        !          2115: " Volume path is requested from user if not specified on command line.\n"
        !          2116: " Type of the restored volume header (normal/hidden) is requested from user if\n"
        !          2117: " not specified with --type. Note that this command drops effective user ID.\n"
        !          2118: " See also --backup-headers.\n"
        !          2119: "\n"
        !          2120: "--test\n"
        !          2121: " Test all internal algorithms used in the process of encryption and decryption.\n"
        !          2122: "\n"
        !          2123: "-V, --version\n"
        !          2124: " Display version information.\n"
        !          2125: "\n"
1.1       root     2126: "MAPPED_VOLUME\n"
                   2127: " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n"
                   2128: " 1) Path to the encrypted TrueCrypt volume.\n\n"
                   2129: " 2) Mount directory of the volume's filesystem (if mounted).\n\n"
                   2130: " 3) Device number of the mapped volume.\n\n"
                   2131: " 4) Device name of the mapped volume.\n\n"
                   2132: "\n"
1.1.1.3 ! root     2133: "--cluster SIZE\n"
        !          2134: " Use specified cluster size when creating a new volume. SIZE defines the number\n"
        !          2135: " of sectors per cluster.\n"
        !          2136: "\n"
        !          2137: "--disable-progress\n"
        !          2138: " Disable display of progress information during creation of a new volume.\n"
        !          2139: "\n"
        !          2140: "--display-keys\n"
        !          2141: " Display encryption keys generated during creation of a new volume.\n"
1.1       root     2142: "\n"
                   2143: "--display-password\n"
                   2144: " Display password characters while typing.\n"
                   2145: "\n"
1.1.1.3 ! root     2146: "--encryption EA\n"
        !          2147: " Use specified encryption algorithm when creating a new volume.\n"
        !          2148: "\n"
1.1       root     2149: "--filesystem TYPE\n"
                   2150: " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n"
1.1.1.3 ! root     2151: " with option -t. Default type is 'auto'. When creating a new volume, this\n"
        !          2152: " option specifies the filesystem to be created on the new volume.\n"
1.1       root     2153: "\n"
1.1.1.3 ! root     2154: "--hash HASH\n"
        !          2155: " Use specified hash algorithm when creating a new volume or changing password\n"
        !          2156: " and/or keyfiles.\n"
1.1       root     2157: "\n"
                   2158: "-k, --keyfile FILE | DIRECTORY\n"
1.1.1.3 ! root     2159: " Use specified keyfile to open a volume to be mapped (or when changing password\n"
        !          2160: " and/or keyfiles). When a directory is specified, all files inside it will be\n"
        !          2161: " used (non-recursively). Additional keyfiles can be specified with multiple -k\n"
        !          2162: " options. See also option -K.\n"
1.1       root     2163: "\n"
                   2164: "-K, --keyfile-protected FILE | DIRECTORY\n"
                   2165: " Use specified keyfile to open a hidden volume to be protected. See also\n"
                   2166: " options -k and -P.\n"
                   2167: "\n"
1.1.1.3 ! root     2168: "--keyfile-add FILE | DIRECTORY\n"
        !          2169: " Add specified keyfile to a volume when changing its password and/or keyfiles.\n"
        !          2170: " This option must be also used to keep all previous keyfiles asigned to a\n"
        !          2171: " volume. See EXAMPLES for more information.\n"
        !          2172: "\n"
        !          2173: "-M, --mount-options OPTIONS\n"
1.1       root     2174: " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n"
                   2175: " command with option -o.\n"
1.1.1.3 ! root     2176: "\n"
        !          2177: "-N, --device-number N\n"
        !          2178: " Use device number N when mapping a volume as a block device\n"
        !          2179: " /dev/mapper/truecryptN. Default is the first available device.\n"
        !          2180: "\n"
1.1       root     2181: "-p, --password PASSWORD\n"
                   2182: " Use specified password to open a volume. Additional passwords can be\n"
                   2183: " specified with multiple -p options. An empty password can also be specified\n"
                   2184: " (\"\" in most shells). Note that passing a password on the command line is\n"
                   2185: " potentially insecure as the password may be visible in the process list\n"
                   2186: " (see ps(1)) and/or stored in a command history file. \n"
                   2187: " \n"
                   2188: "--password-tries NUMBER\n"
                   2189: " Prompt NUMBER of times for a password until the correct password is entered.\n"
                   2190: " Default is to prompt three times.\n"
                   2191: "\n"
                   2192: "-P, --protect-hidden\n"
                   2193: " Write-protect a hidden volume when mapping an outer volume. Before mapping the\n"
                   2194: " outer volume, the user will be prompted for a password to open the hidden\n"
                   2195: " volume. The size and position of the hidden volume is then determined and the\n"
1.1.1.3 ! root     2196: " outer volume is mapped with all sectors belonging to the hidden volume\n"
1.1       root     2197: " protected against write operations. When a write to the protected area is\n"
                   2198: " prevented, the whole volume is switched to read-only mode. Verbose list command\n"
                   2199: " (-vl) can be used to query the state of the hidden volume protection. Warning\n"
                   2200: " message is displayed when a volume switched to read-only is being dismounted.\n"
                   2201: " See also option -r.\n"
1.1.1.3 ! root     2202: "\n"
        !          2203: "--quick\n"
        !          2204: " Use quick format when creating a new volume. This option can be used only\n"
        !          2205: " when creating a device-hosted volume. Quick format is always used when\n"
        !          2206: " creating a hidden volume.\n"
        !          2207: "\n"
1.1       root     2208: "-r, --read-only\n"
1.1.1.3 ! root     2209: " Map and mount a volume as read-only. Write operations to the volume may not\n"
1.1       root     2210: " fail immediately due to the write buffering performed by the system, but the\n"
                   2211: " physical write will still be prevented.\n"
1.1.1.3 ! root     2212: "\n"
        !          2213: "--size SIZE\n"
        !          2214: " Use specified size when creating a new volume. SIZE is defined as number of\n"
        !          2215: " bytes or, when a size suffix K/M/G is used, Kilobytes/Megabytes/Gigabytes.\n"
        !          2216: " Note that size must be a multiple of 512 bytes.\n"
        !          2217: "\n"
        !          2218: "--type TYPE\n"
        !          2219: " Use specified volume type when creating a new volume or restoring a volume\n"
        !          2220: " header. TYPE can be 'normal' or 'hidden'.\n"
        !          2221: "\n"
        !          2222: "-u, --user-mount\n"
        !          2223: " Set default user and group ID of the filesystem being mounted to the user and\n"
        !          2224: " group ID of the parent process. Some filesystems (like FAT) do not support\n"
        !          2225: " user permissions and, therefore, it is necessary to supply a default user and\n"
        !          2226: " group ID to the system when mounting such filesystems.\n"
1.1       root     2227: "\n"
                   2228: "--update-time\n"
                   2229: " Do not preserve access and modification timestamps of volume containers and\n"
                   2230: " access timestamps of keyfiles. By default, timestamps are restored after\n"
                   2231: " a volume is unmapped or after a keyfile is closed.\n"
                   2232: "\n"
                   2233: "-v, --verbose\n"
                   2234: " Enable verbose output. Multiple -v options can be specified to increase the\n"
                   2235: " level of verbosity.\n"
                   2236: "\n"
                   2237: "Examples:\n"
                   2238: "\n"
                   2239: "truecrypt /root/volume.tc /mnt/tc\n"
1.1.1.3 ! root     2240: " Map a volume /root/volume.tc and mount its filesystem at directory /mnt/tc.\n"
        !          2241: "\n"
        !          2242: "truecrypt -u /dev/hda2 /mnt/tc\n"
        !          2243: " Map a volume /dev/hda2 (first ATA disk, primary partition 2) and mount its\n"
        !          2244: " filesystem at /mnt/tc. Default user-id is set, which is useful when mounting\n"
        !          2245: " a filesystem like FAT under a non-admin user account.\n"
1.1       root     2246: "\n"
                   2247: "truecrypt -d\n"
                   2248: " Dismount and unmap all mapped volumes.\n"
                   2249: "  \n"
                   2250: "truecrypt -d /root/volume.tc\n"
                   2251: " Dismount and unmap a volume /root/volume.tc.\n"
                   2252: "\n"
                   2253: "truecrypt -d /mnt/tc\n"
                   2254: " Dismount and unmap a volume mounted at /mnt/tc.\n"
                   2255: "\n"
                   2256: "truecrypt -vl\n"
                   2257: " Display a detailed list of all mapped volumes.\n"
                   2258: " \n"
1.1.1.3 ! root     2259: "truecrypt -N 1 /dev/hdc1 && mkfs /dev/mapper/truecrypt1\n"
1.1       root     2260: " Map a volume /dev/hdc1 and create a new filesystem on it.\n"
                   2261: "\n"
                   2262: "truecrypt -P /dev/hdc1 /mnt/tc\n"
                   2263: " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n"
                   2264: "\n"
                   2265: "truecrypt -p \"\" -p \"\" -k key1 -k key2 -K key_hidden -P volume.tc\n"
                   2266: " Map outer volume ./volume.tc and protect hidden volume within it.\n"
                   2267: " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n"
                   2268: " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n"
                   2269: "\n"
1.1.1.3 ! root     2270: "truecrypt -c\n"
        !          2271: " Create a new volume."
        !          2272: "\n"
        !          2273: "truecrypt -k keyfile --size 10M --encryption AES --hash SHA-1 -c vol.tc\n"
        !          2274: " Create a new volume. Options which are not specified on command line are\n"
        !          2275: " requested from the user.\n"
        !          2276: "\n"
        !          2277: "truecrypt --type normal -c volume.tc && truecrypt --type hidden -c volume.tc\n"
        !          2278: " Create a new volume and then create a hidden volume inside it."
        !          2279: "\n"
        !          2280: "truecrypt --keyfile-add keyfile -C volume.tc\n"
        !          2281: " Change password and add a new keyfile to volume.\n"
        !          2282: "\n"
        !          2283: "truecrypt -k keyfile -C volume.tc\n"
        !          2284: " Change password and remove a keyfile from volume.\n"
        !          2285: "\n"
        !          2286: "truecrypt -k keyfile --keyfile-add keyfile -C volume.tc\n"
        !          2287: " Change password and keep previous keyfile.\n"
        !          2288: "\n"
        !          2289: 
1.1       root     2290: "Report bugs at <http://www.truecrypt.org/bugs>.\n"
                   2291:        );
                   2292: }
                   2293: 
                   2294: static BOOL DumpMountList (int devNo)
                   2295: {
1.1.1.3 ! root     2296:        BOOL found = FALSE;
1.1       root     2297:        int i;
                   2298: 
                   2299:        if (!CheckKernelModuleVersion (FALSE))
                   2300:                return FALSE;
                   2301: 
                   2302:        if (!GetMountList ())
                   2303:                return FALSE;
                   2304: 
1.1.1.3 ! root     2305:        if (devNo == -1 && MountList[0].DeviceNumber == -1)
        !          2306:        {
        !          2307:                error ("No volumes mounted\n");
        !          2308:                return FALSE;
        !          2309:        }
        !          2310: 
1.1       root     2311:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   2312:        {
                   2313:                MountListEntry *e = &MountList[i];
                   2314: 
                   2315:                if (devNo != -1 && e->DeviceNumber != devNo)
                   2316:                        continue;
                   2317: 
1.1.1.3 ! root     2318:                found = TRUE;
        !          2319: 
1.1       root     2320:                if (Verbose == 0)
                   2321:                {
                   2322:                        printf (TC_MAP_DEV "%d %s\n",
                   2323:                                e->DeviceNumber,
                   2324:                                e->VolumePath);
                   2325:                }
                   2326:                else
                   2327:                {
                   2328:                        char eaName[128];
                   2329:                        EAGetName (eaName, e->EA);
                   2330: 
                   2331:                        printf (TC_MAP_DEV "%d:\n"
                   2332:                                        " Volume: %s\n"
                   2333:                                        " Type: %s\n"
                   2334:                                        " Size: %lld bytes\n"
                   2335:                                        " Encryption algorithm: %s\n"
1.1.1.2   root     2336:                                        " Mode of operation: %s\n"
1.1       root     2337:                                        " Read-only: %s\n"
                   2338:                                        " Hidden volume protected: %s\n\n",
                   2339:                                e->DeviceNumber,
                   2340:                                e->VolumePath,
                   2341:                                e->Hidden ? "Hidden" : "Normal",
                   2342:                                e->VolumeSize,
                   2343:                                eaName,
1.1.1.2   root     2344:                                EAGetModeName (e->EA, e->Mode, TRUE),
1.1       root     2345:                                (e->Flags & FLAG_READ_ONLY) ? "Yes" : "No",
                   2346:                                (e->Flags & FLAG_PROTECTION_ACTIVATED) ? "Yes - damage prevented" : (
                   2347:                                        (e->Flags & FLAG_HIDDEN_VOLUME_PROTECTION) ? "Yes" : "No" )
                   2348:                                );
                   2349:                }
                   2350:        }
                   2351: 
1.1.1.3 ! root     2352:        if (!found)
        !          2353:        {
        !          2354:                error (TC_MAP_DEV "%d not mapped\n", devNo);
        !          2355:                return FALSE;
        !          2356:        }
        !          2357: 
1.1       root     2358:        return TRUE;
                   2359: }
                   2360: 
                   2361: 
                   2362: static BOOL EnumMountPoints (char *device, char *mountPoint)
                   2363: {
                   2364:        static FILE *m = NULL;
                   2365: 
                   2366:        if (device == NULL)
                   2367:        {
                   2368:                fclose (m);
                   2369:                m = NULL;
                   2370:                return TRUE;
                   2371:        }
                   2372: 
                   2373:        if (m == NULL)
                   2374:        {
                   2375:                m = fopen ("/proc/mounts", "r");
                   2376:                if (m == NULL)
                   2377:                {
                   2378:                        perror ("fopen /proc/mounts");
                   2379:                        return FALSE;
                   2380:                }
                   2381:        }
                   2382: 
                   2383:        if (fscanf (m, "%" MAX_PATH_STR "s %" MAX_PATH_STR "s %*s %*s %*s %*s",
                   2384:                device, mountPoint) != 2)
                   2385:        {
                   2386:                fclose (m);
                   2387:                m = NULL;
                   2388:                return FALSE;
                   2389:        }
                   2390: 
                   2391:        return TRUE;
                   2392: }
                   2393: 
                   2394: 
                   2395: static BOOL DismountFileSystem (char *device)
                   2396: {
                   2397:        char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
                   2398:        BOOL result = TRUE;
                   2399: 
                   2400:        while (EnumMountPoints (mountedDevice, mountPoint))
                   2401:        {
                   2402:                if (strcmp (mountedDevice, device) == 0)
                   2403:                {
                   2404:                        if (!Execute (FALSE, "umount", mountPoint, NULL))
                   2405:                                result = FALSE;
                   2406:                        else if (Verbose >= 1)
                   2407:                                printf ("Dismounted %s\n", mountPoint);
                   2408:                }
                   2409:        }
                   2410: 
                   2411:        return result;
                   2412: }
                   2413: 
                   2414: 
                   2415: // devNo: -1 = Dismount all volumes
                   2416: static BOOL DismountVolume (int devNo)
                   2417: {
                   2418:        char mapDevice[MAX_PATH];
                   2419:        int nMountedVolumes = 0;
                   2420:        int i;
                   2421:        BOOL found = FALSE;
                   2422:        BOOL status = TRUE;
                   2423: 
                   2424:        if (!CheckKernelModuleVersion (FALSE))
                   2425:                return FALSE;
                   2426: 
                   2427:        if (!GetMountList ())
                   2428:                return FALSE;
                   2429: 
                   2430:        if (devNo == -1 && MountList[0].DeviceNumber == -1)
                   2431:        {
                   2432:                error ("No volumes mounted\n");
                   2433:                return FALSE;
                   2434:        }
                   2435: 
                   2436:        // Flush write buffers before dismount if there are
                   2437:        // mounted volumes with hidden volume protection 
                   2438:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   2439:        {
                   2440:                if (MountList[i].Flags & FLAG_HIDDEN_VOLUME_PROTECTION)
                   2441:                {
                   2442:                        sync ();
                   2443:                        MountListValid = FALSE;
                   2444:                        GetMountList ();
                   2445:                        break;
                   2446:                }
                   2447:        }
                   2448: 
                   2449:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   2450:        {
                   2451:                MountListEntry *e = &MountList[i];
                   2452:                nMountedVolumes++;
                   2453: 
                   2454:                if (devNo == -1 || e->DeviceNumber == devNo)
                   2455:                {
                   2456:                        BOOL dismounted = FALSE;
                   2457:                        found = TRUE;
                   2458: 
                   2459:                        if (e->Flags & FLAG_PROTECTION_ACTIVATED)
                   2460:                                printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath);
                   2461: 
                   2462:                        sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber);
                   2463:                        if (DismountFileSystem (mapDevice))
                   2464:                        {
                   2465:                                char name[32];
                   2466:                                sprintf (name, "truecrypt%d", e->DeviceNumber);
                   2467:                                dismounted = Execute (FALSE, "dmsetup", "remove", name, NULL);
                   2468: 
                   2469:                                if (dismounted && IsFile (e->VolumePath))
                   2470:                                {
                   2471:                                        if (!DeleteLoopDevice (e->DeviceMinor))
                   2472:                                                status = FALSE;
                   2473: 
                   2474:                                        RestoreFileTime (e->VolumePath,
                   2475:                                                UpdateTime ? time (NULL) : (time_t) e->ModTime,
                   2476:                                                UpdateTime ? time (NULL) : (time_t) e->AcTime);
                   2477:                                }
                   2478:                        }
                   2479: 
                   2480:                        if (!dismounted)
                   2481:                        {
                   2482:                                error ("Cannot dismount %s\n", mapDevice);
                   2483:                                status = FALSE;
                   2484:                        }
                   2485:                        else
                   2486:                        {
                   2487:                                nMountedVolumes--;
                   2488:                                if (Verbose >= 1)
                   2489:                                        printf ("Unmapped %s\n", mapDevice);
                   2490:                        }
                   2491: 
                   2492:                        if (devNo != -1)
                   2493:                                break;
                   2494:                }
                   2495:        }
                   2496: 
                   2497:        if (!found)
                   2498:        {
1.1.1.3 ! root     2499:                error (TC_MAP_DEV "%d not mapped\n", devNo);
1.1       root     2500:                return FALSE;
                   2501:        }
                   2502: 
                   2503:        if (nMountedVolumes == 0)
                   2504:        {
                   2505:                // Ignore errors as volumes may be mounted asynchronously
                   2506:                UnloadKernelModule (TRUE);
                   2507:        }
                   2508: 
                   2509:        return status;
                   2510: }
                   2511: 
                   2512: 
                   2513: // Convert a string to device number
                   2514: // text: device number or name or mount point
                   2515: BOOL ToDeviceNumber (char *text, int *deviceNumber)
                   2516: {
                   2517:        char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
                   2518:        int i;
                   2519: 
                   2520:        if (sscanf (text, "%d", deviceNumber) == 1)
                   2521:                return TRUE;
                   2522: 
                   2523:        if (sscanf (text, TC_MAP_DEV "%d", deviceNumber) == 1)
                   2524:                return TRUE;
                   2525: 
                   2526:        while (EnumMountPoints (mountedDevice, mountPoint))
                   2527:        {
                   2528:                if (strcmp (mountPoint, text) == 0
                   2529:                        && sscanf (mountedDevice, TC_MAP_DEV "%d", deviceNumber) == 1)
                   2530:                {
                   2531:                        EnumMountPoints (NULL, NULL);
                   2532:                        return TRUE;
                   2533:                }
                   2534:        }
                   2535: 
                   2536:        if (!GetMountList ())
                   2537:                return FALSE;
                   2538: 
                   2539:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   2540:        {
                   2541:                MountListEntry *e = &MountList[i];
                   2542:                if (e->DeviceNumber == -1)
                   2543:                        break;
                   2544: 
                   2545:                if (strcmp (text, e->VolumePath) == 0)
                   2546:                {
                   2547:                        *deviceNumber = e->DeviceNumber;
                   2548:                        return TRUE;
                   2549:                }
                   2550:        }
                   2551: 
                   2552:        error ("%s not mounted\n", text);
                   2553:        return FALSE;
                   2554: }
                   2555: 
                   2556: 
1.1.1.2   root     2557: int main (int argc, char **argv)
1.1       root     2558: {
                   2559:        char *volumePath = NULL;
                   2560:        char *mountPoint = NULL;
                   2561:        char volumePathBuf[MAX_PATH];
                   2562:        int i, o;
                   2563:        int optIndex = 0;
1.1.1.2   root     2564:        FILE *f;
1.1       root     2565: 
                   2566:        struct option longOptions[] = {
1.1.1.3 ! root     2567:                {"backup-headers", required_argument, 0, 0},
        !          2568:                {"cluster", required_argument, 0, 0},
        !          2569:                {"change", optional_argument, 0, 'C'},
        !          2570:                {"create", optional_argument, 0, 'c'},
        !          2571:                {"device-number", required_argument, 0, 'N'},
1.1       root     2572:                {"dismount", optional_argument, 0, 'd'},
1.1.1.3 ! root     2573:                {"disable-progress", 0, 0, 0},
        !          2574:                {"display-keys", 0, 0, 0},
1.1       root     2575:                {"display-password", 0, 0, 0},
1.1.1.3 ! root     2576:                {"encryption", required_argument, 0, 0},
1.1       root     2577:                {"keyfile", required_argument, 0, 'k'},
1.1.1.3 ! root     2578:                {"keyfile-add", required_argument, 0, 0},
1.1       root     2579:                {"keyfile-protected", required_argument, 0, 'K'},
                   2580:                {"filesystem", required_argument, 0, 0},
1.1.1.3 ! root     2581:                {"keyfile-create", required_argument, 0, 0},
        !          2582:                {"list", optional_argument, 0, 'l'},
        !          2583:                {"hash", required_argument, 0, 0},
1.1       root     2584:                {"help", 0, 0, 'h'},
1.1.1.3 ! root     2585:                {"mount-options", required_argument, 0, 'M'},
1.1       root     2586:                {"password", required_argument, 0, 'l'},
                   2587:                {"password-tries", required_argument, 0, 0},
1.1.1.3 ! root     2588:                {"properties", optional_argument, 0, 0},
1.1       root     2589:                {"protect-hidden", 0, 0, 'P'},
1.1.1.3 ! root     2590:                {"quick", 0, 0, 0},
1.1       root     2591:                {"read-only", 0, 0, 'r'},
1.1.1.3 ! root     2592:                {"restore-header", required_argument, 0, 0},
        !          2593:                {"size", required_argument, 0, 0},
1.1       root     2594:                {"test", 0, 0, 0},
1.1.1.3 ! root     2595:                {"type", required_argument, 0, 0},
1.1       root     2596:                {"update-time", 0, 0, 0},
1.1.1.3 ! root     2597:                {"user-mount", 0, 0, 'u'},
1.1       root     2598:                {"verbose", 0, 0, 'v'},
                   2599:                {"version", 0, 0, 'V'},
                   2600:                {0, 0, 0, 0}
                   2601:        };
                   2602: 
1.1.1.2   root     2603:        // Make sure pipes will not use file descriptors <= STDERR_FILENO
                   2604:        f = fdopen (STDIN_FILENO, "r");
                   2605:        if (f == NULL)
                   2606:                open ("/dev/null", 0);
                   2607: 
                   2608:        f = fdopen (STDOUT_FILENO, "w");
                   2609:        if (f == NULL)
                   2610:                open ("/dev/null", 0);
                   2611: 
                   2612:        f = fdopen (STDERR_FILENO, "w");
                   2613:        if (f == NULL)
                   2614:                open ("/dev/null", 0);
1.1       root     2615: 
                   2616:        signal (SIGHUP, OnSignal);
                   2617:        signal (SIGINT, OnSignal);
                   2618:        signal (SIGQUIT, OnSignal);
                   2619:        signal (SIGABRT, OnSignal);
                   2620:        signal (SIGPIPE, OnSignal);
                   2621:        signal (SIGTERM, OnSignal);
                   2622: 
1.1.1.3 ! root     2623:        LockMemory ();
1.1       root     2624:        atexit (OnExit);
                   2625: 
1.1.1.3 ! root     2626:        RealUserId = getuid ();
        !          2627:        RealGroupId = getgid ();
        !          2628: 
        !          2629:        if (tcgetattr (0, &TerminalAttributes) == 0)
        !          2630:                IsTerminal = TRUE;
        !          2631: 
        !          2632:        while ((o = getopt_long (argc, argv, "c::C::d::hk:K:l::M:N:p:PruvV", longOptions, &optIndex)) != -1)
1.1       root     2633:        {
                   2634:                switch (o)
                   2635:                {
1.1.1.3 ! root     2636:                case 'c':
        !          2637:                        {
        !          2638:                                char *hostPath = NULL;
        !          2639:                                if (optind < argc)
        !          2640:                                {
        !          2641:                                        hostPath = argv[optind++];
        !          2642: 
        !          2643:                                        if (optind < argc)
        !          2644:                                                goto usage;
        !          2645:                                }
        !          2646: 
        !          2647:                                return CreateVolume (hostPath) ? 0 : 1;
        !          2648:                        }
        !          2649: 
        !          2650:                case 'C':
        !          2651:                        {
        !          2652:                                char *hostPath = NULL;
        !          2653:                                if (optind < argc)
        !          2654:                                {
        !          2655:                                        hostPath = argv[optind++];
        !          2656: 
        !          2657:                                        if (optind < argc)
        !          2658:                                                goto usage;
        !          2659:                                }
        !          2660: 
        !          2661:                                return ChangePassword (hostPath) ? 0 : 1;
        !          2662:                        }
        !          2663: 
1.1       root     2664:                case 'd':
                   2665:                        // Dismount
                   2666:                        {
                   2667:                                int devNo;
                   2668: 
                   2669:                                if (optind < argc)
                   2670:                                {
                   2671:                                        if (!ToDeviceNumber (argv[optind++], &devNo))
                   2672:                                                return 1;
                   2673: 
                   2674:                                        if (optind < argc)
                   2675:                                                goto usage;
                   2676:                                }
                   2677:                                else
                   2678:                                        devNo = -1;
                   2679: 
1.1.1.2   root     2680:                                if (!CheckAdminPrivileges ())
                   2681:                                        return 1;
                   2682: 
1.1       root     2683:                                return DismountVolume (devNo) ? 0 : 1;
                   2684:                        }
                   2685: 
                   2686:                case 'l':
                   2687:                        // List
                   2688:                        {
                   2689:                                int devNo;
                   2690: 
                   2691:                                if (optind < argc)
                   2692:                                {
                   2693:                                        if (!ToDeviceNumber (argv[optind++], &devNo))
                   2694:                                                return 1;
                   2695: 
                   2696:                                        if (optind < argc)
                   2697:                                                goto usage;
                   2698:                                }
                   2699:                                else
                   2700:                                        devNo = -1;
                   2701: 
1.1.1.2   root     2702:                                if (!CheckAdminPrivileges ())
                   2703:                                        return 1;
                   2704: 
1.1       root     2705:                                return DumpMountList (devNo) ? 0 : 1;
                   2706:                        }
                   2707: 
                   2708:                case 'k':
                   2709:                case 'K':
                   2710:                        // Keyfile
                   2711:                        {
                   2712:                                KeyFile *kf = malloc (sizeof (KeyFile));
                   2713:                                if (!kf)
                   2714:                                {
                   2715:                                        perror ("malloc");
                   2716:                                        return 1;
                   2717:                                }
                   2718:                                strncpy (kf->FileName, optarg, sizeof (kf->FileName));
                   2719:                                if (o == 'k')
                   2720:                                        FirstKeyFile = KeyFileAdd (FirstKeyFile, kf);
                   2721:                                else
                   2722:                                        FirstProtVolKeyFile = KeyFileAdd (FirstProtVolKeyFile, kf);
                   2723:                        }
                   2724:                        break;
                   2725: 
1.1.1.3 ! root     2726:                case 'M':
        !          2727:                        MountOpts = optarg;
        !          2728:                        break;
        !          2729:                        
        !          2730:                case 'N':
        !          2731:                        if (sscanf (optarg, "%d", &UseDeviceNumber) == 1 && UseDeviceNumber >= 0)
        !          2732:                                break;
        !          2733:                        goto usage;
1.1       root     2734: 
                   2735:                case 'p':
                   2736:                        // Password
                   2737:                        if (!CmdPasswordValid)
                   2738:                        {
1.1.1.3 ! root     2739:                                strncpy ((char *)CmdPassword.Text, optarg, sizeof (CmdPassword.Text));
        !          2740:                                CmdPassword.Length = strlen ((char *)CmdPassword.Text);
1.1       root     2741:                                CmdPasswordValid = TRUE;
                   2742:                        }
                   2743:                        else if (!CmdPassword2Valid)
                   2744:                        {
1.1.1.3 ! root     2745:                                strncpy ((char *)CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text));
        !          2746:                                CmdPassword2.Length = strlen ((char *)CmdPassword2.Text);
1.1       root     2747:                                CmdPassword2Valid = TRUE;
                   2748:                        }
                   2749:                        break;
                   2750: 
                   2751:                case 'P':
                   2752:                        // Hidden volume protection
                   2753:                        ProtectHidden = TRUE;
                   2754:                        break;
                   2755: 
                   2756:                case 'r':
                   2757:                        ReadOnly = TRUE;
                   2758:                        break;
1.1.1.3 ! root     2759:                        
        !          2760:                case 'u':
        !          2761:                        UserMount = TRUE;
        !          2762:                        break;
1.1       root     2763: 
                   2764:                case 'v':
                   2765:                        // Verbose
                   2766:                        Verbose++;
                   2767:                        break;
                   2768: 
                   2769:                case 'V':
                   2770:                        DumpVersion (stdout);
                   2771:                        return 0;
                   2772: 
                   2773:                case 'h':
                   2774:                        // Help
                   2775:                        DumpHelp ();
                   2776:                        return 0;
                   2777: 
                   2778:                case 0:
1.1.1.3 ! root     2779:                        if (strcmp ("backup-headers", longOptions[optIndex].name) == 0)
        !          2780:                        {
        !          2781:                                char *volumePath = NULL;
        !          2782: 
        !          2783:                                if (optind < argc)
        !          2784:                                        volumePath = argv[optind++];
        !          2785: 
        !          2786:                                if (optind < argc)
        !          2787:                                        goto usage;
        !          2788: 
        !          2789:                                if (BackupVolumeHeaders (optarg, volumePath))
        !          2790:                                {
        !          2791:                                        printf ("Backup of volume headers succeeded.\n");
        !          2792:                                        return 0;
        !          2793:                                }
        !          2794: 
        !          2795:                                return 1;
        !          2796:                        }
        !          2797: 
        !          2798:                        if (strcmp ("cluster", longOptions[optIndex].name) == 0)
        !          2799:                        {
        !          2800:                                if (sscanf (optarg, "%d", &ClusterSize) != 1)
        !          2801:                                        goto usage;
        !          2802:                                break;
        !          2803:                        }
        !          2804: 
        !          2805:                        if (strcmp ("display-keys", longOptions[optIndex].name) == 0)
        !          2806:                        {
        !          2807:                                DisplayKeys = TRUE;
        !          2808:                                break;
        !          2809:                        }
        !          2810: 
1.1       root     2811:                        if (strcmp ("display-password", longOptions[optIndex].name) == 0)
                   2812:                        {
                   2813:                                DisplayPassword = TRUE;
                   2814:                                break;
                   2815:                        }
                   2816: 
1.1.1.3 ! root     2817:                        if (strcmp ("disable-progress", longOptions[optIndex].name) == 0)
1.1       root     2818:                        {
1.1.1.3 ! root     2819:                                DisplayProgress = FALSE;
        !          2820:                                break;
        !          2821:                        }
        !          2822: 
        !          2823:                        if (strcmp ("encryption", longOptions[optIndex].name) == 0)
        !          2824:                        {
        !          2825:                                EA = EAGetByName (optarg);
        !          2826: 
        !          2827:                                if (EA == 0)
1.1       root     2828:                                        goto usage;
1.1.1.3 ! root     2829:                                break;
1.1       root     2830:                        }
                   2831: 
                   2832:                        if (strcmp ("filesystem", longOptions[optIndex].name) == 0)
                   2833:                        {
                   2834:                                Filesystem = optarg;
                   2835:                                break;
                   2836:                        }
                   2837: 
1.1.1.3 ! root     2838:                        if (strcmp ("hash", longOptions[optIndex].name) == 0)
        !          2839:                        {
        !          2840:                                HashAlgorithm = 0;
        !          2841:                                for (i = 1; i <= LAST_PRF_ID; i++)
        !          2842:                                {
        !          2843:                                        if (strcasecmp (optarg, HashGetName (i)) == 0)
        !          2844:                                        {
        !          2845:                                                HashAlgorithm = i;
        !          2846:                                                break;
        !          2847:                                        }
        !          2848:                                }
        !          2849: 
        !          2850:                                if (HashAlgorithm == 0)
        !          2851:                                        goto usage;
        !          2852: 
        !          2853:                                break;
        !          2854:                        }
        !          2855: 
        !          2856:                        if (strcmp ("keyfile-add", longOptions[optIndex].name) == 0)
        !          2857:                        {
        !          2858:                                KeyFile *kf = malloc (sizeof (KeyFile));
        !          2859:                                if (!kf)
        !          2860:                                {
        !          2861:                                        perror ("malloc");
        !          2862:                                        return 1;
        !          2863:                                }
        !          2864:                                strncpy (kf->FileName, optarg, sizeof (kf->FileName));
        !          2865:                                FirstNewKeyFile = KeyFileAdd (FirstNewKeyFile, kf);
        !          2866:                                break;
        !          2867:                        }
        !          2868:                        
        !          2869:                        if (strcmp ("keyfile-create", longOptions[optIndex].name) == 0)
        !          2870:                        {
        !          2871:                                return CreateKeyfile (optarg) ? 0 : 1;
        !          2872:                        }
        !          2873: 
        !          2874:                        if (strcmp ("quick", longOptions[optIndex].name) == 0)
        !          2875:                        {
        !          2876:                                Quick = TRUE;
        !          2877:                                break;
        !          2878:                        }
        !          2879: 
        !          2880:                        if (strcmp ("type", longOptions[optIndex].name) == 0)
1.1       root     2881:                        {
1.1.1.3 ! root     2882:                                if (strcasecmp (optarg, "normal") == 0)
        !          2883:                                        VolumeType = VOLUME_TYPE_NORMAL;
        !          2884:                                else if (strcasecmp (optarg, "hidden") == 0)
        !          2885:                                        VolumeType = VOLUME_TYPE_HIDDEN;
        !          2886:                                else
        !          2887:                                        goto usage;
        !          2888: 
1.1       root     2889:                                break;
                   2890:                        }
                   2891: 
                   2892:                        if (strcmp ("password-tries", longOptions[optIndex].name) == 0)
                   2893:                        {
                   2894:                                if (sscanf (optarg, "%d", &PasswordEntryTries) == 1)
                   2895:                                        break;
                   2896:                                else
                   2897:                                        goto usage;
                   2898:                        }
1.1.1.3 ! root     2899: 
        !          2900:                        if (strcmp ("properties", longOptions[optIndex].name) == 0)
        !          2901:                        {
        !          2902:                                char *volumePath = NULL;
        !          2903: 
        !          2904:                                if (optind < argc)
        !          2905:                                        volumePath = argv[optind++];
        !          2906: 
        !          2907:                                if (optind < argc)
        !          2908:                                        goto usage;
        !          2909: 
        !          2910:                                return DumpVolumeProperties (volumePath) ? 0 : 1;
        !          2911:                        }
        !          2912: 
        !          2913: 
        !          2914:                        if (strcmp ("restore-header", longOptions[optIndex].name) == 0)
        !          2915:                        {
        !          2916:                                char *volumePath = NULL;
        !          2917: 
        !          2918:                                if (optind < argc)
        !          2919:                                        volumePath = argv[optind++];
        !          2920: 
        !          2921:                                if (optind < argc)
        !          2922:                                        goto usage;
        !          2923: 
        !          2924:                                if (RestoreVolumeHeader (optarg, volumePath))
        !          2925:                                {
        !          2926:                                        printf ("Restore of volume header succeeded.\n");
        !          2927:                                        return 0;
        !          2928:                                }
        !          2929: 
        !          2930:                                return 1;
        !          2931:                        }
        !          2932: 
        !          2933:                        if (strcmp ("size", longOptions[optIndex].name) == 0)
        !          2934:                        {
        !          2935:                                if (!ParseSize (optarg, &VolumeSize))
        !          2936:                                        goto usage;
        !          2937:                                break;
        !          2938:                        }
        !          2939: 
1.1       root     2940:                        if (strcmp ("test", longOptions[optIndex].name) == 0)
                   2941:                        {
                   2942:                                if (AutoTestAlgorithms ())
                   2943:                                {
                   2944:                                        printf ("Self-tests of all algorithms passed.\n");
                   2945:                                        return 0;
                   2946:                                }
                   2947: 
                   2948:                                printf ("Self-tests of algorithms FAILED!\n");
                   2949:                                return 1;
                   2950:                        }
                   2951: 
                   2952:                        if (strcmp ("update-time", longOptions[optIndex].name) == 0)
                   2953:                        {
                   2954:                                UpdateTime = TRUE;
                   2955:                                break;
                   2956:                        }
                   2957:                        goto usage;
                   2958: 
                   2959:                default:
                   2960:                        goto usage;
                   2961:                }
                   2962:        }
                   2963:        
                   2964:        if (optind >= argc)
                   2965:                goto usage;
                   2966: 
                   2967:        if (optind < argc)
                   2968:                volumePath = argv[optind++];
                   2969: 
                   2970:        if (optind < argc)
                   2971:                mountPoint = argv[optind++];
                   2972: 
                   2973:        if (optind < argc)
                   2974:                goto usage;
                   2975: 
1.1.1.2   root     2976:        if (!CheckAdminPrivileges ())
                   2977:                return 1;
                   2978: 
1.1       root     2979:        // Relative path => absolute
                   2980:        if (volumePath[0] != '/')
                   2981:        {
                   2982:                char s[MAX_PATH];
                   2983:                getcwd (s, sizeof (s));
                   2984:                snprintf (volumePathBuf, sizeof (volumePathBuf), "%s/%s", s, volumePath);
                   2985:                volumePath = volumePathBuf;
                   2986:        }
                   2987: 
                   2988:        return MountVolume (volumePath, mountPoint) == FALSE;
                   2989: 
                   2990: usage:
1.1.1.3 ! root     2991:        DumpUsage (stdout);
1.1       root     2992: 
                   2993:        return 1;
                   2994: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.