我正在寻找创建指向已经存在的文件或目录的硬链接。例如,用户选择创建到名为“路径名”的文件的硬链接,然后用户可以选择链接文件的名称。
答案 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
中的信息。