Merge nixio 0.2
[project/luci.git] / libs / nixio / lua / nixio / fs.lua
1 --[[
2 nixio - Linux I/O library for lua
3
4 Copyright 2009 Steven Barth <steven@midlink.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13 ]]--
14
15 local table = require "table"
16 local nixio = require "nixio"
17 local type, ipairs, setmetatable = type, ipairs, setmetatable
18 require "nixio.util"
19
20
21 module ("nixio.fs", function(m) setmetatable(m, {__index = nixio.fs}) end)
22
23
24 function readfile(path, limit)
25         local fd, code, msg = nixio.open(path, "r")
26         local data
27         if not fd then
28                 return nil, code, msg
29         end
30         
31         data, code, msg = fd:readall(limit)
32         
33         fd:close()
34         return data, code, msg
35 end
36
37
38 function writefile(path, data)
39         local fd, code, msg, stat = nixio.open(path, "w")
40         if not fd then
41                 return nil, code, msg
42         end
43         
44         stat, code, msg = fd:writeall(data)
45         
46         fd:close()
47         return stat, code, msg
48 end
49
50 function datacopy(src, dest, size)
51         local fdin, code, msg = nixio.open(src, "r")
52         if not fdin then
53                 return nil, code, msg
54         end
55         
56         local fdout, code, msg = nixio.open(dest, "w")
57         if not fdout then
58                 return nil, code, msg
59         end     
60         
61         local stat, code, msg, sent = fdin:copy(fdout, size)
62         fdin:close()
63         fdout:close()
64
65         return stat, code, msg, sent
66 end
67
68 function copy(src, dest)
69         local stat, code, msg, res = nixio.lstat(src)
70         if not stat then
71                 return nil, code, msg
72         end
73         
74         if stat.type == "dir" then
75                 if nixio.stat(dest, type) ~= "dir" then
76                         res, code, msg = nixio.mkdir(dest)
77                 else
78                         stat = true
79                 end
80         elseif stat.type == "lnk" then
81                 res, code, msg = nixio.symlink(nixio.readlink(src), dest)
82         else
83                 res, code, msg = datacopy(src, dest)
84         end
85         
86         if not res then
87                 return nil, code, msg
88         end
89         
90         nixio.utimes(dest, stat.atime, stat.mtime)
91         
92         if nixio.lchown then
93                 nixio.lchown(dest, stat.uid, stat.gid)
94         end
95         
96         if stat.type ~= "lnk" then
97                 nixio.chmod(dest, stat.modedec)
98         end
99         
100         return true
101 end
102
103 function move(src, dest)
104         local stat, code, msg = nixio.rename(src, dest)
105         if not stat and code == nixio.const.EXDEV then
106                 stat, code, msg = nixio.copy(src, dest)
107                 if stat then
108                         stat, code, msg = nixio.unlink(src)
109                 end
110         end
111         return stat, code, msg
112 end
113
114 function mkdirr(dest, mode)
115         if nixio.stat(dest, "type") == "dir" then
116                 return true
117         else
118                 local stat, code, msg = nixio.mkdir(dest, mode)
119                 if not stat and code == nixio.const.ENOENT then
120                         stat, code, msg = mkdirr(nixio.dirname(dest), mode)
121                         if stat then
122                                 stat, code, msg = nixio.mkdir(dest, mode)
123                         end
124                 end
125                 return stat, code, msg
126         end
127 end
128
129 local function _recurse(cb, src, dest)
130         local type = nixio.lstat(src, "type")
131         if type ~= "dir" then
132                 return cb(src, dest)
133         else
134                 local stat, se, code, msg, s, c, m = true, nixio.const.sep
135                 if dest then
136                         s, c, m = cb(src, dest)
137                         stat, code, msg = stat and s, c or code, m or msg
138                 end
139
140                 for e in nixio.dir(src) do
141                         if dest then
142                                 s, c, m = _recurse(cb, src .. se .. e, dest .. se .. e)
143                         else
144                                 s, c, m = _recurse(cb, src .. se .. e)
145                         end
146                         stat, code, msg = stat and s, c or code, m or msg
147                 end
148
149                 if not dest then                                                        -- Postfix
150                         s, c, m = cb(src)
151                         stat, code, msg = stat and s, c or code, m or msg
152                 end
153
154                 return stat, code, msg
155         end
156 end
157
158 function copyr(src, dest)
159         return _recurse(copy, src, dest)
160 end
161
162 function mover(src, dest)
163         local stat, code, msg = nixio.rename(src, dest)
164         if not stat and code == nixio.const.EXDEV then
165                 stat, code, msg = _recurse(copy, src, dest)
166                 if stat then
167                         stat, code, msg = _recurse(nixio.remove, src)
168                 end
169         end
170         return stat, code, msg
171 end
172
173 function remover(src)
174         return _recurse(nixio.remove, src)
175 end