简体   繁体   中英

Symbolic links in libzip

I'm using libzip in a c++ application for Linux that will need to be able to zip/unzip directories containing symbolic links. I want to add the link itself without following it. Reading out the link with readlink() and adding it to the zip archive results in a nonsense standard file when unzipped with unzip.

Solution does not need to be portable, it will only be used under Linux. The linux zip command has a --symlinks flags so the zip standard should support it. System calls are not really an option, the number of files is quite large and this makes the application extremely slow.

Is it possible to add symlinks with libzip, and how?

Thanks, Sander

Based on documentation: no

According to its webpage , libzip is based on zlib . The zip program used in Linux, etc, is info-zip , which does not use zlib, but is self-contained (and contains features not in zlib).

Yes it's possible.

Below a function i use for zipping a list of files in c-code. The files to zip are stored in a cJSON struct,no uid/gid set and files/directories relative to a directory "base" (as that is my appliction).

The Function returns 0 on success.

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 archive\n");
     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: %s\n",rel_file);
      } 
      else
      {
         fprintf(stderr,"filename outside base-derectory\n");
         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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM