lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

lynx-dev 2.8.3dev.2 patch 8 - reusing temp files


From: Klaus Weide
Subject: lynx-dev 2.8.3dev.2 patch 8 - reusing temp files
Date: Mon, 28 Jun 1999 18:14:03 -0500 (CDT)

Some more explanation for REUSE_TEMPFILES, below:

In earlier versions (up to 2-7, at least), for example the HISTORY
page, after being created once, would always be the same file
(/tmp/L7013-4TMP.html or whatever).  This changed in connection with
adding protection against /tmp spoofing.  Now each generation of
the HISTORY page would use a new filename.

But this has side effects that have bothered me for a while, in the
following situation:
While connected to the net, I visit various pages that get loaded
into lynx's cache.  Then I disconnect (or get disconnected).  I would
like to be able to read the cached texts now, without re-connecting.
They may not all be in the history list, and I use the HISTORY and
VLINKS commands to select them.  But each time HISTORY and VLINKS
(and INFO etc.) are called up, one of the cached docs is pushed out
of the cache (because for lynx, a new filename means it's a new doc).

The new options makes it possible to revert to the erlier versions'
behavior when it is safe to do so.  On Unix-like systems, with "normal"
precautions that should always be taken (including "sticky flag"
behavior in case of a shared TEMP_SPACE), there is no time window
opened by this option in which symlink spoofing can be successful, *as
far as I can see*, as long as OpenHiddenFile() and IsOurFile() do their
jobs right.  (And if they didn't, we'd already be in trouble with or
without the new option.)

(The call to HTEditable() shouldn't be necessary for protection, it's
there more for its side effect of generating TRACE output than anything
else.)

Some of the benefit of REUSE_TEMPFILES:TRUE might also be realized by
SOURCE_CACHE, but REUSE_TEMPFILES allows to utilize the available
slots in the *rendered docs* cache without the overhead and possible
bugs of the SOURCE_CACHE mechanism.  The REUSE_TEMPFILES benefit can
also be more general, since SOURCE_CACHE normally caches only http docs.

There are some more user interface pages where REUSE_TEMPFILES could be
applied, maybe later.  (I didn't deal with LIST and ADDRLIST for now
because they are not completely separate and there may be issues in
how they interact.)

   Klaus


* New option REUSE_TEMPFILES, see comments in lynx.cfg.
* Use P instead of invalid TR for right-aligned LYNXMESSAGES: link in
  HISTORY page.

Index: lynx2-8-3/src/LYUtils.c
--- lynx2-8-3.old/src/LYUtils.c Mon, 21 Jun 1999 00:31:29 -0500
--- lynx2-8-3/src/LYUtils.c Mon, 28 Jun 1999 16:46:18 -0500
@@ -6114,6 +6114,165 @@
 }
 
 /*
+ * Open a temp-file for writing, possibly re-using a previously used
+ * name and file.
+ * If a non-empty fname is given, it is reused if it indicates a file
+ * previously registered as a temp file and, in case the file still
+ * exists, if it looks like we can write to it safely.  Otherwise a
+ * new temp file (with new name) will be generated and returned in fname.
+ *
+ * File permissions are set so that the file is not readable by unprivileged
+ * other users.
+ *
+ * Suffix is only used if fname is not being reused.
+ * The mode should be "w", others are possible (they may be passed on)
+ * but probably don't make sense. - kw
+ */
+PUBLIC FILE *LYOpenTempRewrite ARGS3(
+       char *,         fname,
+       CONST char *,   suffix,
+       CONST char *,   mode)
+{
+    FILE *fp = 0;
+    BOOL txt = TRUE;
+    char wrt = 'r';
+    BOOL registered = NO;
+    BOOL writable_exists = NO;
+    BOOL is_ours = NO;
+    BOOL still_open = NO;
+    LY_TEMP *p;
+    struct stat stat_buf;
+
+    CTRACE(tfp, "LYOpenTempRewrite(%s,%s,%s)\n", fname, suffix, mode);
+    if (*fname == '\0')                /* first time, no filename yet */
+       return (LYOpenTemp(fname, suffix, mode));
+
+    for (p = ly_temp; p != 0; p = p->next) {
+       if (!strcmp(fname, p->name)) {
+           registered = YES;
+           if (p->file != 0)
+               still_open = YES;
+           CTRACE(tfp, "...used before%s\n",
+               still_open ? ", still open!" : ".");
+           break;
+       }
+    }
+
+    if (registered) {
+#ifndef NO_GROUPS
+       writable_exists = HTEditable(fname); /* existing, can write */
+#else
+       writable_exists = (stat(fname, &stat_buf) == 0); /* existing, assume 
can write */
+#endif
+
+       if (writable_exists) {
+#ifdef UNIX
+           is_ours = IsOurFile(fname);
+#else
+           is_ours = TRUE;     /* assume ok, if we get to here */
+#endif
+       }
+       CTRACE(tfp, "...%s%s\n",
+              writable_exists ? 
+#ifndef NO_GROUPS
+              "exists and is writable, "
+#else
+              "exists, "
+#endif
+              : "",
+              is_ours ? "is our file." : "is NOT our file.");
+    }
+
+    /*
+     *  Note that in cases where LYOpenTemp is called as fallback below,
+     *  we don't call LYRemoveTemp first.  That may be appropriate in some
+     *  cases, but not trying to remove a weird existing file seems safer
+     *  and could help diagnose an unusual situation.  (They may be removed
+     *  anyway later.)
+     */
+    if (still_open) {
+       /*
+        * This should probably not happen.  Make a new one.
+        */
+       return (LYOpenTemp(fname, suffix, mode));
+    } else if (is_ours) {
+       /*
+        *  Yes, it exists, is writable if we checked, and everything
+        *  looks ok so far.  This should be the most regular case.
+        *  We truncate and then append, this avoids having a small
+        *  window in which the file doesn't exist. - kw
+        */
+       if (truncate(fname, 0) != 0) {
+           CTRACE(tfp, "... truncate(%s,0) failed: %s\n",
+                  fname, LYStrerror(errno));
+           return (LYOpenTemp(fname, suffix, mode));
+       } else {
+           return (LYReopenTemp(fname));
+       }
+    } else if (writable_exists) {
+       /*
+        *  File exists, writable if we checked, but something is wrong
+        *  with it.
+        */
+       return (LYOpenTemp(fname, suffix, mode));
+#ifndef NO_GROUPS
+    } else if (registered && (lstat(fname, &stat_buf) == 0)) {
+       /*
+        *  Exists but not writable, and something is wrong with it.
+        */
+       return (LYOpenTemp(fname, suffix, mode));
+#endif
+    } else if (!registered) {
+       /*
+        *  Not registered.  It should have been registered at one point
+        *  though, otherwise we wouldn't be called like this.
+        */
+       return (LYOpenTemp(fname, suffix, mode));
+    } else {
+       /*
+        *  File does not exist, but is registered as a temp file.
+        *  It must have been removed by some means other than
+        *  LYRemoveTemp.  Reuse the name!
+        */
+    }
+
+    while (*mode != '\0') {
+       switch (*mode++) {
+       case 'w':       wrt = 'w';      break;
+       case 'a':       wrt = 'a';      break;
+       case 'b':       txt = FALSE;    break;
+       default:
+               CTRACE(tfp, "%s @%d: BUG\n", __FILE__, __LINE__);
+               return fp;
+       }
+    }
+
+    if (txt) {
+       switch (wrt) {
+       case 'w':
+           fp = LYNewTxtFile (fname);
+           break;
+       case 'a':
+           fp = LYAppendToTxtFile (fname);
+           break;
+       }
+    } else {
+       fp = LYNewBinFile (fname);
+    }
+    p->file = fp;
+
+    CTRACE(tfp, "... LYOpenTempRewrite(%s), %s\n", fname,
+          (fp) ? "ok" : "failed");
+    /*
+     *  We could fall back to trying LYOpenTemp() here in case of failure.
+     *  After all the checks already done above a filure here should be
+     *  pretty unusual though, so maybe it's better to let the user notice
+     *  that something went wrong, and not try to fix it up. - kw
+     */
+    return fp;
+}
+
+/*
  * Special case of LYOpenTemp, used for manipulating bookmark file, i.e., with
  * renaming.
  */
Index: lynx2-8-3/src/LYOptions.c
--- lynx2-8-3.old/src/LYOptions.c Tue, 22 Jun 1999 15:10:44 -0500
--- lynx2-8-3/src/LYOptions.c Mon, 28 Jun 1999 05:01:06 -0500
@@ -4087,13 +4087,17 @@
 #if defined(USE_SLANG) || defined(COLOR_CURSES)
     BOOLEAN can_do_colors;
 #endif
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     FILE *fp0;
     size_t cset_len = 0;
     size_t text_len = COLS - 38;       /* cf: PutLabel */
 
-    LYRemoveTemp(tempfile);
-    fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(tempfile);
+       fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
     if (fp0 == NULL) {
        HTAlert(UNABLE_TO_OPEN_TEMPFILE);
        return(NOT_FOUND);
Index: lynx2-8-3/src/LYPrint.c
--- lynx2-8-3.old/src/LYPrint.c Mon, 21 Jun 1999 22:47:22 -0500
--- lynx2-8-3/src/LYPrint.c Mon, 28 Jun 1999 05:36:00 -0500
@@ -1237,15 +1237,20 @@
        char **,        printed_url,
        int,            lines_in_file)
 {
-    static char my_temp[LY_MAXPATH];
+    static char my_temp[LY_MAXPATH] = "\0";
     char *buffer = 0;
     int count;
     int pages;
     FILE *fp0;
     lynx_printer_item_type *cur_printer;
 
-    LYRemoveTemp(my_temp);
-    if ((fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(my_temp, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(my_temp);
+       fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
        HTAlert(UNABLE_TO_OPEN_PRINTOP_FILE);
        return(-1);
     }
Index: lynx2-8-3/src/LYHistory.c
--- lynx2-8-3.old/src/LYHistory.c Mon, 21 Jun 1999 22:47:22 -0500
--- lynx2-8-3/src/LYHistory.c Mon, 28 Jun 1999 15:25:40 -0500
@@ -395,13 +395,18 @@
 PUBLIC int showhistory ARGS1(
        char **,        newfile)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     char *Title = NULL;
     int x = 0;
     FILE *fp0;
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(tempfile);
+       fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
        HTAlert(CANNOT_OPEN_TEMP);
        return(-1);
     }
@@ -413,7 +418,7 @@
 
     BeginInternalPage(fp0, HISTORY_PAGE_TITLE, HISTORY_PAGE_HELP);
 
-    fprintf(fp0, "<tr align=right> <a href=\"LYNXMESSAGES:\">[%s]</a> </tr>\n",
+    fprintf(fp0, "<p align=right> <a href=\"LYNXMESSAGES:\">[%s]</a>\n",
                 STATUSLINES_TITLE);
 
     fprintf(fp0, "<pre>\n");
@@ -557,7 +562,7 @@
 PUBLIC int LYShowVisitedLinks ARGS1(
        char **,        newfile)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     char *Title = NULL;
     char *Address = NULL;
     int x;
@@ -568,8 +573,13 @@
     if (!cur)
        return(-1);
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(tempfile);
+       fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
        HTAlert(CANNOT_OPEN_TEMP);
        return(-1);
     }
@@ -683,13 +693,18 @@
 PUBLIC int LYshow_statusline_messages ARGS1(
     document *,                              newdoc)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     static char *info_url;
     FILE *fp0;
     int i;
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp (tempfile, HTML_SUFFIX, "w")) == 0) {
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(tempfile);
+       fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
        HTAlert(CANNOT_OPEN_TEMP);
        return(NOT_FOUND);
     }
Index: lynx2-8-3/src/LYUtils.h
--- lynx2-8-3.old/src/LYUtils.h Mon, 21 Jun 1999 00:31:29 -0500
--- lynx2-8-3/src/LYUtils.h Mon, 28 Jun 1999 05:05:54 -0500
@@ -72,6 +72,7 @@
 extern FILE *LYOpenScratch PARAMS((char *result, CONST char *prefix));
 extern FILE *LYOpenTemp PARAMS((char *result, CONST char *suffix, CONST char 
*mode));
 extern FILE *LYReopenTemp PARAMS((char *name));
+extern FILE *LYOpenTempRewrite PARAMS((char *result, CONST char *suffix, CONST 
char *mode));
 extern char *Current_Dir PARAMS((char * pathname));
 extern char *LYLastPathSep PARAMS((char *path));
 extern char *LYPathLeaf PARAMS((char * pathname));
Index: lynx2-8-3/src/LYGlobalDefs.h
--- lynx2-8-3.old/src/LYGlobalDefs.h Mon, 21 Jun 1999 00:31:29 -0500
--- lynx2-8-3/src/LYGlobalDefs.h Mon, 28 Jun 1999 05:01:03 -0500
@@ -383,6 +383,7 @@
 extern BOOLEAN LYPrependCharsetToSource;
 extern BOOLEAN LYQuitDefaultYes;
 extern BOOLEAN LYNonRestartingSIGWINCH;
+extern BOOLEAN LYReuseTempfiles;
 
 #ifndef VMS
 extern BOOLEAN LYNoCore;
Index: lynx2-8-3/src/LYDownload.c
--- lynx2-8-3.old/src/LYDownload.c Fri, 04 Jun 1999 20:52:29 -0500
--- lynx2-8-3/src/LYDownload.c Mon, 28 Jun 1999 05:45:42 -0500
@@ -469,7 +469,7 @@
        char **,        newfile,
        char *,         data_file)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     char *downloaded_url = NULL;
     char *sug_filename = NULL;
     FILE *fp0;
@@ -482,8 +482,13 @@
     StrAllocCopy(sug_filename, *newfile);
     change_sug_filename(sug_filename);
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(tempfile);
+       fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
        HTAlert(CANNOT_OPEN_TEMP);
        return(-1);
     }
Index: lynx2-8-3/src/LYShowInfo.c
--- lynx2-8-3.old/src/LYShowInfo.c Mon, 21 Jun 1999 00:31:29 -0500
--- lynx2-8-3/src/LYShowInfo.c Mon, 28 Jun 1999 05:01:04 -0500
@@ -33,7 +33,7 @@
        document *,     newdoc,
        char *,         owner_address)
 {
-    static char tempfile[LY_MAXPATH];
+    static char tempfile[LY_MAXPATH] = "\0";
     int url_type;
     FILE *fp0;
     char *Address = NULL, *Title = NULL;
@@ -48,8 +48,13 @@
     struct stat dir_info;
 #endif /* DIRED_SUPPORT */
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp (tempfile, HTML_SUFFIX, "w")) == 0) {
+    if (LYReuseTempfiles) {
+       fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+    } else {
+       LYRemoveTemp(tempfile);
+       fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
+    }
+    if (fp0 == NULL) {
        HTAlert(CANNOT_OPEN_TEMP);
        return(-1);
     }
Index: lynx2-8-3/src/LYMain.c
--- lynx2-8-3.old/src/LYMain.c Tue, 22 Jun 1999 15:10:44 -0500
--- lynx2-8-3/src/LYMain.c Mon, 28 Jun 1999 05:01:02 -0500
@@ -409,6 +409,7 @@
 #endif
 
 PUBLIC BOOLEAN LYNonRestartingSIGWINCH = FALSE;
+PUBLIC BOOLEAN LYReuseTempfiles = FALSE;
 
 /* These are declared in cutil.h for current freeWAIS libraries. - FM */
 #ifdef DECLARE_WAIS_LOGFILES
Index: lynx2-8-3/src/LYReadCFG.c
--- lynx2-8-3.old/src/LYReadCFG.c Tue, 08 Jun 1999 13:19:59 -0500
--- lynx2-8-3/src/LYReadCFG.c Mon, 28 Jun 1999 05:01:00 -0500
@@ -1181,6 +1181,7 @@
      PARSE_SET("prepend_charset_to_source", CONF_BOOL, 
&LYPrependCharsetToSource),
      PARSE_FUN("printer", CONF_FUN, printer_fun),
      PARSE_SET("quit_default_yes", CONF_BOOL, &LYQuitDefaultYes),
+     PARSE_SET("reuse_tempfiles", CONF_BOOL, &LYReuseTempfiles),
 #ifndef NO_RULES
      PARSE_FUN("rule", CONF_FUN, HTSetConfiguration),
      PARSE_FUN("rulesfile", CONF_FUN, cern_rulesfile_fun),
Index: lynx2-8-3/lynx.cfg
--- lynx2-8-3.old/lynx.cfg Tue, 22 Jun 1999 15:10:44 -0500
--- lynx2-8-3/lynx.cfg Mon, 28 Jun 1999 16:46:17 -0500
@@ -171,6 +171,25 @@
 #
 #SAVE_SPACE:~/foo/
 
+# Lynx uses temporary files for (among other purposes) the content of
+# various user interface pages.  REUSE_TEMPFILES changes the behavior
+# for some of these temp files, among them pages shown for HISTORY,
+# VLINKS, OPTIONS, INFO, PRINT, DOWNLOAD commands.
+# If set to TRUE, the same file can be used multiple times for the same
+# purpose.  If set to FALSE, a new filename is generated each time before
+# rewriting such a page.  With TRUE, repeated invocation of these commands
+# is less likely to push previous documents out of the cache of rendered
+# texts (see also DEFAULT_CACHE_SIZE).  This is especially useful with
+# intermittent (dialup) network connections, when it is desirable to
+# continue browsing through the cached documents after disconnecting.
+# With the default setting of FALSE, there can be more than one incarnation
+# of e.g. the VLINKS page cached in memory (but still only the most recently
+# generated one is kept as a file), resulting in sometimes less surprising
+# behaviour when returning to such a page via HISTORY or PREV_DOC functions
+# (most users will not encounter and notice this difference).
+#
+#REUSE_TEMPFILES:FALSE
+
 # If LYNX_HOST_NAME is defined here or in userdefs.h, it will be
 # treated as an alias for the local host name in checks for URLs on
 # the local host (e.g., when the -localhost switch is set), and this


reply via email to

[Prev in Thread] Current Thread [Next in Thread]