提问人:programme3219873 提问时间:7/14/2022 最后编辑:Jonathan Lefflerprogramme3219873 更新时间:7/14/2022 访问量:216
查找与文件名关联的目录的文件描述符
Find file descriptor of directory associated with filename
问:
我正在尝试编写一个函数,允许用户以纳秒级精度更改文件时间戳。经过一番研究,我找到了允许我这样做的函数 utimensat()。但是,问题在于该函数采用一个参数,该参数是文件所在目录的文件描述符。int dirfd
使用文件名是否可以以某种方式找到文件所在目录的文件描述符?
例如,如果一个文件位于 ,我如何获取该目录的文件描述符?又名目录。test.txt
/home/user/files/test.txt
test.txt
files
答:
有多种方法可以达到预期的结果,最简单的方法根本不涉及打开目录。
static void set_time(const char *file, struct timespec *tvals)
{
if (utimensat(AT_FDCWD, file, tvals, 0) != 0)
err_sysrem("failed to set time on %s: ", file);
}
这使用幻数,这意味着函数的文件名参数被解释为“正常”。对于作为文件名的命令行参数,建议使用此选项。AT_FDCWD
如果您正在使用 opendir()、readdir
()、closedir() 从 <dirent.h>
处理目录,则可以使用 dirfd
()
获取与当前目录结构关联的目录文件描述符。 您可以使用它来设置文件修改时间。
DIR *
如果你仍然想打开目录,那么你可以使用 dirname() 来查找给定文件名的目录名(你也可以使用 basename()
来查找目录中的文件名)。小心;根据 POSIX 的说法,实现有很多可能性。通常,在将重复的字符串传递给 之前,应创建文件名的副本。您可以在调用字符串之前调用字符串。然后,您可以使用
open(
) 打开仅供读取的目录——可能使用(未广泛使用)或用作打开模式。不要忘记在完成后关闭目录,也不要释放您使用的文件名的副本。dirname()
basename()
dirname()
O_SEARCH
O_RDONLY
下面是一个程序的源代码,它将文件上的时间戳设置为所选时间——默认为当前时间。ft97.c
ft97
#include "posixver.h"
#include <fcntl.h> /* AT_FDCWD on macOS Monterey 12.4 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "stderr.h"
#include "timespec_io.h"
static char optstr[] = "a:hm:t:V";
static char usestr[] = "[-hV] [-a atime] [-m mtime] [-t time] file ...";
static char hlpstr[] =
" -a atime Use this time for the access time (default: now)\n"
" -h Print this help message and exit\n"
" -m mtime Use this time for the modification time (default: now)\n"
" -t time Use this time value for both access and modification time\n"
" -V Print version information and exit\n"
;
static void set_time(const char *file, struct timespec *tvals)
{
if (utimensat(AT_FDCWD, file, tvals, 0) != 0)
err_sysrem("failed to set time on %s: ", file);
}
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
struct timespec tvals[2];
clock_gettime(CLOCK_REALTIME, &tvals[0]);
tvals[1] = tvals[0];
int opt;
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'a':
if (scn_timespec(optarg, &tvals[0]) != 0)
err_error("failed to parse '%s' as a time\n", optarg);
break;
case 'h':
err_help(usestr, hlpstr);
/*NOTREACHED*/
case 'm':
if (scn_timespec(optarg, &tvals[1]) != 0)
err_error("failed to parse '%s' as a time\n", optarg);
break;
case 'V':
err_version("FT97", &"@(#)$Revision$ ($Date$)"[4]);
/*NOTREACHED*/
case 't':
if (scn_timespec(optarg, &tvals[0]) != 0)
err_error("failed to parse '%s' as a time\n", optarg);
tvals[1] = tvals[0];
break;
default:
err_usage(usestr);
/*NOTREACHED*/
}
}
if (argc == optind)
err_usage(usestr);
for (int i = optind; i < argc; i++)
set_time(argv[i], tvals);
return 0;
}
您可以在 GitHub 上的 SOQ(堆栈溢出问题)存储库中找到非标准标头文件和相应的源代码,作为文件 、 、 和 src/libsoq 子目录。stderr.c
stderr.h
posixver.h
timespec_io.c
timespec_io.h
上一个:如何更改文件时间戳,包括纳秒
评论
mode_t
格式? 问题。阅读本文后,请标记此评论“不再需要”。