From 131461ab572e04e01fd34db53ab2a7b213bd3094 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 13 Aug 2020 04:13:27 -0500 Subject: [PATCH] Don't check magic bytes on save (fixes #267) --- Project.toml | 2 +- src/loadsave.jl | 5 ++++- src/query.jl | 15 ++++++++++----- test/loadsave.jl | 13 +++++++++++++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index b4f87d5a..a5bed3b1 100644 --- a/Project.toml +++ b/Project.toml @@ -14,4 +14,4 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["FilePathsBase", "Test", "Random"] +test = ["FilePathsBase", "Random", "Test"] diff --git a/src/loadsave.jl b/src/loadsave.jl index 3107c100..0c30d719 100755 --- a/src/loadsave.jl +++ b/src/loadsave.jl @@ -114,9 +114,12 @@ savestreaming # if a bare filename or IO stream are given, query for the format and dispatch # to the formatted handlers below -for fn in (:load, :loadstreaming, :save, :savestreaming, :metadata) +for fn in (:load, :loadstreaming, :metadata) @eval $fn(file, args...; options...) = $fn(query(file), args...; options...) end +for fn in (:save, :savestreaming) + @eval $fn(file, args...; options...) = $fn(query(file; checkfile=false), args...; options...) +end # return a save function, so you can do `thing_to_save |> save("filename.ext")` save(file; options...) = data -> save(file, data; options...) diff --git a/src/query.jl b/src/query.jl index cd4cb442..5201d9b5 100644 --- a/src/query.jl +++ b/src/query.jl @@ -62,24 +62,29 @@ end """ -`query(filename)` returns a `File` object with information about the + query(filename; checkfile=true) + +Return a `File` object with information about the format inferred from the file's extension and/or magic bytes. +If `filename` already exists, the file's magic bytes will take priority +unless `checkfile` is false. """ -function query(filename) +function query(filename; checkfile::Bool=true) + checkfile &= isfile(filename) _, ext = splitext(filename) if haskey(ext2sym, ext) sym = ext2sym[ext] no_magic = !hasmagic(sym) - if lensym(sym) == 1 && (no_magic || !isfile(filename)) # we only found one candidate and there is no magic bytes, or no file, trust the extension + if lensym(sym) == 1 && (no_magic || !checkfile) # we only found one candidate and there is no magic bytes, or no file, trust the extension return File{DataFormat{sym}}(filename) - elseif !isfile(filename) && lensym(sym) > 1 + elseif !checkfile && lensym(sym) > 1 return File{DataFormat{sym[1]}}(filename) end if no_magic && !hasfunction(sym) error("Some formats with extension ", ext, " have no magic bytes; use `File{format\"FMT\"}(filename)` to resolve the ambiguity.") end end - !isfile(filename) && return File{unknown_df}(filename) # (no extension || no magic byte) && no file + !checkfile && return File{unknown_df}(filename) # (no extension || no magic byte) && no file # Otherwise, check the magic bytes file!(query(open(filename), abspath(filename))) end diff --git a/test/loadsave.jl b/test/loadsave.jl index cc709876..7c85967a 100644 --- a/test/loadsave.jl +++ b/test/loadsave.jl @@ -292,6 +292,19 @@ end # module Dummy @test_throws Exception save("missing.fmt",5) end +@testset "Overwrite file with bad magic bytes" begin + # issue #267 + a = [0x01,0x02,0x03] + fn = tempname()*".dmy" + open(fn, "w") do io + write(io, "Ceci n'est pas un DUMMY") + end + save(fn, a) + @test isa(query(fn), File{format"DUMMY"}) + @test load(fn) == a + rm(fn) +end + del_format(format"DUMMY") # PPM/PBM can be either binary or text. Test that the defaults work,