luci.util.combine now also accepts single objects
[project/luci.git] / libs / core / luasrc / fs.lua
1 --[[
2 LuCI - Filesystem tools
3
4 Description:
5 A module offering often needed filesystem manipulation functions
6
7 FileId:
8 $Id$
9
10 License:
11 Copyright 2008 Steven Barth <steven@midlink.org>
12
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
16
17 http://www.apache.org/licenses/LICENSE-2.0
18
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24
25 ]]--
26
27 local io = require "io"
28 local os = require "os"
29 local ltn12 = require "luci.ltn12"
30 local posix = require "posix"
31
32 local type = type
33
34 --- LuCI filesystem library.
35 module "luci.fs"
36
37 --- Test for file access permission on given path.
38 -- @class function
39 -- @name access
40 -- @param str String value containing the path
41 -- @return Number containing the return code, 0 on sucess or nil on error
42 -- @return String containing the error description (if any)
43 -- @return Number containing the os specific errno (if any)
44 access = posix.access
45
46 --- Evaluate given shell glob pattern and return a table containing all matching
47 -- file and directory entries.
48 -- @class function
49 -- @name glob
50 -- @param filename String containing the path of the file to read
51 -- @return Table containing file and directory entries or nil if no matches
52 -- @return String containing the error description (if no matches)
53 -- @return Number containing the os specific errno (if no matches)
54 glob = posix.glob
55
56 --- Checks wheather the given path exists and points to a regular file.
57 -- @param filename String containing the path of the file to read
58 -- @return Boolean indicating wheather given path points to regular file
59 function isfile(filename)
60 return posix.stat(filename, "type") == "regular"
61 end
62
63 --- Read the whole content of the given file into memory.
64 -- @param filename String containing the path of the file to read
65 -- @return String containing the file contents or nil on error
66 -- @return String containing the error message on error
67 function readfile(filename)
68 local fp, err = io.open(filename)
69
70 if fp == nil then
71 return nil, err
72 end
73
74 local data = fp:read("*a")
75 fp:close()
76 return data
77 end
78
79 --- Write the contents of given string to given file.
80 -- @param filename String containing the path of the file to read
81 -- @param data String containing the data to write
82 -- @return Boolean containing true on success or nil on error
83 -- @return String containing the error message on error
84 function writefile(filename, data)
85 local fp, err = io.open(filename, "w")
86
87 if fp == nil then
88 return nil, err
89 end
90
91 fp:write(data)
92 fp:close()
93
94 return true
95 end
96
97 --- Copies a file.
98 -- @param source Source file
99 -- @param dest Destination
100 -- @return Boolean containing true on success or nil on error
101 function copy(source, dest)
102 return ltn12.pump.all(
103 ltn12.source.file(io.open(source)),
104 ltn12.sink.file(io.open(dest, "w"))
105 )
106 end
107
108 --- Renames a file.
109 -- @param source Source file
110 -- @param dest Destination
111 -- @return Boolean containing true on success or nil on error
112 function rename(source, dest)
113 return os.rename(source, dest)
114 end
115
116 --- Get the last modification time of given file path in Unix epoch format.
117 -- @param path String containing the path of the file or directory to read
118 -- @return Number containing the epoch time or nil on error
119 -- @return String containing the error description (if any)
120 -- @return Number containing the os specific errno (if any)
121 function mtime(path)
122 return posix.stat(path, "mtime")
123 end
124
125 --- Return the last element - usually the filename - from the given path with
126 -- the directory component stripped.
127 -- @class function
128 -- @name basename
129 -- @param path String containing the path to strip
130 -- @return String containing the base name of given path
131 -- @see dirname
132 basename = posix.basename
133
134 --- Return the directory component of the given path with the last element
135 -- stripped of.
136 -- @class function
137 -- @name dirname
138 -- @param path String containing the path to strip
139 -- @return String containing the directory component of given path
140 -- @see basename
141 dirname = posix.dirname
142
143 --- Return a table containing all entries of the specified directory.
144 -- @class function
145 -- @name dir
146 -- @param path String containing the path of the directory to scan
147 -- @return Table containing file and directory entries or nil on error
148 -- @return String containing the error description on error
149 -- @return Number containing the os specific errno on error
150 dir = posix.dir
151
152 --- Create a new directory, recursively on demand.
153 -- @param path String with the name or path of the directory to create
154 -- @param recursive Create multiple directory levels (optional, default is true)
155 -- @return Number with the return code, 0 on sucess or nil on error
156 -- @return String containing the error description on error
157 -- @return Number containing the os specific errno on error
158 function mkdir(path, recursive)
159 if recursive then
160 local base = "."
161
162 if path:sub(1,1) == "/" then
163 base = ""
164 path = path:gsub("^/+","")
165 end
166
167 for elem in path:gmatch("([^/]+)/*") do
168 base = base .. "/" .. elem
169
170 local stat = posix.stat( base )
171
172 if not stat then
173 local stat, errmsg, errno = posix.mkdir( base )
174
175 if type(stat) ~= "number" or stat ~= 0 then
176 return stat, errmsg, errno
177 end
178 else
179 if stat.type ~= "directory" then
180 return nil, base .. ": File exists", 17
181 end
182 end
183 end
184
185 return 0
186 else
187 return posix.mkdir( path )
188 end
189 end
190
191 --- Remove the given empty directory.
192 -- @class function
193 -- @name rmdir
194 -- @param path String containing the path of the directory to remove
195 -- @return Number with the return code, 0 on sucess or nil on error
196 -- @return String containing the error description on error
197 -- @return Number containing the os specific errno on error
198 rmdir = posix.rmdir
199
200 --- Get information about given file or directory.
201 -- @class function
202 -- @name stat
203 -- @param path String containing the path of the directory to query
204 -- @return Table containing file or directory properties or nil on error
205 -- @return String containing the error description on error
206 -- @return Number containing the os specific errno on error
207 stat = posix.stat
208
209 --- Set permissions on given file or directory.
210 -- @class function
211 -- @name chmod
212 -- @param path String containing the path of the directory
213 -- @param perm String containing the permissions to set ([ugoa][+-][rwx])
214 -- @return Number with the return code, 0 on sucess or nil on error
215 -- @return String containing the error description on error
216 -- @return Number containing the os specific errno on error
217 chmod = posix.chmod
218
219 --- Create a hard- or symlink from given file (or directory) to specified target
220 -- file (or directory) path.
221 -- @class function
222 -- @name link
223 -- @param path1 String containing the source path to link
224 -- @param path2 String containing the destination path for the link
225 -- @param symlink Boolean indicating wheather to create a symlink (optional)
226 -- @return Number with the return code, 0 on sucess or nil on error
227 -- @return String containing the error description on error
228 -- @return Number containing the os specific errno on error
229 link = posix.link
230
231 --- Remove the given file.
232 -- @class function
233 -- @name unlink
234 -- @param path String containing the path of the file to remove
235 -- @return Number with the return code, 0 on sucess or nil on error
236 -- @return String containing the error description on error
237 -- @return Number containing the os specific errno on error
238 unlink = posix.unlink
239
240 --- Retrieve target of given symlink.
241 -- @class function
242 -- @name readlink
243 -- @param path String containing the path of the symlink to read
244 -- @return String containing the link target or nil on error
245 -- @return String containing the error description on error
246 -- @return Number containing the os specific errno on error
247 readlink = posix.readlink