Config file handling

Adam Byrtek / alpha alpha at student.uci.agh.edu.pl
Thu Mar 20 22:55:58 UTC 2003


Patch to write config to temporary file and then 'atomicaly' move it
to proper place. 

Moreover it is a fix for following nasty bug which happend when no
~/.mc/ini is found:

open("/usr/local/share/mc/mc.ini",
O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = -1 EACCES (Permission
denied)

We should not try to write to public files, so profile_name should be
used only for reading... But dump_profile still wants to save file
(even unmodified), so we check and save only in home_dir.

Regards
Patch attached and in BTS

Adam

-- 

  _.|._ |_  _.   :  Adam Byrtek /alpha/
 (_|||_)| |(_|   :  email  alpha@(irc.pl|debian.org)
     |           :  jabber alpha.pl(at)jabber.org, pgp 0xB25952C0
-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/mc/src/ChangeLog,v
retrieving revision 1.1145
diff -u -r1.1145 ChangeLog
--- ChangeLog	19 Mar 2003 13:39:48 -0000	1.1145
+++ ChangeLog	20 Mar 2003 22:54:26 -0000
@@ -1,0 +1,12 @@
+2003-03-20  Adam Byrtek  <alpha at debian.org>
+
+	* profile.c (dump_profile): When saving config files, write to
+	a copy, then replace the file. Retain file mode.
+	* hotlist.c (save hotlist): Likewise.
+	
+	* setup.c (dump_profile), setup.c (profile_name), hotlist.c
+	(profile_name), learn.c (profile_name), panelize.c
+	(profile_name): Avoid writing config files outside home
+	directory (happend when no .mc/ini existed). Use profile_name
+	only for reading.
+
Index: hotlist.c
===================================================================
RCS file: /cvs/gnome/mc/src/hotlist.c,v
retrieving revision 1.44
diff -u -r1.44 hotlist.c
--- hotlist.c	21 Dec 2002 08:43:15 -0000	1.44
+++ hotlist.c	20 Mar 2003 22:54:26 -0000
@@ -1328,23 +1328,26 @@
 static void
 clean_up_hotlist_groups (char *section)
 {
-    char	*grp_section;
+    char	*profile, *grp_section;
     void	*profile_keys;
     char	*key, *value;
 
+    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
+
     grp_section = g_strconcat (section, ".Group", NULL);
-    if (profile_has_section (section, profile_name))
-	profile_clean_section (section, profile_name);
-    if (profile_has_section (grp_section, profile_name)) {
-	profile_keys = profile_init_iterator (grp_section, profile_name);
+    if (profile_has_section (section, profile))
+	profile_clean_section (section, profile);
+    if (profile_has_section (grp_section, profile)) {
+	profile_keys = profile_init_iterator (grp_section, profile);
 
 	while (profile_keys) {
 	    profile_keys = profile_iterator_next (profile_keys, &key, &value);
 	    clean_up_hotlist_groups (key);
 	}
-	profile_clean_section (grp_section, profile_name);
+	profile_clean_section (grp_section, profile);
     }
     g_free (grp_section);
+    g_free (profile);
 }
 
 
@@ -1416,16 +1419,17 @@
 save_group (struct hotlist *grp)
 {
     struct hotlist *current = grp->head;
-    char           *group_section;
+    char           *group_section, *profile;
 
+    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
     group_section = find_group_section (grp);
     
-    profile_clean_section (group_section, profile_name);
+    profile_clean_section (group_section, profile);
     for (;current && current->type == HL_TYPE_GROUP; current = current->next){
 	WritePrivateProfileString (group_section,
 				   current->directory,
 				   current->label,
-				   profile_name);
+				   profile);
     }
     g_free (group_section);
 
@@ -1434,13 +1438,14 @@
 	 current = current->next)
 	 save_group (current);
     
-    profile_clean_section (grp->directory, profile_name);
+    profile_clean_section (grp->directory, profile);
     for (;current; current = current->next){
 	WritePrivateProfileString (grp->directory,
 				   current->directory,
 				   current->label,
-				   profile_name);
+				   profile);
     }
+    g_free (profile);
 }
 
 static int  list_level = 0;
@@ -1510,23 +1515,23 @@
     struct      stat stat_buf;
     
     if (!hotlist_state.readonly && hotlist_state.modified && hotlist_file_name) {
-	char	*fbak = g_strconcat (hotlist_file_name, ".bak", NULL);
+	char	*ftmp = g_strconcat (hotlist_file_name, ".tmp", NULL);
 
-	rename (hotlist_file_name, fbak);
-	if ((hotlist_file = fopen (hotlist_file_name, "w")) != 0) {
-	    if (stat (fbak, &stat_buf) == 0)
-		chmod (hotlist_file_name, stat_buf.st_mode);
+	if ((hotlist_file = fopen (ftmp, "w")) != 0) {
+	    if (stat (hotlist_file_name, &stat_buf) == 0)
+		chmod (ftmp, stat_buf.st_mode);
 	    else
-		chmod (hotlist_file_name, S_IRUSR | S_IWUSR);
+		chmod (ftmp, S_IRUSR | S_IWUSR);
 	    hot_save_group (hotlist);
 	    fclose (hotlist_file);
-	    stat (hotlist_file_name, &stat_buf);
-	    hotlist_file_mtime = stat_buf.st_mtime;
-	    saved = 1;
-	    hotlist_state.modified = 0;
-	} else
-	    rename (fbak, hotlist_file_name);
-	g_free (fbak);
+	    if (rename (ftmp, hotlist_file_name) == 0) {
+		stat (hotlist_file_name, &stat_buf);
+		hotlist_file_mtime = stat_buf.st_mtime;
+		saved = 1;
+		hotlist_state.modified = 0;
+	    }
+	}
+	g_free (ftmp);
     }
 
     return saved;
Index: learn.c
===================================================================
RCS file: /cvs/gnome/mc/src/learn.c,v
retrieving revision 1.19
diff -u -r1.19 learn.c
--- learn.c	21 Oct 2002 22:54:21 -0000	1.19
+++ learn.c	20 Mar 2003 22:54:26 -0000
@@ -310,12 +310,15 @@
     int i;
     int profile_changed = 0;
     char *section = g_strconcat ("terminal:", getenv ("TERM"), NULL);
+    char *profile;
 
+    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
+    
     for (i = 0; i < learn_total; i++) {
 	if (learnkeys [i].sequence != NULL) {
 	    profile_changed = 1;
 	    WritePrivateProfileString (section, key_name_conv_tab [i].name,
-	        learnkeys [i].sequence, profile_name);
+	        learnkeys [i].sequence, profile);
 	}
     }
 
@@ -329,6 +332,7 @@
 	sync_profiles ();
 
     g_free (section);
+    g_free (profile);
 }
 
 void learn_keys (void)
Index: panelize.c
===================================================================
RCS file: /cvs/gnome/mc/src/panelize.c,v
retrieving revision 1.33
diff -u -r1.33 panelize.c
--- panelize.c	8 Dec 2002 04:16:30 -0000	1.33
+++ panelize.c	20 Mar 2003 22:54:26 -0000
@@ -327,16 +327,20 @@
 void save_panelize (void)
 {
     struct panelize *current = panelize;
+    char *profile;
     
-    profile_clean_section (panelize_section, profile_name);
+    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
+    
+    profile_clean_section (panelize_section, profile);
     for (;current; current = current->next){
     	if (strcmp (current->label, _("Other command")))
 	    WritePrivateProfileString (panelize_section,
 				       current->label,
 				       current->command,
-				       profile_name);
+				       profile);
     }
     sync_profiles ();
+    g_free(profile);
 }
 
 void done_panelize (void)
Index: profile.c
===================================================================
RCS file: /cvs/gnome/mc/src/profile.c,v
retrieving revision 1.10
diff -u -r1.10 profile.c
--- profile.c	3 Mar 2003 07:59:11 -0000	1.10
+++ profile.c	20 Mar 2003 22:54:26 -0000
@@ -395,16 +395,32 @@
 static void dump_profile (TProfile *p)
 {
     FILE *profile;
+    struct stat stat_buf;
+    char *tmpFileName;
     
     if (!p)
 	return;
     dump_profile (p->link);
     /* .ado: p->FileName can be empty, it's better to jump over */
-    if (p->FileName[0] != (char) 0)
-      if ((profile = fopen (p->FileName, "w")) != NULL){
+    if (p->FileName[0] == (char) 0)
+	return;
+    
+    /* write files in home dir only */
+    if (strncmp (p->FileName, home_dir, sizeof(home_dir)) != 0)
+	return;
+    
+    /* save to temporary file, 'atomic' rename after completion */
+    tmpFileName = g_strconcat (p->FileName, ".tmp", NULL);
+    
+    if ((profile = fopen (tmpFileName, "w")) != NULL){
+	if (stat (p->FileName, &stat_buf) == 0)
+	    chmod (tmpFileName, stat_buf.st_mode);
+	else
+	    chmod (tmpFileName, S_IRUSR | S_IWUSR);
 	dump_sections (profile, p->Section);
 	fclose (profile);
-      }
+	rename (tmpFileName, p->FileName);
+    }
 }
 
 /*
@@ -510,7 +526,6 @@
 
     /* We assume the user has called one of the other initialization funcs */
     if (!find_loaded (file, &section)){
-	fprintf (stderr,"Warning: profile_clean_section called before init\n");
 	return;
     }
     /* We only disable the section, so it will still be freed, but it */
Index: setup.c
===================================================================
RCS file: /cvs/gnome/mc/src/setup.c,v
retrieving revision 1.73
diff -u -r1.73 setup.c
--- setup.c	23 Jan 2003 14:26:22 -0000	1.73
+++ setup.c	20 Mar 2003 22:54:26 -0000
@@ -219,38 +219,42 @@
 void
 panel_save_setup (struct WPanel *panel, char *section)
 {
-    char buffer [BUF_TINY];
+    char buffer [BUF_TINY], *profile;
     int  i;
 
+    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
+
     g_snprintf (buffer, sizeof (buffer), "%d", panel->reverse);
-    save_string (section, "reverse", buffer, profile_name);
+    save_string (section, "reverse", buffer, profile);
     g_snprintf (buffer, sizeof (buffer), "%d", panel->case_sensitive);
-    save_string (section, "case_sensitive", buffer, profile_name);
+    save_string (section, "case_sensitive", buffer, profile);
     for (i = 0; sort_names [i].key; i++)
 	if (sort_names [i].sort_type == (sortfn *) panel->sort_type){
 	    save_string (section, "sort_order",
-				       sort_names [i].key, profile_name);
+				       sort_names [i].key, profile);
 	    break;
 	}
 
     for (i = 0; list_types [i].key; i++)
 	if (list_types [i].list_type == panel->list_type){
-	    save_string (section, "list_mode", list_types [i].key, profile_name);
+	    save_string (section, "list_mode", list_types [i].key, profile);
 	    break;
 	}
 
     save_string (section, "user_format",
-			       panel->user_format, profile_name);
+			       panel->user_format, profile);
 
     for (i = 0; i < LIST_TYPES; i++){
 	g_snprintf (buffer, sizeof (buffer), "user_status%d", i);
 	save_string (section, buffer,
-	    panel->user_status_format [i], profile_name);
+	    panel->user_status_format [i], profile);
     }
 
     g_snprintf (buffer, sizeof (buffer), "%d", panel->user_mini_status);
     save_string (section, "user_mini_status", buffer,
-			       profile_name);
+			       profile);
+    
+    g_free (profile);
 }
 
 void
@@ -290,13 +294,17 @@
 panel_save_type (char *section, int type)
 {
     int i;
+    char *profile;
+
+    profile = concat_dir_and_file (home_dir, PROFILE_NAME);
 
     for (i = 0; panel_types [i].opt_name; i++)
 	if (panel_types [i].opt_type == type){
 	    save_string (section, "display", panel_types [i].opt_name,
-			 profile_name);
+			 profile);
 	    break;
 	}
+    g_free(profile);
 }
 
 void
@@ -347,7 +355,7 @@
 
 #ifdef HAVE_CHARSET
     save_string( "Misc", "display_codepage",
-    		 get_codepage_id( display_codepage ), profile_name );
+    		 get_codepage_id( display_codepage ), profile );
 #endif /* HAVE_CHARSET */
 
     g_free (profile);
@@ -476,7 +484,7 @@
 void
 load_setup (void)
 {
-    char *profile;
+    char *profile, *profile_writable;
     int    i;
 
     profile = setup_init ();
@@ -536,8 +544,10 @@
     /* Load the directory history */
 /*    directory_history_load (); */
     /* Remove the temporal entries */
-    profile_clean_section ("Temporal:New Left Panel", profile_name);
-    profile_clean_section ("Temporal:New Right Panel", profile_name);
+    profile_writable = concat_dir_and_file (home_dir, PROFILE_NAME);
+    profile_clean_section ("Temporal:New Left Panel", profile_writable);
+    profile_clean_section ("Temporal:New Right Panel", profile_writable);
+    g_free (profile_writable);
 #if defined(USE_VFS) && defined (USE_NETCODE)
     ftpfs_init_passwd ();
 #endif /* USE_VFS && USE_NETCODE */


More information about the mc-devel mailing list