summaryrefslogtreecommitdiffhomepage
path: root/libs/core/luasrc/fs.lua
blob: d4247d7830a97382c387f9753ad3ffce0d112bdc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
--[[
LuCI - Filesystem tools

Description:
A module offering often needed filesystem manipulation functions

FileId:
$Id$

License:
Copyright 2008 Steven Barth <steven@midlink.org>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

]]--

local io    = require "io"
local os    = require "os"
local ltn12 = require "luci.ltn12"
local posix = require "posix"

local type  = type

--- LuCI filesystem library.
module "luci.fs"

--- Test for file access permission on given path.
-- @class		function
-- @name		access
-- @param str	String value containing the path
-- @return		Number containing the return code, 0 on sucess or nil on error
-- @return		String containing the error description (if any)
-- @return		Number containing the os specific errno (if any)
access = posix.access

--- Evaluate given shell glob pattern and return a table containing all matching
-- file and directory entries.
-- @class			function
-- @name			glob
-- @param filename	String containing the path of the file to read
-- @return			Table containing file and directory entries or nil if no matches
-- @return			String containing the error description (if no matches)
-- @return			Number containing the os specific errno (if no matches)
glob = posix.glob

--- Checks wheather the given path exists and points to a regular file.
-- @param filename	String containing the path of the file to test
-- @return			Boolean indicating wheather given path points to regular file
function isfile(filename)
	return posix.stat(filename, "type") == "regular"
end

--- Checks wheather the given path exists and points to a directory.
-- @param dirname	String containing the path of the directory to test
-- @return			Boolean indicating wheather given path points to directory
function isdirectory(dirname)
	return posix.stat(dirname, "type") == "directory"
end

--- Read the whole content of the given file into memory.
-- @param filename	String containing the path of the file to read
-- @return			String containing the file contents or nil on error
-- @return			String containing the error message on error
function readfile(filename)
	local fp, err = io.open(filename)

	if fp == nil then
		return nil, err
	end

	local data = fp:read("*a")
	fp:close()
	return data
end

--- Write the contents of given string to given file.
-- @param filename	String containing the path of the file to read
-- @param data		String containing the data to write
-- @return			Boolean containing true on success or nil on error
-- @return			String containing the error message on error
function writefile(filename, data)
	local fp, err = io.open(filename, "w")

	if fp == nil then
		return nil, err
	end

	fp:write(data)
	fp:close()

	return true
end

--- Copies a file.
-- @param source	Source file
-- @param dest		Destination
-- @return			Boolean containing true on success or nil on error
function copy(source, dest)
	return ltn12.pump.all(
		ltn12.source.file(io.open(source)),
		ltn12.sink.file(io.open(dest, "w"))
	)
end

--- Renames a file.
-- @param source	Source file
-- @param dest		Destination
-- @return			Boolean containing true on success or nil on error
function rename(source, dest)
	local stat, err, code = os.rename(source, dest)
	if code == 18 then
		stat, err, code = copy(source, dest)
		if stat then
			stat, err, code = unlink(source)
		end
	end
	return stat, err, code
end

--- Get the last modification time of given file path in Unix epoch format.
-- @param path	String containing the path of the file or directory to read
-- @return		Number containing the epoch time or nil on error
-- @return		String containing the error description (if any)
-- @return		Number containing the os specific errno (if any)
function mtime(path)
	return posix.stat(path, "mtime")
end

--- Set the last modification time  of given file path in Unix epoch format.
-- @param path	String containing the path of the file or directory to read
-- @param mtime	Last modification timestamp
-- @param atime Last accessed timestamp
-- @return		0 in case of success nil on error
-- @return		String containing the error description (if any)
-- @return		Number containing the os specific errno (if any)
utime = posix.utime

--- Return the last element - usually the filename - from the given path with
-- the directory component stripped.
-- @class		function
-- @name		basename
-- @param path	String containing the path to strip
-- @return		String containing the base name of given path
-- @see			dirname
basename = posix.basename

--- Return the directory component of the given path with the last element
-- stripped of.
-- @class		function
-- @name		dirname
-- @param path	String containing the path to strip
-- @return		String containing the directory component of given path
-- @see			basename
dirname = posix.dirname

--- Return a table containing all entries of the specified directory.
-- @class		function
-- @name		dir
-- @param path	String containing the path of the directory to scan
-- @return		Table containing file and directory entries or nil on error
-- @return		String containing the error description on error
-- @return		Number containing the os specific errno on error
dir = posix.dir

--- Create a new directory, recursively on demand.
-- @param path		String with the name or path of the directory to create
-- @param recursive	Create multiple directory levels (optional, default is true)
-- @return			Number with the return code, 0 on sucess or nil on error
-- @return			String containing the error description on error
-- @return			Number containing the os specific errno on error
function mkdir(path, recursive)
	if recursive then
		local base = "."

		if path:sub(1,1) == "/" then
			base = ""
			path = path:gsub("^/+","")
		end

		for elem in path:gmatch("([^/]+)/*") do
			base = base .. "/" .. elem

			local stat = posix.stat( base )

			if not stat then
				local stat, errmsg, errno = posix.mkdir( base )

				if type(stat) ~= "number" or stat ~= 0 then
					return stat, errmsg, errno
				end
			else
				if stat.type ~= "directory" then
					return nil, base .. ": File exists", 17
				end
			end
		end

		return 0
	else
		return posix.mkdir( path )
	end
end

--- Remove the given empty directory.
-- @class		function
-- @name		rmdir
-- @param path	String containing the path of the directory to remove
-- @return		Number with the return code, 0 on sucess or nil on error
-- @return		String containing the error description on error
-- @return		Number containing the os specific errno on error
rmdir = posix.rmdir

--- Get information about given file or directory.
-- @class		function
-- @name		stat
-- @param path	String containing the path of the directory to query
-- @return		Table containing file or directory properties or nil on error
-- @return		String containing the error description on error
-- @return		Number containing the os specific errno on error
stat = posix.stat

--- Set permissions on given file or directory.
-- @class		function
-- @name		chmod
-- @param path	String containing the path of the directory
-- @param perm	String containing the permissions to set ([ugoa][+-][rwx])
-- @return		Number with the return code, 0 on sucess or nil on error
-- @return		String containing the error description on error
-- @return		Number containing the os specific errno on error
chmod = posix.chmod

--- Create a hard- or symlink from given file (or directory) to specified target
-- file (or directory) path.
-- @class			function
-- @name			link
-- @param path1		String containing the source path to link
-- @param path2		String containing the destination path for the link
-- @param symlink	Boolean indicating wheather to create a symlink (optional)
-- @return			Number with the return code, 0 on sucess or nil on error
-- @return			String containing the error description on error
-- @return			Number containing the os specific errno on error
link = posix.link

--- Remove the given file.
-- @class		function
-- @name		unlink
-- @param path	String containing the path of the file to remove
-- @return		Number with the return code, 0 on sucess or nil on error
-- @return		String containing the error description on error
-- @return		Number containing the os specific errno on error
unlink = posix.unlink

--- Retrieve target of given symlink.
-- @class		function
-- @name		readlink
-- @param path	String containing the path of the symlink to read
-- @return		String containing the link target or nil on error
-- @return		String containing the error description on error
-- @return		Number containing the os specific errno on error
readlink = posix.readlink