LCOV - code coverage report
Current view: top level - lisp/net - tramp-cache.el (source / functions) Hit Total Coverage
Test: tramp-tests.info Lines: 125 197 63.5 %
Date: 2017-08-27 09:44:50 Functions: 14 22 63.6 %

          Line data    Source code
       1             : ;;; tramp-cache.el --- file information caching for Tramp  -*- lexical-binding:t -*-
       2             : 
       3             : ;; Copyright (C) 2000, 2005-2017 Free Software Foundation, Inc.
       4             : 
       5             : ;; Author: Daniel Pittman <daniel@inanna.danann.net>
       6             : ;;         Michael Albinus <michael.albinus@gmx.de>
       7             : ;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
       8             : ;; Keywords: comm, processes
       9             : ;; Package: tramp
      10             : 
      11             : ;; This file is part of GNU Emacs.
      12             : 
      13             : ;; GNU Emacs is free software: you can redistribute it and/or modify
      14             : ;; it under the terms of the GNU General Public License as published by
      15             : ;; the Free Software Foundation, either version 3 of the License, or
      16             : ;; (at your option) any later version.
      17             : 
      18             : ;; GNU Emacs is distributed in the hope that it will be useful,
      19             : ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
      20             : ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21             : ;; GNU General Public License for more details.
      22             : 
      23             : ;; You should have received a copy of the GNU General Public License
      24             : ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
      25             : 
      26             : ;;; Commentary:
      27             : 
      28             : ;; An implementation of information caching for remote files.
      29             : 
      30             : ;; Each connection, identified by a `tramp-file-name' structure or by
      31             : ;; a process, has a unique cache. We distinguish 3 kind of caches,
      32             : ;; depending on the key:
      33             : ;;
      34             : ;; - localname is NIL.  This are reusable properties.  Examples:
      35             : ;;   "remote-shell" identifies the POSIX shell to be called on the
      36             : ;;   remote host, or "perl" is the command to be called on the remote
      37             : ;;   host when starting a Perl script.  These properties are saved in
      38             : ;;   the file `tramp-persistency-file-name'.
      39             : ;;
      40             : ;; - localname is a string.  This are temporary properties, which are
      41             : ;;   related to the file localname is referring to.  Examples:
      42             : ;;   "file-exists-p" is t or nil, depending on the file existence, or
      43             : ;;   "file-attributes" caches the result of the function
      44             : ;;   `file-attributes'.  These entries have a timestamp, and they
      45             : ;;   expire after `remote-file-name-inhibit-cache' seconds if this
      46             : ;;   variable is set.
      47             : ;;
      48             : ;; - The key is a process.  This are temporary properties related to
      49             : ;;   an open connection.  Examples: "scripts" keeps shell script
      50             : ;;   definitions already sent to the remote shell, "last-cmd-time" is
      51             : ;;   the time stamp a command has been sent to the remote process.
      52             : 
      53             : ;;; Code:
      54             : 
      55             : (require 'tramp)
      56             : (autoload 'time-stamp-string "time-stamp")
      57             : 
      58             : ;;; -- Cache --
      59             : 
      60             : ;;;###tramp-autoload
      61             : (defvar tramp-cache-data (make-hash-table :test 'equal)
      62             :   "Hash table for remote files properties.")
      63             : 
      64             : ;;;###tramp-autoload
      65             : (defcustom tramp-connection-properties nil
      66             :   "List of static connection properties.
      67             : Every entry has the form (REGEXP PROPERTY VALUE).  The regexp
      68             : matches remote file names.  It can be nil.  PROPERTY is a string,
      69             : and VALUE the corresponding value.  They are used, if there is no
      70             : matching entry for PROPERTY in `tramp-cache-data'.  For more
      71             : details see the info pages."
      72             :   :group 'tramp
      73             :   :version "24.4"
      74             :   :type '(repeat (list (choice :tag "File Name regexp" regexp (const nil))
      75             :                        (choice :tag "        Property" string)
      76             :                        (choice :tag "           Value" sexp)))
      77             :   :require 'tramp)
      78             : 
      79             : ;;;###tramp-autoload
      80             : (defcustom tramp-persistency-file-name
      81             :   (expand-file-name (locate-user-emacs-file "tramp"))
      82             :   "File which keeps connection history for Tramp connections."
      83             :   :group 'tramp
      84             :   :type 'file
      85             :   :require 'tramp)
      86             : 
      87             : (defvar tramp-cache-data-changed nil
      88             :   "Whether persistent cache data have been changed.")
      89             : 
      90             : (defun tramp-get-hash-table (key)
      91             :   "Returns the hash table for KEY.
      92             : If it doesn't exist yet, it is created and initialized with
      93             : matching entries of `tramp-connection-properties'."
      94      238034 :   (or (gethash key tramp-cache-data)
      95        4406 :       (let ((hash
      96        4406 :              (puthash key (make-hash-table :test 'equal) tramp-cache-data)))
      97        4406 :         (when (tramp-file-name-p key)
      98        4288 :           (dolist (elt tramp-connection-properties)
      99        3792 :             (when (string-match
     100        3792 :                    (or (nth 0 elt) "")
     101        3792 :                    (tramp-make-tramp-file-name
     102        3792 :                     (tramp-file-name-method key) (tramp-file-name-user key)
     103        3792 :                     (tramp-file-name-domain key) (tramp-file-name-host key)
     104        3792 :                     (tramp-file-name-port key) nil))
     105        4406 :               (tramp-set-connection-property key (nth 1 elt) (nth 2 elt)))))
     106      238034 :         hash)))
     107             : 
     108             : ;;;###tramp-autoload
     109             : (defun tramp-get-file-property (key file property default)
     110             :   "Get the PROPERTY of FILE from the cache context of KEY.
     111             : Returns DEFAULT if not set."
     112             :   ;; Unify localname.  Remove hop from `tramp-file-name' structure.
     113       19216 :   (setq file (tramp-compat-file-name-unquote file)
     114       19216 :         key (copy-tramp-file-name key))
     115       19216 :   (setf (tramp-file-name-localname key)
     116       19216 :         (tramp-run-real-handler 'directory-file-name (list file))
     117       19216 :         (tramp-file-name-hop key) nil)
     118       19216 :   (let* ((hash (tramp-get-hash-table key))
     119       19216 :          (value (when (hash-table-p hash) (gethash property hash))))
     120       19216 :     (if
     121             :         ;; We take the value only if there is any, and
     122             :         ;; `remote-file-name-inhibit-cache' indicates that it is still
     123             :         ;; valid.  Otherwise, DEFAULT is set.
     124       19216 :         (and (consp value)
     125        7969 :              (or (null remote-file-name-inhibit-cache)
     126        7969 :                  (and (integerp remote-file-name-inhibit-cache)
     127        7514 :                       (<=
     128        7514 :                        (tramp-time-diff (current-time) (car value))
     129        7969 :                        remote-file-name-inhibit-cache))
     130         775 :                  (and (consp remote-file-name-inhibit-cache)
     131           0 :                       (time-less-p
     132       19216 :                        remote-file-name-inhibit-cache (car value)))))
     133        7194 :         (setq value (cdr value))
     134       19216 :       (setq value default))
     135             : 
     136       19216 :     (tramp-message key 8 "%s %s %s" file property value)
     137       19216 :     (when (>= tramp-verbose 10)
     138           0 :       (let* ((var (intern (concat "tramp-cache-get-count-" property)))
     139           0 :              (val (or (bound-and-true-p var)
     140           0 :                       (progn
     141           0 :                         (add-hook 'tramp-cache-unload-hook
     142           0 :                                   (lambda () (makunbound var)))
     143           0 :                         0))))
     144       19216 :         (set var (1+ val))))
     145       19216 :     value))
     146             : 
     147             : ;;;###tramp-autoload
     148             : (defun tramp-set-file-property (key file property value)
     149             :   "Set the PROPERTY of FILE to VALUE, in the cache context of KEY.
     150             : Returns VALUE."
     151             :   ;; Unify localname.  Remove hop from `tramp-file-name' structure.
     152        6287 :   (setq file (tramp-compat-file-name-unquote file)
     153        6287 :         key (copy-tramp-file-name key))
     154        6287 :   (setf (tramp-file-name-localname key)
     155        6287 :         (tramp-run-real-handler 'directory-file-name (list file))
     156        6287 :         (tramp-file-name-hop key) nil)
     157        6287 :   (let ((hash (tramp-get-hash-table key)))
     158             :     ;; We put the timestamp there.
     159        6287 :     (puthash property (cons (current-time) value) hash)
     160        6287 :     (tramp-message key 8 "%s %s %s" file property value)
     161        6287 :     (when (>= tramp-verbose 10)
     162           0 :       (let* ((var (intern (concat "tramp-cache-set-count-" property)))
     163           0 :              (val (or (bound-and-true-p var)
     164           0 :                       (progn
     165           0 :                         (add-hook 'tramp-cache-unload-hook
     166           0 :                                   (lambda () (makunbound var)))
     167           0 :                         0))))
     168        6287 :         (set var (1+ val))))
     169        6287 :     value))
     170             : 
     171             : ;;;###tramp-autoload
     172             : (defun tramp-flush-file-property (key file)
     173             :   "Remove all properties of FILE in the cache context of KEY."
     174        2603 :   (let* ((file (tramp-run-real-handler
     175        2603 :                 'directory-file-name (list file)))
     176        2603 :          (truename (tramp-get-file-property key file "file-truename" nil)))
     177             :     ;; Unify localname.  Remove hop from `tramp-file-name' structure.
     178        2603 :     (setq file (tramp-compat-file-name-unquote file)
     179        2603 :           key (copy-tramp-file-name key))
     180        2603 :     (setf (tramp-file-name-localname key) file
     181        2603 :           (tramp-file-name-hop key) nil)
     182        2603 :     (tramp-message key 8 "%s" file)
     183        2603 :     (remhash key tramp-cache-data)
     184             :     ;; Remove file properties of symlinks.
     185        2603 :     (when (and (stringp truename)
     186        2603 :                (not (string-equal file (directory-file-name truename))))
     187        2603 :       (tramp-flush-file-property key truename))))
     188             : 
     189             : ;;;###tramp-autoload
     190             : (defun tramp-flush-directory-property (key directory)
     191             :   "Remove all properties of DIRECTORY in the cache context of KEY.
     192             : Remove also properties of all files in subdirectories."
     193         309 :   (setq directory (tramp-compat-file-name-unquote directory))
     194         309 :   (let* ((directory (tramp-run-real-handler
     195         309 :                     'directory-file-name (list directory)))
     196         309 :          (truename (tramp-get-file-property key directory "file-truename" nil)))
     197         309 :     (tramp-message key 8 "%s" directory)
     198         309 :     (maphash
     199             :      (lambda (key _value)
     200       18249 :        (when (and (tramp-file-name-p key)
     201       10205 :                   (stringp (tramp-file-name-localname key))
     202        7921 :                   (string-match (regexp-quote directory)
     203       18249 :                                 (tramp-file-name-localname key)))
     204       18249 :          (remhash key tramp-cache-data)))
     205         309 :      tramp-cache-data)
     206             :     ;; Remove file properties of symlinks.
     207         309 :     (when (and (stringp truename)
     208         309 :                (not (string-equal directory (directory-file-name truename))))
     209         309 :       (tramp-flush-directory-property key truename))))
     210             : 
     211             : ;; Reverting or killing a buffer should also flush file properties.
     212             : ;; They could have been changed outside Tramp.  In eshell, "ls" would
     213             : ;; not show proper directory contents when a file has been copied or
     214             : ;; deleted before.  We must apply `save-match-data', because it would
     215             : ;; corrupt other packages otherwise (reported from org).
     216             : (defun tramp-flush-file-function ()
     217             :   "Flush all Tramp cache properties from `buffer-file-name'.
     218             : This is suppressed for temporary buffers."
     219        1784 :   (save-match-data
     220        1784 :     (unless (or (null (buffer-name))
     221        1784 :                 (string-match "^\\( \\|\\*\\)" (buffer-name)))
     222          12 :       (let ((bfn (if (stringp (buffer-file-name))
     223           0 :                      (buffer-file-name)
     224          12 :                    default-directory))
     225             :             (tramp-verbose 0))
     226          12 :         (when (tramp-tramp-file-p bfn)
     227          12 :           (with-parsed-tramp-file-name bfn nil
     228        1784 :             (tramp-flush-file-property v localname)))))))
     229             : 
     230             : (add-hook 'before-revert-hook 'tramp-flush-file-function)
     231             : (add-hook 'eshell-pre-command-hook 'tramp-flush-file-function)
     232             : (add-hook 'kill-buffer-hook 'tramp-flush-file-function)
     233             : (add-hook 'tramp-cache-unload-hook
     234             :           (lambda ()
     235             :             (remove-hook 'before-revert-hook
     236             :                          'tramp-flush-file-function)
     237             :             (remove-hook 'eshell-pre-command-hook
     238             :                          'tramp-flush-file-function)
     239             :             (remove-hook 'kill-buffer-hook
     240             :                          'tramp-flush-file-function)))
     241             : 
     242             : ;;; -- Properties --
     243             : 
     244             : ;;;###tramp-autoload
     245             : (defun tramp-get-connection-property (key property default)
     246             :   "Get the named PROPERTY for the connection.
     247             : KEY identifies the connection, it is either a process or a
     248             : `tramp-file-name' structure.  A special case is nil, which is
     249             : used to cache connection properties of the local machine.  If the
     250             : value is not set for the connection, returns DEFAULT."
     251             :   ;; Unify key by removing localname and hop from `tramp-file-name'
     252             :   ;; structure.  Work with a copy in order to avoid side effects.
     253      195938 :   (when (tramp-file-name-p key)
     254      104834 :     (setq key (copy-tramp-file-name key))
     255      104834 :     (setf (tramp-file-name-localname key) nil
     256      195938 :           (tramp-file-name-hop key) nil))
     257      195938 :   (let* ((hash (tramp-get-hash-table key))
     258             :          (value
     259             :           ;; If the key is an auxiliary process object, check whether
     260             :           ;; the process is still alive.
     261      195938 :           (if (and (processp key) (not (process-live-p key)))
     262          51 :               default
     263      195887 :             (if (hash-table-p hash)
     264      195887 :                 (gethash property hash default)
     265      195938 :               default))))
     266      195938 :     (tramp-message key 7 "%s %s" property value)
     267      195938 :     value))
     268             : 
     269             : ;;;###tramp-autoload
     270             : (defun tramp-set-connection-property (key property value)
     271             :   "Set the named PROPERTY of a connection to VALUE.
     272             : KEY identifies the connection, it is either a process or a
     273             : `tramp-file-name' structure.  A special case is nil, which is
     274             : used to cache connection properties of the local machine.
     275             : PROPERTY is set persistent when KEY is a `tramp-file-name' structure."
     276             :   ;; Unify key by removing localname and hop from `tramp-file-name'
     277             :   ;; structure.  Work with a copy in order to avoid side effects.
     278       16593 :   (when (tramp-file-name-p key)
     279        4598 :     (setq key (copy-tramp-file-name key))
     280        4598 :     (setf (tramp-file-name-localname key) nil
     281       16593 :           (tramp-file-name-hop key) nil))
     282       16593 :   (let ((hash (tramp-get-hash-table key)))
     283       16593 :     (puthash property value hash)
     284       16593 :     (setq tramp-cache-data-changed t)
     285       16593 :     (tramp-message key 7 "%s %s" property value)
     286       16593 :     value))
     287             : 
     288             : ;;;###tramp-autoload
     289             : (defun tramp-connection-property-p (key property)
     290             :   "Check whether named PROPERTY of a connection is defined.
     291             : KEY identifies the connection, it is either a process or a
     292             : `tramp-file-name' structure.  A special case is nil, which is
     293             : used to cache connection properties of the local machine."
     294        3378 :   (not (eq (tramp-get-connection-property key property 'undef) 'undef)))
     295             : 
     296             : ;;;###tramp-autoload
     297             : (defun tramp-flush-connection-property (key)
     298             :   "Remove all properties identified by KEY.
     299             : KEY identifies the connection, it is either a process or a
     300             : `tramp-file-name' structure.  A special case is nil, which is
     301             : used to cache connection properties of the local machine."
     302             :   ;; Unify key by removing localname and hop from `tramp-file-name'
     303             :   ;; structure.  Work with a copy in order to avoid side effects.
     304          93 :   (when (tramp-file-name-p key)
     305          50 :     (setq key (copy-tramp-file-name key))
     306          50 :     (setf (tramp-file-name-localname key) nil
     307          93 :           (tramp-file-name-hop key) nil))
     308          93 :   (tramp-message
     309          93 :    key 7 "%s %s" key
     310          93 :    (let ((hash (gethash key tramp-cache-data))
     311             :          properties)
     312          93 :      (when (hash-table-p hash)
     313        1143 :        (maphash (lambda (x _y) (add-to-list 'properties x 'append)) hash))
     314          93 :      properties))
     315          93 :   (setq tramp-cache-data-changed t)
     316          93 :   (remhash key tramp-cache-data))
     317             : 
     318             : ;;;###tramp-autoload
     319             : (defun tramp-cache-print (table)
     320             :   "Print hash table TABLE."
     321           0 :   (when (hash-table-p table)
     322           0 :     (let (result)
     323           0 :       (maphash
     324             :        (lambda (key value)
     325             :          ;; Remove text properties from KEY and VALUE.
     326             :          ;; `cl-struct-slot-*' functions exist since Emacs 25 only; we
     327             :          ;; ignore errors.
     328           0 :          (when (tramp-file-name-p key)
     329             :            ;; (dolist
     330             :            ;;     (slot
     331             :            ;;   (mapcar 'car (cdr (cl-struct-slot-info 'tramp-file-name))))
     332             :            ;;   (when (stringp (cl-struct-slot-value 'tramp-file-name slot key))
     333             :            ;;     (setf (cl-struct-slot-value 'tramp-file-name slot key)
     334             :            ;;        (substring-no-properties
     335             :            ;;         (cl-struct-slot-value 'tramp-file-name slot key))))))
     336           0 :            (dotimes (i (length key))
     337           0 :              (when (stringp (elt key i))
     338           0 :                (setf (elt key i) (substring-no-properties (elt key i))))))
     339           0 :          (when (stringp key)
     340           0 :            (setq key (substring-no-properties key)))
     341           0 :          (when (stringp value)
     342           0 :            (setq value (substring-no-properties value)))
     343             :          ;; Dump.
     344           0 :          (let ((tmp (format
     345             :                      "(%s %s)"
     346           0 :                      (if (processp key)
     347           0 :                          (prin1-to-string (prin1-to-string key))
     348           0 :                        (prin1-to-string key))
     349           0 :                      (if (hash-table-p value)
     350           0 :                          (tramp-cache-print value)
     351           0 :                        (if (bufferp value)
     352           0 :                            (prin1-to-string (prin1-to-string value))
     353           0 :                          (prin1-to-string value))))))
     354           0 :            (setq result (if result (concat result " " tmp) tmp))))
     355           0 :        table)
     356           0 :       result)))
     357             : 
     358             : ;;;###tramp-autoload
     359             : (defun tramp-list-connections ()
     360             :   "Return all known `tramp-file-name' structs according to `tramp-cache'."
     361           0 :     (let (result tramp-verbose)
     362           0 :       (maphash
     363             :        (lambda (key _value)
     364           0 :          (when (and (tramp-file-name-p key)
     365           0 :                     (null (tramp-file-name-localname key))
     366           0 :                     (tramp-connection-property-p key "process-buffer"))
     367           0 :            (add-to-list 'result key)))
     368           0 :        tramp-cache-data)
     369           0 :       result))
     370             : 
     371             : (defun tramp-dump-connection-properties ()
     372             :   "Write persistent connection properties into file `tramp-persistency-file-name'."
     373             :   ;; We shouldn't fail, otherwise Emacs might not be able to be closed.
     374           0 :   (ignore-errors
     375           0 :     (when (and (hash-table-p tramp-cache-data)
     376           0 :                (not (zerop (hash-table-count tramp-cache-data)))
     377           0 :                tramp-cache-data-changed
     378           0 :                (stringp tramp-persistency-file-name))
     379           0 :       (let ((cache (copy-hash-table tramp-cache-data))
     380             :             print-length print-level)
     381             :         ;; Remove temporary data.  If there is the key "login-as", we
     382             :         ;; don't save either, because all other properties might
     383             :         ;; depend on the login name, and we want to give the
     384             :         ;; possibility to use another login name later on.  Key
     385             :         ;; "started" exists for the "ftp" method only, which must be
     386             :         ;; be kept persistent.
     387           0 :         (maphash
     388             :          (lambda (key value)
     389           0 :            (if (and (tramp-file-name-p key) value
     390           0 :                     (not (tramp-file-name-localname key))
     391           0 :                     (not (gethash "login-as" value))
     392           0 :                     (not (gethash "started" value)))
     393           0 :                (progn
     394           0 :                  (remhash "process-name" value)
     395           0 :                  (remhash "process-buffer" value)
     396           0 :                  (remhash "first-password-request" value))
     397           0 :              (remhash key cache)))
     398           0 :          cache)
     399             :         ;; Dump it.
     400           0 :         (with-temp-file tramp-persistency-file-name
     401           0 :           (insert
     402             :            ";; -*- emacs-lisp -*-"
     403             :            ;; `time-stamp-string' might not exist in all Emacs flavors.
     404           0 :            (condition-case nil
     405           0 :                (progn
     406           0 :                  (format
     407             :                   " <%s %s>\n"
     408           0 :                   (time-stamp-string "%02y/%02m/%02d %02H:%02M:%02S")
     409           0 :                   tramp-persistency-file-name))
     410           0 :              (error "\n"))
     411             :            ";; Tramp connection history.  Don't change this file.\n"
     412             :            ";; You can delete it, forcing Tramp to reapply the checks.\n\n"
     413           0 :            (with-output-to-string
     414           0 :              (pp (read (format "(%s)" (tramp-cache-print cache)))))))))))
     415             : 
     416             : (unless noninteractive
     417             :   (add-hook 'kill-emacs-hook 'tramp-dump-connection-properties))
     418             : (add-hook 'tramp-cache-unload-hook
     419             :           (lambda ()
     420             :             (remove-hook 'kill-emacs-hook
     421             :                          'tramp-dump-connection-properties)))
     422             : 
     423             : ;;;###tramp-autoload
     424             : (defun tramp-parse-connection-properties (method)
     425             :   "Return a list of (user host) tuples allowed to access for METHOD.
     426             : This function is added always in `tramp-get-completion-function'
     427             : for all methods.  Resulting data are derived from connection history."
     428          12 :   (let (res)
     429          12 :     (maphash
     430             :      (lambda (key _value)
     431         156 :        (if (and (tramp-file-name-p key)
     432          72 :                 (string-equal method (tramp-file-name-method key))
     433         156 :                 (not (tramp-file-name-localname key)))
     434           4 :            (push (list (tramp-file-name-user key)
     435           4 :                        (tramp-file-name-host key))
     436         156 :                  res)))
     437          12 :      tramp-cache-data)
     438          12 :     res))
     439             : 
     440             : ;; When "emacs -Q" has been called, both variables are nil.  We do not
     441             : ;; load the persistency file then, in order to have a clean test environment.
     442             : ;;;###tramp-autoload
     443             : (defvar tramp-cache-read-persistent-data (or init-file-user site-run-file)
     444             :   "Whether to read persistent data at startup time.")
     445             : 
     446             : ;; Read persistent connection history.
     447             : (when (and (stringp tramp-persistency-file-name)
     448             :            (zerop (hash-table-count tramp-cache-data))
     449             :            tramp-cache-read-persistent-data)
     450             :   (condition-case err
     451             :       (with-temp-buffer
     452             :         (insert-file-contents tramp-persistency-file-name)
     453             :         (let ((list (read (current-buffer)))
     454             :               (tramp-verbose 0)
     455             :               element key item)
     456             :           (while (setq element (pop list))
     457             :             (setq key (pop element))
     458             :             (when (tramp-file-name-p key)
     459             :               (while (setq item (pop element))
     460             :                 ;; We set only values which are not contained in
     461             :                 ;; `tramp-connection-properties'.  The cache is
     462             :                 ;; initialized properly by side effect.
     463             :                 (unless (tramp-connection-property-p key (car item))
     464             :                   (tramp-set-connection-property key (pop item) (car item)))))))
     465             :         (setq tramp-cache-data-changed nil))
     466             :     (file-error
     467             :      ;; Most likely because the file doesn't exist yet.  No message.
     468             :      (clrhash tramp-cache-data))
     469             :     (error
     470             :      ;; File is corrupted.
     471             :      (message "Tramp persistency file `%s' is corrupted: %s"
     472             :               tramp-persistency-file-name (error-message-string err))
     473             :      (clrhash tramp-cache-data))))
     474             : 
     475             : (add-hook 'tramp-unload-hook
     476             :           (lambda ()
     477             :             (unload-feature 'tramp-cache 'force)))
     478             : 
     479             : (provide 'tramp-cache)
     480             : 
     481             : ;;; tramp-cache.el ends here

Generated by: LCOV version 1.12