使用C在Linux上查找任意文件的设备或挂载点

时间:2014-09-25 19:51:44

标签: c linux mount-point

这个问题是针对Linux的;解决方案不需要是便携式的。

我正在寻找一个库函数/系统调用,或者它的一些组合,它将为任意文件提供设备(例如:/dev/sdb1)或挂载点(例如:/home)。看起来f_fsid结构的statfs字段会起作用,但它不会在Linux上使用。

我可以使用shell轻松找到这些信息:

df "$filename" | awk 'NR==1 {next} {print $6; exit}'

但似乎没有exec函数系列从运行的命令返回输出,我宁愿保持我的解决方案纯C。

3 个答案:

答案 0 :(得分:1)

似乎stat(2)(或lstat)是您正在寻找的功能。它将为您提供st_dev中的设备编号。

我认为df(1)只是读取/ etc / mtab。

答案 1 :(得分:0)

我使用stat()编写了一个纯C解决方案。对于那些可能在搜索中找到这个的人来说,这里有一个功能:

int getmntpt(char *path, char *mount_point) {
    struct stat cur_stat;
    struct stat last_stat;

    char dir_name[PATH_MAX];
    char *dirname_p = dir_name;
    char cur_cwd[255];
    char *cur_cwd_p = cur_cwd;
    char saved_cwd[PATH_MAX];
    if (getcwd(saved_cwd, PATH_MAX) == NULL) {
        errno = EIO;
        return ERROR;
    }

    if (lstat(path, &cur_stat) < 0) {
        errno = EIO;
        return ERROR;
    }

    if (S_ISDIR (cur_stat.st_mode)) {
        last_stat = cur_stat;
        if (chdir("..") < 0)
            return ERROR;
        if (getcwd(cur_cwd_p, 255) == NULL) {
            errno = EIO;
            return ERROR;
        }
    } else { /* path is a file */
        size_t path_len, suffix_len, dir_len;
        path_len = strlen(path);
        suffix_len = strlen(strrchr(path, 47)); /* 47 = '/' */
        dir_len = path_len - suffix_len;
        dirname_p = strncpy(dirname_p, path, dir_len);
        if (chdir(dirname_p) < 0) 
            return ERROR;
        if (lstat(".", &last_stat) < 0)
            return ERROR;
    }

    for (;;) {
        if (lstat("..", &cur_stat) < 0)
            return ERROR;
        if (cur_stat.st_dev != last_stat.st_dev || cur_stat.st_ino == last_stat.st_ino)
            break; /* this is the mount point */
        if (chdir("..") < 0)
            return ERROR;
        last_stat = cur_stat;
    }
    if (getcwd(mount_point, PATH_MAX) == NULL)
        return ERROR;
    if (chdir(saved_cwd) < 0)
        return ERROR;
    return SUCCESS;
}

答案 2 :(得分:0)

这是我根据@DarrenKirby的答案编写的C解决方案,但它避免使用chdir,并且更短。 [此外,它还处理了将挂载点本身作为参数传递的极端情况。

int getmntpt(char const  *path, char *mount_point) {

    char *test_path = malloc(PATH_MAX), *test_end;
    struct stat cur_stat, prev_stat;

    if (lstat(path, &prev_stat) < 0)
        return ERROR;

    test_end = stpcpy(test_path, path);
    if (!S_ISDIR(prev_stat.st_mode)) {
        test_end = strrchr(test_path, '/');
        if (test_end == NULL)
            test_end = stpcpy(test_path, ".");
        else
            *test_end = '\0';
    }

    for (;;) {
        test_end = stpcpy(test_end, "/..");     
        if (lstat(test_path, &cur_stat) < 0)
            return ERROR;
        if (cur_stat.st_dev != prev_stat.st_dev || cur_stat.st_ino == prev_stat.st_ino) /* root */
            break; /* this is the mount point */
        prev_stat = cur_stat;
    }

    *(test_end - 3) = '\0';
    if (realpath(test_path, mount_point) == NULL) {
        free(test_path);
        return -1;
    }

    return 0;
}