lua_funcs.txt 14.7 KB
Newer Older
1 2 3 4 5
Lua injections
==============

We inject several functions into the lua global environment. Since
there's no good place to document them (like .h files for C code),
6
they are listed here.
7 8 9 10

Logging
-------

11
log(level, depth, msg, msg, msg, ...)::
12 13 14 15 16 17 18
  This is a low-level function used for logging. It should not be used
  directly by lua code. The messages are just strings that are
  concatenated together before outputting. The level is one of:
  - DIE
  - ERROR
  - WARN
  - DBG
Karel Koci's avatar
Karel Koci committed
19
  - TRACE
20 21 22 23
  The depth argument specifies how many functions on the top of the stack
  are to be disregarded when printing the source file, line number and
  function name to the logs. 0 means the function directly calling log,
  1 is its caller, etc.
24 25 26
ERROR(msg, msg, ...)::
WARN(msg, msg, ...)::
DBG(msg, msg, ...)::
Karel Koci's avatar
Karel Koci committed
27
TRACE(msg, msg, ...)::
28 29 30 31 32
  These output a message to the logs with a given level. The messages
  are concatenated together.
DIE(msg, msg, ...)::
  In addition to outputting the message on the ``DIE`` level, it also
  terminates the application with error exit code.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
update_state(state)::
  Dump the message for given state into `/tmp/update-state/state`.
  Allowed states are as follow:
  - `LS_INIT`: Initial state (`initialize`)
  - `LS_CONF`: Running configuration scripts (`configuration`)
  - `LS_PLAN`: Generating plan (`planning`)
  - `LS_DOWN`: Downloading needed packages (`downloading`)
  - `LS_PREUPD`: Running updater's preupdate hooks (`preupdate-hooks`)
  - `LS_UNPACK`: Unpacking downloaded packages (`unpacking`)
  - `LS_CHECK`: Checking for files collisions and more (`checking`)
  - `LS_INST`: Running preinst scripts and merging files to filesystem (`install`)
  - `LS_POST`: Running postinst scripts (`post-install`)
  - `LS_REM`: Removing leftover files (`removals`)
  - `LS_CLEANUP`: Cleaning up control files (`cleanup`)
  - `LS_POSTUPD`: Running updater's postupdate hooks (`postupdate-hooks`)
  - `LS_EXIT`: Updater exit (`exit`)
  - `LS_FAIL`: Detected failure, exiting. (`failure`)
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
Cleanup
-------

It's common to have code that requires cleanup. But ensuring that cleanup is
really called is tedious task. But thanks to atexit function and common DIE
function we can ensure that cleanup functions will be called. We defined function
to register, unregister and call cleanup function.

cleanup_register(function)::
  This registers given function as to be called when cleanup is requested.

cleanup_unregister(function)::
  This removes previously registered function from list of functions to be called
  for cleanup. This is done without calling given function.

cleanup_run(function)::
  This runs previously registered function and removes it from list of functions
  to be called for cleanup.

Note: This is for simplicity not implemented completely in C but lua functions
handlers is implemented in Lua it self. But we can't have that completely detached
as we have to ensure that order of cleanup holds even if Lua and C calls are mixed
together.

Following functions are defined for internal use of cleanup functionality only.
But they are not documented outside of the code usage so here they are:

cleanup_register_handle(index)::
  This function registers new cleanup for Lua. It expect index identifying this
  cleanup in global table of cleanup functions. It is used to register lua cleanup
  function handle to C cleanups. Exact Lua function is stored in Lua table and
  only index identifying given cleanup is passed to C.

cleanup_unregister_handle(index)::
  This function unregisters existing cleanup for Lua. It expect index identifying
  this cleanup in global table of cleanup functions. It reverse function or
  `cleanup_register_handle`.

89 90 91
Subprocesses
------------

92
Family of functions `subproc*` defined in `subprocess.h` are exported to lua
93
in form of functions `subprocess`.
94 95

Function `subprocess` is defined as follows:
96
`subprocess(type, message, timeout, callback, command ...)`
97

98
* `type` is identification used to specify what type of subprocess it's. Allowed
99
  predefined constants are as follows:
100 101
  - `LST_PKG_SCRIPT` Any script provided by package (pre/post inst/rm)
  - `LST_HOOK` Hook script executed on some updater state
102
  - `LST_USIGN` usign binary used for signature validation
103

104
* `message` is string describing what this subprocess is to user. It's human
105 106
  readable description of executed command.

107
* `timeout` is time in milliseconds after which subprocess will be automatically
108 109
  killed.

110 111 112
* `callback` is optional function that would be called in subprocess just before
  It executes given command. If you don't want to specify it then you can pass nil
  Or you can just drop it out (in that case command is expeted on this argument
113
  Place). This functions should have no arguments and shouldn't return anything.
114

115
* `command` is any arbitrary number of string arguments that are passed as command
116 117 118 119 120 121
  and its additional arguments.

This function returns exit code of executed subprocess as first argument. And
output of this process as second argument. (Output includes both stdout and
stderr).

122 123 124 125
Note::
  There is some problem with printing from lua to stdout in callback on some
  platforms.

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
Asynchronous events
-------------------

Some of the functions from ``events.h`` are exposed to lua code, with
minor modifications.

Currently, it is possible to run external commands with the
`run_command` function. The code would look like this:

  function terminated(exit_code, killed, stdout, stderr)
    -- The command terminated
  end

  function postfork()
    -- Run after fork in the child ‒ set up the environment
  end

  local id = run_command(terminated, postfork, input, term_timeout, kill_timeout, command, param, param)

  events_wait(id)

The functionality is very similar to the C functions, with these
differences:

* It doesn't take the `events` parameter, one global `events`
  structure per interpreter is used.
* The callbacks don't take the `data` or `wait_id` parameters, since
  lua has closures and passing information into the callbacks is easy.
* Lua naturally supports strings with embedded zero bytes, therefore
  there are no lengths of the inputs or outputs.
* The `exit_code` in the callback is not the raw integer from the
  system call, but decoded to the exit code of the process or signal
  number that terminated it.
* `killed` is a string, one of:
  - `TERMINATED`
  - `TERMED`
  - `KILLED`
  - `SIGNAL_OTHER`
* The events_wait take any number of ip parameters instead of an
  array.

The `postfork` and `input` parameters may be nil. The `term_timeout`
and `kill_timeout` take -1 to mean no timeout.

There may be any number of the `param` parameters, which are passed to
the command.

Currently, there's no way to cancel running command from lua, since
that would make the wrapper code needlessly complex (while there seems
to be no need to cancel them currently).
176

177 178 179 180 181 182 183
For calling standard shell utility, or in fact every busybox function,
`run_util` is provided. It is same as `run_command` except it accepts
as `command` parameter one of supported busybox function names. So you
pass for example `rm` instead of `/bin/rm`. This is preferred way of
calling them, because when busybox is embedded then we don't rely on
system utilities and so it should be more reliable.

184 185 186 187 188 189 190 191 192 193
The other event is `download`:

  function callback(status, content)
    if status == 200 then
      print("Downloaded: " .. content)
    else
      print("Download failed (" .. content .. ")")
    end
  end

194
  local id = download(callback, "https://example.org/file", "/path/to/cert", "/path/to/crl", true)
195 196 197 198 199 200

  events_wait(id)

The example is mostly self-explanatory and again, this acts very
similar to the C version.

201 202 203 204 205 206 207 208
Filesystem manipulation
-----------------------

mkdtemp([directory])::
  It creates a temporary directory. If directory is provided, it is
  created as a subdirectory of the given directory, otherwise it is
  created inside `/tmp`. It returns path to the new directory, or
  `nil` and an error message.
209 210 211 212 213 214

chdir(directory)::
  Change the current working directory to the one provided.

getcwd()::
  Get the current working directory.
215 216 217 218 219 220 221

mkdir(directory)::
  Create a directory. All the parent directories must already exist.
  The directory itself shall not exist. It throws on error.

move(old, new)::
  Move a file from the old location to the new. It tries to cope with
222
  paths on different devices.
223 224

ls(directory)::
225 226 227 228 229 230 231 232 233 234 235
  Return a table with file names under the given directory (acts like
  shell's `ls -a`, omitting the `.` and `..` entries). Value of
  each is the type of the file there, which may be:
  b;; A block device
  c;; A character device
  d;; A directory
  f;; A named pipe
  l;; A symbolic link
  r;; A regular file
  s;; A unix-domain socket
  ?;; Failed to determine the type
236

237
stat(path)::
238 239 240
  Statistics about the given file. If the file does not exist, it
  returns nothing. Otherwise, the file type is returned (see the types
  of `ls`). The second result is the permissions of the file, in the
241 242 243 244
  imitation of shell's `ls -l`, like `rwxr-x---`.

lstat(path)::
  Same as `stat` except the `lstat` behaviour is preferred.
245 246
  (eg. provides info about symbolic link if it is a link, instead of
  the target).
247

248 249 250 251
sync()::
  Writes everything to a permanent storage (equivalent to the shell's
  `sync` command).

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
252 253 254 255 256 257 258
locks.acquire(path)::
  Lock a file with the `lockf` call. Fail if the lock is already held
  by other process. Create the file as needed. Return a lock object as
  a result. It has release() method, to release the lock. The lock is
  also released when the object is garbage collected, but there's no
  guarantee how soon it may be.

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
Journal manipulation
--------------------

All the journal manipulation is located in the `journal` module. This
is about the lua interface. For the on-disk format, look at the
`journal` document.

The location of the journal can be set by the `path` variable inside
the module (it exists mostly for testing purposes).

There are several constants for the journal record types:

 `START`:: Automatically inserted at the beginning of journal.
 `FINISH`:: Automatically inserted when the journal is closed.
 `UNPACKED`:: Packages are unpacked and ready to be installed.
 `CHECKED`:: Pre-installation checks (like collision checks) are
   successfully performed.
 `MOVED`:: The files are moved into place.
 `SCRIPTS`:: All the post/pre-* scripts were run.
 `CLEANED`:: Cleanup of temporary files is successful.

There are following functions:

  fresh():: Open a new journal. It fails if there's a journal file
    already.
  recover():: Open a previous journal. It returns table with the
285
    content of the journal. If there is no journal nil is returned.
286 287 288 289 290 291 292 293 294 295 296 297 298 299
  finish([keep]):: Close the journal. If the keep is set to true,
    it keeps the journal in place, otherwise it is deleted. The idea
    is that the application would close the journal when it succeeds,
    but would leave it there in case of interrupted operation, so
    usually nothing is set, the flag is for testing purposes.
  write(type, ...):: Write a journal record of the given type (see
    above). Any other parameters are stored as parameters. Data
    structures must not contain meta tables and functions.
  opened():: Returns if the journal is opened. This is for testing
    purposes.

The format of journal returned by recover is a table with records.
Each record contains `type` ‒ one of the types above, and `params` ‒
table with all the parameters stored with the record.
300

Karel Koci's avatar
Karel Koci committed
301
Picosat
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
-------

Picosat can be used trough module `picosat`. Here is briefly described
its interface as it can be used from Lua. For more information about
usage see Picosat documentation in its source file.

You can create picosat instance by calling `picosat.new` function.
It returns object with following methods:

  var(count):: Creates given number of new variables and returns them.
    If no argument is given, it returns one new variable.
  clause(var, ...):: Adds clause. Arguments `var` are variables
    previously created with `var` method. Appending minus before variable
    adds boolean negation.
  assume(var):: Adds assumption about value `val` for next satisfiable
    check. Appending minus before `var` assumes false, not appending it
    assumes true.
  satisfiable():: Checks if clauses are satisfiable with given
    assumptions. Returns true or false accordingly.
  max_satisfiable():: Generates maximal satisfiable subset of assumptions.
322 323 324
    Can be called only after `satisfiable`. Returns set of all assumptions
    that can be assumed at the same time. Note that this reassumes previous
    assumptions, so they are again valid for next `satisfiable` call.
325 326 327 328 329 330

After calling `satisfiable` you can access assigned values by indexing
object with variable you are interested in. It returns true or false.
It can also return nil if variable was added after `satisfiable` method
call.

Karel Koci's avatar
Karel Koci committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
PkgSorter
---------

This is module implementing tree sorting algorithm with priorities.

TODO document what priority for node and for edge means

You can create new instance by calling `pkgsorter.new` function.
It returns object with following methods:

  node(name, priority):: Create new node with given priority.
  edge(priority, from, to, reverse):: Add edge between two nodes.
    Note that if you have edge from low priority node to higher priority
    one then priority of such node is increased to be the same.
  prune():: Prune edges forming cycles and return report about it.
    TODO
  isnode(name):: Check if we have node of given name.
  iterator(root):: Returns iterator to go trough resulting order. You
    have to call it after `prune` is called. As optional argument you
    can specify root then instead of looking for all roots only given
    one is expanded and iterated trough.

353 354 355 356 357 358 359 360 361 362 363 364
Others
------

There are some other functions.

DataDumper(variable)::
  A function that converts (almost any) variable to a string
  containing a lua chunk. The chunk, when run, returns equivalent
  value as passed. Simply stated, this serializes data into lua code.
  It is a third-party code from
  `http://lua-users.org/wiki/DataDumper`. Note that some data
  (userdata, for example) can't be represented this way.
365 366 367 368

setenv(name, value)::
  Set the environment variable with the given name to the given value.
  Errors in case of failure, otherwise returns nothing.
369

370
reexec(args,...)::
371 372 373
  Try to run the program from the beginning, preserving the command
  line arguments and working directory. It depends on being set up
  properly at the start of the program.
374 375
  As arguments you can specify additional arguments that will be appended
  at the end of original ones.
376 377 378 379 380

uri_internal_get(name)::
  Function to access embedded files using `internal:` uri. Argument `name`
  is name of requested embedded file. Returns file content. If there is
  no file under given name, error is raised.
381 382 383 384

system_reboot(stick)::
  Reboots system. Argument `stick` if set to true results in that this
  newer returns.
385 386 387

get_updater_version()::
  Returns string containing updater's version.