Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Nov 19, 2013
2 parents 9d1e5e8 + 95c07c1 commit 2126e18
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 55 deletions.
31 changes: 2 additions & 29 deletions base/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ end
# The following use Unix command line facilites

rm(path::String) = FS.unlink(path)
cp(src::String, dst::String) = run(`cp $src $dst`)
mv(src::String, dst::String) = run(`mv $src $dst`)
cp(src::String, dst::String) = FS.sendfile(src, dst)
mv(src::String, dst::String) = FS.rename(src, dst)
touch(path::String) = run(`touch $path`)

# Obtain a temporary filename.
Expand Down Expand Up @@ -133,33 +133,6 @@ end
end
end

downloadcmd = nothing
function download(url::String, filename::String)
global downloadcmd
if downloadcmd === nothing
for checkcmd in (:curl, :wget, :fetch)
if success(`which $checkcmd` |> DevNull)
downloadcmd = checkcmd
break
end
end
end
if downloadcmd == :wget
run(`wget -O $filename $url`)
elseif downloadcmd == :curl
run(`curl -o $filename -L $url`)
elseif downloadcmd == :fetch
run(`fetch -f $filename $url`)
else
error("no download agent available; install curl, wget, or fetch")
end
filename
end
function download(url::String)
filename = tempname()
download(url, filename)
end

function readdir(path::String)
# Allocate space for uv_fs_t struct
uv_readdir_req = zeros(Uint8, ccall(:jl_sizeof_uv_fs_t, Int32, ()))
Expand Down
47 changes: 47 additions & 0 deletions base/fs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export File,
# close,
write,
unlink,
rename,
sendfile,
JL_O_WRONLY,
JL_O_RDONLY,
JL_O_RDWR,
Expand Down Expand Up @@ -102,6 +104,51 @@ function unlink(f::File)
f
end

# For move command
function rename(src::String, dst::String)
err = ccall(:jl_fs_rename, Int32, (Ptr{Uint8}, Ptr{Uint8}), bytestring(src),
bytestring(dst))

# on error, default to cp && rm
if err < 0
# first copy
err = sendfile(src, dst)
uv_error("sendfile when moving file", err)

# then rm
err = unlink(src)
uv_error("removing when moving file", err)
end
end

# For copy command
function sendfile(src::String, dst::String)
flags = JL_O_RDONLY
src_file = open(src, flags)
if !src_file.open
error("Src file is not open")
end

flags = JL_O_CREAT | JL_O_RDWR
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH
dst_file = open(dst, flags, mode)
if !dst_file.open
error("Dst file is not open")
end

src_stat = stat(src_file)
err = ccall(:jl_fs_sendfile, Int32, (Int32, Int32, Int64, Csize_t),
fd(src_file), fd(dst_file), 0, src_stat.size)
uv_error("sendfile", err)

if src_file.open
close(src_file)
end
if dst_file.open
close(dst_file)
end
end

function write(f::File, buf::Ptr{Uint8}, len::Integer, offset::Integer=-1)
if !f.open
error("file is not open")
Expand Down
29 changes: 29 additions & 0 deletions base/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,35 @@ print_with_color(color::Symbol, io::IO, msg::String...) =
print_with_color(color::Symbol, msg::String...) =
print_with_color(color, STDOUT, msg...)

## file downloading ##

downloadcmd = nothing
function download(url::String, filename::String)
global downloadcmd
if downloadcmd === nothing
for checkcmd in (:curl, :wget, :fetch)
if success(`which $checkcmd` |> DevNull)
downloadcmd = checkcmd
break
end
end
end
if downloadcmd == :wget
run(`wget -O $filename $url`)
elseif downloadcmd == :curl
run(`curl -o $filename -L $url`)
elseif downloadcmd == :fetch
run(`fetch -f $filename $url`)
else
error("no download agent available; install curl, wget, or fetch")
end
filename
end
function download(url::String)
filename = tempname()
download(url, filename)
end

## warnings and messages ##

function info(msg::String...; prefix="INFO: ")
Expand Down
18 changes: 18 additions & 0 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,24 @@ DLLEXPORT int jl_fs_unlink(char *path)
return ret;
}

DLLEXPORT int jl_fs_rename(char *src_path, char *dst_path)
{
uv_fs_t req;
int ret = uv_fs_rename(jl_io_loop, &req, src_path, dst_path, NULL);
uv_fs_req_cleanup(&req);
return ret;
}

DLLEXPORT int jl_fs_sendfile(int src_fd, int dst_fd,
int64_t in_offset, size_t len)
{
uv_fs_t req;
int ret = uv_fs_sendfile(jl_io_loop, &req, dst_fd, src_fd,
in_offset, len, NULL);
uv_fs_req_cleanup(&req);
return ret;
}

DLLEXPORT int jl_fs_write(int handle, char *buf, size_t len, size_t offset)
{
uv_fs_t req;
Expand Down
2 changes: 2 additions & 0 deletions src/julia.expmap
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@
jl_fs_poll_start;
jl_fs_event_init;
jl_fs_unlink;
jl_fs_rename;
jl_fs_sendfile;
jl_fs_write;
jl_fs_write_byte;
jl_fs_read;
Expand Down
83 changes: 57 additions & 26 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ close(open(file,"w")) # like touch, but lets the operating system update the tim
#######################################################################
# This section tests some of the features of the stat-based file info #
#######################################################################
@test isdir(dir) == true
@test isfile(dir) == false
@test islink(dir) == false
@test isdir(file) == false
@test isfile(file) == true
@test islink(file) == false
@test isreadable(file) == true
@test iswritable(file) == true
@test isdir(dir)
@test !isfile(dir)
@test !islink(dir)
@test !isdir(file)
@test isfile(file)
@test !islink(file)
@test isreadable(file)
@test iswritable(file)
# Here's something else that might be UNIX-specific?
run(`chmod -w $file`)
@test iswritable(file) == false
@test !iswritable(file)
run(`chmod +w $file`)
@test isexecutable(file) == false
@test !isexecutable(file)
@test filesize(file) == 0
# On windows the filesize of a folder is the accumulation of all the contained
# files and is thus zero in this case.
# On windows the filesize of a folder is the accumulation of all the contained
# files and is thus zero in this case.
@windows_only begin
@test filesize(dir) == 0
end
Expand All @@ -35,10 +35,28 @@ end
# rename file
newfile = joinpath(dir, "bfile.txt")
mv(file, newfile)
@test ispath(file) == false
@test isfile(newfile) == true
@test !ispath(file)
@test isfile(newfile)
file = newfile

# Test renaming directories
a_tmpdir = mktempdir()
b_tmpdir = joinpath(dir, "b_tmpdir")

# grab a_tmpdir's file info before renaming
a_stat = stat(a_tmpdir)

# rename, then make sure b_tmpdir does exist and a_tmpdir doesn't
mv(a_tmpdir, b_tmpdir)
@test isdir(b_tmpdir)
@test !ispath(a_tmpdir)

# get b_tmpdir's file info and compare with a_tmpdir
b_stat = stat(b_tmpdir)
@test Base.samefile(a_stat, b_stat)

rmdir(b_tmpdir)

#######################################################################
# This section tests file watchers. #
#######################################################################
Expand All @@ -53,25 +71,20 @@ function test_timeout(tval)
@async test_file_poll(channel,tval)
tr = take(channel)
t_elapsed = toq()

@test tr == false

@test !tr
@test tval <= t_elapsed
end

function test_touch(slval)
tval = slval*1.1
channel = RemoteRef()
@async test_file_poll(channel, tval)

sleep(tval/10) # ~ one poll period
f = open(file,"a")
write(f,"Hello World\n")
close(f)

tr = take(channel)

@test tr == true
@test tr
end


Expand Down Expand Up @@ -102,7 +115,7 @@ function test_monitor_wait(tval)
@test events.changed
end

# Commented out the tests below due to issues 3015, 3016 and 3020
# Commented out the tests below due to issues 3015, 3016 and 3020
test_timeout(0.1)
test_timeout(1)
# the 0.1 second tests are too optimistic
Expand Down Expand Up @@ -143,7 +156,7 @@ write(s, [0xffffffffffffffff,
0x000000001fffffff])
close(s)
s = open(file, "r")
@test isreadonly(s) == true
@test isreadonly(s)
b = mmap_bitarray((17,13), s)
@test b == trues(17,13)
@test_throws mmap_bitarray((7,3), s)
Expand All @@ -155,7 +168,7 @@ msync(b)
b0 = copy(b)
close(s)
s = open(file, "r")
@test isreadonly(s) == true
@test isreadonly(s)
b = mmap_bitarray((17,19), s)
@test b == b0
close(s)
Expand Down Expand Up @@ -184,10 +197,28 @@ emptyf = open(emptyfile)
close(emptyf)
rm(emptyfile)

# Test copy file
afile = joinpath(dir, "a.txt")
touch(afile)
af = open(afile, "r+")
write(af, "This is indeed a test")

bfile = joinpath(dir, "b.txt")
cp(afile, bfile)

a_stat = stat(afile)
b_stat = stat(bfile)
@test a_stat.mode == b_stat.mode
@test a_stat.size == b_stat.size

close(af)
rm(afile)
rm(bfile)

############
# Clean up #
############
rm(file)
rmdir(dir)
@test ispath(file) == false
@test ispath(dir) == false
@test !ispath(file)
@test !ispath(dir)

0 comments on commit 2126e18

Please sign in to comment.