--- xchat-2.0.7/src/common/servlist.c.orig 2004-04-15 00:24:41.000000000 +0000 +++ xchat-2.0.7/src/common/servlist.c 2004-04-15 00:24:47.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include "xchat.h" @@ -34,6 +35,8 @@ #include "servlist.h" +void try(int result,int *acc_res); + struct defaultserver { char *network; @@ -929,67 +931,115 @@ { FILE *fp; - char buf[256]; + char realfname[256]; + char tmpfname[256]; + char textbuf[256]; ircnet *net; ircserver *serv; GSList *list; GSList *hlist; int first = FALSE; + struct stat fd_stat; + + int docommit = TRUE; + int res; - snprintf (buf, sizeof (buf), "%s/servlist_.conf", get_xdir_fs ()); + snprintf (realfname, sizeof (realfname), "%s/servlist_.conf", get_xdir_fs ()); + snprintf (tmpfname, sizeof (tmpfname), "%s/servlist_.conf.tmp", get_xdir_fs ()); + - if (access (buf, F_OK) != 0) + if (stat(realfname, &fd_stat) != 0) first = TRUE; - fp = fopen (buf, "w"); + fp = fopen (tmpfname, "w"); if (!fp) return; #ifndef WIN32 - if (first) + if (first) { - chmod (buf, 0600); + fchmod (fileno(fp), 0600); + } else { + fchmod (fileno(fp), fd_stat.st_mode); + fchown (fileno(fp), fd_stat.st_uid, fd_stat.st_gid); + } #endif - fprintf (fp, "v="VERSION"\n\n"); + try(fprintf (fp, "v="VERSION"\n\n"),&res); list = network_list; while (list) { net = list->data; - fprintf (fp, "N=%s\n", net->name); + try(fprintf (fp, "N=%s\n", net->name),&res); if (net->nick) - fprintf (fp, "I=%s\n", net->nick); + try(fprintf (fp, "I=%s\n", net->nick),&res); if (net->user) - fprintf (fp, "U=%s\n", net->user); + try(fprintf (fp, "U=%s\n", net->user),&res); if (net->real) - fprintf (fp, "R=%s\n", net->real); + try(fprintf (fp, "R=%s\n", net->real),&res); if (net->pass) - fprintf (fp, "P=%s\n", net->pass); + try(fprintf (fp, "P=%s\n", net->pass),&res); if (net->autojoin) - fprintf (fp, "J=%s\n", net->autojoin); + try(fprintf (fp, "J=%s\n", net->autojoin),&res); if (net->encoding && strcasecmp (net->encoding, "System") && strcasecmp (net->encoding, "System default")) { - fprintf (fp, "E=%s\n", net->encoding); + try(fprintf (fp, "E=%s\n", net->encoding),&res); if (!servlist_check_encoding (net->encoding)) { - snprintf (buf, sizeof (buf), _("Warning: \"%s\" character set is unknown. No conversion will be applied for network %s."), + snprintf (textbuf, sizeof (textbuf), _("Warning: \"%s\" character set is unknown. No conversion will be applied for network %s."), net->encoding, net->name); - fe_message (buf, FALSE); + fe_message (textbuf, FALSE); } } if (net->command) - fprintf (fp, "C=%s\n", net->command[0] == '/' ? net->command+1 : net->command); - fprintf (fp, "F=%d\nD=%d\n", net->flags, net->selected); + try(fprintf (fp, "C=%s\n", net->command[0] == '/' ? net->command+1 : net->command),&res); + try(fprintf (fp, "F=%d\nD=%d\n", net->flags, net->selected),&res); hlist = net->servlist; while (hlist) { serv = hlist->data; - fprintf (fp, "S=%s\n", serv->hostname); + try(fprintf (fp, "S=%s\n", serv->hostname),&res); hlist = hlist->next; } - fprintf (fp, "\n"); + try(fprintf (fp, "\n"),&res); list = list->next; + + if(res < 0 ) { + docommit = FALSE; + break; + } } fclose (fp); + + if(docommit) { + int errc; + if ( (errc = rename (tmpfname,realfname)) != 0) { + snprintf (textbuf, sizeof (textbuf), _("Warning: Error \"%s\" occurred while replacing old server list with new version. The server list might be lost."), strerror(-1 * errno)); + fe_message(textbuf,FALSE); + } + } else { + remove (tmpfname); + } +} + +int res_errorcode (int res) { + if (res < 0 ) { + return -1 * res; + } + return 0; +} + +void try(int result, int *acc_res) +{ + // if failed: no recovery + if(*acc_res < 0) + return; + + if(result < 0) { + char textbuf[256]; + *acc_res = -1; + snprintf (textbuf, sizeof (textbuf), _("Warning: Error \"%s\" occurred while writing the new server list."), strerror(res_errorcode(errno))); + fe_message(textbuf,FALSE); + } }