diff options
| author | Tomas Bzatek <tbzatek@redhat.com> | 2024-10-25 21:09:21 +0200 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@redhat.com> | 2024-10-25 21:09:21 +0200 |
| commit | 1e0e627a510785edd1fcd6ae460b8575647d598b (patch) | |
| tree | 03f54035c41d5a9e0c6654df7f81972d51e82888 /zip/zip.cpp | |
| parent | 03f0a6cd93da2a10f7be8f9616fe807a6c41d8c8 (diff) | |
| download | tuxcmd-modules-1e0e627a510785edd1fcd6ae460b8575647d598b.tar.xz | |
zip: Implement manual file write
Diffstat (limited to 'zip/zip.cpp')
| -rw-r--r-- | zip/zip.cpp | 189 |
1 files changed, 145 insertions, 44 deletions
diff --git a/zip/zip.cpp b/zip/zip.cpp index 4ccf693..aefb9f5 100644 --- a/zip/zip.cpp +++ b/zip/zip.cpp @@ -175,6 +175,9 @@ struct TVFSGlobs { TVFSAskPasswordCallback callback_ask_password; TVFSProgressCallback callback_progress; void *callback_data; + + int open_file_mode; + gboolean after_exception; }; @@ -290,6 +293,7 @@ VFSNew (TVFSLogFunc log_func) globs->block_size = DEFAULT_BLOCK_SIZE; globs->log_func = log_func; + globs->open_file_mode = -1; return globs; } @@ -617,7 +621,7 @@ VFSMkDir (struct TVFSGlobs *globs, const char *sDirName, GError **error) g_free (s); header.SetCreationTime (time (NULL)); header.SetModificationTime (time (NULL)); - bRet = globs->zip->OpenNewFile (header, 0, NULL); + bRet = globs->zip->OpenNewFile (header, CZipCompressor::levelStore, NULL); globs->zip->CloseNewFile (); if (! bRet) { log_error ("VFSMkDir: Error creating new directory '%s'", sDirName); @@ -1116,7 +1120,7 @@ VFSCopyFromLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDs try { try_again = FALSE; s = exclude_leading_path_sep (sDstName); - if (! globs->zip->AddNewFile (sSrcName, s, -1, CZipArchive::zipsmSafeSmart, globs->block_size)) { + if (! globs->zip->AddNewFile (sSrcName, s, CZipCompressor::levelDefault, CZipArchive::zipsmSafeSmart, globs->block_size)) { globs->zip->CloseNewFile (true); globs->zip->CloseFile (NULL, true); log_error ("VFSCopyFromLocal: Error while copying in, archive closed = %d.", globs->zip->IsClosed ()); @@ -1185,35 +1189,59 @@ VFSOpenFile (struct TVFSGlobs *globs, const char *APath, int Mode, GError **erro switch (Mode) { case cVFS_OpenRead: + case cVFS_OpenWrite: /* OK, break */ break; - case cVFS_OpenWrite: case cVFS_OpenAppend: - g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Writing files in the archive is not supported"); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Appending files in the archive is not supported"); return NULL; default: g_set_error (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Invalid file open mode %d", Mode); return NULL; } + globs->open_file_mode = Mode; log_notice ("VFSOpenFile: Opening file '%s'", APath); - file_no = filelist_find_original_index_by_path (globs->files, APath) - 1; - if (file_no < 0) { - log_error ("VFSOpenFile: can't find file '%s'", APath); - g_set_error (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Cannot find file '%s'", APath); - return NULL; - } - try { do { try { try_again = FALSE; - if (! globs->zip->OpenFile (file_no)) { - log_error ("VFSOpenFile: Error opening file, archive closed = %d.", globs->zip->IsClosed ()); - g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Error opening file."); - return NULL; - } + globs->after_exception = FALSE; + + /* Open for read */ + if (Mode == cVFS_OpenRead) { + file_no = filelist_find_original_index_by_path (globs->files, APath) - 1; + if (file_no < 0) { + log_error ("VFSOpenFile: can't find file '%s'", APath); + g_set_error (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Cannot find file '%s'", APath); + return NULL; + } + if (! globs->zip->OpenFile (file_no)) { + log_error ("VFSOpenFile: Error opening file, archive closed = %d.", globs->zip->IsClosed ()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Error opening file."); + return NULL; + } + } else + + /* Open for write */ + if (Mode == cVFS_OpenWrite) { + CZipFileHeader header; + gchar *s; + + s = exclude_leading_path_sep (APath); + header.SetFileName (s); + header.SetSystemAttr (ZipPlatform::GetDefaultAttributes()); + g_free (s); + /* FIXME: Encryption? */ + if (! globs->zip->OpenNewFile (header, CZipCompressor::levelDefault, NULL)) { + log_error ("VFSOpenFile: Error opening new file, archive closed = %d.", globs->zip->IsClosed ()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Error opening new file."); + return NULL; + } + globs->archive_modified = TRUE; + file_no = 1; /* bogus, unused */ + } else g_warn_if_reached (); } catch (CZipException& e) { log_error ("VFSOpenFile: Error opening file: [%d] %s, archive closed = %d.", @@ -1228,6 +1256,7 @@ VFSOpenFile (struct TVFSGlobs *globs, const char *APath, int Mode, GError **erro g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); g_error_free (local_error); } + globs->after_exception = TRUE; return NULL; } try_again = TRUE; @@ -1236,6 +1265,7 @@ VFSOpenFile (struct TVFSGlobs *globs, const char *APath, int Mode, GError **erro zip_error_to_gerror (e, &local_error); g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); g_error_free (local_error); + globs->after_exception = TRUE; return NULL; } } @@ -1246,6 +1276,7 @@ VFSOpenFile (struct TVFSGlobs *globs, const char *APath, int Mode, GError **erro log_error ("VFSCopyToLocal: Fatal error while opening file..., archive closed = %d.", globs->zip->IsClosed()); g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Fatal error while opening file."); globs->zip->CloseFile (NULL, true); + globs->after_exception = TRUE; return NULL; } @@ -1257,34 +1288,50 @@ VFSCloseFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, GError **erro { GError *local_error = NULL; int r; + gboolean b; try { try { - /* FIXME: cannot distinguish between clean close and close after exception */ - r = globs->zip->CloseFile (); - if (r != 1) { - /* Returns one of the following values: - * 1 : The operation was successful. - * 0 : There is no file opened. - * -1 : Some bytes were left to uncompress - probably due to a bad password or a corrupted archive. - * -2 : Setting extracted file date and attributes was not successful. - */ - log_error ("VFSCloseFile: Error closing file, archive closed = %d.", globs->zip->IsClosed ()); - switch (r) { - case 0: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, - "There is no file opened."); - break; - case -1: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, - "Some bytes were left to uncompress - probably due to a bad password or a corrupted archive."); - break; - case -2: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, - "Setting extracted file date and attributes was not successful."); - break; - default: - g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, "Error closing file."); + if (globs->open_file_mode == cVFS_OpenWrite || globs->open_file_mode == cVFS_OpenAppend) { + b = globs->zip->CloseNewFile (globs->after_exception); + globs->open_file_mode = -1; + globs->after_exception = FALSE; + if (globs->archive_modified) { + log_debug ("VFSCloseFile: archive modified, rebuilding the tree."); + globs->zip->FlushBuffers (); + build_global_filelist (globs); + } + if (! b) { + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, "Error closing new file."); + return FALSE; + } + } else { + r = globs->zip->CloseFile (NULL, globs->after_exception); + globs->open_file_mode = -1; + globs->after_exception = FALSE; + if (r != 1) { + /* Returns one of the following values: + * 1 : The operation was successful. + * 0 : There is no file opened. + * -1 : Some bytes were left to uncompress - probably due to a bad password or a corrupted archive. + * -2 : Setting extracted file date and attributes was not successful. + */ + log_error ("VFSCloseFile: Error closing file, archive closed = %d.", globs->zip->IsClosed ()); + switch (r) { + case 0: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, + "There is no file opened."); + break; + case -1: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, + "Some bytes were left to uncompress - probably due to a bad password or a corrupted archive."); + break; + case -2: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, + "Setting extracted file date and attributes was not successful."); + break; + default: + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, "Error closing file."); + } + return FALSE; } - globs->zip->CloseFile (NULL, true); - return FALSE; } } catch (CZipException& e) { @@ -1293,7 +1340,6 @@ VFSCloseFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, GError **erro zip_error_to_gerror (e, &local_error); g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, local_error->message); g_error_free (local_error); - globs->zip->CloseFile (NULL, true); return FALSE; } } @@ -1301,7 +1347,6 @@ VFSCloseFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, GError **erro { log_error ("VFSCloseFile: Fatal error while closing file..., archive closed = %d.", globs->zip->IsClosed()); g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, "Fatal error while closing file."); - globs->zip->CloseFile (NULL, true); return FALSE; } @@ -1330,7 +1375,6 @@ VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffe catch (CZipException& e) { log_error ("VFSReadFile: Error reading file: [%d] %s, archive closed = %d.", e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); - globs->zip->CloseFile (NULL, true); switch (e.m_iCause) { case CZipException::badPassword: if (! handle_password_prompt (globs, "VFSReadFile", &local_error)) { @@ -1341,6 +1385,7 @@ VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffe g_error_free (local_error); } globs->zip->CloseFile (NULL, true); + globs->after_exception = TRUE; return -1; } try_again = TRUE; @@ -1350,6 +1395,7 @@ VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffe g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); g_error_free (local_error); globs->zip->CloseFile (NULL, true); + globs->after_exception = TRUE; return -1; } } @@ -1360,6 +1406,7 @@ VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffe log_error ("VFSCopyToLocal: Fatal error while opening file..., archive closed = %d.", globs->zip->IsClosed()); g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Fatal error while opening file."); globs->zip->CloseFile (NULL, true); + globs->after_exception = TRUE; return -1; } @@ -1370,7 +1417,61 @@ VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffe gint64 VFSWriteFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, guint64 BytesCount, GError **error) { - g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_WRITE_FILE, "Writing files in the archive is not supported"); + gboolean try_again; + GError *local_error = NULL; + + try { + do { + try { + try_again = FALSE; + + if (! globs->zip->WriteNewFile (Buffer, BytesCount)) { + log_error ("VFSWriteFile: Error writing new file data, archive closed = %d.", globs->zip->IsClosed ()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_WRITE_FILE, "Error writing file data."); + return -1; + } + globs->archive_modified = TRUE; + return BytesCount; /* can't seem to have control on how many bytes got actually written */ + } + catch (CZipException& e) { + log_error ("VFSWriteFile: Error writing file: [%d] %s, archive closed = %d.", + e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + switch (e.m_iCause) { + case CZipException::badPassword: + if (! handle_password_prompt (globs, "VFSWriteFile", &local_error)) { + if (g_error_matches (local_error, TUXCMD_ERROR, TUXCMD_ERROR_CANCELLED)) + g_propagate_error (error, local_error); + else { + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_WRITE_FILE, local_error->message); + g_error_free (local_error); + } + globs->zip->CloseNewFile (true); + globs->after_exception = TRUE; + return -1; + } + try_again = TRUE; + break; + default: + zip_error_to_gerror (e, &local_error); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_WRITE_FILE, local_error->message); + g_error_free (local_error); + globs->zip->CloseNewFile (true); + globs->after_exception = TRUE; + return -1; + } + } + } while (try_again); + } + catch (...) + { + log_error ("VFSWriteFile: Fatal error while writing new file data..., archive closed = %d.", globs->zip->IsClosed()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_WRITE_FILE, "Fatal error while writing new file data."); + globs->zip->CloseNewFile (true); + globs->after_exception = TRUE; + return -1; + } + + g_warn_if_reached (); return -1; } |
