2 * UDP Gateway single-file bundle utility functions
3 * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
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; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <glib/gmessages.h>
24 #include <sys/types.h>
27 #include <glib/gmem.h>
33 #include "bundle-util.h" /* self */
38 static G_CONST_RETURN guint8 *bundle_util_file_retrieve(guint32 *data_length_return,const gchar *basename)
42 g_return_val_if_fail(data_length_return!=NULL,NULL);
43 g_return_val_if_fail(basename!=NULL,NULL);
46 g_message(_("Retrieving internally stored: %s"),basename);
47 data=g_hash_table_lookup(bundle_hash_new(),basename);
48 g_return_val_if_fail(data!=NULL,NULL);
49 *data_length_return=GUINT32_FROM_BE(*(guint32 *)data);
50 data+=sizeof(*data_length_return);
55 /* Returns TRUE if it safe to overwrite/unlink the file.
57 static gboolean bundle_util_file_backup_conditional(const gchar *pathname,const gchar *basename)
64 char strftime_buffer[LINE_MAX];
65 const gchar *destination;
68 g_return_val_if_fail(pathname!=NULL,FALSE);
69 g_return_val_if_fail(basename!=NULL,FALSE);
71 if (!(data=bundle_util_file_retrieve(&data_length,basename)))
74 if (-1==(fd=open(pathname,O_RDONLY))) {
78 g_warning(_("Error checking file modifications of \"%s\": %m"),pathname);
83 /* WARNING: 'data_found' allocated in this block! */
84 data_found=g_malloc(data_length+1);
85 if (-1==(got=read(fd,data_found,data_length+1)))
86 g_warning(_("Error reading during the check of file modifications of \"%s\": %m"),pathname);
88 g_warning(_("Error closing the file \"%s\" during the check of its modifications: %m"),pathname);
89 /* memcmp(3) requires 'data_found'! */
90 if (got==(int)data_length && !memcmp(data_found,data,data_length)) {
96 time_current=time(NULL); /* It is segfault to gmtime(NULL). */
97 if (!strftime(strftime_buffer,sizeof(strftime_buffer),"GMT%FT%T",gmtime(&time_current))) {
98 g_warning("strftime(3): %m"); /* shouldn't happen */
101 destination=udpgate_printf_alloca("%s-%s-%d",pathname,strftime_buffer,(int)getpid());
102 if (rename(pathname,destination)) {
103 g_warning(_("Error renaming your modified file \"%s\" to the backup \"%s\", giving up: %m"),
104 pathname,destination);
111 gboolean bundle_util_file_remove(const gchar *pathname,const gchar *basename)
113 g_return_val_if_fail(pathname!=NULL,FALSE);
114 g_return_val_if_fail(basename!=NULL,FALSE);
116 if (!bundle_util_file_backup_conditional(pathname,basename))
119 if (unlink(pathname) && errno!=ENOENT) {
120 g_warning(_("Error removing the file \"%s\": %m"),pathname);
127 gboolean bundle_util_file_write(const gchar *pathname,const gchar *basename,mode_t pathname_mode,gboolean pathname_backup)
133 g_return_val_if_fail(pathname!=NULL,FALSE);
134 g_return_val_if_fail(basename!=NULL,FALSE);
136 if (!(data=bundle_util_file_retrieve(&data_length,basename)))
139 if (pathname_backup && !bundle_util_file_backup_conditional(pathname,basename))
142 if (-1==(fd=open(pathname,O_WRONLY|O_CREAT|O_TRUNC,pathname_mode))) {
143 g_warning(_("Error opening the file \"%s\" for rewrite: %m"),pathname);
146 if ((int)data_length!=write(fd,data,data_length)) {
147 g_warning(_("Error writing the data of the file \"%s\" being overwritten: %m"),pathname);
148 close(fd); /* errors ignored */
152 g_warning(_("Error closing the file \"%s\" after its rewrite: %m"),pathname);