libzip中的符号链接

Symbolic links in libzip

本文关键字:符号链接 libzip      更新时间:2023-10-16

我在Linux的c++应用程序中使用libzip,它需要能够压缩/解压缩包含符号链接的目录。我想添加链接本身,而不跟随它。使用readlink()读取链接并将其添加到zip归档文件中,在使用unzip解压缩时将得到一个无意义的标准文件。

解决方案不需要可移植,它只会在Linux下使用。linux zip命令有一个——symlinks标志,因此zip标准应该支持它。系统调用不是一个真正的选择,文件的数量相当大,这使得应用程序极其缓慢。

是否可以添加符号链接与libzip,以及如何?

谢谢,桑德

基于文档:no

根据其网页,libzip是基于zlib的。Linux等中使用的zip程序是info-zip,它不使用zlib,但它是自包含的(并且包含zlib中没有的功能)。

这是可能的。

在c代码中用于压缩文件列表的函数下面。要压缩的文件存储在cJSON结构中,没有uid/gid集和相对于目录"base"的文件/目录(因为这是我的应用程序)。

函数成功返回0。

int list_zip_it(char * upload_zip_name,char * base, cJSON * filelist)
{
   int result=0;
   int error_n = 0;
   struct zip *archive = zip_open(upload_zip_name, ZIP_TRUNCATE | ZIP_CREATE, &error_n);
   if(!archive)
   {
     printf(stderr,"could not open or create archiven");
     return -1;
   }
   mode_t mode=0;
   cJSON * item;
   cJSON_ArrayForEach(item,filelist)
   {
      char * path=NULL; 
      path=item->valuestring;
      // stat the item
      struct stat sb;
      if (stat(path, &sb) == 0 ) mode=sb.st_mode;
      zip_uint32_t attr=0;
      attr=((mode ) << 16L);
      char rel_file[1024];
      if (strncmp(path,CI_PROJECT_DIR,strlen(base))==0 )
      {
          snprintf(rel_file,1024,"%s",path+strlen(base)+1);
          printf("archive filename: %sn",rel_file);
      } 
      else
      {
         fprintf(stderr,"filename outside base-derectoryn");
         continue;
      }
      if (S_ISDIR(mode))
      {
        int index = (int)zip_add_dir(archive, rel_file);
        if (index>0) zip_file_set_external_attributes(archive, index, 0, ZIP_OPSYS_UNIX, attr);
      }
      else if (S_ISLNK(mode)) // symlink
      {
        char link[1024];//=calloc(1, 1024);
        memset(link, 0, 1024);
        ssize_t size_link=readlink(path , link, 1023);
        if (size_link > 0)
        {
            struct zip_source *source = zip_source_buffer(archive , link, ( zip_uint64_t)size_link,0);
            if (source)
            {
                int index = (int)zip_add(archive, rel_file, source);
                if (index>0) zip_file_set_external_attributes(archive, index, 0, ZIP_OPSYS_UNIX, attr);
             }
             else
             {
                printf(stderr,"failed to create source buffer: %s n", zip_strerror(archive) );
                zip_source_free(source);
             }
           }
           else error("failed to read link: %s n",path );
       }
       else if (S_ISREG(mode))
       {
         struct zip_source *source = zip_source_file(archive, path, 0, 0);
         if(source == NULL)
         {
             error("failed to create source buffer: %s n", zip_strerror(archive) );
             result=1;
             break;
          }
          // todo calculate filename relative to project_dir
          int index = (int)zip_add(archive, rel_file, source);
          if(index < 0 )
          {
              int zep,sep;
              zip_error_get(archive, &zep, &sep);
              if (zep== ZIP_ER_EXISTS )
              {
                  fprintf(stderr,"failed to add file to archive: %s n", zip_strerror(archive) );
                  zip_source_free(source);
              }
              else
              {
                 fprintf(stderr,"failed to add file to archive: %s n", zip_strerror(archive) );
                 zip_source_free(source);
                 result=1;
                 break;
               }
           }
           else
           {
                zip_file_set_external_attributes(archive, index, 0, ZIP_OPSYS_UNIX, attr);
           }
        }
    }
    zip_close(archive);
    return result;
}