plug part of the history problems until we can do better:
do not change the underlying file when truncating; rather, copy everything back from the tmpfile to histfd while the latter is locked
This commit is contained in:
parent
b903a5e66a
commit
bfa79a4e4b
13
Build.sh
13
Build.sh
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.725 2017/05/15 13:35:38 tg Exp $'
|
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.726 2017/08/07 20:40:56 tg Exp $'
|
||||||
#-
|
#-
|
||||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||||
# 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
# 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||||
|
@ -2090,6 +2090,11 @@ ac_test mmap lock_fcntl 0 'for mmap and munmap' <<-'EOF'
|
||||||
munmap(NULL, 0)); }
|
munmap(NULL, 0)); }
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
ac_test ftruncate mmap 0 'for ftruncate' <<-'EOF'
|
||||||
|
#include <unistd.h>
|
||||||
|
int main(void) { return (ftruncate(0, 0)); }
|
||||||
|
EOF
|
||||||
|
|
||||||
ac_test nice <<-'EOF'
|
ac_test nice <<-'EOF'
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
int main(void) { return (nice(4)); }
|
int main(void) { return (nice(4)); }
|
||||||
|
@ -2244,8 +2249,8 @@ EOF
|
||||||
# other checks
|
# other checks
|
||||||
#
|
#
|
||||||
fd='if to use persistent history'
|
fd='if to use persistent history'
|
||||||
ac_cache PERSISTENT_HISTORY || case $HAVE_MMAP$HAVE_FLOCK$HAVE_LOCK_FCNTL in
|
ac_cache PERSISTENT_HISTORY || case $HAVE_FTRUNCATE$HAVE_MMAP$HAVE_FLOCK$HAVE_LOCK_FCNTL in
|
||||||
11*|101) fv=1 ;;
|
111*|1101) fv=1 ;;
|
||||||
esac
|
esac
|
||||||
test 1 = $fv || check_categories="$check_categories no-histfile"
|
test 1 = $fv || check_categories="$check_categories no-histfile"
|
||||||
ac_testdone
|
ac_testdone
|
||||||
|
@ -2404,7 +2409,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
|
||||||
addsrcs USE_PRINTF_BUILTIN printf.c
|
addsrcs USE_PRINTF_BUILTIN printf.c
|
||||||
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
|
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
|
||||||
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
|
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
|
||||||
add_cppflags -DMKSH_BUILD_R=551
|
add_cppflags -DMKSH_BUILD_R=561
|
||||||
|
|
||||||
$e $bi$me: Finished configuration testing, now producing output.$ao
|
$e $bi$me: Finished configuration testing, now producing output.$ao
|
||||||
|
|
||||||
|
|
120
histrap.c
120
histrap.c
|
@ -27,7 +27,7 @@
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.162 2017/04/29 22:04:28 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.163 2017/08/07 20:40:57 tg Exp $");
|
||||||
|
|
||||||
Trap sigtraps[ksh_NSIG + 1];
|
Trap sigtraps[ksh_NSIG + 1];
|
||||||
static struct sigaction Sigact_ign;
|
static struct sigaction Sigact_ign;
|
||||||
|
@ -714,26 +714,65 @@ histsave(int *lnp, const char *cmd, int svmode, bool ignoredups)
|
||||||
|
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
static const unsigned char sprinkle[2] = { HMAGIC1, HMAGIC2 };
|
static const unsigned char sprinkle[2] = { HMAGIC1, HMAGIC2 };
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
static int
|
||||||
hist_init(Source *s)
|
hist_persist_back(int srcfd)
|
||||||
|
{
|
||||||
|
off_t tot, mis;
|
||||||
|
ssize_t n, w;
|
||||||
|
char *buf, *cp;
|
||||||
|
int rv = 0;
|
||||||
|
#define MKSH_HS_BUFSIZ 4096
|
||||||
|
|
||||||
|
if ((buf = malloc_osfunc(MKSH_HS_BUFSIZ)) == NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
tot = lseek(srcfd, (off_t)0, SEEK_END);
|
||||||
|
lseek(srcfd, (off_t)0, SEEK_SET);
|
||||||
|
lseek(histfd, (off_t)0, SEEK_SET);
|
||||||
|
|
||||||
|
mis = tot;
|
||||||
|
while (mis > 0) {
|
||||||
|
if ((n = blocking_read(srcfd, (cp = buf),
|
||||||
|
MKSH_HS_BUFSIZ)) == -1) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
intrcheck();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
goto copy_error;
|
||||||
|
}
|
||||||
|
mis -= n;
|
||||||
|
while (n) {
|
||||||
|
if (intrsig)
|
||||||
|
goto has_intrsig;
|
||||||
|
if ((w = write(histfd, cp, n)) != -1) {
|
||||||
|
n -= w;
|
||||||
|
cp += w;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (errno == EINTR) {
|
||||||
|
has_intrsig:
|
||||||
|
intrcheck();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
goto copy_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ftruncate(histfd, tot)) {
|
||||||
|
copy_error:
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
free_osfunc(buf);
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hist_persist_init(void)
|
||||||
{
|
{
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
|
||||||
unsigned char *base;
|
unsigned char *base;
|
||||||
int lines, fd;
|
int lines, fd;
|
||||||
enum { hist_init_first, hist_init_retry, hist_init_restore } hs;
|
enum { hist_init_first, hist_init_retry, hist_use_it } hs;
|
||||||
#endif
|
|
||||||
|
|
||||||
histsave(NULL, NULL, HIST_DISCARD, true);
|
|
||||||
|
|
||||||
if (Flag(FTALKING) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
hstarted = true;
|
|
||||||
hist_source = s;
|
|
||||||
|
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
|
||||||
if (((hname = str_val(global("HISTFILE"))) == NULL) || !*hname) {
|
if (((hname = str_val(global("HISTFILE"))) == NULL) || !*hname) {
|
||||||
hname = NULL;
|
hname = NULL;
|
||||||
return;
|
return;
|
||||||
|
@ -753,9 +792,8 @@ hist_init(Source *s)
|
||||||
mksh_lockfd(histfd);
|
mksh_lockfd(histfd);
|
||||||
|
|
||||||
histfsize = lseek(histfd, (off_t)0, SEEK_END);
|
histfsize = lseek(histfd, (off_t)0, SEEK_END);
|
||||||
if (histfsize > MKSH_MAXHISTFSIZE || hs == hist_init_restore) {
|
if (histfsize > MKSH_MAXHISTFSIZE) {
|
||||||
/* we ignore too large files but still append to them */
|
/* we ignore too large files but still append to them */
|
||||||
/* we also don't need to re-read after truncation */
|
|
||||||
goto hist_init_tail;
|
goto hist_init_tail;
|
||||||
} else if (histfsize > 2) {
|
} else if (histfsize > 2) {
|
||||||
/* we have some data, check its validity */
|
/* we have some data, check its validity */
|
||||||
|
@ -781,6 +819,7 @@ hist_init(Source *s)
|
||||||
if ((fd = binopen3(nhname, O_RDWR | O_CREAT | O_TRUNC |
|
if ((fd = binopen3(nhname, O_RDWR | O_CREAT | O_TRUNC |
|
||||||
O_EXCL, 0600)) < 0) {
|
O_EXCL, 0600)) < 0) {
|
||||||
/* just don't truncate then, meh. */
|
/* just don't truncate then, meh. */
|
||||||
|
hs = hist_use_it;
|
||||||
goto hist_trunc_dont;
|
goto hist_trunc_dont;
|
||||||
}
|
}
|
||||||
if (fstat(histfd, &sb) >= 0 &&
|
if (fstat(histfd, &sb) >= 0 &&
|
||||||
|
@ -795,28 +834,26 @@ hist_init(Source *s)
|
||||||
hp = history;
|
hp = history;
|
||||||
while (hp < histptr) {
|
while (hp < histptr) {
|
||||||
if (!writehistline(fd,
|
if (!writehistline(fd,
|
||||||
s->line - (histptr - hp), *hp))
|
hist_source->line - (histptr - hp), *hp))
|
||||||
goto hist_trunc_abort;
|
goto hist_trunc_abort;
|
||||||
++hp;
|
++hp;
|
||||||
}
|
}
|
||||||
/* now unlock, close both, rename, rinse, repeat */
|
/* now transfer back */
|
||||||
|
if (!hist_persist_back(fd)) {
|
||||||
|
/* success! */
|
||||||
|
hs = hist_use_it;
|
||||||
|
}
|
||||||
|
hist_trunc_abort:
|
||||||
|
/* remove temporary file */
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
hist_finish();
|
unlink(nhname);
|
||||||
if (rename(nhname, hname) < 0) {
|
/* use whatever is in the file now */
|
||||||
hist_trunc_abort:
|
|
||||||
if (fd != -1)
|
|
||||||
close(fd);
|
|
||||||
unlink(nhname);
|
|
||||||
if (fd != -1)
|
|
||||||
goto hist_trunc_dont;
|
|
||||||
/* darn! restore histfd and pray */
|
|
||||||
}
|
|
||||||
hs = hist_init_restore;
|
|
||||||
hist_trunc_dont:
|
hist_trunc_dont:
|
||||||
afree(nhname, ATEMP);
|
afree(nhname, ATEMP);
|
||||||
if (hs == hist_init_restore)
|
if (hs == hist_use_it)
|
||||||
goto retry;
|
goto hist_trunc_done;
|
||||||
|
goto hist_init_fail;
|
||||||
}
|
}
|
||||||
} else if (histfsize != 0) {
|
} else if (histfsize != 0) {
|
||||||
/* negative or too small... */
|
/* negative or too small... */
|
||||||
|
@ -840,9 +877,26 @@ hist_init(Source *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hist_trunc_done:
|
||||||
histfsize = lseek(histfd, (off_t)0, SEEK_END);
|
histfsize = lseek(histfd, (off_t)0, SEEK_END);
|
||||||
hist_init_tail:
|
hist_init_tail:
|
||||||
mksh_unlkfd(histfd);
|
mksh_unlkfd(histfd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
hist_init(Source *s)
|
||||||
|
{
|
||||||
|
histsave(NULL, NULL, HIST_DISCARD, true);
|
||||||
|
|
||||||
|
if (Flag(FTALKING) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hstarted = true;
|
||||||
|
hist_source = s;
|
||||||
|
|
||||||
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
|
hist_persist_init();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue