poe

Уређивач .po фајлова
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 7ee1d7823b76f9314d428855f7f423399a99901a
родитељ dc52ccf5e0c9b70d9c86b17b2b43de7692b52014
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Wed,  2 Mar 2022 18:15:59 +0100

More sophisticated handling of file mode and symlinks

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
Mpo.c | 39++++++++++++++++++++++++++++++++++++---
Mpo.h | 6+++++-
измењених датотека: 2, додавања: 41(+), брисања: 4(-)

diff --git a/po.c b/po.c @@ -1,5 +1,9 @@ /* See the file LICENSE for copyright and license details. */ +#define _POSIX_C_SOURCE 200809L +#define _DEFAULT_SOURCE +#define _XOPEN_SOURCE + #include <libgen.h> #include <stdio.h> #include <stdlib.h> @@ -508,24 +512,52 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, char* backup_filename = NULL; #endif struct stat st; + char* real_filename = NULL; + size_t rfn_len = 0; + if (!(real_filename = calloc(MAXPATH, 1))) + return SAVE_ERR_CANT_ALLOC; #ifdef CREATE_BACKUPS if (!(backup_filename = calloc(MAXPATH, 1))) return SAVE_ERR_CANT_ALLOC; #endif #ifdef CREATE_BACKUPS - if (stat(filename, &st) != -1) + if (lstat(filename, &st) != -1) { + if (S_ISLNK(st.st_mode)) + { + rfn_len = readlink(filename, real_filename, MAXPATH); + if (rfn_len == -1) + return SAVE_ERR_CANT_READLINK; + real_filename[rfn_len] = 0; + if (stat(real_filename, &st) == -1) + return SAVE_ERR_CANT_STAT_FILE; + } strcpy(backup_filename, filename); strcat(backup_filename, backup_suffix); - if (rename(filename, backup_filename) == -1) + if (rename(rfn_len > 0 ? real_filename : filename, + backup_filename) + == -1) return SAVE_ERR_CANT_MOVE_FILE; } + else + return SAVE_ERR_CANT_STAT_FILE; #endif - if (!(output = fopen(filename, "wt"))) + if (!(output = fopen(rfn_len > 0 ? real_filename : filename, "wt"))) return SAVE_ERR_CANT_OPEN_FILE; +#ifdef CREATE_BACKUPS + if (rfn_len > 0) + { + if (unlink(filename) == -1) + return SAVE_ERR_CANT_UNLINK; + if (symlink(real_filename, filename) == -1) + return SAVE_ERR_CANT_SYMLINK; + } + chmod(rfn_len > 0 ? real_filename : filename, st.st_mode); +#endif + save_loop_entries_start: if (current >= entries + real_msgid_count) goto save_loop_entries_done; @@ -856,6 +888,7 @@ save_loop_entries_done: #ifdef CREATE_BACKUPS free(backup_filename); #endif + free(real_filename); return SAVE_ERR_NONE; } diff --git a/po.h b/po.h @@ -35,7 +35,11 @@ enum { SAVE_ERR_NONE = 0, SAVE_ERR_CANT_ALLOC = 1, SAVE_ERR_CANT_OPEN_FILE = 2, - SAVE_ERR_CANT_MOVE_FILE = 3 + SAVE_ERR_CANT_MOVE_FILE = 3, + SAVE_ERR_CANT_STAT_FILE = 4, + SAVE_ERR_CANT_READLINK = 5, + SAVE_ERR_CANT_SYMLINK = 6, + SAVE_ERR_CANT_UNLINK = 7 }; typedef enum {