Explorar el Código

Z991239-1931 #comment fix: 优化压缩和解压代码

Signed-Off-By: commit-hook
刘文涛80174520 hace 4 años
padre
commit
f81e29d140

+ 405 - 44
Module/mod_UpgradeRun/XUnZipZilb.cpp

@@ -11,6 +11,13 @@
 #define ZIP_ZILP_MAX_FILENAME 512
 #define ZIP_ZILP_READ_SIZE 4096
 
+#define ZIP_ZILP_HOST_SYSTEM(VERSION_MADEBY)  ((uint8_t)(VERSION_MADEBY >> 8))
+#define ZIP_ZILP_HOST_SYSTEM_MSDOS            (0)
+#define ZIP_ZILP_HOST_SYSTEM_UNIX             (3)
+#define ZIP_ZILP_HOST_SYSTEM_WINDOWS_NTFS     (10)
+#define ZIP_ZILP_HOST_SYSTEM_RISCOS           (13)
+#define ZIP_ZILP_HOST_SYSTEM_OSX_DARWIN       (19)
+
 int UnZipToDir(string zipFileName, string destDirPath)
 {
 	//	Dbg("zipFileName %s destDirPath %s", zipFileName.c_str(), destDirPath.c_str());
@@ -52,6 +59,146 @@ int UnZipToDir(string zipFileName, string destDirPath)
 	return 0;
 }
 
+//int unZipCurrentFile(zipFile zf, string destDirPath)
+//{
+//	unz_file_info file_info;
+//	char zipFilename[ZIP_ZILP_MAX_FILENAME];
+//	memset(zipFilename, 0, ZIP_ZILP_MAX_FILENAME);
+//	
+//	string newFileName = "";
+//	bool isDir = false;
+//	if (unzGetCurrentFileInfo(zf, &file_info, zipFilename, ZIP_ZILP_MAX_FILENAME, NULL, 0, NULL, 0) != UNZ_OK)
+//	{
+//		Dbg("could not read file info");
+//		return -1;
+//	}
+//#ifdef RVC_OS_WIN
+//	if (is_str_utf8(zipFilename)) {
+//		//Dbg("file name is UTF8");
+//		newFileName = utf8_to_gbk(zipFilename);
+//	}
+//	else {
+//		//Dbg("file name is GBK");
+//		newFileName = zipFilename;
+//	}
+//#else
+//	if (!is_str_utf8(zipFilename)) {
+//		//Dbg("file name is GBK");
+//		//newFileName = gbk_to_utf8(zipFilename);
+//		unsigned char* tempName = utf8_string_create((const char*)zipFilename);
+//		if (tempName == NULL) {
+//			Dbg("get utf8 str is null");
+//			return -1;
+//		}
+//		newFileName = (const char*)tempName;
+//		free(tempName);
+//	}
+//	else {
+//		//Dbg("file name is UTF8");
+//		newFileName = zipFilename;
+//	}
+//#endif // RVC_OS_WIN
+//	Dbg("unZipCurrentFile newFileName %s", newFileName.c_str());
+//	string filestr = newFileName;
+//	//判断是文件还是文件夹
+//
+//	if (filestr.substr(filestr.length() - 1, 1) == "/") {
+//		isDir = true;
+//	}
+//
+//	if (isDir)
+//	{   //创建文件夹
+//		string dirPath = destDirPath + SPLIT_SLASH_STR + newFileName;
+//		Dbg("creating directory: %s", dirPath.c_str());
+//		if (!CreateDirA(dirPath.c_str(), true))
+//		{
+//			Dbg("creating directory fail: dirPath(%s) zipFileName(%s)", dirPath.c_str(), newFileName.c_str());
+//			return -1;
+//		}
+//	}
+//	else
+//	{   //打开zip里面的文件
+//		string fileNamePath = destDirPath + SPLIT_SLASH_STR + newFileName;
+//		Dbg("creating file:%s", fileNamePath.c_str());
+//
+//		//先创建文件的父文件夹
+//		int pos = fileNamePath.find_last_of(SPLIT_SLASH);
+//		string newFileDirPath(fileNamePath.substr(0, pos));
+//		//Dbg("creating dir:%s", newFileDirPath.c_str());
+//		if (!CreateDirA(newFileDirPath.c_str(), true)) {
+//			Dbg("creating zip file dir fail: dirPath(%s)", newFileDirPath.c_str());
+//			return -1;
+//		}
+//
+//		if (unzOpenCurrentFile(zf) != UNZ_OK)
+//		{
+//			Dbg("could not open zip file ,%s", newFileName);
+//			return -1;
+//		}
+//		// Open a file to write out the data.
+//		FILE* out = fopen(fileNamePath.c_str(), "wb");
+//
+//		if (out == NULL)
+//		{
+//			Dbg("could not open destination file, %s", fileNamePath.c_str());
+//			unzCloseCurrentFile(zf);
+//			return -1;
+//		}
+//
+//		int err = UNZ_OK;
+//		unsigned char * read_buffer= new unsigned char[ZIP_ZILP_READ_SIZE];
+//		memset(read_buffer, 0, ZIP_ZILP_READ_SIZE);
+//		do
+//		{
+//			err = unzReadCurrentFile(zf, read_buffer, ZIP_ZILP_READ_SIZE);
+//			if (err < 0)
+//			{
+//				Dbg("error %d with zipfile in unzReadCurrentFile", err);
+//				break;
+//			}
+//
+//			// Write data to file.
+//			if (err > 0)
+//			{
+//				if (fwrite(read_buffer, err, 1, out) != 1) {
+//					Dbg("error in writing extracted file");
+//					err = UNZ_ERRNO;
+//					break;
+//				}
+//			}
+//		} while (err > 0);
+//
+//		delete[] read_buffer;//删除临时对象
+//
+//		if (out!=NULL) {
+//			if (fclose(out)!=0) {
+//				Dbg("fclose new file from zip fail, %s", fileNamePath.c_str());
+//				unzCloseCurrentFile(zf);
+//				return -1;
+//			}
+//		}
+//
+//		if (err == UNZ_OK) {
+//			//正常结束
+//			err = unzCloseCurrentFile(zf);
+//			if (err != UNZ_OK) {
+//				Dbg("error %d with zipfile in unzCloseCurrentFile", err);
+//				return -1;
+//			}
+//			if (changeUnZipFileAtt(fileNamePath.c_str())!=0) {
+//				return -1;
+//			}
+//			return 0;
+//		}
+//		else {
+//			//异常结束
+//			unzCloseCurrentFile(zf); /* don't lose the error */
+//			return -1;
+//		}
+//	}
+//	return 0;
+//}
+
 int unZipCurrentFile(zipFile zf, string destDirPath)
 {
 	unz_file_info file_info;
@@ -65,6 +212,7 @@ int unZipCurrentFile(zipFile zf, string destDirPath)
 		Dbg("could not read file info");
 		return -1;
 	}
+	//转码
 #ifdef RVC_OS_WIN
 	if (is_str_utf8(zipFilename)) {
 		//Dbg("file name is UTF8");
@@ -91,6 +239,7 @@ int unZipCurrentFile(zipFile zf, string destDirPath)
 		newFileName = zipFilename;
 	}
 #endif // RVC_OS_WIN
+
 	Dbg("unZipCurrentFile newFileName %s", newFileName.c_str());
 	string filestr = newFileName;
 	//判断是文件还是文件夹
@@ -99,6 +248,14 @@ int unZipCurrentFile(zipFile zf, string destDirPath)
 		isDir = true;
 	}
 
+	//替换newFileName字符串中的'/'到对应平台路径
+#ifdef RVC_OS_WIN
+	if (!replaceInPlace(newFileName, "/", "\\")) {
+		Dbg("replaceInPlace zip fileName fail:zipFileName(%s) \n", newFileName.c_str());
+		return -1;
+	}
+#endif // DEBUG
+
 	if (isDir)
 	{   //创建文件夹
 		string dirPath = destDirPath + SPLIT_SLASH_STR + newFileName;
@@ -117,7 +274,7 @@ int unZipCurrentFile(zipFile zf, string destDirPath)
 		//先创建文件的父文件夹
 		int pos = fileNamePath.find_last_of(SPLIT_SLASH);
 		string newFileDirPath(fileNamePath.substr(0, pos));
-		//Dbg("creating dir:%s", newFileDirPath.c_str());
+
 		if (!CreateDirA(newFileDirPath.c_str(), true)) {
 			Dbg("creating zip file dir fail: dirPath(%s)", newFileDirPath.c_str());
 			return -1;
@@ -128,63 +285,49 @@ int unZipCurrentFile(zipFile zf, string destDirPath)
 			Dbg("could not open zip file ,%s", newFileName);
 			return -1;
 		}
-		// Open a file to write out the data.
-		FILE* out = fopen(fileNamePath.c_str(), "wb");
-
-		if (out == NULL)
-		{
-			Dbg("could not open destination file, %s", fileNamePath.c_str());
-			unzCloseCurrentFile(zf);
-			return -1;
-		}
-
-		int err = UNZ_OK;
-		unsigned char * read_buffer= new unsigned char[ZIP_ZILP_READ_SIZE];
-		memset(read_buffer, 0, ZIP_ZILP_READ_SIZE);
-		do
-		{
-			err = unzReadCurrentFile(zf, read_buffer, ZIP_ZILP_READ_SIZE);
-			if (err < 0)
-			{
-				Dbg("error %d with zipfile in unzReadCurrentFile", err);
-				break;
-			}
 
-			// Write data to file.
-			if (err > 0)
-			{
-				if (fwrite(read_buffer, err, 1, out) != 1) {
-					Dbg("error in writing extracted file");
-					err = UNZ_ERRNO;
-					break;
-				}
-			}
-		} while (err > 0);
+		bool isSymlink = false;
+#ifdef RVC_OS_WIN
+		isSymlink = false;//windows 默认不创建链接文件
+		//if (entry_is_symlink(file_info) == 0) {
+		//	isSymlink = true;
+		//	printf("entry is link file, %s\n", newFileName.c_str());
+		//}
+#else
+		isSymlink = false;//linux 默认不创建链接文件
+		//if (entry_is_symlink(file_info) == 0) {
+		//	isSymlink = true;
+		//	Dbg("entry is link file, %s\n", newFileName.c_str());
+		//}
+#endif
 
-		delete[] read_buffer;//删除临时对象
+		// Open a file to write out the data.
+		int saveSucc = 0;
 
-		if (out!=NULL) {
-			if (fclose(out)!=0) {
-				Dbg("fclose new file from zip fail, %s", fileNamePath.c_str());
-				unzCloseCurrentFile(zf);
-				return -1;
-			}
+		if (isSymlink) {
+			//链接文件
+			saveSucc = saveSymlink(zf, fileNamePath);
+		}
+		else {
+			//一般文件
+			saveSucc = saveNormalFile(zf, fileNamePath);
 		}
 
-		if (err == UNZ_OK) {
+		if (saveSucc == 0) {
 			//正常结束
-			err = unzCloseCurrentFile(zf);
+			int err = unzCloseCurrentFile(zf);
 			if (err != UNZ_OK) {
-				Dbg("error %d with zipfile in unzCloseCurrentFile", err);
+				Dbg("zipfile  unzCloseCurrentFile is %d\n", err);
 				return -1;
 			}
-			if (changeUnZipFileAtt(fileNamePath.c_str())!=0) {
+			//文件赋权
+			if (changeUnZipFileAtt(fileNamePath.c_str()) != 0) {
 				return -1;
 			}
 			return 0;
 		}
 		else {
-			//异常结束
+			//保存异常
 			unzCloseCurrentFile(zf); /* don't lose the error */
 			return -1;
 		}
@@ -277,6 +420,224 @@ int changeUnZipFileAtt(const char* path)
 #endif
 }
 
+bool replacePlace(string& str, string const& replaceThis, string const& withThis)
+{
+	bool replaced = false;
+	size_t i = str.find(replaceThis);
+	while (i != string::npos) {
+		replaced = true;
+		str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size());
+		if (i < str.size() - withThis.size())
+			i = str.find(replaceThis, i + withThis.size());
+		else
+			i = string::npos;
+	}
+	return replaced;
+}
+
+int saveNormalFile(zipFile zf, string savePath) {
+	// Open a file to write out the data.
+	FILE* out = fopen(savePath.c_str(), "wb");
+
+	if (out == NULL)
+	{
+		Dbg("could not open destination file, %s\n", savePath.c_str());
+		return -1;
+	}
+
+	int err = 0;
+	unsigned char* read_buffer = new unsigned char[ZIP_ZILP_READ_SIZE];
+	memset(read_buffer, 0, ZIP_ZILP_READ_SIZE);
+	do
+	{
+		err = unzReadCurrentFile(zf, read_buffer, ZIP_ZILP_READ_SIZE);
+		if (err < 0)
+		{
+			Dbg("zipfile in unzReadCurrentFile is fail:%d\n", err);
+			err = -1;
+			break;
+		}
+		if (err > 0)
+		{
+			// Write data to file.
+			if (fwrite(read_buffer, err, 1, out) != 1) {
+				Dbg("writing extracted normal file is fail\n");
+				err = -1;
+				break;
+			}
+		}
+		if (err == 0) {
+			//已经到结尾
+			break;
+		}
+	} while (true);
+
+	delete[] read_buffer;//删除临时对象
+
+	if (out != NULL) {
+		if (fclose(out) != 0) {
+			Dbg("fclose normal file fail");
+			return -1;
+		}
+	}
+	return err;
+}
+
+int saveSymlink(zipFile zf, string savePath) {
+	//链接文件
+	char* srcPath = new char[4096];//链接的原地址路径
+	memset(srcPath, 0, 4096);
+	string destPath = savePath;//新地址
+
+	unsigned char* readStr = new unsigned char[512];
+	memset(readStr, 0, 512);
+
+	int err = 0;
+	int copy = 0;
+	do
+	{
+		err = unzReadCurrentFile(zf, readStr, 512);
+		if (err < 0)
+		{
+			Dbg("zipfile in unzReadCurrentFile is fail:%d\n", err);
+			err = -1;
+			break;
+		}
+		// Write data to file.
+		if (err > 0)
+		{
+			if ((copy + err) <= 4096) {
+				memcpy(srcPath + copy, readStr, err);
+				copy += err;
+			}
+			else {
+				Dbg("link content len over 4096 ,check zipfile in unzReadCurrentFile, %s \n", savePath.c_str());
+				err = -1;
+				break;
+			}
+		}
+		if (err == 0) {
+			//已经到结尾
+			break;
+		}
+	} while (true);
+
+	delete[] readStr;
+
+	if (err == 0) {
+		err = os_make_symlink((const char*)srcPath, destPath.c_str());
+		delete[] srcPath; //删除临时对象
+		return err;
+	}
+	else {
+		delete[] srcPath;//删除临时对象
+		return -1;
+	}
+	return 0;
+}
+
+int entry_is_symlink(unz_file_info file_info)
+{
+	uint32_t posix_attrib = 0;
+	uint8_t system = ZIP_ZILP_HOST_SYSTEM(file_info.version);
+	int32_t err = 0;
+
+	err = zip_attrib_convert(system, file_info.external_fa, ZIP_ZILP_HOST_SYSTEM_UNIX, &posix_attrib);
+	if (err == 0) {
+		if ((posix_attrib & 0170000) == 0120000) /* S_ISLNK */
+			return 0;
+	}
+
+	return -1;
+}
+
+int zip_attrib_convert(uint8_t src_sys, uint32_t src_attrib, uint8_t target_sys, uint32_t* target_attrib)
+{
+	if (target_attrib == NULL)
+		return -1;
+
+	*target_attrib = 0;
+
+	if ((src_sys == ZIP_ZILP_HOST_SYSTEM_MSDOS) || (src_sys == ZIP_ZILP_HOST_SYSTEM_WINDOWS_NTFS)) {
+		if ((target_sys == ZIP_ZILP_HOST_SYSTEM_MSDOS) || (target_sys == ZIP_ZILP_HOST_SYSTEM_WINDOWS_NTFS)) {
+			*target_attrib = src_attrib;
+			return 0;
+		}
+		if ((target_sys == ZIP_ZILP_HOST_SYSTEM_UNIX) || (target_sys == ZIP_ZILP_HOST_SYSTEM_OSX_DARWIN) || (target_sys == ZIP_ZILP_HOST_SYSTEM_RISCOS))
+			return zip_attrib_win32_to_posix(src_attrib, target_attrib);
+	}
+	else if ((src_sys == ZIP_ZILP_HOST_SYSTEM_UNIX) || (src_sys == ZIP_ZILP_HOST_SYSTEM_OSX_DARWIN) || (src_sys == ZIP_ZILP_HOST_SYSTEM_RISCOS)) {
+		if ((target_sys == ZIP_ZILP_HOST_SYSTEM_UNIX) || (target_sys == ZIP_ZILP_HOST_SYSTEM_OSX_DARWIN) || (target_sys == ZIP_ZILP_HOST_SYSTEM_RISCOS)) {
+			/* If high bytes are set, it contains unix specific attributes */
+			if ((src_attrib >> 16) != 0)
+				src_attrib >>= 16;
+
+			*target_attrib = src_attrib;
+			return 0;
+		}
+		if ((target_sys == ZIP_ZILP_HOST_SYSTEM_MSDOS) || (target_sys == ZIP_ZILP_HOST_SYSTEM_WINDOWS_NTFS))
+			return zip_attrib_posix_to_win32(src_attrib, target_attrib);
+	}
+
+	return -2;
+}
+
+int zip_attrib_posix_to_win32(uint32_t posix_attrib, uint32_t* win32_attrib)
+{
+	if (win32_attrib == NULL)
+		return -1;
+
+	*win32_attrib = 0;
+
+	/* S_IWUSR | S_IWGRP | S_IWOTH | S_IXUSR | S_IXGRP | S_IXOTH */
+	if ((posix_attrib & 0000333) == 0 && (posix_attrib & 0000444) != 0)
+		*win32_attrib |= 0x01;      /* FILE_ATTRIBUTE_READONLY */
+	/* S_IFLNK */
+	if ((posix_attrib & 0170000) == 0120000)
+		*win32_attrib |= 0x400;     /* FILE_ATTRIBUTE_REPARSE_POINT */
+	/* S_IFDIR */
+	else if ((posix_attrib & 0170000) == 0040000)
+		*win32_attrib |= 0x10;      /* FILE_ATTRIBUTE_DIRECTORY */
+	/* S_IFREG */
+	else
+		*win32_attrib |= 0x80;      /* FILE_ATTRIBUTE_NORMAL */
+
+	return 0;
+}
+
+int zip_attrib_win32_to_posix(uint32_t win32_attrib, uint32_t* posix_attrib)
+{
+	if (posix_attrib == NULL)
+		return -1;
+
+	*posix_attrib = 0000444;        /* S_IRUSR | S_IRGRP | S_IROTH */
+	/* FILE_ATTRIBUTE_READONLY */
+	if ((win32_attrib & 0x01) == 0)
+		*posix_attrib |= 0000222;   /* S_IWUSR | S_IWGRP | S_IWOTH */
+	/* FILE_ATTRIBUTE_REPARSE_POINT */
+	if ((win32_attrib & 0x400) == 0x400)
+		*posix_attrib |= 0120000;   /* S_IFLNK */
+	/* FILE_ATTRIBUTE_DIRECTORY */
+	else if ((win32_attrib & 0x10) == 0x10)
+		*posix_attrib |= 0040111;   /* S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH */
+	else
+		*posix_attrib |= 0100000;   /* S_IFREG */
+
+	return 0;
+}
+
+int os_make_symlink(const char* srcPath, const char* target_path) {
+#ifdef RVC_OS_WIN
+	return 0;//暂不实现,暂时写入后缀名是link的文件
+#else
+	if (symlink(srcPath, target_path) != 0) {
+		Dbg("symlink fail,errno = %d", errno);
+		return -1;
+	}
+	return 0;
+#endif // RVC_OS_WIN
+}
+
 #ifdef RVC_OS_WIN
 #else
 unsigned char* utf8_string_create(const char* string) {

+ 16 - 0
Module/mod_UpgradeRun/XUnZipZilb.h

@@ -65,6 +65,22 @@ int unZipCurrentFile(zipFile zf, string destDirPath);
 bool is_str_utf8(const char* str);
 
 int changeUnZipFileAtt(const char* path);
+
+bool replacePlace(string& str, string const& replaceThis, string const& withThis);
+
+int saveNormalFile(zipFile zf, string savePath);
+
+int saveSymlink(zipFile zf, string savePath);
+
+int entry_is_symlink(unz_file_info file_info);
+
+int zip_attrib_convert(uint8_t src_sys, uint32_t src_attrib, uint8_t target_sys, uint32_t* target_attrib);
+
+int zip_attrib_posix_to_win32(uint32_t posix_attrib, uint32_t* win32_attrib);
+
+int zip_attrib_win32_to_posix(uint32_t win32_attrib, uint32_t* posix_attrib);
+
+int os_make_symlink(const char* srcPath, const char* target_path);
 #ifdef RVC_OS_WIN
 #else
 unsigned char* utf8_string_create(const char* string);

+ 3 - 0
Module/mod_upload/XZipZilb.cpp

@@ -117,6 +117,9 @@ bool AddFileToZip(zipFile zf, const char* fileNameInZip, const char* srcFile)
 		while (!feof(srcfp) && !ferror(srcfp))
 		{
 			numBytes = fread(buf, 1, sizeof(buf), srcfp);
+			if (numBytes == 0) {
+				continue;
+			}
 			int ret = zipWriteInFileInZip(zf, buf, numBytes);
 			if (ret != ZIP_OK) {
 				Dbg("文件写入zip压缩包失败1: %s", srcFile);