From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9578 invoked from network); 22 Jun 2007 20:29:19 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.1 (2007-05-02) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.1 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 22 Jun 2007 20:29:19 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 82112 invoked from network); 22 Jun 2007 20:29:13 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 22 Jun 2007 20:29:13 -0000 Received: (qmail 16838 invoked by alias); 22 Jun 2007 20:29:11 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 23581 Received: (qmail 16828 invoked from network); 22 Jun 2007 20:29:11 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 22 Jun 2007 20:29:11 -0000 Received: (qmail 81845 invoked from network); 22 Jun 2007 20:29:11 -0000 Received: from mtaout03-winn.ispmail.ntl.com (81.103.221.49) by a.mx.sunsite.dk with SMTP; 22 Jun 2007 20:29:07 -0000 Received: from aamtaout02-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout03-winn.ispmail.ntl.com with ESMTP id <20070622202855.VMMA13.mtaout03-winn.ispmail.ntl.com@aamtaout02-winn.ispmail.ntl.com> for ; Fri, 22 Jun 2007 21:28:55 +0100 Received: from pws-pc.ntlworld.com ([81.107.45.67]) by aamtaout02-winn.ispmail.ntl.com with SMTP id <20070622202855.PXOB17393.aamtaout02-winn.ispmail.ntl.com@pws-pc.ntlworld.com> for ; Fri, 22 Jun 2007 21:28:55 +0100 Date: Fri, 22 Jun 2007 21:28:25 +0100 From: Peter Stephenson To: zsh-workers@sunsite.dk Subject: Re: zsh history gets destroyed when running out of disk space Message-Id: <20070622212825.a8d29679.p.w.stephenson@ntlworld.com> In-Reply-To: <20070621080454.GA3303@fsst.voodoo.lan> References: <2007-06-11T21-20-52@devnull.michael-prokop.at> <20070621080454.GA3303@fsst.voodoo.lan> X-Mailer: Sylpheed 2.3.1 (GTK+ 2.10.8; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Thu, 21 Jun 2007 10:04:54 +0200 Frank Terbeck wrote: > Michael Prokop : > > Problem: > > > > Zsh truncates the zsh history file if you are running out of disk > > space (AKA ENOSPC). If you don't have any space left in your $HOME > > and exit zsh you'll find an empty $HISTFILE left. > > Hey, I experienced just the same a few days back. So, I also think > this should be addressed. The following detects errors during writing better. If you're writing a new file it'll leave it wherever it gets to; if you're replacing an old file it will leave the old file alone. That's about the best we can do. I haven't tested this on a failure, but it should be better than what we've got. Index: Src/hist.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/hist.c,v retrieving revision 1.66 diff -u -r1.66 hist.c --- Src/hist.c 1 Nov 2006 12:25:22 -0000 1.66 +++ Src/hist.c 22 Jun 2007 20:19:50 -0000 @@ -2158,6 +2158,7 @@ Histent he; zlong xcurhist = curhist - !!(histactive & HA_ACTIVE); int extended_history = isset(EXTENDEDHISTORY); + int ret; if (!interact || savehistsiz <= 0 || !hist_ring || (!fn && !(fn = getsparam("HISTFILE")))) @@ -2242,59 +2243,69 @@ } t = start = he->node.nam; if (extended_history) { - fprintf(out, ": %ld:%ld;", (long)he->stim, - he->ftim? (long)(he->ftim - he->stim) : 0L); + ret = fprintf(out, ": %ld:%ld;", (long)he->stim, + he->ftim? (long)(he->ftim - he->stim) : 0L); } else if (*t == ':') - fputc('\\', out); + ret = fputc('\\', out); - for (; *t; t++) { + for (; ret >= 0 && *t; t++) { if (*t == '\n') - fputc('\\', out); - fputc(*t, out); + if ((ret = fputc('\\', out)) < 0) + break; + if ((ret = fputc(*t, out)) < 0) + break; } - fputc('\n', out); + if (ret < 0 || (ret = fputc('\n', out)) < 0) + break; } - if (start && writeflags & HFILE_USE_OPTIONS) { + if (ret >= 0 && start && writeflags & HFILE_USE_OPTIONS) { struct stat sb; - fflush(out); - if (fstat(fileno(out), &sb) == 0) { - lasthist.fsiz = sb.st_size; - lasthist.mtim = sb.st_mtime; + if ((ret = fflush(out)) >= 0) { + if (fstat(fileno(out), &sb) == 0) { + lasthist.fsiz = sb.st_size; + lasthist.mtim = sb.st_mtime; + } + zsfree(lasthist.text); + lasthist.text = ztrdup(start); } - zsfree(lasthist.text); - lasthist.text = ztrdup(start); - } - fclose(out); - if (tmpfile) { - if (rename(tmpfile, unmeta(fn)) < 0) - zerr("can't rename %s.new to $HISTFILE", fn); - free(tmpfile); } + if (fclose(out) < 0 && ret >= 0) + ret = -1; + if (ret >= 0) { + if (tmpfile) { + if (rename(tmpfile, unmeta(fn)) < 0) + zerr("can't rename %s.new to $HISTFILE", fn); + free(tmpfile); + } - if (writeflags & HFILE_SKIPOLD - && !(writeflags & (HFILE_FAST | HFILE_NO_REWRITE))) { - int remember_histactive = histactive; - - /* Zeroing histactive avoids unnecessary munging of curline. */ - histactive = 0; - /* The NULL leaves HISTFILE alone, preserving fn's value. */ - pushhiststack(NULL, savehistsiz, savehistsiz, -1); - - hist_ignore_all_dups |= isset(HISTSAVENODUPS); - readhistfile(fn, err, 0); - hist_ignore_all_dups = isset(HISTIGNOREALLDUPS); - if (histlinect) - savehistfile(fn, err, 0); + if (writeflags & HFILE_SKIPOLD + && !(writeflags & (HFILE_FAST | HFILE_NO_REWRITE))) { + int remember_histactive = histactive; + + /* Zeroing histactive avoids unnecessary munging of curline. */ + histactive = 0; + /* The NULL leaves HISTFILE alone, preserving fn's value. */ + pushhiststack(NULL, savehistsiz, savehistsiz, -1); + + hist_ignore_all_dups |= isset(HISTSAVENODUPS); + readhistfile(fn, err, 0); + hist_ignore_all_dups = isset(HISTIGNOREALLDUPS); + if (histlinect) + savehistfile(fn, err, 0); - pophiststack(); - histactive = remember_histactive; + pophiststack(); + histactive = remember_histactive; + } } - } else if (err) { + } else + ret = -1; + + if (ret < 0 && err) { if (tmpfile) { - zerr("can't write history file %s.new", fn); + zerr("can't write history file %s.new: %e", fn); free(tmpfile); } else - zerr("can't write history file %s", fn); + zerr("can't write history file %s: %e", fn); } unlockhistfile(fn); -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/