luci-base: luci.util: rewrite threadlocal code to not confuse minifier
[project/luci.git] / modules / luci-base / 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 fs        = require "nixio.fs"
31 local nutil = require "nixio.util"
32
33 local type  = type
34
35 --- LuCI filesystem library.
36 module "luci.fs"
37
38 --- Test for file access permission on given path.
39 -- @class               function
40 -- @name                access
41 -- @param str   String value containing the path
42 -- @return              Number containing the return code, 0 on sucess or nil on error
43 -- @return              String containing the error description (if any)
44 -- @return              Number containing the os specific errno (if any)
45 access = fs.access
46
47 --- Evaluate given shell glob pattern and return a table containing all matching
48 -- file and directory entries.
49 -- @class                       function
50 -- @name                        glob
51 -- @param filename      String containing the path of the file to read
52 -- @return                      Table containing file and directory entries or nil if no matches
53 -- @return                      String containing the error description (if no matches)
54 -- @return                      Number containing the os specific errno (if no matches)
55 function glob(...)
56         local iter, code, msg = fs.glob(...)
57         if iter then
58                 return nutil.consume(iter)
59         else
60                 return nil, code, msg
61         end
62 end
63
64 --- Checks wheather the given path exists and points to a regular file.
65 -- @param filename      String containing the path of the file to test
66 -- @return                      Boolean indicating wheather given path points to regular file
67 function isfile(filename)
68         return fs.stat(filename, "type") == "reg"
69 end
70
71 --- Checks wheather the given path exists and points to a directory.
72 -- @param dirname       String containing the path of the directory to test
73 -- @return                      Boolean indicating wheather given path points to directory
74 function isdirectory(dirname)
75         return fs.stat(dirname, "type") == "dir"
76 end
77
78 --- Read the whole content of the given file into memory.
79 -- @param filename      String containing the path of the file to read
80 -- @return                      String containing the file contents or nil on error
81 -- @return                      String containing the error message on error
82 readfile = fs.readfile
83
84 --- Write the contents of given string to given file.
85 -- @param filename      String containing the path of the file to read
86 -- @param data          String containing the data to write
87 -- @return                      Boolean containing true on success or nil on error
88 -- @return                      String containing the error message on error
89 writefile = fs.writefile
90
91 --- Copies a file.
92 -- @param source        Source file
93 -- @param dest          Destination
94 -- @return                      Boolean containing true on success or nil on error
95 copy = fs.datacopy
96
97 --- Renames a file.
98 -- @param source        Source file
99 -- @param dest          Destination
100 -- @return                      Boolean containing true on success or nil on error
101 rename = fs.move
102
103 --- Get the last modification time of given file path in Unix epoch format.
104 -- @param path  String containing the path of the file or directory to read
105 -- @return              Number containing the epoch time or nil on error
106 -- @return              String containing the error description (if any)
107 -- @return              Number containing the os specific errno (if any)
108 function mtime(path)
109         return fs.stat(path, "mtime")
110 end
111
112 --- Set the last modification time  of given file path in Unix epoch format.
113 -- @param path  String containing the path of the file or directory to read
114 -- @param mtime Last modification timestamp
115 -- @param atime Last accessed timestamp
116 -- @return              0 in case of success nil on error
117 -- @return              String containing the error description (if any)
118 -- @return              Number containing the os specific errno (if any)
119 function utime(path, mtime, atime)
120         return fs.utimes(path, atime, mtime)
121 end
122
123 --- Return the last element - usually the filename - from the given path with
124 -- the directory component stripped.
125 -- @class               function
126 -- @name                basename
127 -- @param path  String containing the path to strip
128 -- @return              String containing the base name of given path
129 -- @see                 dirname
130 basename = fs.basename
131
132 --- Return the directory component of the given path with the last element
133 -- stripped of.
134 -- @class               function
135 -- @name                dirname
136 -- @param path  String containing the path to strip
137 -- @return              String containing the directory component of given path
138 -- @see                 basename
139 dirname = fs.dirname
140
141 --- Return a table containing all entries of the specified directory.
142 -- @class               function
143 -- @name                dir
144 -- @param path  String containing the path of the directory to scan
145 -- @return              Table containing file and directory entries or nil on error
146 -- @return              String containing the error description on error
147 -- @return              Number containing the os specific errno on error
148 function dir(...)
149         local iter, code, msg = fs.dir(...)
150         if iter then
151                 local t = nutil.consume(iter)
152                 t[#t+1] = "."
153                 t[#t+1] = ".."
154                 return t
155         else
156                 return nil, code, msg
157         end
158 end
159
160 --- Create a new directory, recursively on demand.
161 -- @param path          String with the name or path of the directory to create
162 -- @param recursive     Create multiple directory levels (optional, default is true)
163 -- @return                      Number with the return code, 0 on sucess or nil on error
164 -- @return                      String containing the error description on error
165 -- @return                      Number containing the os specific errno on error
166 function mkdir(path, recursive)
167         return recursive and fs.mkdirr(path) or fs.mkdir(path)
168 end
169
170 --- Remove the given empty directory.
171 -- @class               function
172 -- @name                rmdir
173 -- @param path  String containing the path of the directory to remove
174 -- @return              Number with the return code, 0 on sucess or nil on error
175 -- @return              String containing the error description on error
176 -- @return              Number containing the os specific errno on error
177 rmdir = fs.rmdir
178
179 local stat_tr = {
180         reg = "regular",
181         dir = "directory",
182         lnk = "link",
183         chr = "character device",
184         blk = "block device",
185         fifo = "fifo",
186         sock = "socket"
187 }
188 --- Get information about given file or directory.
189 -- @class               function
190 -- @name                stat
191 -- @param path  String containing the path of the directory to query
192 -- @return              Table containing file or directory properties or nil on error
193 -- @return              String containing the error description on error
194 -- @return              Number containing the os specific errno on error
195 function stat(path, key)
196         local data, code, msg = fs.stat(path)
197         if data then
198                 data.mode = data.modestr
199                 data.type = stat_tr[data.type] or "?"
200         end
201         return key and data and data[key] or data, code, msg
202 end
203
204 --- Set permissions on given file or directory.
205 -- @class               function
206 -- @name                chmod
207 -- @param path  String containing the path of the directory
208 -- @param perm  String containing the permissions to set ([ugoa][+-][rwx])
209 -- @return              Number with the return code, 0 on sucess or nil on error
210 -- @return              String containing the error description on error
211 -- @return              Number containing the os specific errno on error
212 chmod = fs.chmod
213
214 --- Create a hard- or symlink from given file (or directory) to specified target
215 -- file (or directory) path.
216 -- @class                       function
217 -- @name                        link
218 -- @param path1         String containing the source path to link
219 -- @param path2         String containing the destination path for the link
220 -- @param symlink       Boolean indicating wheather to create a symlink (optional)
221 -- @return                      Number with the return code, 0 on sucess or nil on error
222 -- @return                      String containing the error description on error
223 -- @return                      Number containing the os specific errno on error
224 function link(src, dest, sym)
225         return sym and fs.symlink(src, dest) or fs.link(src, dest)
226 end
227
228 --- Remove the given file.
229 -- @class               function
230 -- @name                unlink
231 -- @param path  String containing the path of the file to remove
232 -- @return              Number with the return code, 0 on sucess or nil on error
233 -- @return              String containing the error description on error
234 -- @return              Number containing the os specific errno on error
235 unlink = fs.unlink
236
237 --- Retrieve target of given symlink.
238 -- @class               function
239 -- @name                readlink
240 -- @param path  String containing the path of the symlink to read
241 -- @return              String containing the link target or nil on error
242 -- @return              String containing the error description on error
243 -- @return              Number containing the os specific errno on error
244 readlink = fs.readlink