Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleanup of Filesystem-related functions #12819

Merged
merged 10 commits into from
Nov 10, 2015
Prev Previous commit
Next Next commit
move file and poll into the Filesystem module
  • Loading branch information
vtjnash committed Nov 10, 2015
commit 33ac5ae85f18c95d20e1c5a80993c3adfd4fb4f3
119 changes: 112 additions & 7 deletions base/file.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

# Operations with the file system (paths) ##

export
cd,
chmod,
cp,
cptree,
mkdir,
mkpath,
mktemp,
mktempdir,
mv,
pwd,
rename,
readlink,
readdir,
rm,
samefile,
sendfile,
symlink,
tempdir,
tempname,
touch,
walkdir

# get and set current directory

function pwd()
Expand Down Expand Up @@ -66,7 +91,7 @@ mkpath(path::AbstractString, mode::Signed) = throw(ArgumentError("mode must be a
function rm(path::AbstractString; recursive::Bool=false)
if islink(path) || !isdir(path)
@windows_only if (filemode(path) & 0o222) == 0; chmod(path, 0o777); end # is writable on windows actually means "is deletable"
Filesystem.unlink(path)
unlink(path)
else
if recursive
for p in readdir(path)
Expand Down Expand Up @@ -116,7 +141,7 @@ function cptree(src::AbstractString, dst::AbstractString; remove_destination::Bo
cptree(srcname, joinpath(dst, name); remove_destination=remove_destination,
follow_symlinks=follow_symlinks)
else
Filesystem.sendfile(srcname, joinpath(dst, name))
sendfile(srcname, joinpath(dst, name))
end
end
end
Expand All @@ -129,22 +154,22 @@ function cp(src::AbstractString, dst::AbstractString; remove_destination::Bool=f
elseif isdir(src)
cptree(src, dst; remove_destination=remove_destination, follow_symlinks=follow_symlinks)
else
Filesystem.sendfile(src, dst)
sendfile(src, dst)
end
end

function mv(src::AbstractString, dst::AbstractString; remove_destination::Bool=false)
checkfor_mv_cp_cptree(src, dst, "moving"; remove_destination=remove_destination)
Filesystem.rename(src, dst)
rename(src, dst)
end

function touch(path::AbstractString)
f = Filesystem.open(path, JL_O_WRONLY | JL_O_CREAT, 0o0666)
f = open(path, JL_O_WRONLY | JL_O_CREAT, 0o0666)
try
t = time()
futime(f,t,t)
finally
Filesystem.close(f)
close(f)
end
end

Expand Down Expand Up @@ -202,7 +227,7 @@ function tempname(temppath::AbstractString,uunique::UInt32)
end
function mktemp(parent=tempdir())
filename = tempname(parent, UInt32(0))
return (filename, open(filename,"r+"))
return (filename, Base.open(filename, "r+"))
end
function mktempdir(parent=tempdir())
seed::UInt32 = rand(UInt32)
Expand Down Expand Up @@ -329,3 +354,83 @@ function walkdir(root; topdown=true, follow_symlinks=false, onerror=throw)
Task(_it)
end

function unlink(p::AbstractString)
err = ccall(:jl_fs_unlink, Int32, (Cstring,), p)
uv_error("unlink", err)
nothing
end

# For move command
function rename(src::AbstractString, dst::AbstractString)
err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), src, dst)
# on error, default to cp && rm
if err < 0
# remove_destination: is already done in the mv function
cp(src, dst; remove_destination=false, follow_symlinks=false)
rm(src; recursive=true)
end
nothing
end

function sendfile(src::AbstractString, dst::AbstractString)
local src_open = false,
dst_open = false,
src_file,
dst_file
try
src_file = open(src, JL_O_RDONLY)
src_open = true
dst_file = open(dst, JL_O_CREAT | JL_O_TRUNC | JL_O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH)
dst_open = true

bytes = filesize(stat(src_file))
sendfile(dst_file, src_file, Int64(0), Int(bytes))
finally
if src_open && isopen(src_file)
close(src_file)
end
if dst_open && isopen(dst_file)
close(dst_file)
end
end
end

@windows_only const UV_FS_SYMLINK_JUNCTION = 0x0002
function symlink(p::AbstractString, np::AbstractString)
@windows_only if Base.windows_version() < Base.WINDOWS_VISTA_VER
error("Windows XP does not support soft symlinks")
end
flags = 0
@windows_only if isdir(p); flags |= UV_FS_SYMLINK_JUNCTION; p = abspath(p); end
err = ccall(:jl_fs_symlink, Int32, (Cstring, Cstring, Cint), p, np, flags)
@windows_only if err < 0
Base.warn_once("Note: on Windows, creating file symlinks requires Administrator privileges.")
end
uv_error("symlink",err)
end

function readlink(path::AbstractString)
req = Libc.malloc(_sizeof_uv_fs)
try
ret = ccall(:uv_fs_readlink, Int32,
(Ptr{Void}, Ptr{Void}, Cstring, Ptr{Void}),
eventloop(), req, path, C_NULL)
if ret < 0
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req)
uv_error("readlink", ret)
assert(false)
end
tgt = bytestring(ccall(:jl_uv_fs_t_ptr, Ptr{Cchar}, (Ptr{Void}, ), req))
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req)
return tgt
finally
Libc.free(req)
end
end

function chmod(p::AbstractString, mode::Integer)
err = ccall(:jl_fs_chmod, Int32, (Cstring, Cint), p, mode)
uv_error("chmod",err)
nothing
end
100 changes: 7 additions & 93 deletions base/filesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,9 @@ const S_IRWXO = 0o007

export File,
# open,
# close,
write,
unlink,
rename,
sendfile,
symlink,
readlink,
chmod,
futime,
unlink,
write,
JL_O_WRONLY,
JL_O_RDONLY,
JL_O_RDWR,
Expand All @@ -44,10 +38,13 @@ export File,
S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXG,
S_IROTH, S_IWOTH, S_IXOTH, S_IRWXO

import Base: uvtype, uvhandle, eventloop, fd, position, stat, close, write, read, read!, readbytes, isopen,
check_open, _sizeof_uv_fs, uv_error, show
import Base: uvtype, uvhandle, eventloop, fd, position, stat, close,
write, read, read!, readbytes, isopen, show,
check_open, _sizeof_uv_fs, uv_error, UVError

include("stat.jl")
include("file.jl")
include("poll.jl")
include(string(length(Core.ARGS)>=2?Core.ARGS[2]:"","file_constants.jl")) # include($BUILDROOT/base/file_constants.jl)

## Operations with File (fd) objects ##
Expand Down Expand Up @@ -197,87 +194,4 @@ end
fd(f::File) = f.handle
stat(f::File) = stat(f.handle)

# Operations with the file system (paths) ##

function unlink(p::AbstractString)
err = ccall(:jl_fs_unlink, Int32, (Cstring,), p)
uv_error("unlink", err)
nothing
end

# For move command
function rename(src::AbstractString, dst::AbstractString)
err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), src, dst)
# on error, default to cp && rm
if err < 0
# remove_destination: is already done in the mv function
cp(src, dst; remove_destination=false, follow_symlinks=false)
rm(src; recursive=true)
end
nothing
end

function sendfile(src::AbstractString, dst::AbstractString)
local src_open = false,
dst_open = false,
src_file,
dst_file
try
src_file = open(src, JL_O_RDONLY)
src_open = true
dst_file = open(dst, JL_O_CREAT | JL_O_TRUNC | JL_O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH)
dst_open = true

bytes = filesize(stat(src_file))
sendfile(dst_file, src_file, Int64(0), Int(bytes))
finally
if src_open && isopen(src_file)
close(src_file)
end
if dst_open && isopen(dst_file)
close(dst_file)
end
end
end

@windows_only const UV_FS_SYMLINK_JUNCTION = 0x0002
function symlink(p::AbstractString, np::AbstractString)
@windows_only if Base.windows_version() < Base.WINDOWS_VISTA_VER
error("Windows XP does not support soft symlinks")
end
flags = 0
@windows_only if isdir(p); flags |= UV_FS_SYMLINK_JUNCTION; p = abspath(p); end
err = ccall(:jl_fs_symlink, Int32, (Cstring, Cstring, Cint), p, np, flags)
@windows_only if err < 0
Base.warn_once("Note: on Windows, creating file symlinks requires Administrator privileges.")
end
uv_error("symlink",err)
end

function readlink(path::AbstractString)
req = Libc.malloc(_sizeof_uv_fs)
try
ret = ccall(:uv_fs_readlink, Int32,
(Ptr{Void}, Ptr{Void}, Cstring, Ptr{Void}),
eventloop(), req, path, C_NULL)
if ret < 0
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req)
uv_error("readlink", ret)
assert(false)
end
tgt = bytestring(ccall(:jl_uv_fs_t_ptr, Ptr{Cchar}, (Ptr{Void}, ), req))
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req)
return tgt
finally
Libc.free(req)
end
end

function chmod(p::AbstractString, mode::Integer)
err = ccall(:jl_fs_chmod, Int32, (Cstring, Cint), p, mode)
uv_error("chmod",err)
nothing
end

end
30 changes: 24 additions & 6 deletions base/poll.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

# TODO: move file into Filesystem module
# filesystem operations

export
watch_file,
poll_fd,
poll_file,
FileMonitor,
PollingFileWatcher,
FDWatcher

import Base: @handle_as, wait, close, uvfinalize, eventloop, notify_error, stream_wait,
_sizeof_uv_poll, _sizeof_uv_fs_poll, _sizeof_uv_fs_event, _uv_hook_close,
associate_julia_struct, disassociate_julia_struct
@windows_only import Base.WindowsRawSocket

# libuv file watching event flags
const UV_RENAME = 1
Expand Down Expand Up @@ -34,7 +47,6 @@ FDEvent(flags::Integer) = FDEvent((flags & UV_READABLE) != 0,
(flags & FD_TIMEDOUT) != 0)
fdtimeout() = FDEvent(false, false, true)


type FileMonitor
handle::Ptr{Void}
file::ByteString
Expand Down Expand Up @@ -188,7 +200,7 @@ end
function _uv_hook_close(uv::PollingFileWatcher)
uv.handle = C_NULL
uv.active = false
notify(uv.notify, (Filesystem.StatStruct(), Filesystem.StatStruct()))
notify(uv.notify, (StatStruct(), StatStruct()))
nothing
end

Expand All @@ -199,6 +211,12 @@ function _uv_hook_close(uv::FileMonitor)
nothing
end

function __init__()
global uv_jl_pollcb = cfunction(uv_pollcb, Void, (Ptr{Void}, Cint, Cint))
global uv_jl_fspollcb = cfunction(uv_fspollcb, Void, (Ptr{Void}, Cint, Ptr{Void}, Ptr{Void}))
global uv_jl_fseventscb = cfunction(uv_fseventscb, Void, (Ptr{Void}, Ptr{Int8}, Int32, Int32))
end

function uv_fseventscb(handle::Ptr{Void}, filename::Ptr, events::Int32, status::Int32)
t = @handle_as handle FileMonitor
fname = filename == C_NULL ? "" : bytestring(convert(Ptr{UInt8}, filename))
Expand All @@ -225,8 +243,8 @@ function uv_fspollcb(handle::Ptr{Void}, status::Int32, prev::Ptr, curr::Ptr)
if status != 0
notify_error(t.notify, UVError("PollingFileWatcher", status))
else
prev_stat = Filesystem.StatStruct(convert(Ptr{UInt8}, prev))
curr_stat = Filesystem.StatStruct(convert(Ptr{UInt8}, curr))
prev_stat = StatStruct(convert(Ptr{UInt8}, prev))
curr_stat = StatStruct(convert(Ptr{UInt8}, curr))
notify(t.notify, (prev_stat, curr_stat))
end
nothing
Expand Down Expand Up @@ -394,7 +412,7 @@ function poll_file(s::AbstractString, interval_seconds::Real=5.007, timeout_s::R

wait(wt)
if result === :timeout
return (Filesystem.StatStruct(), Filesystem.StatStruct())
return (StatStruct(), StatStruct())
end
return result
else
Expand Down
3 changes: 0 additions & 3 deletions base/stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,6 @@ function reinit_stdio()
global uv_jl_recvcb = cfunction(uv_recvcb, Void, (Ptr{Void}, Cssize_t, Ptr{Void}, Ptr{Void}, Cuint))
global uv_jl_sendcb = cfunction(uv_sendcb, Void, (Ptr{Void}, Cint))
global uv_jl_return_spawn = cfunction(uv_return_spawn, Void, (Ptr{Void}, Int64, Int32))
global uv_jl_pollcb = cfunction(uv_pollcb, Void, (Ptr{Void}, Cint, Cint))
global uv_jl_fspollcb = cfunction(uv_fspollcb, Void, (Ptr{Void}, Cint, Ptr{Void}, Ptr{Void}))
global uv_jl_fseventscb = cfunction(uv_fseventscb, Void, (Ptr{Void}, Ptr{Int8}, Int32, Int32))

global uv_eventloop = ccall(:jl_global_event_loop, Ptr{Void}, ())
global STDIN = init_stdio(ccall(:jl_stdin_stream ,Ptr{Void},()))
Expand Down
4 changes: 0 additions & 4 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ include("multimedia.jl")
importall .Multimedia
include("grisu.jl")
import .Grisu.print_shortest
include("file.jl")
include("methodshow.jl")

# core math functions
Expand Down Expand Up @@ -208,9 +207,6 @@ include("managers.jl")
# code loading
include("loading.jl")

# Polling (requires multi.jl)
include("poll.jl")

# memory-mapped and shared arrays
include("mmap.jl")
import .Mmap
Expand Down