library("R.utils") verbose <- Arguments$getVerbose(TRUE, timestamp=TRUE) # Run only tests if this platform/client supports symbolic file links canSymlink <- tryCatch({ res <- file.symlink(".", "test-symlink-dir") if (isDirectory("test-symlink-dir")) removeDirectory("test-symlink-dir") res }, error = function(ex) FALSE) # Test only if symlinks are supported if (canSymlink) { # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Local functions # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - fileAccessT <- function(pathname, modes=c(exist=0, exec=1, write=2, read=4)) { sapply(modes, FUN=function(mode) fileAccess(pathname, mode=mode)) } filename <- "foo.txt" paths <- list(".", tempdir()) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # FILES # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - for (path in paths) { verbose && enter(verbose, "Symbolic links to files") verbose && cat(verbose, "Path: ", path) pathnameS <- pathname <- file.path(path, filename) # WORKAROUND: On Windows, file.symlink() does not translate forward # slashes for you! Fixed (PR#15631) in r64711 2014-01-09. if (.Platform$OS.type == "windows") { pathnameS <- gsub("/", "\\", pathname, fixed=TRUE) } # Create a target file cat("Hello", file=pathname) # Create a symbolic link pathnameL <- file.path(path, sprintf("link-to-%s", filename)) file.symlink(pathnameS, pathnameL) stopifnot(isFile(pathnameL)) stopifnot(identical(lastModified(pathnameL), lastModified(pathname))) # Get target pathname pathnameT <- Sys.readlink2(pathnameL) # Should be equal stopifnot(getAbsolutePath(pathnameT) == getAbsolutePath(pathname)) # Read contents (directly and via link) bfr <- readChar(pathname, n=1e6) bfrL <- readChar(pathnameL, n=1e6) # Should be identical content stopifnot(identical(bfrL, bfr)) # Append content (via link) cat(" world!", file=pathnameL, append=TRUE) # Read contents (directly and via link) bfr <- readChar(pathname, n=1e6) printf("Target content: '%s'\n", bfr) bfrL <- readChar(pathnameL, n=1e6) printf("Link content : '%s'\n", bfrL) # Should be identical content stopifnot(identical(bfrL, bfr)) # Retrieve file information (directly and via link) fi <- file.info(pathname) printf("*** file.info('%s'):\n", pathname) print(fi) fiL <- file.info2(pathnameL) printf("*** file.info2('%s'):\n", pathnameL) print(fiL) # Should be equal file information except the filenames stopifnot(all.equal(fiL, fi, check.attributes=FALSE)) stopifnot(identical(lastModified(pathnameL), lastModified(pathname))) # Note that file.info() does not follow links on Windows if (.Platform$OS.type == "windows") { fiLx <- file.info(pathnameL) printf("*** file.info('%s'):\n", pathnameL) print(fiLx) res <- all.equal(fiLx, fi, check.attributes=FALSE) } # Renaming verbose && enter(verbose, "Renaming file link") pathnameL2 <- sprintf("%s-new", pathnameL) renameFile(pathnameL, pathnameL2) stopifnot(isFile(pathnameL2)) stopifnot(!isFile(pathnameL)) renameFile(pathnameL2, pathnameL) stopifnot(isFile(pathnameL)) stopifnot(!isFile(pathnameL2)) verbose && exit(verbose) # File access verbose && enter(verbose, "Testing file permissions & access information") fa <- fileAccessT(pathname) faL <- fileAccessT(pathnameL) stopifnot(identical(faL, fa)) # Disable write permission on target Sys.chmod(pathname, mode="0077") fa <- fileAccessT(pathname) faL <- fileAccessT(pathnameL) stopifnot(identical(faL, fa)) # Reset Sys.chmod(pathname, mode="0777") verbose && exit(verbose) # Removing & cleanup verbose && enter(verbose, "Cleanup") verbose && enter(verbose, "Removing file link") verbose && cat(verbose, "Link: ", pathnameL) verbose && cat(verbose, "Target: ", pathname) file.remove(pathnameL) # unlink() cannot remove symbolic links stopifnot(!file.exists(pathnameL)) stopifnot(isFile(pathname)) verbose && exit(verbose) verbose && enter(verbose, "Removing target") file.remove(pathname) stopifnot(!file.exists(pathname)) verbose && exit(verbose) verbose && exit(verbose) verbose && exit(verbose) } # for (path in ...) } # if (canSymlink)