我想存储符号链接指向bufff
的文件的路径。这适用于我使用readlink
的当前实现,但它获取了我不需要的额外数据,因为bufsize
的值是任意的。我不知道如何根据符号链接指向的路径来确定它的大小,因为我所拥有的只是指向符号链接的路径。它存储在path
中,这是一个char数组。如果我所拥有的只是符号链接的路径,我如何知道如何使用链接的直接路径字符串的大小来确定bufff
的大小?
char bufff[100];
size_t bufsize = 100;
readlink(path,bufff,bufsize);
发布于 2014-09-12 13:43:07
readlink()
函数返回复制到缓冲区的字节数,而不返回最终的\0
。这意味着,如果使用缓冲区为100字节的readlink()
调用,而readlink()
返回100字节,则需要更多的空间(即使路径正好是100个字节,在末尾添加空字符仍然需要至少一个字节)。
解决方案是在循环中增加缓冲区:
size_t bufsize = 255; /* Initial buffer size */
ssize_t result;
char* buf = malloc(bufsize); /* Initial buffer allocation */
while ((result = readlink(path, buf, bufsize)) >= bufsize) {
/* We double the buffer size, so next call should succeed ! */
bufsize *= 2;
buf = realloc(buf, bufsize);
}
buf[result] = '\0';
警告:这只是一个例子,如果出现错误,我们不会检查readlink
是否返回-1。malloc
和realloc
也是如此。你应该检查真实世界中的错误。
发布于 2014-09-12 13:19:12
readlink()
返回路径的长度,它不会将尾部NUL放入缓冲区。你需要自己做:
size_t pathlength = readlink(path, bufff, sizeof(bufff)-1);
bufff[pathlength] = 0;
请注意,我从缓冲区的大小中减去1,以确保NUL有空间。
发布于 2016-03-07 14:14:11
一个基于Thibaut D.的回答的完整函数:
char *do_get_symlink(char *path, struct stat attr) {
/*
* a much more elegant solution would be to use realpath(),
* but it is 35% slower and produces different results on /proc
*/
if (S_ISLNK(attr.st_mode)) {
/*
* st_size appears to be an unreliable source of the link length
* PATH_MAX is artificial and not used by the GNU C Library
*/
ssize_t length;
size_t buffer = 128;
char *symlink = malloc(sizeof(char) * buffer);
if (!symlink) {
fprintf(stderr, "%s: malloc(): %s\n", program, strerror(errno));
return strdup("");
}
/*
* if readlink() fills the buffer, double it and run again
* even if it equals, because we need a character for the termination
*/
while ((length = readlink(path, symlink, buffer)) > 0 && (size_t)length >= buffer) {
buffer *= 2;
symlink = realloc(symlink, buffer);
if (!symlink) {
fprintf(stderr, "%s: realloc(): %s\n", program, strerror(errno));
return strdup("");
}
}
if (length < 0) {
fprintf(stderr, "%s: readlink(%s): %s\n", program, path, strerror(errno));
free(symlink);
return strdup("");
}
symlink[length] = '\0';
return symlink;
}
/*
* the entry is not a symlink
* strdup is needed to keep the output free-able
*/
return strdup("");
}
https://stackoverflow.com/questions/25816944
复制相似问题