⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsutils.c

📁 Cryptmount是对Linux系统下的文件系统以及用户设备、文档等进行加密的系统.
💻 C
字号:
/* *  filesystem-related utilities for cryptmount *  $Revision: 125 $, $Date: 2006-09-22 20:39:18 +0100 (Fri, 22 Sep 2006) $ *  Copyright 2005-2006, RW Penney *//*    This file is part of cryptmount    cryptmount is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    As a special exemption, permission is granted to link cryptmount    with the OpenSSL project's "OpenSSL" library and distribute    the linked code without invoking clause 2(b) of the GNU GPL version 2.    cryptmount is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with cryptmount; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include <config.h>#include <ctype.h>#include <fcntl.h>#include <mntent.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/mount.h>#include <sys/stat.h>#include <sys/statvfs.h>#include <sys/types.h>#include <sys/wait.h>#include "cryptmount.h"#include "delegates.h"#include "dmutils.h"#include "fsutils.h"#if WITH_CSWAP#  include <sys/swap.h>#endif#define ETCMTAB     "/etc/mtab"#define ETCMTABTMP  "/etc/mtab.cm"enum {    F_MATCHUID = 0x01, F_CLOSE1 = 0x02 };static int run_sucommand(const char *path, const char *argv[],                        unsigned switches, int failflag);int do_addmntent(const cment_t *cment);int do_rmvmntent(const cment_t *cment);#if ERSATZ_MOUNTint fs_mount(const char *mntdev, const cment_t *cment)    /* fallback version of mount(8) using mount(2) */{   unsigned long mflags;    int eflag=ERR_NOERROR;    char *errstr=NULL;    if (parse_fsoptions(cment->fsoptions, &mflags) != 0) {        return ERR_BADMOUNT;    }    errstr = (char*)malloc((size_t)(strlen(mntdev) + strlen(cment->dir) + 64));    sprintf(errstr, "mounting \"%s\" on \"%s\" failed", mntdev, cment->dir);    if (mount(mntdev, cment->dir, cment->fstype, mflags, NULL) == 0) {        (void)do_addmntent(cment);    } else {        perror(errstr);        eflag = ERR_BADMOUNT;    }    free((void*)errstr);    return eflag;}#else   /* !ERSATZ_MOUNT */int fs_mount(const char *dev, const cment_t *cment)    /* delegate filesystem mounting to mount(8) */{   int idx,eflag=ERR_NOERROR;    const char *argv[16];    /* construct argument list for mount -t ... -o ... <dev> <dir> */    idx = 0;    argv[idx++] = "[cryptmount-mount]";    if (cment->fstype != NULL) {        argv[idx++] = "-t"; argv[idx++] = cment->fstype;    }    if (cment->fsoptions != NULL) {        argv[idx++] = "-o"; argv[idx++] = cment->fsoptions;    }    argv[idx++] = dev; argv[idx++] = cment->dir;    argv[idx++] = NULL;    eflag = run_sucommand(DLGT_MOUNT, argv, F_MATCHUID, ERR_BADMOUNT);    return eflag;}#endif  /* ERSATZ_MOUNT */#if ERSATZ_UMOUNTint fs_unmount(const cment_t *cment)    /* fallback version of umount(8) using umount(2) */{   int eflag=ERR_NOERROR;    char *errstr=NULL;    errstr = (char*)malloc((size_t)(strlen(cment->dir) + 64));    sprintf(errstr, "unmounting \"%s\" failed", cment->dir);    if (umount(cment->dir) == 0) {        (void)do_rmvmntent(cment);    } else {        perror(errstr);        eflag = ERR_BADMOUNT;    }    free((void*)errstr);    return eflag;}#else   /* !ERSATZ_UMOUNT */int fs_unmount(const cment_t *cment)    /* delegate filesystem mounting to umount(8) */{   int idx,eflag=ERR_NOERROR;    const char *argv[16];    /* construct argument list for umount -t ... <dir> */    idx = 0;    argv[idx++] = "[cryptmount-umount]";#ifdef PARANOID    if (cment->fstype != NULL) {        argv[idx++] = "-t"; argv[idx++] = cment->fstype;    }    if (cment->fsoptions != NULL) {        argv[idx++] = "-O"; argv[idx++] = cment->fsoptions;    }#endif    argv[idx++] = cment->dir;    argv[idx++] = NULL;    eflag = run_sucommand(DLGT_UMOUNT, argv, F_MATCHUID, ERR_BADMOUNT);    return eflag;}#endif  /* ERSATZ_UMOUNT */#if WITH_CSWAPint fs_swapon(const char *mntdev, const cment_t *cment){   int idx,eflag=ERR_NOERROR;    const char *argv[8];    int prio=(SWAP_FLAG_PREFER | (0x100 & SWAP_FLAG_PRIO_MASK));    if (strcmp(cment->fstype,"swap") != 0) {        fprintf(stderr, _("unsuitable filesystem type \"%s\" for swapping\n"),                cment->fstype);        eflag = ERR_BADSWAP;        goto bail_out;    }    if ((cment->flags & FLG_MKSWAP) != 0) {        /* construct argument list for mkswap <dev> */        idx = 0;        argv[idx++] = "[cryptmount-mkswap]";        argv[idx++] = mntdev;        argv[idx++] = NULL;        eflag = run_sucommand(DLGT_MKSWAP, argv, F_CLOSE1, ERR_BADSWAP);        if (eflag != ERR_NOERROR) goto bail_out;    }    if (swapon(mntdev, prio) != 0) {        eflag = ERR_BADSWAP;        goto bail_out;    }  bail_out:    return eflag;}int fs_swapoff(const cment_t *cment){   char *mntdev=NULL;    int eflag=ERR_NOERROR;    if (strcmp(cment->fstype,"swap") != 0) {        eflag = ERR_BADSWAP;        goto bail_out;    }    devmap_path(&mntdev, cment->ident);    if (swapoff(mntdev) != 0) {        eflag = ERR_BADSWAP;        goto bail_out;    }  bail_out:    if (mntdev != NULL) free((void*)mntdev);    return eflag;}#endif  /* WITH_CSWAP */int parse_fsoptions(const char *buff, unsigned long *mflags)    /* convert string of mount-options into binary flags */{   struct fsopt_t {        const char *str;        unsigned long mask; };    struct fsopt_t fsopts[] = {        { "defaults",   0 },        { "noatime",    MS_NOATIME },        { "nodev",      MS_NODEV },        { "noexec",     MS_NOEXEC },        { "nosuid",     MS_NOSUID },        { "ro",         MS_RDONLY },        { "sync",       MS_SYNCHRONOUS },        { NULL, 0 } };    unsigned idx,len;    *mflags = 0;    if (buff == NULL) return 0;    for (;;) {        for (len=0; buff[len]!='\0' && buff[len]!=','; ++len);        for (idx=0; fsopts[idx].str!=NULL; ++idx) {            if (strncmp(buff, fsopts[idx].str, (size_t)len) == 0) {                *mflags |= fsopts[idx].mask;                break;            }        }        if (fsopts[idx].str == NULL) {            fprintf(stderr, "bad option \"%s\"\n", buff);            return 1;        }        if (buff[len] == '\0') break;        buff += len + 1;    }    return 0;}int do_addmntent(const cment_t *cment)    /* add entry into /etc/mtab for newly-mounted filing system */{   char *mntdev=NULL;    struct mntent mntinfo;    FILE *fp;    int eflag=ERR_NOERROR;    devmap_path(&mntdev, cment->ident);    mntinfo.mnt_fsname = mntdev;    mntinfo.mnt_dir = cment->dir;    mntinfo.mnt_type = cment->fstype;    mntinfo.mnt_opts = "none";    mntinfo.mnt_freq = 0;    mntinfo.mnt_passno = 0;    fp = setmntent(ETCMTAB, "a");    if (fp == NULL) {        eflag = ERR_BADFILE;        goto bail_out;    }    (void)addmntent(fp, &mntinfo);    endmntent(fp);  bail_out:    if (mntdev != NULL) free((void*)mntdev);    return eflag;}int do_rmvmntent(const cment_t *cment)    /* remove entry from /etc/mtab after unmounting filing system */{   char *mntdev=NULL;    struct mntent *mntinfo;    FILE *fp_in=NULL,*fp_out=NULL;    struct stat sbuff;    int i,eflag=ERR_NOERROR,found=0;    /* FIXME - add lots more checks on integrity: */    devmap_path(&mntdev, cment->ident);    /* open old /etc/mtab & create temporary replacement: */    fp_in = setmntent(ETCMTAB, "r");    fp_out = setmntent(ETCMTABTMP, "w");    if (fp_in == NULL || fp_out == NULL) {        eflag = ERR_BADFILE;        goto bail_out;    }    i = stat(ETCMTAB, &sbuff);    if (i != 0 || !S_ISREG(sbuff.st_mode)) {        fprintf(stderr, "%s is not a valid file\n", ETCMTAB);        eflag = ERR_BADFILE;        goto bail_out;    }    /* transfer entries from old /etc/mtab to prototype replacement file: */    while ((mntinfo = getmntent(fp_in)) != NULL) {        if (strcmp(mntinfo->mnt_fsname, mntdev) == 0          && strcmp(mntinfo->mnt_dir, cment->dir) == 0) {            ++found;        } else {            addmntent(fp_out, mntinfo);        }    }    /* transfer ownership & permissions from old /etc/mtab to new: */    if (chown(ETCMTABTMP, sbuff.st_uid, sbuff.st_gid) != 0      || chmod(ETCMTABTMP, sbuff.st_mode) != 0) {        fprintf(stderr, "cannot transfer ownership/modes to \"%s\"\n",                ETCMTABTMP);        eflag = ERR_BADFILE;        goto bail_out;    }    endmntent(fp_in); fp_in = NULL;    if (rename(ETCMTABTMP, ETCMTAB)) {        fprintf(stderr, "failed to recreate %s\n", ETCMTAB);    }  bail_out:    if (fp_in != NULL) endmntent(fp_in);    if (fp_out != NULL) endmntent(fp_out);    if (mntdev != NULL) free((void*)mntdev);    return eflag;}int is_mounted(const cment_t *cment)    /* check if target is mounted */{   int mounted=0;    struct stat sbuff;    char *mntdev=NULL;    struct mntent *mntinfo;    FILE *fp;    /* check if underlying device has been configured at all: */    if (!is_configured(cment->ident, NULL)) return 0;    devmap_path(&mntdev, cment->ident);    if (stat(mntdev, &sbuff) != 0) return 0;    /* check entries in /etc/mtab: */    fp = setmntent(ETCMTAB, "r");    if (fp == NULL) {        return 0;       /* indeterminate case - assume not mounted */    }    while ((mntinfo = getmntent(fp)) != NULL && !mounted) {        if (strcmp(mntinfo->mnt_fsname, mntdev) == 0          && strcmp(mntinfo->mnt_type, cment->fstype) == 0) {            mounted = 1;        }    }    endmntent(fp);    return mounted;}int is_readonlyfs(const char *path)    /* check if filesystem containing *path is read-only */{   struct statvfs sbuff;    return ((statvfs(path, &sbuff) != 0 || (sbuff.f_flag & ST_RDONLY) != 0));}#if WITH_FSCKint fs_check(const char *dev, const cment_t *cment){   int idx,eflag=ERR_NOERROR;    const char *argv[16];    /* construct argument list for fsck -T -t ... <dev> */    idx = 0;    argv[idx++] = "[cryptmount-fsck]";    argv[idx++] = "-T";    if (cment->fstype != NULL) {        argv[idx++] = "-t"; argv[idx++] = cment->fstype;    }    argv[idx++] = dev;    argv[idx++] = NULL;    eflag = run_sucommand(DLGT_FSCK, argv, F_MATCHUID, ERR_BADFSCK);    return eflag;}#endif  /* WITH_FSCK */#if !ERSATZ_MOUNT || !ERSATZ_UMOUNT || WITH_FSCK || WITH_CSWAPstatic int run_sucommand(const char *path, const char **argv,                        unsigned switches, int failflag)    /* fork (& wait for) system-command as root */{   pid_t child;    int stat=0,fd,eflag=ERR_NOERROR;    switch ((child = fork())) {        case -1:        /* fork failed */            fprintf(stderr, "failed to fork (%s)\n", path);            eflag = failflag;            break;        case 0:         /* child fork */            if ((switches & F_MATCHUID) != 0) {                /* change real UID to match effective UID                   (probably only useful if euid==root): */                setuid(geteuid());            }            if ((switches & F_CLOSE1) != 0) {                /* redirect standard output to /dev/null */                fd = open("/dev/null", O_WRONLY);                if (fd >= 0) dup2(fd, STDOUT_FILENO);                else close(STDOUT_FILENO);            }            execv(path, (char *const *)argv);            fprintf(stderr, "failed to invoke \"%s\"\n", path);            exit(1);            break;        default:        /* parent fork */            if (waitpid(child, &stat, 0) == child) {                eflag = (stat != 0 ? failflag : ERR_NOERROR);            }            break;    }    return eflag;}#endif/* *  fsutils.c *  (C)Copyright 2005-2006, RW Penney */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -