]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Add FS_RenameOnClose, to be able to mark open files for renaming on closing.
authorDes <xon@damianv.com.ar>
Fri, 9 Aug 2024 16:29:43 +0000 (13:29 -0300)
committerDes - <gitlab@damianv.com.ar>
Fri, 16 Aug 2024 20:06:47 +0000 (20:06 +0000)
fs.c
fs.h

diff --git a/fs.c b/fs.c
index 2ce128e86cf61fda5e11f477381bb469a4d26f34..50bff6ae3286bd83cf87e37ba4539e96ef1f0dbb 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -298,6 +298,8 @@ typedef struct
 #define QFILE_FLAG_DATA (1 << 2)
 /// real file will be removed on close
 #define QFILE_FLAG_REMOVE (1 << 3)
+/// real file will be renamed on close to reanameto
+#define QFILE_FLAG_RENAME (1 << 4)
 
 #define FILE_BUFF_SIZE 2048
 typedef struct
@@ -326,7 +328,9 @@ struct qfile_s
 
        const unsigned char *data;      ///< For data files.
 
-       const char *filename; ///< Kept around for QFILE_FLAG_REMOVE, unused otherwise
+       const char *filename; ///< Kept around for QFILE_FLAG_REMOVE and QFILE_FLAG_RENAME, unused otherwise
+       char *renameto;       ///< For QFILE_FLAG_RENAME
+       const char *mode;     ///< Kept around for QFILE_FLAG_RENAME, unused otherwise
 };
 
 
@@ -2495,6 +2499,7 @@ qfile_t* FS_SysOpen (const char* filepath, const char* mode, qbool nonblocking)
        }
 
        file->filename = Mem_strdup(fs_mempool, filepath);
+       file->mode = Mem_strdup(fs_mempool, mode);
 
        file->real_length = FILEDESC_SEEK (file->handle, 0, SEEK_END);
 
@@ -2990,10 +2995,20 @@ int FS_Close (qfile_t* file)
                                // like.
                        }
                }
+               if (file->flags & QFILE_FLAG_RENAME && file->renameto)
+               {
+                       FS_CreatePath (file->renameto);
+                       if (rename(file->filename, file->renameto) == -1)
+                               Con_Printf(CON_WARN "WARNING: could not rename %s to %s on close.\n", file->filename, file->renameto);
+                       Mem_Free((void *) file->renameto);
+               }
 
                Mem_Free((void *) file->filename);
        }
 
+       if (file->mode)
+               Mem_Free((void *) file->mode);
+
        if (file->ztk)
        {
                qz_inflateEnd (&file->ztk->zstream);
@@ -3009,6 +3024,24 @@ void FS_RemoveOnClose(qfile_t* file)
        file->flags |= QFILE_FLAG_REMOVE;
 }
 
+void FS_RenameOnClose(qfile_t* file, char *newname)
+{
+       char real_path [MAX_OSPATH];
+       if(file->mode[0] == 'r')
+       {
+               Con_Printf("FS_RenameOnClose(\"%s\") file opened in read-only mode, won't rename it\n", file->filename);
+               return;
+       }
+       if (FS_CheckNastyPath(newname, false))
+       {
+               Con_Printf("FS_RenameOnClose(\"%s\"): nasty filename rejected\n", newname);
+               return;
+       }
+       file->flags |= QFILE_FLAG_RENAME;
+       dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, newname);
+       file->renameto = Mem_strdup(fs_mempool, real_path);
+}
+
 /*
 ====================
 FS_Write
diff --git a/fs.h b/fs.h
index b81d84d2d88a4ba248e976beb77c607a4ddfc4f5..dc4f219a0730d29db593093e9e79ddf75fce5bb2 100644 (file)
--- a/fs.h
+++ b/fs.h
@@ -71,6 +71,7 @@ qfile_t* FS_OpenVirtualFile (const char* filepath, qbool quiet);
 qfile_t* FS_FileFromData (const unsigned char *data, const size_t size, qbool quiet);
 int FS_Close (qfile_t* file);
 void FS_RemoveOnClose(qfile_t* file);
+void FS_RenameOnClose(qfile_t* file, char *newname);
 fs_offset_t FS_Write (qfile_t* file, const void* data, size_t datasize);
 fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize);
 int FS_Print(qfile_t* file, const char *msg);