如何在C中创建到现有文件或目录的硬链接?

时间:2018-12-06 03:24:10

标签: c hardlink

我正在寻找创建指向已经存在的文件或目录的硬链接。例如,用户选择创建到名为“路径名”的文件的硬链接,然后用户可以选择链接文件的名称。

1 个答案:

答案 0 :(得分:0)

在大多数现代版本的Unix(或Unix的变体)上,您不能创建指向目录的硬链接。如果您具有足够的特权并且系统支持它,则POSIX会允许它。但是,(我相信大多数人)某些系统不允许它。

要创建硬链接,您需要使用link()函数(系统调用):

Activity

请注意,新名称必须完整,与 if(mNetwork != null) { mNetwork.stop(); } 命令不同。您不能将目录指定为新名称。您必须在目录中指定文件名。


  

您能否更详细地介绍if (link(existing_file, new_name) != 0) …link failed… 函数的工作原理?

如果以ln的形式调用,则必须以link()的名称存在某种文件(除非您具有“适当的特权”,否则它不能是目录-这意味着超级用户或link(source, target)特权),并且在source中不得有名称相同的文件,但是所有导致由root命名的文件的目录都必须存在。假设满足前提条件,则在系统调用成功之后,您可以使用target中的名称或target中的名称来引用相同的文件内容。

  

例如,如果我要求用户选择一个现有路径,然后为要创建的硬链接选择一个名称,我将如何处理?

FWIW,不要打扰提示-使用命令行参数,就像ln命令一样。

  

我还读到我必须取消原始文件的链接。

您可能没有,但这取决于要实现的语义以及“原始文件”的含义。可以编写代码删除目标文件(如果已存在)(例如source会删除目标文件(如果已存在))。链接成功后,可能会编写删除源文件名的代码(例如target-注意不同的命令名)。可能会编写代码来尝试确保创建所有通往目标的目录(如果它们不存在)(例如ln -f source target)。等等,您可以决定允许通过命令行选项指定目标目录,而不仅仅是使用最后一个参数作为目标目录。等等,有很多可能性-您只需要确定所需的语义并实现它们即可。请注意,符号(软)链接和symlink()函数的规则与硬链接的规则不同。

以下是一些代码(源文件mv source target):

mkdir -p $(dirname target)

末尾的link37.c并不是必须的。从#include "stderr.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> int main(int argc, char **argv) { err_setarg0(argv[0]); if (argc != 3) err_usage("source target"); char *source = argv[1]; char *target = argv[2]; struct stat sb; if (stat(source, &sb) != 0) err_syserr("cannot access source file '%s': ", source); if (stat(target, &sb) == 0) { if (!S_ISDIR(sb.st_mode)) err_error("name '%s' exists and is not a directory\n", target); else { char *slash = strrchr(source, '/'); if (slash == 0) slash = source; else slash++; if (*slash == '\0') err_error("name '%s' cannot end with a slash\n", source); size_t baselen = strlen(target); size_t filelen = strlen(slash); size_t namelen = baselen + filelen + 2; char *name = malloc(namelen); if (name == 0) err_syserr("failed to allocate %zu bytes memory: ", namelen); memmove(name, target, baselen); memmove(name + baselen, "/", 1); memmove(name + baselen + 1, slash, filelen + 1); target = name; } } if (link(source, target) != 0) err_syserr("failed to link '%s' to '%s': ", source, target); if (target != argv[2]) free(target); return 0; } 开始的函数在GitHub上的SOQ(堆栈溢出问题)存储库中,作为src/libsoq子目录中的文件free()err_提供。它们就是我报告程序错误的方式。有些系统具有标头stderr.c和各种各样的功能,这些功能可以完成我的程序包所执行的某些工作-可以与它们一起玩(我不喜欢它们,但也有很多NIH综合征的情况)。还有其他方法可以串联文件名组件;一种方法是使用stderr.h而不是3个<err.h>操作。

样品运行:

sprintf(name, "%s/%s", target, slash)

我已经有一个目录memmove()(因此$ link37 link37.c chameleon $ mkdir -p doc $ link37 link37.c doc $ link37 /Users/jonathanleffler/soq/ src link37: name '/Users/jonathanleffler/soq/' cannot end with a slash $ link37 /Users/jonathanleffler/soq src link37: failed to link '/Users/jonathanleffler/soq' to 'src/soq': error (1) Operation not permitted $ link37 link37.c chameleon link37: name 'chameleon' exists and is not a directory $ link37 /no/where/file.c /some/where/ link37: cannot access source file '/no/where/file.c': error (2) No such file or directory $ link37 link37.c /some/where/ link37: failed to link 'link37.c' to '/some/where/': error (2) No such file or directory $ rm -f doc/link37.c chameleon $ rmdir doc 2>/dev/null $ 没做任何事情),但是最后的doc也没有损坏。这就是为什么我没有使用mkdir -p doc的原因-我有要保留在rmdir doc中的信息。