【问题标题】:Retrieve path of symbolic link检索符号链接的路径
【发布时间】:2014-11-07 03:27:02
【问题描述】:

我想将符号链接指向的文件的路径存储到bufff。这适用于我当前使用readlink 的实现,但它会获取我不需要的额外数据,因为我的bufsize 是任意值的。我不确定如何根据符号链接指向的路径来调整它的大小,因为我所拥有的只是符号链接的路径。这存储在path 中,这是一个字符数组。如果我只有符号链接的路径,我怎么知道bufff 的大小和链接的直接路径字符串的大小一样?

char bufff[100];
size_t bufsize = 100;
readlink(path,bufff,bufsize);

【问题讨论】:

    标签: c linux path size symlink


    【解决方案1】:

    基于 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("");
    }
    

    【讨论】:

      【解决方案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。 mallocrealloc 相同。您应该在现实世界中检查错误。

      【讨论】:

        【解决方案3】:

        readlink() 返回路径的长度,它不会将尾随的 NUL 放入缓冲区。你需要自己做:

        size_t pathlength = readlink(path, bufff, sizeof(bufff)-1);
        bufff[pathlength] = 0;
        

        请注意,我从缓冲区的大小中减去了 1,以确保 NUL 有空间。

        【讨论】:

        • 我经常在path 缓冲区之前使用readlink 清除memset。因此,即使在 readlink 失败时,path 也有一个合理的、以 NUL 结尾的字符串。失败时,您的 pathlength 为 -1,buff[pathlength] 赋值为 未定义的行为(如果不走运,则为 solar system might collapse
        猜你喜欢
        • 2015-06-10
        • 1970-01-01
        • 2022-10-16
        • 2012-11-02
        • 1970-01-01
        • 2011-07-23
        • 2012-09-16
        • 1970-01-01
        • 2019-02-12
        相关资源
        最近更新 更多