]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
don't lock the file if it has been renamed
authorAlan T. DeKok <aland@freeradius.org>
Mon, 26 Feb 2018 19:41:41 +0000 (14:41 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 26 Feb 2018 19:41:41 +0000 (14:41 -0500)
src/main/exfile.c

index 5a3953753ee35ded0376bfde3b6ee035f244bb1f..4802d94cbad88d40251f0b0d3afe5030b3f70d9e 100644 (file)
@@ -33,6 +33,8 @@ typedef struct exfile_entry_t {
        int             fd;             //!< File descriptor associated with an entry.
        uint32_t        hash;           //!< Hash for cheap comparison.
        time_t          last_used;      //!< Last time the entry was used.
+       dev_t           st_dev;         //!< device inode
+       ino_t           st_ino;         //!< inode number
        char            *filename;      //!< Filename.
 } exfile_entry_t;
 
@@ -325,6 +327,16 @@ int exfile_open(exfile_t *ef, char const *filename, mode_t permissions)
                        PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
                        return -1;
                }
+
+               if (fstat(ef->entries[i].fd, &st) < 0) goto error;
+
+               /*
+                *      Remember which device and inode this file is
+                *      for.
+                */
+               ef->entries[i].st_dev = st.st_dev;
+               ef->entries[i].st_ino = st.st_ino;
+
        } else {
                i = found;
        }
@@ -378,8 +390,7 @@ int exfile_open(exfile_t *ef, char const *filename, mode_t permissions)
        }
 
        /*
-        *      Maybe someone deleted the file while we were waiting
-        *      for the lock.  If so, re-open it.
+        *      See which file it really is.
         */
        if (fstat(ef->entries[i].fd, &st) < 0) {
                fr_strerror_printf("Failed to stat file %s: %s", filename, strerror(errno));
@@ -387,16 +398,19 @@ int exfile_open(exfile_t *ef, char const *filename, mode_t permissions)
        }
 
        /*
-        *      It's unlinked from the file system, close the FD and
-        *      try to re-open it.
+        *      Maybe the file was unlinked from the file system, OR
+        *      the file we opened is NOT the one we had cached.  If
+        *      so, close the file and re-open it from scratch.
         */
-       if (st.st_nlink == 0) {
+       if ((st.st_nlink == 0) ||
+           (st.st_dev != ef->entries[i].st_dev) ||
+           (st.st_ino != ef->entries[i].st_ino)) {
                close(ef->entries[i].fd);
                goto reopen;
        }
 
        /*
-        *      If we're appending, eek to the end of the file before
+        *      If we're appending, seek to the end of the file before
         *      returning the FD to the caller.
         */
        (void) lseek(ef->entries[i].fd, 0, SEEK_END);