2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "claws-features.h"
33 #include "file-utils.h"
35 static gboolean
prefs_is_readonly (const gchar
*path
);
38 *\brief Open preferences file for reading
40 *\param path Filename with path of preferences file to read
42 *\return PrefFile * preferences file struct
44 PrefFile
*prefs_read_open(const gchar
*path
)
49 cm_return_val_if_fail(path
!= NULL
, NULL
);
51 if ((fp
= claws_fopen(path
, "rb")) == NULL
) {
52 FILE_OP_ERROR(path
, "claws_fopen");
56 pfile
= g_new(PrefFile
, 1);
58 pfile
->orig_fp
= NULL
;
59 pfile
->path
= g_strdup(path
);
60 pfile
->writing
= FALSE
;
66 *\brief Open preferences file for writing
67 * Prefs are written to a temp file: Call prefs_file_close()
68 * to rename this to the final filename
70 *\param path Filename with path of preferences file to write
72 *\return PrefFile * preferences file struct
74 PrefFile
*prefs_write_open(const gchar
*path
)
80 cm_return_val_if_fail(path
!= NULL
, NULL
);
82 if (prefs_is_readonly(path
)) {
83 g_warning("no write permission on '%s'", path
);
87 tmppath
= g_strconcat(path
, ".tmp", NULL
);
88 if ((fp
= claws_fopen(tmppath
, "wb")) == NULL
) {
89 FILE_OP_ERROR(tmppath
, "claws_fopen");
94 if (change_file_mode_rw(fp
, tmppath
) < 0)
95 FILE_OP_ERROR(tmppath
, "chmod");
99 pfile
= g_new(PrefFile
, 1);
101 pfile
->orig_fp
= NULL
;
102 pfile
->path
= g_strdup(path
);
103 pfile
->writing
= TRUE
;
108 gboolean
prefs_common_get_flush_metadata (void);
111 *\brief Close and free preferences file
112 * Creates final file from temp, creates backup
114 *\param pfile Preferences file struct
116 *\return 0 on success, -1 on failure
118 gint
prefs_file_close(PrefFile
*pfile
)
123 gchar
*bakpath
= NULL
;
126 cm_return_val_if_fail(pfile
!= NULL
, -1);
129 orig_fp
= pfile
->orig_fp
;
132 if (!pfile
->writing
) {
140 while (claws_fgets(buf
, sizeof(buf
), orig_fp
) != NULL
) {
143 if (claws_fputs(buf
, fp
) == EOF
) {
144 g_warning("failed to write configuration to file");
145 prefs_file_close_revert(pfile
);
153 while (claws_fgets(buf
, sizeof(buf
), orig_fp
) != NULL
)
154 if (claws_fputs(buf
, fp
) == EOF
) {
155 g_warning("failed to write configuration to file");
156 prefs_file_close_revert(pfile
);
160 claws_fclose(orig_fp
);
163 tmppath
= g_strconcat(path
, ".tmp", NULL
);
165 if (claws_safe_fclose(fp
) == EOF
) {
166 FILE_OP_ERROR(tmppath
, "claws_fclose");
167 claws_unlink(tmppath
);
173 if (is_file_exist(path
)) {
174 bakpath
= g_strconcat(path
, ".bak", NULL
);
176 claws_unlink(bakpath
);
178 if (g_rename(path
, bakpath
) < 0) {
179 FILE_OP_ERROR(path
, "rename");
180 claws_unlink(tmppath
);
191 if (g_rename(tmppath
, path
) < 0) {
192 FILE_OP_ERROR(tmppath
, "rename");
193 claws_unlink(tmppath
);
208 *\brief Close and free preferences file, delete temp file
210 *\param pfile Preferences file struct
212 gint
prefs_file_close_revert(PrefFile
*pfile
)
214 gchar
*tmppath
= NULL
;
216 cm_return_val_if_fail(pfile
!= NULL
, -1);
219 claws_fclose(pfile
->orig_fp
);
221 tmppath
= g_strconcat(pfile
->path
, ".tmp", NULL
);
222 claws_fclose(pfile
->fp
);
223 if (pfile
->writing
) {
224 if (claws_unlink(tmppath
) < 0) FILE_OP_ERROR(tmppath
, "unlink");
234 *\brief Check if "path" is a file and read-only
236 static gboolean
prefs_is_readonly(const gchar
* path
)
241 return (access(path
, W_OK
) != 0 && access(path
, F_OK
) == 0);
245 *\brief Check if "rcfile" is in rcdir, a file and read-only
247 gboolean
prefs_rc_is_readonly(const gchar
* rcfile
)
255 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
, rcfile
, NULL
);
256 result
= prefs_is_readonly(rcpath
);
263 *\brief Selects current section in preferences file
264 * Creates section if file is written
266 *\param pfile Preferences file struct
268 *\return 0 on success, -1 on failure
270 gint
prefs_set_block_label(PrefFile
*pfile
, const gchar
*label
)
275 block_label
= g_strdup_printf("[%s]", label
);
276 if (!pfile
->writing
) {
277 while (claws_fgets(buf
, sizeof(buf
), pfile
->fp
) != NULL
) {
280 val
= strncmp(buf
, block_label
, strlen(block_label
));
282 debug_print("Found %s\n", block_label
);
287 if ((pfile
->orig_fp
= claws_fopen(pfile
->path
, "rb")) != NULL
) {
288 gboolean block_matched
= FALSE
;
290 while (claws_fgets(buf
, sizeof(buf
), pfile
->orig_fp
) != NULL
) {
293 val
= strncmp(buf
, block_label
, strlen(block_label
));
295 debug_print("Found %s\n", block_label
);
296 block_matched
= TRUE
;
299 if (claws_fputs(buf
, pfile
->fp
) == EOF
) {
300 g_warning("failed to write configuration to file");
301 prefs_file_close_revert(pfile
);
309 if (!block_matched
) {
310 claws_fclose(pfile
->orig_fp
);
311 pfile
->orig_fp
= NULL
;
315 if (claws_fputs(block_label
, pfile
->fp
) == EOF
||
316 claws_fputc('\n', pfile
->fp
) == EOF
) {
317 g_warning("failed to write configuration to file");
318 prefs_file_close_revert(pfile
);