You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

libzip函数返回成功但无实际操作的问题排查与解决

libzip创建ZIP文件问题调试与解决

问题描述

我正在Windows 11系统下使用Visual Studio 2022和C语言学习libzip库的使用,目标是创建包含多文件夹多文件的ZIP文件。目前我仅需创建基础ZIP文件,但库的表现不符合预期:明明未执行任何可检测的请求操作,却返回成功状态。我并非仅寻求代码修复(当然也不拒绝),更想了解如何调试这种“返回成功但明显失败”的库问题。

测试现象

  • 当定义_UseFqn_并使用完整路径文件名(fqn)执行以下基础流程时,能成功创建ZIP文件(Windows无法读取但7-Zip可以,暂可接受):
zip_open()
zip_source_file(fqn)
zip_file_add(fqn)
zip_close()
  • 当调用SetCurrentDirectory()切换到文件所在目录(fpath),尝试添加无路径信息的文件(fname)时,无错误返回但也未生成ZIP文件:
zip_open()
SetCurrentDirectory(fpath)
zip_source_file(fname)
zip_file_add(fname)
zip_close()
  • 无论使用上述哪种流程,调用zip_dir_add()添加目录时,同样无错误返回但未生成ZIP文件。

测试源码

假设调用方式为:_MakeZipFile("testfile.zip","C:\path\to\file\something.log\0");

// -------------------------------------------------------------------------
// Add a single file to the zip
static int _AddFileToZip( zip_t *zipFile, char *szFileName )
{
   int            rc = NO_ERROR;
   zip_source_t  *source;

   source = zip_source_file( zipFile, szFileName, 0, ZIP_LENGTH_TO_END );
   if( source == NULL )
   {
      printf( "ZipTest>  Failed to src file for zip:  '%s'...\n", szFileName );
      printf( "ZipTest>  libzip:  %s\n", zip_strerror( zipFile ) );
      rc = ERROR_INVALID_PARAMETER;
   }
   else if( zip_file_add( zipFile, szFileName, source, ZIP_FL_ENC_RAW ) < 0 )
   {
      zip_source_free( source );
      printf( "ZipTest>  Failed to add file to zip:  '%s'...\n", szFileName );
      printf( "ZipTest>  libzip:  %s\n", zip_strerror( zipFile ) );
      rc = ERROR_INVALID_FUNCTION;
   }
   else
   {  // print a diagnostic for debugging
      printf( "ZipTest>  added file:  '%s'...\n", szFileName );
   }
   return rc;
}

// -------------------------------------------------------------------------
// Add all folder levels, from top to bottom, recursively
static BOOL _AddFolderToZip( zip_t *zipFile, char *szFolder )
{
   char         sz[_MAX_PATH];
   char        *cp;
   BOOL         bResult;
   zip_error_t *pze;

   if( ':' == szFolder[1] )
   {  // Remove drive letter, if present
      szFolder += 2;
   }
   if( '\\' == *szFolder )
   {  // Remove leading backslash, if present
      szFolder++;
   }
   
   strcpy( sz, szFolder ); // copy so we don't trash the original
   cp = strrchr( sz, '\\' );
   if( cp && ('\0' == *(cp+1)) )
   {  // Remove trailing backslash
      *cp = '\0';
   }

   // Is this a sub-folder?
   cp = strrchr( sz, '\\' );
   if( cp && (cp != sz) )
   {  // Yes, call self to add parent first
      *cp = '\0';
      if( !_AddFolderToZip( zipFile, sz ) )
      {  // Failure, back out with errors
         return FALSE;
      }
      *cp = '\\';
   }

   // else No, time to add this folder.
   bResult = TRUE;
   if( zip_dir_add( zipFile, sz, ZIP_FL_ENC_RAW ) < 0 )
   {  // Error, but there's one error that is OK...
      pze = zip_get_error( zipFile );
      if( ZIP_ER_EXISTS != pze->zip_err )
      {  // Multiple files in same folder are OK.
         bResult = FALSE;
         printf( "ZipTest>  Failed to add directory to zip:  '%s'...\n", szFolder );
         printf( "ZipTest>  libzip:  %s\n", zip_strerror( zipFile ) );
      }
   }
   if( bResult )
   {  // print a diagnostic for debugging
      printf( "ZipTest>  added directory:  '%s'...\n", sz );
   }
   return bResult;
}

// ------------------------------------------------------------------------
#define _UseFqn_ 1   // Use Fully qualified file names and no directories
// comment this out to change directory, add the file folder, and add the filename
// ------------------------------------------------------------------------

// szzSourceList is a buffoer containing some number of NULL terminated
//               strings that ends with an empty string (i.e. double-NULL)
BOOL _MakeZipFile( char *szZipFileName, char *szzSourceList )
{
   BOOL              result = FALSE;
   int               errorp = NO_ERROR;
   zip_t            *zipFile;
   char             *cpFilePath;
   zip_error_t       ziperror;
   zip_error_t      *pze;
#if !defined(_UseFqn_)
   char              szDrive[_MAX_PATH];
   char              szPath[_MAX_PATH];
   char              szFile[_MAX_PATH];
   char              szExt[_MAX_PATH];
   char              szFolder[_MAX_PATH];
#endif
   char              szStartPath[_MAX_PATH];

   GetCurrentDirectory( sizeof(szStartPath), szStartPath );

   zipFile = zip_open( szZipFileName, ZIP_CREATE | ZIP_TRUNCATE, &errorp );
   if( zipFile == NULL )
   {
      zip_error_init_with_code( &ziperror, errorp );
      printf( "ZipTest>  Failed to open output file '%s'...\n", szZipFileName );
      printf( "ZipTest>  libzip:  %s\n", zip_error_strerror( &ziperror ) );
      return FALSE;
   }

   __try
   {
      cpFilePath = szzSourceList;
      while( *cpFilePath )
      {
#if defined(_UseFqn_)
         _AddFileToZip( zipFile, cpFilePath );
#else
         _splitpath( cpFilePath, szDrive, szPath, szFile, szExt );
         sprintf( szFolder, "%s%s", szDrive, szPath );
         SetCurrentDirectory( szFolder );
         _AddFolderToZip( zipFile, szPath );
         strcat( szFile, szExt );
         _AddFileToZip( zipFile, szFile );
#endif

         // Find next entry in \0\0 terminated string list
         while( *cpFilePath )
         {
            cpFilePath++;
         }
         cpFilePath++;
      }
   }
   __finally
   {
      if( NO_ERROR == zip_close( zipFile ) )
      {
         result = TRUE;
      }
      else
      {
         pze = zip_get_error( zipFile );
         printf( "ZipTest>  Failed to create output file '%s'...\n", szZipFileName );
         printf( "ZipTest>  libzip:  %s\n", zip_strerror( zipFile ) );
         printf( "ZipTest>  zip_err = %d   sys_err = %d\n", pze->zip_err, pze->sys_err );
      }
   }

   SetCurrentDirectory( szStartPath );

   return result;
}

问题解决关键点(调试libzip源码后发现)

  • zip_open()函数并不会实际创建文件,仅保存文件名供后续zip_close()使用。如果在处理过程中更改了当前目录且未在调用zip_close()前恢复,ZIP文件会被创建在最后设置的当前目录下。这属于库的设计缺陷——若zip_open()调用未指定路径,应将当前目录预先添加到保存的ZIP文件名中,以便zip_close()正确使用。
  • 除了传递给zip_source_file()的文件名需要完整路径外,移除所有文件夹和文件名中的驱动器号并保留反斜杠后,操作效果更好。而zip_file_add()在文件的“半限定名”开头不含C:\(或其他驱动器号)时表现更佳。

内容的提问来源于stack exchange,提问作者Steve Valliere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:47:02