我想将符号链接指向的文件的路径存储到bufff
中。这适用于我当前使用readlink
的实现,但它抓取了我不需要的额外数据,因为我的bufsize
是任意值的。我不确定如何根据符号链接指向的路径来调整大小,因为我所拥有的只是符号链接的路径。它存储在path
中,这是一个char数组。如果只有符号链接的路径,我怎么知道用链接的直接路径字符串的大小来bufff
呢?
char bufff[100];
size_t bufsize = 100;
readlink(path,bufff,bufsize);
答案 0 :(得分:2)
readlink()
返回路径的长度,它不会将尾随的NUL放入缓冲区。你需要自己做:
size_t pathlength = readlink(path, bufff, sizeof(bufff)-1);
bufff[pathlength] = 0;
请注意,我从缓冲区的大小中减去1,以确保NUL有空间。
答案 1 :(得分:2)
readlink()
函数返回复制到缓冲区的字节数,而不是最终的\0
。这意味着如果使用100字节的缓冲区调用readlink()
并且readlink()
返回100,则需要更多空间(即使路径正好是100字节,您仍然需要至少1个字节才能添加最后一个空字符。)
解决方案是在循环中增加缓冲区:
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
也是如此。你应该检查现实世界中的错误。
答案 2 :(得分:0)
基于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("");
}