summaryrefslogtreecommitdiff
path: root/zip/zip.cpp
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2024-10-25 21:09:21 +0200
committerTomas Bzatek <tbzatek@redhat.com>2024-10-25 21:09:21 +0200
commit1e0e627a510785edd1fcd6ae460b8575647d598b (patch)
tree03f54035c41d5a9e0c6654df7f81972d51e82888 /zip/zip.cpp
parent03f0a6cd93da2a10f7be8f9616fe807a6c41d8c8 (diff)
downloadtuxcmd-modules-1e0e627a510785edd1fcd6ae460b8575647d598b.tar.xz
zip: Implement manual file write
Diffstat (limited to 'zip/zip.cpp')
-rw-r--r--zip/zip.cpp189
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;
}