Skip to content

Commit

Permalink
Fix a bug with opening local files
Browse files Browse the repository at this point in the history
  • Loading branch information
chpock committed Sep 15, 2024
1 parent 2b0d426 commit a0cee64
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 4 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2024-09-15 Konstantin Kushnir <[email protected]>
* Fix a bug with opening local files when their path starts as a VFS mount
point

2024-09-14 Konstantin Kushnir <[email protected]>
* Fix -eofchar issue on Windows and Tcl 9.0b3

Expand Down
8 changes: 4 additions & 4 deletions generic/vfsDriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ static ThreadSpecificData *CookfsGetThreadSpecificData(void) {
static int CookfsPathInFilesystem(Tcl_Obj *pathPtr,
ClientData *clientDataPtr)
{
//CookfsLog(printf("CookfsPathInFilesystem: start; looking for [%s]",
// Tcl_GetString(pathPtr)));
// CookfsLog(printf("CookfsPathInFilesystem: start; looking for [%s]",
// Tcl_GetString(pathPtr)));

Tcl_Obj *normPathObj = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normPathObj == NULL) {
Expand Down Expand Up @@ -193,8 +193,8 @@ static int CookfsPathInFilesystem(Tcl_Obj *pathPtr,
Cookfs_PathObjIncrRefCount(internalRep->pathObj);

*clientDataPtr = (ClientData)internalRep;
//CookfsLog(printf("CookfsPathInFilesystem: return found entry as"
// " an internalRep [%p]", (void *)internalRep));
// CookfsLog(printf("CookfsPathInFilesystem: return found entry as"
// " an internalRep [%p]", (void *)internalRep));
return TCL_OK;
}

Expand Down
21 changes: 21 additions & 0 deletions generic/vfsVfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,27 @@ Cookfs_Vfs *Cookfs_CookfsSplitWithVfs(Tcl_Obj *path,
{
continue;
}
// Also, we check that we have filesystem separator in the search
// string at the point after the end of the VFS mount or the search
// string is the VFS mount point (they are the same length).
// This will prevent files like '/foo/mount.bar' from being considered
// as belonging to the mount point '/foo/mount'. Here we expect
// a normalized input path with the internal Tcl file system
// separator '/'. Thus, we don't check for '\' on Windows and '/'
// on Unix.
//
// However, we also should consider a case where mount point contains
// a filesystem separator at the end. For example, if we have a mount
// point like 'mount://'. In this case, we don't need to perform
// the above check because we have already verified that the start
// of the search string matches the VFS mount point.
if (e->mountStr[mountLen - 1] != VFS_SEPARATOR &&
mountLen != searchLen &&
searchStr[mountLen] != VFS_SEPARATOR)
{
continue;
}

// We found matching the mount point.
foundSize = mountLen;
foundEntry = e;
Expand Down
65 changes: 65 additions & 0 deletions tests/vfs.test
Original file line number Diff line number Diff line change
Expand Up @@ -1568,3 +1568,68 @@ tcltest::test cookfsVfs-20.1.2 "Don't crash when stamp is not present and archiv
unset -nocomplain data index file ok
} -returnCodes error -result {Unable to create Cookfs object: index not found}

tcltest::test cookfsVfs-21.1 "Open a file that starts as a mount point without an error" -setup {
set cfs [tcltest::makeBinFile {} pages.cfs]
set checkfile1 [tcltest::makeFile {OUTSIDE} pages.cfs.test]
} -body {
cookfs::Mount $cfs $cfs -compression none
set checkfile2 [tcltest::makeFile {INSIDE} test $cfs]
list [tcltest::viewFile $checkfile1] [tcltest::viewFile $checkfile2]
} -cleanup {
catch { cookfs::Unmount $cfs }
tcltest::removeFile $checkfile1
tcltest::removeFile $cfs
unset -nocomplain cfs checkfile1 checkfile2
} -result {OUTSIDE INSIDE}

tcltest::test cookfsVfs-22.1.1 "Verify VFS mount point with a filesystem separator at the end" -setup {
set cfs [tcltest::makeBinFile {} pages.cfs]
set mnt "mount:/"
} -body {
cookfs::Mount $cfs $mnt -compression none -volume
tcltest::makeFile {INSIDE} test $mnt
tcltest::viewFile "${mnt}test"
} -cleanup {
catch { cookfs::Unmount $mnt }
tcltest::removeFile $cfs
unset -nocomplain cfs mnt
} -result {INSIDE}

tcltest::test cookfsVfs-22.1.2 "Verify VFS mount point with a filesystem separator at the end (using join)" -setup {
set cfs [tcltest::makeBinFile {} pages.cfs]
set mnt "mount:/"
} -body {
cookfs::Mount $cfs $mnt -compression none -volume
tcltest::makeFile {INSIDE} test $mnt
tcltest::viewFile [file join $mnt "test"]
} -cleanup {
catch { cookfs::Unmount $mnt }
tcltest::removeFile $cfs
unset -nocomplain cfs mnt
} -result {INSIDE}

tcltest::test cookfsVfs-22.2.1 "Verify VFS mount point with 2 filesystem separators at the end" -setup {
set cfs [tcltest::makeBinFile {} pages.cfs]
set mnt "mount://"
} -body {
cookfs::Mount $cfs $mnt -compression none -volume
tcltest::makeFile {INSIDE} test $mnt
tcltest::viewFile "${mnt}test"
} -cleanup {
catch { cookfs::Unmount $mnt }
tcltest::removeFile $cfs
unset -nocomplain cfs mnt
} -result {INSIDE}

tcltest::test cookfsVfs-22.2.2 "Verify VFS mount point with 2 filesystem separators at the end (using join)" -setup {
set cfs [tcltest::makeBinFile {} pages.cfs]
set mnt "mount://"
} -body {
cookfs::Mount $cfs $mnt -compression none -volume
tcltest::makeFile {INSIDE} test $mnt
tcltest::viewFile [file join $mnt "test"]
} -cleanup {
catch { cookfs::Unmount $mnt }
tcltest::removeFile $cfs
unset -nocomplain cfs mnt
} -result {INSIDE}

0 comments on commit a0cee64

Please sign in to comment.