# Lua/APR binding documentation

The Lua/APR binding aims to bring most of the functionality in the Apache Portable Runtime (APR) to the small and flexible programming language Lua. This document contains the documentation for the Lua/APR binding. Some notes about this documentation:

- Most of the documentation is based on the official APR documentation but I've had to consult the APR source code here and there when the official documentation didn’t suffice. If anything seems amiss please let me know.

- The entries for all functions are automatically generated from the C and Lua source code of the binding to prevent that documentation and implementation become out of sync.

This document was generated from the Lua/APR 0.17 source code.

## Table of contents

Base64 encoding
  - apr.base64_encode()
  - apr.base64_decode()
Cryptography routines
  - apr.md5_encode()
  - apr.password_validate()
  - apr.password_get()
  - apr.md5_init()
  - md5_context:update()
  - md5_context:digest()
  - md5_context:reset()
  - apr.sha1_init()
  - sha1_context:update()
  - sha1_context:digest()
  - sha1_context:reset()
  - apr.md5()
  - apr.sha1()
Date parsing
  - apr.date_parse_http()
  - apr.date_parse_rfc()
Relational database drivers
  - apr.dbd()
  - driver:open()
  - driver:dbname()
  - driver:driver()
  - driver:check()
  - driver:query()
  - driver:select()
  - driver:transaction_start()
  - driver:transaction_end()
  - driver:transaction_mode()
  - driver:prepare()
  - prepared_statement:query()
  - prepared_statement:select()
  - result_set:columns()
  - result_set:row()
  - result_set:rows()
  - result_set:tuple()
  - result_set:tuples()
  - result_set:pairs()
  - #result_set
  - driver:close()
DBM routines
  - apr.dbm_open()
  - apr.dbm_getnames()
  - dbm:exists()
  - dbm:fetch()
  - dbm:store()
  - dbm:delete()
  - dbm:firstkey()
  - dbm:nextkey()
  - dbm:close()
Environment manipulation
  - apr.env_get()
  - apr.env_set()
  - apr.env_delete()
File path manipulation
  - apr.filepath_root()
  - apr.filepath_parent()
  - apr.filepath_name()
  - apr.filepath_merge()
  - apr.filepath_list_split()
  - apr.filepath_list_merge()
  - apr.filepath_get()
  - apr.filepath_set()
  - apr.filepath_which()
Filename matching
  - apr.fnmatch()
  - apr.fnmatch_test()
  - apr.glob()
Directory manipulation
  - apr.temp_dir_get()
  - apr.dir_make()
  - apr.dir_make_recursive()
  - apr.dir_remove()
  - apr.dir_remove_recursive()
  - apr.dir_open()
  - directory:read()
  - directory:rewind()
  - directory:entries()
  - directory:close()
File I/O handling
  - apr.file_link()
  - apr.file_copy()
  - apr.file_append()
  - apr.file_rename()
  - apr.file_remove()
  - apr.file_mtime_set()
  - apr.file_attrs_set()
  - apr.file_perms_set()
  - apr.stat()
  - apr.file_open()
  - file:stat()
  - file:lines()
  - file:read()
  - file:write()
  - file:seek()
  - file:flush()
  - file:lock()
  - file:unlock()
  - pipe:timeout_get()
  - pipe:timeout_set()
  - file:inherit_set()
  - file:inherit_unset()
  - file:close()
Network I/O handling
  - apr.socket_create()
  - apr.hostname_get()
  - apr.host_to_addr()
  - apr.addr_to_host()
  - socket:connect()
  - socket:bind()
  - socket:listen()
  - socket:accept()
  - socket:read()
  - socket:write()
  - socket:lines()
  - socket:timeout_get()
  - socket:timeout_set()
  - socket:opt_get()
  - socket:opt_set()
  - socket:addr_get()
  - socket:shutdown()
  - socket:close()
Pipe I/O handling
  - apr.pipe_open_stdin()
  - apr.pipe_open_stdout()
  - apr.pipe_open_stderr()
  - apr.namedpipe_create()
  - apr.pipe_create()
Memcached client
  - apr.memcache()
  - mc_client:hash()
  - mc_client:find_server_hash()
  - mc_client:add_server()
  - mc_client:find_server()
  - mc_client:enable_server()
  - mc_client:disable_server()
  - mc_client:get()
  - mc_client:set()
  - mc_client:add()
  - mc_client:replace()
  - mc_client:delete()
  - mc_client:incr()
  - mc_client:decr()
  - mc_client:version()
  - mc_client:stats()
Command argument parsing
  - apr.getopt()
HTTP request parsing
  - apr.parse_headers()
  - apr.parse_multipart()
  - apr.parse_cookie_header()
  - apr.parse_query_string()
  - apr.header_attribute()
  - apr.uri_encode()
  - apr.uri_decode()
Process handling
  - apr.proc_create()
  - apr.proc_detach()
  - apr.proc_fork()
  - process:addrspace_set()
  - process:user_set()
  - process:group_set()
  - process:cmdtype_set()
  - process:env_set()
  - process:dir_set()
  - process:detach_set()
  - process:error_check_set()
  - process:io_set()
  - process:in_set()
  - process:out_set()
  - process:err_set()
  - process:in_get()
  - process:out_get()
  - process:err_get()
  - process:exec()
  - process:wait()
  - process:kill()
Shared memory
  - apr.shm_create()
  - apr.shm_attach()
  - apr.shm_remove()
  - shm:read()
  - shm:write()
  - shm:seek()
  - shm:detach()
  - shm:destroy()
String routines
  - apr.strnatcmp()
  - apr.strnatcasecmp()
  - apr.strfsize()
  - apr.tokenize_to_argv()
Multi threading
  - apr.thread_create()
  - apr.thread_yield()
  - thread:detach()
  - thread:join()
  - thread:status()
Thread queues
  - apr.thread_queue()
  - queue:push()
  - queue:pop()
  - queue:trypush()
  - queue:trypop()
  - queue:close()
Time routines
  - apr.sleep()
  - apr.time_now()
  - apr.time_explode()
  - apr.time_implode()
  - apr.time_format()
Uniform resource identifier parsing
  - apr.uri_parse()
  - apr.uri_unparse()
  - apr.uri_port_of_scheme()
User/group identification
  - apr.user_get()
  - apr.user_homepath_get()
Universally unique identifiers
  - apr.uuid_get()
  - apr.uuid_format()
  - apr.uuid_parse()
Character encoding translation
  - apr.xlate()
XML parsing
  - apr.xml()
  - xml_parser:feed()
  - xml_parser:done()
  - xml_parser:geterror()
  - xml_parser:getinfo()
  - xml_parser:close()
Miscellaneous functions
  - apr.platform_get()
  - apr.version_get()
  - apr.os_default_encoding()
  - apr.os_locale_encoding()
  - apr.type()
Miscellaneous sections
  - File system permissions
  - Error handling
  - Example: HTTP client
  - Example: Single threaded webserver
  - Example: Multi threaded webserver

## Base64 encoding

The functions in this module can be used to encode strings in base64 and to decode base64 encoded strings. The base64 format uses the printable characters `A-Z`, `a-z`, `0-9`, `+` and `/` to encode binary data. This can be useful when your data is used in a context that isn’t 8-bit clean, for example in e-mail attachments and data: URLs. You can read more about base64 encoding in this Wikipedia article.

### test coverage: 91%
`apr.base64_encode(plain) → coded`

Encode the string `plain` using base64 encoding. On success the coded string is returned, otherwise a `nil` followed by an error message is returned. As an example, here is how to convert an image file into a data: URL:

    > image = io.open 'lua-logo.png'
    > encoded_data = apr.base64_encode(image:read '*a')
    > data_url = 'data:image/png;base64,' .. encoded_data
    > = '<img src="' .. url .. '" width=16 height=16 alt="Lua logo">'
    <img src="data:image/png;base64, " width=16 height=16 alt="Lua logo">

This is what the result looks like (might not work in older web browsers):

This function is binary safe.

### test coverage: 83%
`apr.base64_decode(coded) → plain`

Decode the base64 encoded string `coded`. On success the decoded string is returned, otherwise a `nil` followed by an error message is returned.

This function is binary safe.

## Cryptography routines

These functions support the MD5 and SHA1 cryptographic hash functions. You can also use them to encrypt plain text passwords using a salt, validate plain text passwords against their encrypted, salted digest and read passwords from standard input while masking the characters typed by the user.

The MD5 and SHA1 functions can be used to hash binary data. This is useful because the hash is only 16 or 32 bytes long, yet it still changes significantly when the binary data changes by just one byte.

If that doesn’t look useful consider the following scenario: The Lua authors have just finished a new release of Lua and are about to publish the source code on http://lua.org. Before they publish the tarball they first calculate its MD5 and SHA1 hashes. They then publish the archive and hashes on the downloads page. When a user downloads the tarball they can verify whether it was corrupted or manipulated since it was published on http://lua.org by comparing the published hash against the hash of the tarball they just downloaded:

    > handle = io.open('lua-5.1.4.tar.gz', 'rb')
    > data = handle:read('*a'); handle:close()
    > = apr.md5(data) == 'd0870f2de55d59c1c8419f36e8fac150'
    true
    > = apr.sha1(data) == '2b11c8e60306efb7f0734b747588f57995493db7'
    true

### `apr.md5(input [, binary]) → digest`

Calculate the MD5 message digest of the string `input`. On success the digest is returned as a string of 32 hexadecimal characters, or a string of 16 bytes if `binary` evaluates to `true`. Otherwise a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 90%
`apr.md5_encode(password, salt) → digest`

Encode the string `password` using the MD5 algorithm and a salt string. On success the digest is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`apr.password_validate(password, digest) → valid`

Validate the string `password` against a `digest` created by one of the APR-supported algorithms (MD5 and SHA1). On success `true` is returned, otherwise a `nil` followed by an error message is returned.

Hashes created by crypt are supported only on platforms that provide crypt(3), so don’t rely on that function unless you know that your application will be run only on platforms that support it. On platforms that don’t support crypt(3), this falls back to a clear text string comparison.

This function is not binary safe.

### test coverage: none
`apr.password_get(prompt) → password`

Display the string `prompt` on the command-line prompt and read in a password from standard input. If your platform allows it, the typed password will be masked by a placeholder like `*`. On success the password is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 75%
`apr.md5_init() → md5_context`

Create and return an object that can be used to calculate MD5 message digests in steps. If an error occurs a `nil` followed by an error message is returned. This can be useful when you want to calculate message digests of large inputs, for example files like ISO images and backups:

    > function md5_file(path, binary)
    >>  local handle = assert(io.open(path, 'rb'))
    >>  local context = assert(apr.md5_init())
    >>  while true do
    >>    local block = handle:read(1024 * 1024)
    >>    if not block then break end
    >>    assert(context:update(block))
    >>  end
    >>  return context:digest(binary)
    >> end
    >
    > md5_file 'ubuntu-10.04-desktop-i386.iso'
    'd044a2a0c8103fc3e5b7e18b0f7de1c8'

### `md5_context:update(input) → status`

Continue an MD5 message digest operation by processing another message block and updating the context. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is binary safe.

### `md5_context:digest([binary]) → digest`

End an MD5 message digest operation. On success the digest is returned as a string of 32 hexadecimal characters, or a string of 16 bytes if `binary` evaluates to `true`. Otherwise a `nil` followed by an error message is returned.

If you want to re-use the context object after calling this method see md5_context:reset().

### `md5_context:reset() → status`

Use this method to reset the context after calling md5_context:digest(). This enables you to re-use the same context to perform another message digest calculation. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### `apr.sha1(input [, binary]) → digest`

Calculate the SHA1 message digest of the string `input`. On success the digest is returned as a string of 40 hexadecimal characters, or a string of 20 bytes if `binary` evaluates to `true`. Otherwise a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 83%
`apr.sha1_init() → sha1_context`

Create and return an object that can be used to calculate SHA1 message digests in steps. See also the example for apr.md5_init().

### `sha1_context:update(input) → status`

Continue an SHA1 message digest operation by processing another message block and updating the context.

This function is binary safe.

### `sha1_context:digest([binary]) → digest`

End an SHA1 message digest operation. On success the digest is returned as a string of 40 hexadecimal characters, or a string of 20 bytes if `binary` evaluates to `true`. Otherwise a `nil` followed by an error message is returned.

If you want to re-use the context object after calling this method see sha1_context:reset().

### `sha1_context:reset() → status`

Use this method to reset the context after calling sha1_context:digest(). This enables you to re-use the same context to perform another message digest calculation.

## Date parsing

### test coverage: 85%
`apr.date_parse_http(string) → time`

Parses an HTTP date in one of three standard forms:

- `'Sun, 06 Nov 1994 08:49:37 GMT'` – RFC 822, updated by RFC 1123
- `'Sunday, 06-Nov-94 08:49:37 GMT'` – RFC 850, obsoleted by RFC 1036
- `'Sun Nov 6 08:49:37 1994'` – ANSI C’s asctime() format

On success the date is returned as a number like documented under time routines. If the date string is out of range or invalid `nil` is returned.

This function is not binary safe.

### test coverage: 85%
`apr.date_parse_rfc(string) → time`

Parses a string resembling an RFC 822 date. This is meant to be lenient in its parsing of dates and hence will parse a wider range of dates than apr.date_parse_http().

The prominent mailer (or poster, if mailer is unknown) that has been seen in the wild is included for the unknown formats:

- `'Sun, 06 Nov 1994 08:49:37 GMT'` – RFC 822, updated by RFC 1123
- `'Sunday, 06-Nov-94 08:49:37 GMT'` – RFC 850, obsoleted by RFC 1036
- `'Sun Nov 6 08:49:37 1994'` – ANSI C’s asctime() format
- `'Sun, 6 Nov 1994 08:49:37 GMT'` – RFC 822, updated by RFC 1123
- `'Sun, 06 Nov 94 08:49:37 GMT'` – RFC 822
- `'Sun, 6 Nov 94 08:49:37 GMT'` – RFC 822
- `'Sun, 06 Nov 94 08:49 GMT'` – Unknown [drtr@ast.cam.ac.uk]
- `'Sun, 6 Nov 94 08:49 GMT'` – Unknown [drtr@ast.cam.ac.uk]
- `'Sun, 06 Nov 94 8:49:37 GMT'` – Unknown [Elm 70.85]
- `'Sun, 6 Nov 94 8:49:37 GMT'` – Unknown [Elm 70.85]

On success the date is returned as a number like documented under time routines. If the date string is out of range or invalid `nil` is returned.

This function is not binary safe.

## Relational database drivers

The APR DBD module makes it possible to query relational database engines like SQLite, MySQL, PostgreSQL, Oracle, ODBC and FreeTDS. This module currently has some drawbacks which appear to be unavoidable given the design of the Apache Portable Runtime DBD framework:

- Booleans and numbers are returned as strings because result set types are not known to the Lua/APR binding (and type guessing is too error prone)

- String arguments and results are not binary safe, this means they will be truncated at the first zero byte (see the apr-dev mailing list thread “current dbd initiatives” for discussion about this limitation of APR)

Note that if you control the data going into the database you can overcome the second limitation by using APR’s built in support for Base64 encoding.

### Installing drivers

On Debian/Ubuntu Linux you can install one or more of the following packages to enable support for the corresponding database driver (dependencies will be installed automatically by the package management system):

- libaprutil1-dbd-sqlite3
- libaprutil1-dbd-mysql
- libaprutil1-dbd-pgsql
- libaprutil1-dbd-odbc
- libaprutil1-dbd-freetds

### Debugging “DSO load failed” errors

In my initial tests on Ubuntu I installed libaprutil1-dbd-sqlite3 but kept getting an error when trying to load the driver:

    $ lua -e "print(require('apr').dbd('sqlite3'))"
    nil  DSO load failed  EDSOOPEN

After a while I found the problem using LD_DEBUG:

    $ LD_DEBUG=libs lua -e "require('apr').dbd('sqlite3')" 2>&1 | grep undefined
    /usr/lib/apr-util-1/apr_dbd_sqlite3-1.so: error: symbol lookup error: undefined symbol: apr_pool_cleanup_null (fatal)

Having identified the problem, finding a workaround was easy:

    $ export LD_PRELOAD='/usr/lib/libapr-1.so.0:/usr/lib/libaprutil-1.so.0'
    $ lua -e "print(require('apr').dbd('sqlite3'))"
    database driver (0x853bdfc)

### test coverage: 77%
`apr.dbd(name) → driver`

Create a database driver object. The string `name` decides which database engine to use. On success the driver object is returned, otherwise a `nil` followed by an error message is returned. Currently supported engines include:

- `'mysql'`
- `'pgsql'`
- `'sqlite3'`
- `'sqlite2'`
- `'oracle'`
- `'freetds'`
- `'odbc'`

Note that in its default configuration the Apache Portable Runtime uses dynamic loading to load database drivers which means apr.dbd() can fail because a driver can’t be loaded.

### test coverage: 50%
`driver:open(params) → status`

Open a connection to a backend. The string `params` contains the arguments to the driver (implementation-dependent). On success `true` is returned, otherwise a `nil` followed by an error message is returned. The syntax of `params` is as follows:

- PostgreSQL: `params` is passed directly to the PQconnectdb() function, check the PostgreSQL documentation for more details on the syntax

- SQLite2: `params` is split on a colon, with the first part used as the filename and the second part converted to an integer and used as the file mode

- SQLite3: `params` is passed directly to the sqlite3_open() function as a filename to be opened, check the SQLite3 documentation for more details (hint: if `params` is `':memory:'` a private, temporary in-memory database is created for the connection)

- Oracle: `params` can have ‘user’, ‘pass’, ‘dbname’ and ‘server’ keys, each followed by an equal sign and a value. Such key/value pairs can be delimited by space, CR, LF, tab, semicolon, vertical bar or comma

- MySQL: `params` can have ‘host’, ‘port’, ‘user’, ‘pass’, ‘dbname’, ‘sock’, ‘flags’ ‘fldsz’, ‘group’ and ‘reconnect’ keys, each followed by an equal sign and a value. Such key/value pairs can be delimited by space, CR, LF, tab, semicolon, vertical bar or comma. For now, ‘flags’ can only recognize `CLIENT_FOUND_ROWS` (check MySQL manual for details). The value associated with ‘fldsz’ determines maximum amount of memory (in bytes) for each of the fields in the result set of prepared statements. By default, this value is 1 MB. The value associated with ‘group’ determines which group from configuration file to use (see `MYSQL_READ_DEFAULT_GROUP` option of mysql_options() in MySQL manual). Reconnect is set to 1 by default (i.e. `true`)

- FreeTDS: `params` can have ‘username’, ‘password’, ‘appname’, ‘dbname’, ‘host’, ‘charset’, ‘lang’ and ‘server’ keys, each followed by an equal sign and a value

This function is not binary safe.

### test coverage: 100%
`driver:dbname(name) → status`

Select the database `name`. On succes `true` is returned, otherwise a `nil` followed by an error message is returned. Not supported for all drivers (e.g. SQLite by definition only knows a single database).

This function is not binary safe.

### test coverage: 100%
`driver:driver() → name`

Get the name of the database driver. Returns one of the strings listed for apr.dbd().

### `driver:check() → status`

Check the status of the database connection. When the connection is still alive `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`driver:query(sql) → status, affected_rows`

Execute an SQL query that doesn’t return a result set. On success `true` followed by the number of affected rows is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 88%
`driver:select(sql [, random_access]) → result_set`

Execute an SQL query that returns a result set. On success a result set object is returned, otherwise a `nil` followed by an error message is returned. To enable support for random access you can pass the optional argument `random_access` as `true`.

This function is not binary safe.

### test coverage: 100%
`driver:transaction_start() → status`

Start a transaction. May be a no-op. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

Note that transaction modes, set by calling driver:transaction_mode(), will affect all query/select calls within a transaction. By default, any error in query/select during a transaction will cause the transaction to inherit the error code and any further query/select calls will fail immediately. Put transaction in `'ignore-errors'` mode to avoid that. Use `'rollback'` mode to do explicit rollback.

### test coverage: 100%
`driver:transaction_end() → status`

End a transaction (commit on success, rollback on error). May be a no-op. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 84%
`driver:transaction_mode([mode]) → mode`

Get or set the transaction mode, one of:

- `'commit'`: commit the transaction
- `'rollback'`: rollback the transaction
- `'ignore-errors'`: ignore transaction errors

On success the new transaction mode is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 87%
`driver:prepare(sql) → prepared_statement`

Prepare a statement. On success a prepared statement object is returned, otherwise a `nil` followed by an error message is returned.

To specify parameters of the prepared query, use `%s`, `%d` etc. (see below for full list) in place of database specific parameter syntax (e.g. for PostgreSQL, this would be `$1`, `$2`, for SQLite3 this would be `?`, etc.). For instance: `SELECT name FROM customers WHERE name = %s` would be a query that this function understands. Here is the list of supported format specifiers and what they map to in SQL (generally you'll only need the types marked in bold text):

- `%hhd`: TINY INT
- `%hhu`: UNSIGNED TINY INT
- `%hd`: SHORT
- `%hu`: UNSIGNED SHORT
- `%d`: INT
- `%u`: UNSIGNED INT
- `%ld`: LONG
- `%lu`: UNSIGNED LONG
- `%lld`: LONG LONG
- `%llu`: UNSIGNED LONG LONG
- `%f`: FLOAT, REAL
- `%lf`: DOUBLE PRECISION
- `%s`: VARCHAR
- `%pDt`: TEXT
- `%pDi`: TIME
- `%pDd`: DATE
- `%pDa`: DATETIME
- `%pDs`: TIMESTAMP
- `%pDz`: TIMESTAMP WITH TIME ZONE
- `%pDn`: NULL

This function is not binary safe.

### test coverage: 100%
`prepared_statement:query(...) → status`

Using a prepared statement, execute an SQL query that doesn’t return a result set. On success `true` followed by the number of affected rows is returned, otherwise a `nil` followed by an error message is returned.

If you pass a list then the values in the list become query parameters, otherwise all function arguments become query parameters.

This function is not binary safe.

### test coverage: 90%
`prepared_statement:select(random_access, ...) → result_set`

Using a prepared statement, execute an SQL query that returns a result set. On success a result set object is returned, otherwise a `nil` followed by an error message is returned. To enable support for random access pass `random_access` as `true`, otherwise pass it as `false`.

If you pass a list then the values in the list become query parameters, otherwise all function arguments after `random_access` become query parameters.

TODO Make the `random_access` argument an attribute of the prepared statement object so that we can get rid of the argument here?!

This function is not binary safe.

### test coverage: 100%
`result_set:columns([num]) → name [, ...]`

If no arguments are given return the names of all columns in the result set, otherwise return the name of the column with index `num` (counting from one). For example:

    > driver = assert(apr.dbd 'sqlite3')
    > assert(driver:open ':memory:')
    > results = assert(driver:select [[ SELECT 1 AS col1, 2 AS col2 ]])
    > = assert(results:columns())
    { 'col1', 'col2' }

This function is not binary safe.

### test coverage: 100%
`result_set:row(num) → row`

Return a table with named fields for the next row in the result set or the row with index `rownum` if given. When there are no more rows nothing is returned, in case of an error a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`result_set:rows() → iterator`

Return an iterator that produces a table with named fields for each (remaining) row in the result set.

In Lua 5.2 you can also use `pairs(result_set)`.

This function is not binary safe.

### test coverage: 100%
`result_set:tuple([rownum]) → value [, ...]`

Return a tuple for the next row in the result set or the row with index `rownum` if given. If more than one value is returned, the return values will be in the same order as the column list in the SQL query. When there are no more rows nothing is returned, in case of an error a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`result_set:tuples() → iterator`

Return an iterator that produces a tuple for each (remaining) row in the result set. The tuples produced by the iterator are in the same order as the column list in the SQL query, for example:

    > driver = assert(apr.dbd 'sqlite3')
    > assert(driver:open 'quotes.sqlite3')
    > results = assert(driver:select [[ SELECT author, quote FROM quotes ]])
    > for author, quote in results:tuples() do
    >>  print(author, 'wrote:')
    >>  print(quote)
    >>  print()
    >> end

This function is not binary safe.

### test coverage: 100%
`result_set:pairs() → iterator`

Return an iterator that produces a row number and a table with named fields for each (remaining) row in the result set.

In Lua 5.2 you can also use `ipairs(result_set)`.

This function is not binary safe.

### test coverage: 100%
`#result_set → num_tuples`

Get the number of rows in a result set of a synchronous select. If the results are asynchronous -1 is returned.

### test coverage: 100%
`driver:close() → status`

Close a connection to a backend.

## DBM routines

This module enables the creation and manipulation of dbm databases. If you've never heard of dbm before you can think of it as a Lua table that only supports string keys and values but is backed by a file, so that you can stop and restart your application and find the exact same contents. This module supports the following libraries/implementations:

- `'db'` for Berkeley DB files
- `'gdbm'` for GDBM files
- `'ndbm'` for NDBM files
- `'sdbm'` for SDBM files (the default)

The SDBM format is the default database format for Lua/APR because APR has built-in support for SDBM while the other libraries need to be separately installed. This is why not all types may be available at run time.

### test coverage: 87%
`apr.dbm_open(path [, mode [, permissions [, type ]]]) → dbm object`

Open a dbm file by `path`. On success a database object is returned, otherwise a `nil` followed by an error message is returned. The following `mode` strings are supported:

- `'r'` to open an existing database for reading only (this is the default)
- `'w'` to open an existing database for reading and writing
- `'c'` to open a database for reading and writing, creating it if it doesn’t exist
- `'n'` to open a database for reading and writing, truncating it if it already exists

The permissions string is documented elsewhere. Valid values for `type` are listed in the introductory text for this module. Also note that the `path` string may not be a real file name, as many dbm packages append suffixes for separate data and index files (see also apr.dbm_getnames()).

This function is not binary safe.

### test coverage: 84%
`apr.dbm_getnames(path [, type]) → used1 [, used2]`

If the specified `path` were passed to apr.dbm_open(), return the actual pathnames which would be (created and) used. At most, two files may be used; `used2` is `nil` if only one file is used. The dbm file(s) don’t need to exist because this function only manipulates the pathnames. Valid values for `type` are listed in the introductory text for this module.

This function is not binary safe.

### test coverage: 100%
`dbm:exists(key) → status`

Check whether the dbm record with the given string `key` exists.

This function is binary safe.

### test coverage: 90%
`dbm:fetch(key) → value`

Fetch the dbm record with the given string `key`. On success the fetched value is returned as a string, if the key doesn’t exist nothing is returned and on error a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 100%
`dbm:store(key, value) → status`

Store the dbm record `value` (a string) by the given string `key`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 100%
`dbm:delete(key) → status`

Delete the dbm record with the given string `key`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 88%
`dbm:firstkey() → key`

Retrieve the first record key from a dbm. On success the first key is returned as a string, when there are no keys nothing is returned. In case of error a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 70%
`dbm:nextkey(key1) → key2`

Retrieve the next record key from a dbm. This function works just like Lua’s next() function: On success the next key is returned as a string, when there are no more keys nothing is returned. In case of error a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 100%
`dbm:close() → status`

Close a dbm database handle and return `true` (this can’t fail).

## Environment manipulation

Operating systems organize tasks into processes. One of the simplest means of communication between processes is the use of environment variables. If you're not familiar with environment variables, picture every process on your computer having an associated Lua table with string key/value pairs. When a process creates or overwrites a key/value pair only the table of that process changes. When the process spawns a child process the child gets a copy of the table which from that point onwards is no longer associated with the parent process.

### test coverage: 90%
`apr.env_get(name) → value`

Get the value of the environment variable `name`. On success the string value is returned. If the variable does not exist nothing is returned. Otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`apr.env_set(name, value) → status`

Set the value of the environment variable `name` to the string `value`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`apr.env_delete(name) → status`

Delete the environment variable `name`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

## File path manipulation

### test coverage: 90%
`apr.filepath_root(path [, option, ...]) → root, path`

Extract the root from the file path `path`. On success the extracted root and the relative path following the root are returned, otherwise a `nil` followed by an error message is returned. Either or both of the following options may be given after `path`:

- `'true-name'` verifies that the root exists and resolves its `true` case. If the root does not exist, a `nil` followed by an error message is returned
- `'native'` uses the file system’s native path format (e.g. path delimiters of `:` on MacOS9, `\` on Win32, etc.) in the resulting root

These options only influence the resulting root. The path after the root is returned as is. If you want to convert a whole file path to its `true` case and/or native format use apr.filepath_merge() instead.

This function is not binary safe.

### test coverage: 80%
`apr.filepath_parent(path [, option, ...]) → parent, filename`

Split the file path `path` into its parent path and filename. This function supports the same options as apr.filepath_root(). If any options are given they're applied to `path` before it is split, so the options influence both of the resulting values. If `path` is a filename and the `'true-name'` option isn’t given then the returned parent path will be an empty string.

This function is not binary safe.

### test coverage: 100%
`apr.filepath_name(path [, split]) → filename [, extension]`

Extract the filename (the final element) from the file path `path`. If `split` evaluates `true` then the extension will be split from the filename and returned separately. Some examples of what is considered a filename or an extension:

    > -- regular file path
    > = apr.filepath_name('/usr/bin/lua', true)
    'lua', ''

    > -- hidden file on UNIX
    > = apr.filepath_name('/home/xolox/.vimrc', true)
    '.vimrc', ''

    > -- multiple extensions
    > = apr.filepath_name('index.html.en', true)
    'index.html', '.en'

This function is not binary safe.

### test coverage: 86%
`apr.filepath_merge(root, path [, option, ...]) → merged`

Merge the file paths `root` and `path`. On success the merged file path is returned, otherwise a `nil` followed by an error message is returned. Any combination of one or more of the following options may be given:

- `'true-name'` resolves the `true` case of existing elements in `path`, resolving any aliases on Windows, and appends a trailing slash if the final element is a directory
- `'native'` uses the file system’s native path format (e.g. path delimiters of `:` on MacOS9, `\` on Win32, etc.)
- `'not-above-root'` fails if `path` is above `root`, e.g. if `root` is `/foo/bar` and `path` is `../baz`
- `'not-absolute'` fails if the merged path is absolute
- `'not-relative'` fails if the merged path is relative
- `'secure-root'` fails if `path` is above `root`, even given the `root` `/foo/bar` and the `path` `../bar/bash`

This function can be used to generate absolute file paths as follows:

    apr.filepath_merge('.', 'filepath.c', 'not-relative')
    -- the above is equivalent to the below:
    apr.filepath_merge(apr.filepath_get(), 'filepath.c', 'not-relative')

This function is not binary safe.

### test coverage: 90%
`apr.filepath_list_split(searchpath) → components`

Split a search path string into a table of separate components. On success the table of components is returned, otherwise a `nil` followed by an error message is returned. Empty elements do not become part of the returned table.

An example of a search path is the $PATH environment variable available in UNIX and Windows operating systems which controls the way program names are resolved to absolute pathnames (see apr.filepath_which()).

This function is not binary safe.

### test coverage: 77%
`apr.filepath_list_merge(components) → searchpath`

Merge a table of search path components into a single search path string. On success the table of components is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 87%
`apr.filepath_get([native]) → path`

Get the default filepath for relative filenames. If `native` evaluates `true` the file system’s native path format is used. On success the filepath is returned, otherwise a `nil` followed by an error message is returned.

On at least Windows and UNIX the default file path for relative file names is the current working directory. Because some operating systems supported by APR don’t use this convention Lua/APR uses the term ‘default filepath’ instead.

This function is not binary safe.

### test coverage: 100%
`apr.filepath_set(path) → status`

Set the default file path for relative file names to the string `path`. On success `true` is returned, otherwise a `nil` followed by an error message is returned. Also see the notes for apr.filepath_get().

This function is not binary safe.

### `apr.filepath_which(program [, find_all]) → pathname`

Find the full pathname of `program` by searching the directories in the $PATH environment variable and return the pathname of the first program that’s found. If `find_all` is `true` then a list with the pathnames of all matching programs is returned instead.

## Filename matching

### test coverage: 100%
`apr.fnmatch(pattern, input [, ignorecase]) → status`

Try to match a string against a filename pattern. When the string matches the pattern `true` is returned, otherwise `false`. The supported pattern items are the following subset of shell wild cards:

- `?` matches one character (any character)
- `*` matches zero or more characters (any character)
- `\x` escapes the special meaning of the character `x`
- `[set]` matches one character within set. A range of characters can be specified by separating the characters of the range with a `-` character
- `[^set]` matches the complement of set, where set is defined as above

If the optional argument `ignorecase` is `true`, characters are compared case-insensitively.

This function is not binary safe.

### test coverage: 100%
`apr.fnmatch_test(pattern) → status`

Determine if a file path `pattern` contains one or more of the wild cards that are supported by apr.fnmatch(). On success `true` is returned, otherwise `false`.

This function is not binary safe.

### `apr.glob(pattern [, ignorecase]) → iterator`

Split `pattern` into a directory path and a filename pattern and return an iterator which returns all filenames in the directory that match the extracted filename pattern. The apr.fnmatch() function is used for filename matching so the documentation there applies.

This function is not binary safe.

## Directory manipulation

### test coverage: 85%
`apr.temp_dir_get() → path`

Find an existing directory suitable as a temporary storage location. On success the directory file path is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`apr.dir_make(path [, permissions]) → status`

Create the directory `path` on the file system. On success `true` is returned, otherwise a `nil` followed by an error message is returned. See the documentation on permissions for the optional second argument.

This function is not binary safe.

### test coverage: 100%
`apr.dir_make_recursive(path [, permissions]) → status`

Create the directory `path` on the file system, creating intermediate directories as required. On success `true` is returned, otherwise a `nil` followed by an error message is returned. See the documentation on permissions for the optional second argument.

This function is not binary safe.

### test coverage: 100%
`apr.dir_remove(path) → status`

Remove the empty directory `path` from the file system. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 78%
`apr.dir_remove_recursive(path) → status`

Remove the directory `path` and all its contents from the file system. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

Note: This function isn’t part of the Apache Portable Runtime but has been implemented on top of it by the author of the Lua/APR binding. It also hasn’t been properly tested yet.

This function is not binary safe.

### test coverage: 66%
`apr.dir_open(path) → directory handle`

Open the directory `path` for reading. On success a directory object is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 61%
`directory:read([property, ...]) → value, ...`

Return the requested properties for the next directory entry. On success the requested properties are returned, otherwise a `nil` followed by an error message is returned. This function implements the same interface as apr.stat().

### test coverage: 100%
`directory:rewind() → status`

Rewind the directory handle to start from the first entry. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`directory:entries([property, ...]) → iterator, directory handle`

Return a function that iterates over the (remaining) directory entries and returns the requested properties for each entry. If you don’t request any properties, a table with the available properties will be returned for each directory entry:

    > directory = apr.dir_open 'examples'
    > for info in directory:entries() do print(info) end
    {
      type = 'file', name = 'webserver.lua',
      user = 'peter', group = 'peter', protection = 'rw-r--r--',
      size = 2789, csize = 4096, inode = 12455648, dev = 64514, nlink = 1,
      path = '/home/peter/Development/Lua/APR/examples/webserver.lua',
      mtime = 1293753884.3382, atime = 1293994993.3855, ctime = 1293753884.3382,
    }
    {
     type = 'file', name = 'download.lua',
     user = 'peter' group = 'peter', protection = 'rw-r--r--',
     size = 2580, csize = 4096, inode = 12455598, dev = 64514, nlink = 1,
     path = '/home/peter/Development/Lua/APR/examples/download.lua',
     mtime = 1293753884.3382, atime = 1293994993.3855, ctime = 1293753884.3382,
    }

This function implements the same interface as apr.stat() with one exception: If you pass property names to directory:entries() that are not available they will be returned as `false` instead of `nil` because of a technical limitation in the Lua iterator protocol:

> “On each iteration, the iterator function is called to produce a new value, stopping when this new value is `nil`.”

### test coverage: 100%
`directory:close() → status`

Close the directory handle. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

## File I/O handling

### `apr.file_link(source, target) → status`

Create a hard link to the specified file. On success `true` is returned, otherwise a `nil` followed by an error message is returned. Both files must reside on the same device.

Please note that this function will only be available when the Lua/APR binding is compiled against APR 1.4 or newer because the apr_file_link() function wasn’t available in earlier releases.

This function is not binary safe.

### test coverage: 100%
`apr.file_copy(source, target [, permissions]) → status`

Copy the file `source` to `target`. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The permissions argument is documented elsewhere. The new file does not need to exist, it will be created if required. If the new file already exists, its contents will be overwritten.

This function is not binary safe.

### test coverage: 100%
`apr.file_append(source, target [, permissions]) → status`

Append the file `source` to `target`. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The permissions argument is documented elsewhere. The new file does not need to exist, it will be created if required.

This function is not binary safe.

### test coverage: 100%
`apr.file_rename(source, target) → status`

Rename the file `source` to `target`. On success `true` is returned, otherwise a `nil` followed by an error message is returned. If a file exists at the new location, then it will be overwritten. Moving files or directories across devices may not be possible.

This function is not binary safe.

### test coverage: 100%
`apr.file_remove(path) → status`

Delete the file pointed to by `path`. On success `true` is returned, otherwise a `nil` followed by an error message is returned. If the file is open, it won’t be removed until all instances of the file are closed.

This function is not binary safe.

### test coverage: 100%
`apr.file_mtime_set(path, mtime) → status`

Set the last modified time of the file pointed to by `path` to `mtime`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 60%
`apr.file_attrs_set(path, attributes) → status`

Set the attributes of the file pointed to by `path`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

The table `attributes` should consist of string keys and boolean values. The supported attributes are `readonly`, `hidden` and `executable`.

This function should be used in preference to explicit manipulation of the file permissions, because the operations to provide these attributes are platform specific and may involve more than simply setting permission bits.

This function is not binary safe.

### test coverage: 100%
`apr.file_perms_set(path, permissions) → status`

Set the permissions of the file specified by `path`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

Warning: Some platforms may not be able to apply all of the available permission bits, in this case a third value `'INCOMPLETE'` is returned (see error handling).

This function is not binary safe.

### test coverage: 100%
`apr.stat(path [, property, ...]) → value, ...`

Get the status of the file pointed to by `path`. On success, if no properties are given a table of property name/value pairs is returned, otherwise the named properties are returned in the same order as the arguments. On failure a `nil` followed by an error message is returned.

The following fields are supported:

- `name` is a string containing the name of the file in proper case
- `path` is a string containing the absolute pathname of the file
- `type` is one of the strings `'directory'`, `'file'`, `'link'`, `'pipe'`, `'socket'`, `'block device'`, `'character device'` or `'unknown'`
- `user` is a string containing the name of user that owns the file
- `group` is a string containing the name of the group that owns the file
- `size` is a number containing the size of the file in bytes
- `csize` is a number containing the storage size consumed by the file
- `ctime` is the time the file was created, or the inode was last changed
- `atime` is the time the file was last accessed
- `mtime` is the time the file was last modified
- `nlink` is the number of hard links to the file
- `inode` is a unique number within the file system on which the file resides
- `dev` is a number identifying the device on which the file is stored
- `protection` is a 9 character string with the file system permissions
- `link` is a special flag that does not return a field, instead it is used to signal that symbolic links should not be followed, i.e. the status of the link itself should be returned

Here are some examples:

    > -- Here's an example of a table with all properties:
    > = apr.stat('lua-5.1.4.tar.gz')
    {
     name = 'lua-5.1.4.tar.gz',
     path = 'lua-5.1.4.tar.gz',
     type = 'file',
     user = 'peter',
     group = 'peter',
     size = 216679,
     csize = 217088,
     ctime = 1284159662.7264,
     atime = 1287954158.6019,
     mtime = 1279317348.194,
     nlink = 1,
     inode = 1838576,
     dev  = 64514,
     protection = 'rw-r--r--',
    }
    > -- To check whether a directory exists:
    > function isdir(p) return apr.stat(p, 'type') == 'directory' end
    > = isdir('.')
    true
    > -- To get a file's size in bytes:
    > function filesize(p) return apr.stat(p, 'size') end
    > = filesize('lua-5.1.4.tar.gz')
    216679

This function is not binary safe.

### test coverage: 78%
`apr.file_open(path [, mode [, permissions]]) → file`

This function imitates Lua’s io.open() function, so here is the documentation for that function:

This function opens a file, in the mode specified in the string `mode`. It returns a new file handle, or, in case of errors, `nil` plus an error message. The `mode` string can be any of the following:

- `'r'`: read mode (the default)
- `'w'`: write mode
- `'a'`: append mode
- `'r+'`: update mode, all previous data is preserved
- `'w+'`: update mode, all previous data is erased
- `'a+'`: append update mode, previous data is preserved, writing is only allowed at the end of file

The `mode` string may also have a `b` at the end, which is needed in some systems to open the file in binary mode. This string is exactly what is used in the standard C function fopen(). The permissions argument is documented elsewhere.

This function is not binary safe.

### test coverage: 90%
`file:stat([field, ...]) → value, ...`

This method works like apr.stat() except that it uses a file handle instead of a filepath to access the file.

### test coverage: 100%
`file:lines() → iterator`

This function implements the interface of the file:lines() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Return an iterator function that, each time it is called, returns a new line read from the file. Therefore, the construction

    for line in file:lines() do body end

will iterate over all lines. This function does not close the file when the loop ends.

### test coverage: 100%
`file:read([format, ...]) → mixed value, ...`

This function implements the interface of the file:read() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Read from file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or `nil` if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).

The available formats are:

- `'*n'`: reads a number; this is the only format that returns a number instead of a string
- `'*a'`: reads all data from the file, starting at the current position. On end of input, it returns the empty string
- `'*l'`: reads the next line (skipping the end of line), returning `nil` on end of input (this is the default format)
- `number`: reads a string with up to this number of characters, returning `nil` on end of input. If number is zero, it reads nothing and returns an empty string, or `nil` on end of input

### test coverage: 100%
`file:write(value [, ...]) → status`

This function implements the interface of the file:write() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Write the value of each argument to file. The arguments must be strings or numbers. To write other values, use tostring() or string.format() before this function.

### test coverage: 70%
`file:seek([whence [, offset]]) → offset`

This function implements the interface of the file:seek() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Sets and gets the file position, measured from the beginning of the file, to the position given by `offset` plus a base specified by the string `whence`, as follows:

- `'set'`: base is position 0 (beginning of the file)
- `'cur'`: base is current position
- `'end'`: base is end of file

In case of success, function `seek` returns the final file position, measured in bytes from the beginning of the file. If this function fails, it returns `nil`, plus a string describing the error.

The default value for `whence` is `'cur'`, and for offset is 0. Therefore, the call file:seek() returns the current file position, without changing it; the call `file:seek('set')` sets the position to the beginning of the file (and returns 0); and the call `file:seek('end')` sets the position to the end of the file, and returns its size.

### test coverage: none
`file:flush() → status`

Saves any written data to `file`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: none
`file:lock(type [, nonblocking ]) → status`

Establish a lock on the open file `file`. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The `type` must be one of:

- `'shared'`: Shared lock. More than one process or thread can hold a shared lock at any given time. Essentially, this is a “read lock”, preventing writers from establishing an exclusive lock
- `'exclusive'`: Exclusive lock. Only one process may hold an exclusive lock at any given time. This is analogous to a “write lock”

If `nonblocking` is `true` the call will not block while acquiring the file lock.

The lock may be advisory or mandatory, at the discretion of the platform. The lock applies to the file as a whole, rather than a specific range. Locks are established on a per-thread/process basis; a second lock by the same thread will not block.

### test coverage: none
`file:unlock() → status`

Remove any outstanding locks on the file. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: none
`pipe:timeout_get() → timeout`

Get the timeout value or blocking state of `pipe`. On success the timeout value is returned, otherwise a `nil` followed by an error message is returned.

The `timeout` `true` means wait forever, `false` means don’t wait at all and a number is the microseconds to wait.

### test coverage: none
`pipe:timeout_set(timeout) → status`

Set the timeout value or blocking state of `pipe`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

The `timeout` `true` means wait forever, `false` means don’t wait at all and a number is the microseconds to wait. For example:

    -- Configure read end of pipe to block for a maximum of 5 seconds.
    pipe:timeout_set(1000000 * 5)
    for line in pipe:lines() do
      print(line)
    end

### test coverage: none
`file:inherit_set() → status`

Set a file to be inherited by child processes. By default, file descriptors will not be inherited by child processes created by apr.proc_create().

At the time of writing this seems to only apply to UNIX where APR will close all open file handles after performing a fork() unless you explicitly set your files to be inheritable.

### test coverage: none
`file:inherit_unset() → status`

Unset a file from being inherited by child processes.

### test coverage: 100%
`file:close() → status`

Close `file`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

## Network I/O handling

### test coverage: 92%
`apr.socket_create([protocol [, family]]) → socket`

Create a network socket. On success the new socket object is returned, otherwise a `nil` followed by an error message is returned. Valid values for the `protocol` argument are:

- `'tcp'` to create a TCP socket (this is the default)
- `'udp'` to create a UDP socket

These are the valid values for the `family` argument:

- `'inet'` to create a socket using the IPv4 address family
- `'inet6'` to create a socket using the IPv6 address family
- `'unspec'` to pick the system default type (this is the default)

Note that `'inet6'` is only supported when `apr.socket_supports_ipv6` is `true`.

### test coverage: 85%
`apr.hostname_get() → name`

Get the name of the current machine. On success the host name string is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 90%
`apr.host_to_addr(hostname [, family]) → ip_address`

Resolve a host name to an IP-address. On success the IP-address is returned as a string, otherwise a `nil` followed by an error message is returned. The optional `family` argument is documented under apr.socket_create().

    > = apr.host_to_addr 'www.lua.org'
    '89.238.129.35'

This function is not binary safe.

### test coverage: 90%
`apr.addr_to_host(ip_address [, family]) → hostname`

Look up the host name from an IP-address (also known as a reverse DNS lookup). On success the host name is returned as a string, otherwise a `nil` followed by an error message is returned. The optional `family` argument is documented under apr.socket_create().

    > = apr.addr_to_host '89.238.129.35'
    'flounder.pepperfish.net'

This function is not binary safe.

### test coverage: 100%
`socket:connect(host, port) → status`

Issue a connection request to a socket either on the same machine or a different one, as indicated by the `host` string and `port` number. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`socket:bind(host, port) → status`

Bind the socket to the given `host` string and `port` number. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The special `host` value `'*'` can be used to select the default ‘any’ address. For example if you want to create a web server you can start with the following:

    -- Basic single threaded server
    server = assert(apr.socket_create())
    assert(server:bind('*', 80))
    assert(server:listen(10))
    while true do
      local client = assert(server:accept())
      -- Here you can receive data from the client by calling client:read()
      -- and send data to the client by calling client:write()
    end

This function can fail if you try to bind a port below 1000 without superuser privileges or if another process is already bound to the given port number.

This function is not binary safe.

### test coverage: 100%
`socket:listen(backlog) → status`

To listen for incoming network connections three steps must be performed:

1. First a socket is created with apr.socket_create()
2. Next a willingness to accept incoming connections and a queue limit for incoming connections are specified with socket:listen() (this call doesn’t block)
3. Finally socket:accept() is called to wait for incoming connections

On success `true` is returned, otherwise a `nil` followed by an error message is returned. The `backlog` argument indicates the number of outstanding connections allowed in the socket’s listen queue. If this value is less than zero, the listen queue size is set to zero. As a special case, if you pass the string `'max'` as `backlog` then a platform specific maximum value is chosen based on the compile time constant SOMAXCONN.

### test coverage: 88%
`socket:accept() → client_socket`

Accept a connection request on a server socket. On success a socket is returned which forms the connection to the client, otherwise a `nil` followed by an error message is returned. This function blocks until a client connects.

### test coverage: 100%
`socket:read([format, ...]) → mixed value, ...`

This function implements the interface of the file:read() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Read from socket, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or `nil` if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).

The available formats are:

- `'*n'`: reads a number; this is the only format that returns a number instead of a string
- `'*a'`: reads all data from the socket, starting at the current position. On end of input, it returns the empty string
- `'*l'`: reads the next line (skipping the end of line), returning `nil` on end of input (this is the default format)
- `number`: reads a string with up to this number of characters, returning `nil` on end of input. If number is zero, it reads nothing and returns an empty string, or `nil` on end of input

### test coverage: 85%
`socket:write(value [, ...]) → status`

This function implements the interface of the file:write() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Write the value of each argument to socket. The arguments must be strings or numbers. To write other values, use tostring() or string.format() before this function.

### test coverage: 100%
`socket:lines() → iterator`

This function implements the interface of the file:lines() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Return an iterator function that, each time it is called, returns a new line read from the socket. Therefore, the construction

    for line in socket:lines() do body end

will iterate over all lines. This function does not close the socket when the loop ends.

### test coverage: none
`socket:timeout_get() → timeout`

Get the timeout value or blocking state of `socket`. On success the timeout value is returned, otherwise a `nil` followed by an error message is returned.

The `timeout` `true` means wait forever, `false` means don’t wait at all and a number is the microseconds to wait.

### test coverage: none
`socket:timeout_set(timeout) → status`

Set the timeout value or blocking state of `socket`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

The `timeout` `true` means wait forever, `false` means don’t wait at all and a number is the microseconds to wait.

### test coverage: none
`socket:opt_get(name) → value`

Query socket options for the specified socket. Valid values for `name` are:

- `'debug'`: turn on debugging information
- `'keep-alive'`: keep connections active
- `'linger'`: lingers on close if data is present
- `'non-block'`: turns blocking on/off for socket
- `'reuse-addr'`: the rules used in validating addresses supplied to bind should allow reuse of local addresses
- `'sndbuf'`: set the send buffer size
- `'rcvbuf'`: set the receive buffer size
- `'disconnected'`: query the disconnected state of the socket (currently only used on Windows)

The `'sndbuf'` and `'rcvbuf'` options have integer values, all other options have a boolean value.

### test coverage: none
`socket:opt_set(name, value) → status`

Setup socket options for the specified socket. Valid values for `name` are documented under socket:opt_get(), `value` should be a boolean or integer value. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: none
`socket:addr_get([type]) → ip_address [, hostname]`

Get one of the addresses associated with `socket`, according to `type`:

- `'local'` to get the address to which the socket is bound locally
- `'remote'` to get the address of the peer to which the socket is connected (this is the default)

On success the local or remote IP-address is returned as a string, otherwise a `nil` followed by an error message is returned. If a host name is available that will be returned as the second value.

This function is not binary safe.

### test coverage: none
`socket:shutdown(mode) → status`

Shutdown either reading, writing, or both sides of a socket. On success `true` is returned, otherwise a `nil` followed by an error message is returned. Valid values for `mode` are:

- `'read'`: no longer allow read requests
- `'write'`: no longer allow write requests
- `'both'`: no longer allow read or write requests

This does not actually close the socket descriptor, it just controls which calls are still valid on the socket. To close sockets see socket:close().

### test coverage: 100%
`socket:close() → status`

Close `socket`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

## Pipe I/O handling

Lua/APR represents pipes as files just like Lua’s standard library function io.popen() does because it works fairly well, however there are some differences between files and pipes which impact the API:

- File objects implement pipe:timeout_get() and pipe:timeout_set() even though these methods only make sense for pipe objects

- Pipe objects implement file:seek() but don’t support it

One of the reasons that file/pipe support is so interwoven in APR and thus Lua/APR is that you can create a named pipe with apr.namedpipe_create() and access it using apr.file_open() and APR won’t know or even care that you're reading/writing a pipe instead of a file.

### test coverage: 100%
`apr.pipe_open_stdin() → pipe`

Open standard input as a pipe. On success the pipe is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`apr.pipe_open_stdout() → pipe`

Open standard output as a pipe. On success the pipe is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`apr.pipe_open_stderr() → pipe`

Open standard error as a pipe. On success the pipe is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`apr.namedpipe_create(name [, permissions]) → status`

Create a named pipe. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The permissions argument is documented elsewhere.

Named pipes can be used for interprocess communication:

1. Check if the named pipe already exists, if it doesn’t then create it
2. Have each process access the named pipe using apr.file_open()
3. Communicate between the two processes over the read/write ends of the named pipe and close it when the communication is finished.

Note that APR supports named pipes on UNIX but not on Windows. If you try anyhow the error message “This function has not been implemented on this platform” is returned.

This function is not binary safe.

### test coverage: none
`apr.pipe_create() → input, output`

Create an anonymous pipe. On success the write and read ends of the pipe are returned, otherwise a `nil` followed by an error message is returned. There’s an example use of this function in the documentation for process:in_set().

## Memcached client

Memcached is a “distributed memory object caching system”. It’s designed as an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering. The memcached client module makes it possible to read from and write to one or more memcached servers over a network socket in Lua.

To-do: Find out if “flags” can be any 32 bits value and how useful it is to Lua.

### test coverage: 72%
`apr.memcache([max_servers]) → mc_client`

Create a memcached client. The optional argument `max_servers` determines the maximum number of memcached servers supported by the client (defaults to 10). On success the client object is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 100%
`mc_client:hash(str) → hash`

Create a CRC32 hash used to split keys between servers. The hash is not compatible with old memcached clients.

This function is binary safe.

### test coverage: 88%
`mc_client:find_server_hash(hash) → mc_server`

Picks a server based on a hash. Returns the info of the server that controls the specified hash.

### test coverage: 89%
`mc_client:add_server(host, port [, min [, smax [, max [, ttl]]]]) → mc_server`

Create a new server object and add it to the client object. On success the server object is returned, otherwise a `nil` followed by an error message is returned. The parameters have the following meaning:

- `host`: hostname of server
- `port`: port of server (usually 11211)
- `min`: minimum number of client sockets to open (defaults to 0)
- `smax`: soft maximum number of client connections to open (defaults to 1)
- `max`: hard maximum number of client connections (defaults to 1)
- `ttl`: time to live in microseconds of a client connection (defaults to 60000)

Note that `min`, `smax` and `max` are only used when APR was compiled with threads. Also a word of caution: Changing servers after startup may cause keys to go to different servers.

### test coverage: 90%
`mc_client:find_server(host, port) → mc_server`

Finds a server object based on a (hostname, port) pair. On success the server with matching host name and port is returned, otherwise nothing is returned.

### test coverage: 100%
`mc_client:enable_server(mc_server) → status`

Enable a server for use again after disabling the server with mc_client:disable_server(). On success `true` is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 100%
`mc_client:disable_server(mc_server) → status`

Disable a server. On success `true` is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 85%
`mc_client:get(key [, ...]) → status, value [, ...]`

Get one or more values from the server. On success `true` is returned followed by the retrieved value(s), otherwise `nil` followed by an error message is returned. The keys are null terminated strings and the return values are binary safe strings. Keys that don’t have an associated value result in `nil`.

### test coverage: 100%
`mc_client:set(key, value [, timeout]) → status`

Sets a value by key on the server. If the key already exists the old value will be overwritten. The `key` is a null terminated string, the `value` is a binary safe string and `timeout` is the time in seconds for the data to live on the server (a number, defaults to 60 seconds). On success `true` is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 100%
`mc_client:add(key, value [, timeout]) → status`

Adds a value by key on the server. If the key already exists this call will fail and the old value will be preserved. The arguments and return values are documented under mc_client:set().

### test coverage: 100%
`mc_client:replace(key, value [, timeout]) → status`

Replace a value by key on the server. If the key doesn’t exist no value will be set. The arguments and return values are documented under mc_client:set().

### test coverage: 100%
`mc_client:delete(key [, timeout]) → status`

Delete a key from the server. The `key` is a null terminated string and `timeout` is the time in seconds for the delete to stop other clients from adding (a number, defaults to 10 seconds). On success `true` is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 88%
`mc_client:incr(key [, number]) → value`

Increment a value. The `key` is a null terminated string and the optional argument `number` is the number to increment by (defaults to 1). On success the new value after incrementing is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 88%
`mc_client:decr(key [, number]) → value`

Decrement a value. The `key` is a null terminated string and the optional argument `number` is the number to decrement by (defaults to 1). On success the new value after decrementing is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 90%
`mc_client:version(mc_server) → version`

Query a server’s version. On success the version string is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 96%
`mc_client:stats() → statistics`

Query a server for statistics. On success a table with information is returned, otherwise `nil` followed by an error message is returned. The following fields are supported:

- `version`: version string of the server
- `pid`: process ID of the server process
- `uptime`: number of seconds this server has been running
- `time`: current UNIX time according to the server
- `rusage_user`: accumulated user time for this process
- `rusage_system`: accumulated system time for this process
- `curr_items`: current number of items stored by the server
- `total_items`: total number of items stored by this server
- `bytes`: current number of bytes used by this server to store items
- `curr_connections`: number of open connections
- `total_connections`: total number of connections opened since the server started running
- `connection_structures`: number of connection structures allocated by the server
- `cmd_get`: cumulative number of retrieval requests
- `cmd_set`: Cumulative number of storage requests
- `get_hits`: number of keys that have been requested and found present
- `get_misses`: number of items that have been requested and not found
- `evictions`: number of items removed from cache because they passed their expiration time
- `bytes_read`: total number of bytes read by this server
- `bytes_written`: total number of bytes sent by this server
- `limit_maxbytes`: number of bytes this server is allowed to use for storage
- `threads`: number of threads the server is running (if built with threading)

## Command argument parsing

### test coverage: 92%
`apr.getopt(usage [, config ]) → options, arguments`

Parse the command line arguments according to the option letters and/or long options defined in the string `usage` (see the example below) and return a table with the matched options and a table with any remaining positional arguments. When an option is matched multiple times, the resulting value in `options` depends on the following context:

- If the option doesn’t take an argument, the value will be a number indicating the number of times that the option was matched

- If the option takes an argument and only one option/argument pair is matched, the value will be the argument (a string). When more than one pair is matched for the same option letter/name, the values will be collected in a table

The optional `config` table can be used to change the following defaults:

- When `usage` mentions `-h` or `--help` and either of these options is matched in the arguments, apr.getopt() will print the usage message and call os.exit(). To avoid this set `config.show_usage` to `false` (not `nil`!)

- When an error is encountered during argument parsing, apr.getopt() will print a warning about the invalid argument and call os.exit(). To avoid this set `config.handle_errors` to `false` (not `nil`!)

- By default the arguments in the global variable arg will be used, but you can set `config.args` to a table of arguments to be used instead

Here is a short example of a valid Lua script that doesn’t really do anything useful but demonstrates the use of apr.getopt():

    apr = require 'apr'
    opts, args = apr.getopt [[
    Usage: echo.lua [OPTIONS] ARG...
      -h, --help     show this message and exit
      -v, --verbose  make more noise
          --version  print version and exit
    ]]
    if opts.version then
      print "This is version 0.1"
    else
      if opts.verbose then
        print("Got", #args, "arguments")
      end
      if opts.verbose >= 2 then
        print "Here they are:"
      end
      for i = 1, #args do print(args[i]) end
    end

The apr.getopt() function is very similar to Lapp by Steve Donovan although Lapp is more full featured, for example it validates and converts argument types.

## HTTP request parsing

This module is an experimental binding to the apreq2 library which enables HTTP request parsing of query strings, headers and multipart messages. Some general notes about the functions in this module:

- None of the extracted strings (except maybe for request bodies) are binary safe because (AFAIK) HTTP headers are not binary safe

- Parsed name/value pairs are converted to a Lua table using two rules: names without a value get the value `true` and duplicate names result in a table that collects all values for the given name

- When a parse error is encountered after successfully parsing part of the input, the results of the function are followed by an error message and error code (see below)

The functions in this module return three values on error: a `nil` followed by an error message and an error code. This module defines the following error codes (in addition to the generic Lua/APR error codes):

- `'EBADARG'`: bad arguments
- `'GENERAL'`: internal apreq2 error
- `'TAINTED'`: attempted to perform unsafe action with tainted data
- `'INTERRUPT'`: parsing interrupted
- `'BADDATA'`: invalid input data
- `'BADCHAR'`: invalid character
- `'BADSEQ'`: invalid byte sequence
- `'BADATTR'`: invalid attribute
- `'BADHEADER'`: invalid header
- `'BADUTF8'`: invalid UTF-8 encoding
- `'NODATA'`: missing input data
- `'NOTOKEN'`: missing required token
- `'NOATTR'`: missing attribute
- `'NOHEADER'`: missing header
- `'NOPARSER'`: missing parser
- `'MISMATCH'`: conflicting information
- `'OVERLIMIT'`: exceeds configured maximum limit
- `'UNDERLIMIT'`: below configured minimum limit
- `'NOTEMPTY'`: setting already configured

### test coverage: 90%
`apr.parse_headers(request) → headers, body`

Parse the headers in a HTTP request string according to RFC 822. On success a table of header name/value pairs and the request body string are returned, otherwise `nil` followed by an error message is returned.

There are some gotchas in using this function:

- It will fail if anything comes before the headers, so be sure to strip the status line from the request string before calling this function

- If the request string doesn’t contain an empty line to separate the headers from the body, the last header might be silently discarded

### test coverage: 90%
`apr.parse_multipart(request, enctype [, limit [, tempdir]]) → parts`

Parse a multipart/form-data or multipart/related HTTP request body according to RFC 2388 and the boundary string in `enctype`. On success the table with parameter name/value pairs is returned, otherwise a `nil` followed by an error message is returned.

The optional number `limit` gives the maximum in-memory bytes that the data structure used to parse the request may use (it defaults to 1024 KB), but be aware that because of internal copying apr.parse_multipart() can use more than double this amount of memory while parsing a request.

The optional string `tempdir` is the directory used for temporary storage of large uploads.

### test coverage: 100%
`apr.parse_cookie_header(header) → cookies`

Parse a cookie header and store the cookies in a Lua table. On success the table with cookie name/value pairs is returned, otherwise `nil` followed by an error message and error code is returned.

### test coverage: 90%
`apr.parse_query_string(query_string) → parameters`

Parse a URL encoded string into a Lua table. On success the table with parameter name/value pairs is returned, otherwise `nil` followed by an error message and error code is returned.

This function uses `&` and `;` as the set of tokens to delineate words, and will treat a word without `=` as a name/value pair with the value `true`.

### test coverage: 100%
`apr.header_attribute(header, name) → value`

Search a header string for the value of a particular named attribute. On success the matched value is returned, otherwise `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`apr.uri_encode(string) → encoded`

Encode unsafe bytes in `string` using percent-encoding so that the string can be embedded in a URI query string.

This function is not binary safe.

### test coverage: none
`apr.uri_decode(encoded) → string`

Decode all percent-encoded bytes in the string `encoded`.

This function is binary safe.

## Process handling

### test coverage: 100%
`apr.proc_create(program) → process`

Create a child process that will execute the given `program` when started. Once you've called this function you still need to execute the process using the process:exec() function. Here’s a simple example that emulates Lua’s os.execute() function:

    function execute(command)
      local arguments = apr.tokenize_to_argv(command)
      local progname = table.remove(arguments, 1)
      local process = apr.proc_create(progname)
      process:cmdtype_set('shellcmd/env')
      process:exec(arguments)
      local done, code, why = process:wait(true)
      return code
    end

    execute 'echo This can be any process...'

This function is not binary safe.

### test coverage: none
`apr.proc_detach(daemonize) → status`

Detach the current process from the controlling terminal. If `daemonize` evaluates to `true` the process will daemonize and become a background process, otherwise it will stay in the foreground. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 85%
`apr.proc_fork() → process, context`

This is currently the only non-portable function in APR and by extension Lua/APR. It performs a standard UNIX fork. If the fork succeeds a `process` object and `context` string (`'parent'` or `'child'`) are returned, otherwise a `nil` followed by an error message is returned. The parent process can use the returned `process` object to wait for the child process to die:

    if apr.proc_fork then -- forking supported?
      process, context = assert(apr.proc_fork())
      if context == 'parent' then
        print "Parent waiting for child.."
        process:wait(true)
        print "Parent is done!"
      else -- context == 'child'
        print "Child simulating activity.."
        apr.sleep(10)
        print "Child is done!"
      end
    end

As the above example implies the apr.proc_fork() function will only be defined when forking is supported on the current platform.

### test coverage: none
`process:addrspace_set(separate) → status`

If `separate` evaluates to `true` the child process will start in its own address space, otherwise the child process executes in the current address space from its parent. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The default is no on NetWare and yes on other platforms.

### test coverage: none
`process:user_set(username [, password]) → status`

Set the user under which the child process will run. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

On Windows and other platforms where `apr.user_set_requires_password` is `true` this method requires a password.

This function is not binary safe.

### test coverage: none
`process:group_set(groupname) → status`

Set the group under which the child process will run. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`process:cmdtype_set(type) → status`

Set what type of command the child process will execute. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The argument `type` must be one of:

- `'shellcmd'`: Use the shell to invoke the program
- `'shellcmd/env'`: Use the shell to invoke the program, replicating our environment
- `'program'`: Invoke the program directly, without copying the environment
- `'program/env'`: Invoke the program directly, replicating our environment
- `'program/env/path'`: Find program in `$PATH`, replicating our environment

### test coverage: 73%
`process:env_set(environment) → status`

Set the environment variables of the child process to the key/value pairs in the table `environment`. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

Please note that the environment table is ignored for the command types `'shellcmd/env'`, `'program/env'` and `'program/env/path'` (set using the process:cmdtype_set() method).

This function is not binary safe.

### test coverage: none
`process:dir_set(path) → status`

Set which directory the child process should start executing in. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

By default child processes inherit this directory from their parent process at the moment when the process:exec() call is made. To find out the current directory see the apr.filepath_get() function.

This function is not binary safe.

### test coverage: none
`process:detach_set(detach) → status`

Determine if the child should start in detached state. On success `true` is returned, otherwise a `nil` followed by an error message is returned. Default is no.

### test coverage: none
`process:error_check_set(enabled) → nothing`

Specify that process:exec() should do whatever it can to report failures directly, rather than find out in the child that something is wrong. This leads to extra overhead in the calling process, but it may help you handle these errors more gracefully.

Note that this option is only useful on platforms where fork() is used.

### test coverage: 100%
`process:io_set(stdin, stdout, stderr) → status`

Determine if the child process should be linked to its parent through one or more pipes. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

Each argument gives the blocking mode of a pipe, which can be one of the following strings:

- `'none'`: Don’t create a pipe
- `'full-block'`: Create a pipe that blocks until the child process writes to the pipe or dies
- `'full-nonblock'`: Create a pipe that doesn’t block
- `'parent-block'`: Create a pipe that only blocks on the parent’s end
- `'child-block'`: Create a pipe that only blocks on the child’s end

Once the child process has been started with process:exec(), the pipes can be accessed with the methods process:in_get(), process:out_get() and process:err_get().

Here’s an example that executes the external command `tr a-z A-Z` to translate some characters to uppercase:

    > p = apr.proc_create 'tr'
    > p:cmdtype_set('shellcmd/env')
    > p:io_set('child-block', 'parent-block', 'none')
    > p:exec{'a-z', 'A-Z'}
    > input = p:in_get()
    > output = p:out_get()
    > input:write('Testing, 1, 2, 3\n')
    > input:close()
    > print(output:read())
    TESTING, 1, 2, 3
    > output:close()
    > p:wait(true)

### test coverage: none
`process:in_set(child_in [, parent_in]) → status`

Initialize the standard input pipe of the child process to an existing pipe or a pair of pipes. This can be useful if you have already opened a pipe (or multiple files) that you wish to use, perhaps persistently across multiple process invocations – such as a log file. On success `true` is returned, otherwise a `nil` followed by an error message is returned. Here’s a basic example that connects two processes using an anonymous pipe:

    -- Create a gzip process to decompress the Lua source code archive.
    gzip = apr.proc_create 'gunzip'
    gzip:cmdtype_set 'shellcmd/env'
    gzip:in_set(apr.file_open('lua-5.1.4.tar.gz', 'rb'))

    -- Create a tar process to list the files in the decompressed archive.
    tar = apr.proc_create 'tar'
    tar:cmdtype_set 'shellcmd/env'
    tar:out_set(apr.pipe_open_stdout())

    -- Connect the two processes using an anonymous pipe.
    input, output = assert(apr.pipe_create())
    gzip:out_set(output)
    tar:in_set(input)

    -- Start the pipeline by executing both processes.
    gzip:exec()
    tar:exec{'-t'}

### test coverage: none
`process:out_set(child_out [, parent_out]) → status`

Initialize the standard output pipe of the child process to an existing pipe or a pair of pipes. This can be useful if you have already opened a pipe (or multiple files) that you wish to use, perhaps persistently across multiple process invocations – such as a log file. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: none
`process:err_set(child_err [, parent_err]) → status`

Initialize the standard error pipe of the child process to an existing pipe or a pair of pipes. This can be useful if you have already opened a pipe (or multiple files) that you wish to use, perhaps persistently across multiple process invocations – such as a log file. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`process:in_get() → pipe`

Get the parent end of the standard input pipe (a writable pipe).

### test coverage: 100%
`process:out_get() → pipe`

Get the parent end of the standard output pipe (a readable pipe).

### test coverage: 100%
`process:err_get() → pipe`

Get the parent end of the standard error pipe (a readable pipe).

### test coverage: 91%
`process:exec([args]) → status`

Create the child process and execute a program or shell command inside it. On success `true` is returned, otherwise a `nil` followed by an error message is returned. If the `args` array is given the contained strings become the command line arguments to the child process. The program name for the child process defaults to the name passed into apr.proc_create(), but you can change it by setting `args[0]`.

This function is not binary safe.

### test coverage: 73%
`process:wait(how) → done [, why, code]`

Wait for the child process to die. If `how` is `true` the call blocks until the process dies, otherwise the call returns immediately regardless of if the process is dead or not. The first return value is `false` if the process isn’t dead yet. If it’s `true` the process died and two more return values are available. The second return value is the reason the process died, which is one of:

- `'exit'`: Process exited normally
- `'signal'`: Process exited due to a signal
- `'signal/core'`: Process exited and dumped a core file

The third return value is the exit code of the process. If an error occurs a `nil` followed by an error message is returned.

### test coverage: none
`process:kill(how) → status`

Terminate a running child process. On success `true` is returned, otherwise a `nil` followed by an error message is returned. The parameter `how` must be one of:

- `'never'`: The process is never sent any signals
- `'always'`: The process is sent the SIGKILL signal when its Lua userdata is garbage collected
- `'timeout'`: Send the SIGTERM signal, wait for 3 seconds, then send the SIGKILL signal
- `'wait'`: Wait forever for the process to complete
- `'once'`: Send the SIGTERM signal and then wait

## Shared memory

Shared memory is memory that may be simultaneously accessed by multiple programs with an intent to provide communication among them. The Lua/APR binding represents shared memory as file objects through the shm:read(), shm:write() and shm:seek() methods.

### test coverage: 78%
`apr.shm_create(filename, size) → shm object`

Create and make accessible a shared memory segment. The `filename` argument is the file to use for shared memory on platforms that require it. The `size` argument is the desired size of the segment.

A note about anonymous vs. named shared memory segments: Not all platforms support anonymous shared memory segments, but in some cases it is preferred over other types of shared memory implementations. Passing a `nil` `filename` parameter to this function will cause the subsystem to use anonymous shared memory segments. If such a system is not available, the error `'ENOTIMPL'` is returned as the third return value (the first and second being `nil` and an error message string).

This function is not binary safe.

### test coverage: 90%
`apr.shm_attach(filename) → shm object`

Attach to a shared memory segment that was created by another process. The `filename` argument is the file used to create the original segment (this must match the original filename). On success a shared memory object is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`apr.shm_remove(filename) → status`

Remove the named resource associated with a shared memory segment, preventing attachments to the resource, but not destroying it. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is only supported on platforms which support name-based shared memory segments, and will return the error code `'ENOTIMPL'` on platforms without such support. Removing the file while the shared memory is in use is not entirely portable, caller may use this to enhance obscurity of the resource, but be prepared for the the call to fail, and for concurrent attempts to create a resource of the same name to also fail.

Note that the named resource is also removed when a shared memory object created by apr.shm_create() is garbage collected.

This function is not binary safe.

### test coverage: 100%
`shm:read([format, ...]) → mixed value, ...`

This function implements the interface of the file:read() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Read from shared memory, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or `nil` if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below).

The available formats are:

- `'*n'`: reads a number; this is the only format that returns a number instead of a string
- `'*a'`: reads all data from the shared memory, starting at the current position. On end of input, it returns the empty string
- `'*l'`: reads the next line (skipping the end of line), returning `nil` on end of input (this is the default format)
- `number`: reads a string with up to this number of characters, returning `nil` on end of input. If number is zero, it reads nothing and returns an empty string, or `nil` on end of input

### test coverage: 100%
`shm:write(value [, ...]) → status`

This function implements the interface of the file:write() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Write the value of each argument to shared memory. The arguments must be strings or numbers. To write other values, use tostring() or string.format() before this function.

### test coverage: 85%
`shm:seek([whence [, offset]]) → offset`

This function implements the interface of the file:seek() function described in the Lua 5.1 reference manual. Here is the description from the reference manual:

Sets and gets the shared memory position, measured from the beginning of the shared memory, to the position given by `offset` plus a base specified by the string `whence`, as follows:

- `'set'`: base is position 0 (beginning of the shared memory)
- `'cur'`: base is current position
- `'end'`: base is end of shared memory

In case of success, function `seek` returns the final shared memory position, measured in bytes from the beginning of the shared memory. If this function fails, it returns `nil`, plus a string describing the error.

The default value for `whence` is `'cur'`, and for offset is 0. Therefore, the call shm:seek() returns the current shared memory position, without changing it; the call `shm:seek('set')` sets the position to the beginning of the shared memory (and returns 0); and the call `shm:seek('end')` sets the position to the end of the shared memory, and returns its size.

### test coverage: 100%
`shm:detach() → status`

Detach from a shared memory segment without destroying it. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`shm:destroy() → status`

Destroy a shared memory segment and associated memory. On success `true` is returned, otherwise a `nil` followed by an error message is returned. Note that this will be done automatically when the shared memory object is garbage collected and has not already been destroyed.

## String routines

### test coverage: 100%
`apr.strnatcmp(left, right) → status`

Do a natural order comparison of two strings. Returns `true` when the `left` string is less than the `right` string, `false` otherwise. This function can be used as a callback for Lua’s standard library function table.sort().

    > -- the canonical example:
    > list = { 'rfc1.txt', 'rfc2086.txt', 'rfc822.txt' }
    > -- collate order:
    > table.sort(list)
    > for _, name in ipairs(list) do print(name) end
    rfc1.txt
    rfc2086.txt
    rfc822.txt
    > -- natural order:
    > table.sort(list, apr.strnatcmp)
    > for _, name in ipairs(list) do print(name) end
    rfc1.txt
    rfc822.txt
    rfc2086.txt

This function is not binary safe.

### test coverage: 100%
`apr.strnatcasecmp(left, right) → status`

Like apr.strnatcmp(), but ignores the case of the strings.

This function is not binary safe.

### test coverage: 100%
`apr.strfsize(number [, padding]) → readable`

Format a binary size positive `number` to a compacted human readable string. If the optional `padding` argument evaluates to `true` the resulting string will be padded with spaces to make it four characters wide, otherwise no padding will be applied.

    > = apr.strfsize(1024)
    '1.0K'
    > = apr.strfsize(1024 ^ 2)
    '1.0M'
    > = apr.strfsize(1024 ^ 3)
    '1.0G'

Here’s a simplified implementation of the UNIX command `ls -l --human-readable` which makes use of the `padding` argument to nicely line up the fields following the size:

    function ls(dirpath)
      local directory = assert(apr.dir_open(dirpath))
      for info in directory:entries() do
        io.write(info.protection, ' ')
        io.write(info.user, ' ')
        io.write(info.group, ' ')
        io.write(apr.strfsize(info.size, true), ' ')
        io.write(apr.time_format('%Y-%m-%d %H:%I', info.ctime), ' ')
        io.write(info.name, '\n')
      end
      assert(directory:close())
    end

This is what the result looks like for the source code directory of the Lua/APR project:

    > ls 'lua-apr/src'
    rw-r--r-- peter peter 5.4K 2011-01-02 22:10 apr.lua
    rw-r--r-- peter peter 4.7K 2011-01-02 06:06 base64.c
    rw-r--r-- peter peter  11K 2010-10-27 13:01 buffer.c
    rw-r--r-- peter peter  13K 2011-01-02 21:09 crypt.c
    rw-r--r-- peter peter 2.8K 2010-12-31 01:01 date.c
    rw-r--r-- peter peter 9.4K 2011-01-01 16:04 dbm.c
    rw-r--r-- peter peter 2.5K 2010-09-25 23:11 env.c
    rw-r--r-- peter peter  17K 2011-01-02 22:10 errno.c
    rw-r--r-- peter peter  10K 2011-01-02 22:10 filepath.c
    rw-r--r-- peter peter 1.9K 2011-01-02 04:04 fnmatch.c
    rw-r--r-- peter peter  12K 2010-12-31 01:01 io_dir.c
    rw-r--r-- peter peter  25K 2011-01-02 04:04 io_file.c
    rw-r--r-- peter peter  17K 2010-12-31 01:01 io_net.c
    rw-r--r-- peter peter 4.6K 2011-01-02 22:10 io_pipe.c
    rw-r--r-- peter peter  11K 2011-01-02 11:11 lua_apr.c
    rw-r--r-- peter peter 9.0K 2011-01-02 11:11 lua_apr.h
    rw-r--r-- peter peter 6.9K 2010-12-29 14:02 permissions.c
    rw-r--r-- peter peter  26K 2011-01-02 22:10 proc.c
    rw-r--r-- peter peter 866  2010-10-23 00:12 refpool.c
    rw-r--r-- peter peter 4.8K 2010-12-29 14:02 stat.c
    rw-r--r-- peter peter 3.5K 2011-01-02 22:10 str.c
    rw-r--r-- peter peter 9.8K 2010-12-31 01:01 time.c
    rw-r--r-- peter peter 4.7K 2010-09-25 23:11 uri.c
    rw-r--r-- peter peter 2.5K 2010-09-25 23:11 user.c
    rw-r--r-- peter peter 2.9K 2010-10-22 19:07 uuid.c
    rw-r--r-- peter peter 3.8K 2011-01-02 04:04 xlate.c

Note: It seems that apr.strfsize() doesn’t support terabyte range sizes.

### test coverage: 90%
`apr.tokenize_to_argv(cmdline) → arguments`

Convert the string `cmdline` to a table of arguments. On success the table of arguments is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

## Multi threading

This is an experimental multi threading module that makes it possible to execute Lua functions in dedicated Lua states and operating system threads. When you create a thread you can pass it any number of arguments and when a thread exits it can return any number of return values. In both cases the following types are valid:

- `nil`
- boolean
- number
- string (binary safe)
- any userdata object created by the Lua/APR binding

Please consider the following issues when using this module:

- When you pass a userdata object to another thread you shouldn’t use it from the original thread after that, because the Lua/APR binding doesn’t protect object access with a thread safe lock. This will probably be fixed in the near future (hey, I said it was experimental)

- When a thread object is garbage collected while the thread is still running, the Lua/APR binding will join the thread using an internal mutex and condition variable from inside the garbage collection handler. This is to avoid that the parent Lua state and the operating system process exit while the child is still running, because this can lead to hard to debug segmentation faults deep inside libc

### test coverage: 71%
`apr.thread_create(code [, ...]) → thread`

Execute the Lua code in the string argument `code` in a dedicated Lua state and operating system thread. Any extra arguments are passed onto the Lua code (where they can be accessed with the expression `...`). On success a thread object is returned, otherwise a `nil` followed by an error message is returned. You can use thread:join() to wait for the thread to finish and get its return values.

This function is binary safe.

### test coverage: 100%
`apr.thread_yield() → nothing`

Force the current thread to yield the processor. This causes the currently executing thread to temporarily pause and allow other threads to execute.

### test coverage: none
`thread:detach() → status`

Detach a thread to make the operating system automatically reclaim storage for the thread once it terminates. On success `true` is returned, otherwise `nil` followed by an error message is returned.

### test coverage: 78%
`thread:join() → status [, result, ...]`

Block until a thread stops executing and return its result. If the thread terminated with an error a `nil` followed by an error message is returned, otherwise `true` is returned, followed by any return values of the thread function.

This function is binary safe.

### test coverage: 100%
`thread:status() → status`

Returns a string describing the state of the thread:

- `'running'`: the thread is currently running
- `'done'`: the thread terminated successfully
- `'error'`: the thread encountered an error

## Thread queues

The valid types that can be transported through thread queues are documented in the multi threading module.

### test coverage: 90%
`apr.thread_queue([capacity]) → queue`

Create a FIFO queue. The optional argument `capacity` controls the maximum size of the queue and defaults to 1. On success the queue object is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 100%
`queue:push(value [, ...]) → status`

Add a tuple of one or more values to the queue. This call will block if the queue is full. On success `true` is returned, otherwise a `nil` followed by an error message and error code is returned:

- `'APR_EINTR'`: the blocking was interrupted (try again)
- `'APR_EOF'`: the queue has been terminated

This function is binary safe.

### test coverage: 100%
`queue:pop() → value [, ...]`

Get an object from the queue. This call will block if the queue is empty. On success `true` is returned, otherwise a `nil` followed by an error message and error code is returned:

- `'APR_EINTR'`: the blocking was interrupted (try again)
- `'APR_EOF'`: the queue has been terminated

This function is binary safe.

### test coverage: 100%
`queue:trypush(value [, ...]) → status`

Add a tuple of one or more values to the queue. This call doesn’t block if the queue is full. On success `true` is returned, otherwise a `nil` followed by an error message and error code is returned:

- `'APR_EINTR'`: the blocking was interrupted (try again)
- `'APR_EAGAIN'`: the queue is full
- `'APR_EOF'`: the queue has been terminated

This function is binary safe.

### test coverage: 100%
`queue:trypop() → value [, ...]`

Get an object from the queue. This call doesn’t block if the queue is empty. On success `true` is returned, otherwise a `nil` followed by an error message and error code is returned:

- `'APR_EINTR'`: the blocking was interrupted (try again)
- `'APR_EAGAIN'`: the queue is empty
- `'APR_EOF'`: the queue has been terminated

This function is binary safe.

### test coverage: none
`queue:close() → status`

Close the handle `queue` and (if no other threads are using the queue) destroy the queue and release the associated memory. This function always returns `true` (it cannot fail).

This will be done automatically when the `queue` object is garbage collected which means you don’t need to call this unless you want to reclaim memory as soon as possible.

## Time routines

Lua represents dates as numbers though the meaning of these numbers is not specified. The manual does state (in the documentation for os.time()) that on POSIX, Windows and some other systems these numbers count the number of seconds since some given start time called the epoch. This epoch is 00:00:00 January 1, 1970 UTC. The Apache Portable Runtime represents dates as the number of microseconds since that same epoch. As a compromise between the two units Lua/APR uses seconds but supports sub-second resolution in the decimal part of floating point numbers (see this thread on lua-l for discussion about the API).

### test coverage: 100%
`apr.sleep(seconds) → nothing`

Sleep for the specified number of `seconds`. Sub-second resolution is supported so you can for example give 0.5 to sleep for half a second. This function may sleep for longer than the specified time because of platform limitations.

### test coverage: 100%
`apr.time_now() → time`

Get the current time as the number of seconds since 00:00:00 January 1, 1970 UTC. If Lua is compiled with floating point support then more precision will be available in the decimal part of the returned number.

### test coverage: 87%
`apr.time_explode([time [, timezone]]) → components`

Convert the numeric value `time` (current time if none given) to its human readable components. If `timezone` isn’t given or evaluates to `false` the local timezone is used. If its a number then this number is used as the offset in seconds from GMT. The value `true` is treated the same as 0, i.e. GMT. On success the table of components is returned, otherwise a `nil` followed by an error message is returned. The resulting table contains the following fields:

- `usec` is the number of microseconds past `sec`
- `sec` is the number of seconds past `min` (0-61)
- `min` is the number of minutes past `hour` (0-59)
- `hour` is the number of hours past midnight (0-23)
- `day` is the day of the month (1-31)
- `month` is the month of the year (0-11).
- `year` is the year since 1900
- `wday` is the number of days since Sunday (0-6)
- `yday` is the number of days since January 1 (0-365)
- `gmtoff` is the number of seconds east of UTC
- `isdst` is `true` when daylight saving time is in effect

All of these fields are numbers except for `isdst` which is a boolean. Here’s an example of the output returned by apr.time_explode():

    > -- Note that numeric dates are always in UTC while tables with
    > -- date components are in the local timezone by default.
    > components = apr.time_explode(1032030336.18671)
    > = components
    {
     usec = 186710,
     sec = 36,
     min = 5,
     hour = 21,
     day = 14,
     month = 9,
     year = 2002,
     wday = 7,
     yday = 257,
     gmtoff = 7200, -- my local timezone
     isdst = true,
    }
    > -- To convert a table of date components back into a number
    > -- you can use the apr.time_implode() function as follows:
    > = apr.time_implode(components)
    1032030336.18671

### test coverage: 85%
`apr.time_implode(components) → time`

Convert a table of time `components` to its numeric value. On success the time is returned, otherwise a `nil` followed by an error message is returned. See apr.time_explode() for a list of supported components.

### test coverage: 69%
`apr.time_format(format [, time]) → formatted`

Format `time` (current time if none given) according to string `format`. On success the formatted time is returned, otherwise a `nil` followed by an error message is returned. The two special formats `'ctime'` and `'rfc822'` result in a fixed length string of 24 or 29 characters in length. The `time` argument may be either a number or a table with components like those returned by apr.time_explode().

    > = apr.time_format('%Y-%m-%d %H:%I:%S', apr.time_now())
    '2010-09-25 17:05:08'
    > = apr.time_format('ctime', apr.time_now())
    'Sat Sep 25 17:26:22 2010'
    > = apr.time_format('rfc822', apr.time_now())
    'Sat, 25 Sep 2010 15:26:36 GMT'

This function is not binary safe.

## Uniform resource identifier parsing

### test coverage: 93%
`apr.uri_parse(uri) → components`

Parse the Uniform Resource Identifier `uri`. On success a table of components is returned, otherwise a `nil` followed by an error message is returned. The table of components can have the following fields, all strings:

- `scheme` is the part of the URI before `://` (as in `http`, `ftp`, etc.)
- `user` is the user name, as in `scheme://user:pass@host:port/`
- `password` is the password, as in `scheme://user:pass@host:port/`
- `hostinfo` is the combined `[user[:password]@]hostname[:port]`
- `hostname` is the host name or IP address
- `port` is the port number
- `path` is the request path (`/` if only `scheme://hostname` was given)
- `query` is everything after a `?` in the path, if present
- `fragment` is the trailing `#fragment` string, if present

This function is not binary safe.

### test coverage: 100%
`apr.uri_unparse(components [, option]) → uri`

Convert a table of URI `components` into a URI string. On success the URI string is returned, otherwise a `nil` followed by an error message is returned. The list of fields in the `components` table is available in the documentation for apr.uri_parse(). The argument `option` may be one of the following:

- `hostinfo` to unparse the components `[user[:password]@]hostname[:port]`
- `pathinfo` to unparse the components `path[?query[#fragment]]`

This function is not binary safe.

### test coverage: 85%
`apr.uri_port_of_scheme(scheme) → port`

Return the default port for the given URI `scheme` string. Since at least APR 1.2.8 the following schemes are supported: `acap`, `ftp`, `gopher`, `http`, `https`, `imap`, `ldap`, `nfs`, `nntp`, `pop`, `prospero`, `rtsp`, `sip`, `snews`, `ssh`, `telnet`, `tip`, `wais`, `z39.50r` and `z39.50s`.

## User/group identification

### test coverage: 91%
`apr.user_get() → username, groupname`

Get the username and groupname of the calling process. On success the username and groupname are returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 87%
`apr.user_homepath_get(username) → homepath`

Get the home directory for the named user. On success the directory pathname is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

## Universally unique identifiers

Universally unique identifiers are a standard for generating unique strings that are specific to the machine on which they are generated and/or the time at which they are generated. They can be used as primary keys in databases and are used to uniquely identify file system types and instances on modern operating systems. This is what a standard format UUID looks like:

    > = apr.uuid_format(apr.uuid_get())
    '0ad5d4a4-591e-41f7-8be4-07d7961a8079'

### test coverage: 100%
`apr.uuid_get() → binary`

Generate and return a UUID as a binary string of 16 bytes.

### test coverage: 75%
`apr.uuid_format(binary) → formatted`

Format a UUID of 16 bytes following the standard format of 32 hexadecimal digits, displayed in 5 groups separated by hyphens, in the form `8-4-4-4-12` for a total of 36 characters, like `f5dc3464-6c8f-654e-a407-b15b7a30f038`. On success the formatted UUID is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: 70%
`apr.uuid_parse(formatted) → binary`

Parse a standard format UUID and return its 16-byte equivalent. On success the parsed UUID is returned, otherwise a `nil` followed by an error message is returned.

## Character encoding translation

### test coverage: 71%
`apr.xlate(input, from, to) → translated`

Translate a string of text from one character encoding to another. The `from` and `to` arguments are strings identifying the source and target character encoding. The special value `'locale'` indicates the character set of the current locale. On success the translated string is returned, otherwise a `nil` followed by an error message is returned.

Which character encodings are supported by apr.xlate() is system dependent because APR can use both the system’s iconv implementation and the bundled library apr-iconv. To get a list of valid character encoding names you can look through the apr-iconv/ccs and apr-iconv/ces directories (those are links to the web interface of the apr-iconv repository).

This function is binary safe.

## XML parsing

This module enables parsing of XML documents. Unlike LuaExpat the parsers returned by apr.xml() don’t use callbacks, instead they parse XML into a document object model which is then exposed to Lua. Because of this you can’t use apr.xml() for incremental parsing. To parse an XML document you follow these steps:

1. Create an XML parser object by calling apr.xml()
2. Parse the document by calling xml_parser:feed() repeatedly until the full document has been parsed
3. Signal to the parser that the full document has been parsed by calling xml_parser:done()
4. Get the parse information by calling xml_parser:getinfo()

Right now the only way to get the parse information is by calling xml_parser:getinfo() which converts the information to a Lua table following the Lua object model defined by LuaExpat. The Lua object model is a mapping of XML to Lua tables that’s not 100% complete (e.g. it doesn’t include namespaces) but makes it a lot easier to deal with XML in Lua.

In the future this module might expose the full XML parse tree to Lua as userdata objects, so that Lua has access to all parse information. This would also make it possible to expose the apr_xml_to_text() function.

### test coverage: 70%
`apr.xml([filename]) → xml_parser`

Create an XML parser. If the optional string `filename` is given, the file pointed to by `filename` will be parsed. On success the parser object is returned, otherwise a `nil` followed by an error message is returned.

This function is not binary safe.

### test coverage: 100%
`xml_parser:feed(input) → status`

Feed the string `input` into the XML parser. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

This function is binary safe.

### test coverage: 100%
`xml_parser:done() → status`

Terminate the parsing and save the resulting parse information. On success `true` is returned, otherwise a `nil` followed by an error message is returned.

### test coverage: none
`xml_parser:geterror() → message`

Fetch additional error information from the parser after one of its methods has failed.

### test coverage: 100%
`xml_parser:getinfo() → table`

Convert the parse information to a Lua table following the Lua Object Model defined by LuaExpat.

### test coverage: 100%
`xml_parser:close() → status`

Close the XML parser and destroy any parse information. This will be done automatically when the `xml_parser` object is garbage collected which means you don’t need to call this unless you want to reclaim memory as soon as possible (e.g. because you just parsed a large XML document).

## Miscellaneous functions

### test coverage: 100%
`apr.platform_get() → name`

Get the name of the platform for which the Lua/APR binding was compiled. Returns one of the following strings:

- `'UNIX'`
- `'WIN32'`
- `'NETWARE'`
- `'OS2'`

Please note that the labels returned by apr.platform_get() don’t imply that these platforms are fully supported; the author of the Lua/APR binding doesn’t have NETWARE and OS2 environments available for testing.

### test coverage: 100%
`apr.version_get() → apr_version [, apu_version]`

Get the version number of the Apache Portable Runtime as a string. The string contains three numbers separated by dots. These numbers have the following meaning:

- The 1st number is used for major API changes that can cause compatibility problems between the Lua/APR binding and APR library
- The 2nd number is used for minor API changes that shouldn’t impact existing functionality in the Lua/APR binding
- The 3rd number is used exclusively for bug fixes

The second return value, the version number of the APR utility library, is only available when Lua/APR is compiled against APR 1.x because in APR 2.x the utility library has been absorbed back into the APR library; there is no longer a distinction between the APR core and APR utility libraries.

This function can be useful when you want to know whether a certain bug fix has been applied to APR and/or APR-util or if you want to report a bug in APR, APR-util or the Lua/APR binding.

If you're looking for the version of the Lua/APR binding you can use the `apr._VERSION` string, but note that Lua/APR currently does not adhere to the above versioning rules.

### test coverage: 100%
`apr.os_default_encoding() → name`

Get the name of the system default character set as a string.

### test coverage: 100%
`apr.os_locale_encoding() → name`

Get the name of the current locale character set as a string. If the current locale’s data cannot be retrieved on this system, the name of the system default character set is returned instead.

### test coverage: 88%
`apr.type(object) → name`

Return the type of a userdata object created by the Lua/APR binding. If `object` is of a known type one of the following strings will be returned, otherwise nothing is returned:

- `'file'`
- `'directory'`
- `'socket'`
- `'thread'`
- `'process'`
- `'dbm'`
- `'database driver'`
- `'prepared statement'`
- `'result set'`
- `'memcache client'`
- `'memcache server'`
- `'md5 context'`
- `'sha1 context'`
- `'xml parser'`

## File system permissions

The Apache Portable Runtime represents file system permissions somewhat similar to those of UNIX. There are three categories of permissions: the user, the group and everyone else (the world). Each category supports read and write permission bits while the meaning of the third permission bit differs between categories.

### How Lua/APR presents permissions

The Lua/APR binding uses a string of 9 characters to represent file system permissions such as those returned by apr.stat(). Here’s an example:

    > = apr.stat('.', 'protection')
    'rwxr-xr-x'

This is the syntax of these permissions strings:

- Character 1: `r` if the user has read permissions, `-` otherwise
- Character 2: `w` if the user has write permissions, `-` otherwise
- Character 3: `x` if the user has execute permissions, `S` if the user has set user id permissions or `s` if the user has both permissions
- Characters 4..6: the same respective permissions for the group
- Characters 7..8: the same respective permissions for the world
- Character 9: `x` if the world has execute permissions, `T` if the world has sticky permissions or `t` if the world has both permissions

As an example, `rwxrwx---` means the user and group have full permissions while the world has none. Another example: `r-xr-xr-x` means no-one has write permissions.

### How you can request permissions

When you need to request file system permissions for an operation like reading or copying a file there are two string formats you can use. The first format is a string of nine characters that lists each permission explicitly. This is the format documented above.

The second format is very flexible and is one of the formats accepted by the Linux command line program chmod. The permissions are split in three groups with a one-letter code: user is `u`, group is `g` and world is `o` (for “others”). One or more permissions can then be assigned to one or more of these groups. Here’s an example that requests read permission for user, group and others: `ugo=r`. Now when you also need write permission for user and group, you can use `ugo=r,ug=w`.

## Error handling

Most functions in the Lua/APR binding follow the Lua idiom of returning `nil` followed by an error message string. These functions also return a third argument which is the symbolic name of the error (or the error code in case a symbolic name cannot be determined). The following symbolic names are currently defined (there’s actually a lot more but they shouldn’t be relevant when working in Lua):

- `'ENOSTAT'`: APR was unable to perform a stat on the file
- `'EBADDATE'`: APR was given an invalid date
- `'EINVALSOCK'`: APR was given an invalid socket
- `'ENOPROC'`: APR was not given a process structure
- `'ENOTIME'`: APR was not given a time structure
- `'ENODIR'`: APR was not given a directory structure
- `'ENOTHREAD'`: APR was not given a thread structure
- `'EBADIP'`: the specified IP address is invalid
- `'EBADMASK'`: the specified netmask is invalid
- `'EDSOOPEN'`: APR was unable to open the DSO object
- `'EABSOLUTE'`: the given path was absolute
- `'ERELATIVE'`: the given path was relative
- `'EINCOMPLETE'`: the given path was neither relative nor absolute
- `'EABOVEROOT'`: the given path was above the root path
- `'EBADPATH'`: the given path was bad
- `'EPATHWILD'`: the given path contained wildcards
- `'ESYMNOTFOUND'`: could not find the requested symbol
- `'EPROC_UNKNOWN'`: the given process was not recognized by APR
- `'ENOTENOUGHENTROPY'`: APR could not gather enough entropy to continue
- `'TIMEUP'`: the operation did not finish before the timeout
- `'INCOMPLETE'`: the operation was incomplete although some processing was performed and the results are partially valid
- `'EOF'`: APR has encountered the end of the file
- `'ENOTIMPL'`: the APR function has not been implemented on this platform, either because nobody has gotten to it yet, or the function is impossible on this platform
- `'EMISMATCH'`: two passwords do not match
- `'EACCES'`: permission denied
- `'EEXIST'`: file exists
- `'ENAMETOOLONG'`: path name is too long
- `'ENOENT'`: no such file or directory
- `'ENOTDIR'`: not a directory
- `'ENOSPC'`: no space left on device
- `'ENOMEM'`: not enough memory
- `'EMFILE'`: too many open files
- `'ENFILE'`: file table overflow
- `'EBADF'`: bad file number
- `'EINVAL'`: invalid argument
- `'ESPIPE'`: illegal seek
- `'EAGAIN'`: operation would block
- `'EINTR'`: interrupted system call
- `'ENOTSOCK'`: socket operation on a non-socket
- `'ECONNREFUSED'`: connection refused
- `'EINPROGRESS'`: operation now in progress
- `'ECONNABORTED'`: software caused connection abort
- `'ECONNRESET'`: connection Reset by peer
- `'ETIMEDOUT'`: operation timed out (deprecated)
- `'EHOSTUNREACH'`: no route to host
- `'ENETUNREACH'`: network is unreachable
- `'EFTYPE'`: inappropriate file type or format
- `'EPIPE'`: broken pipe
- `'EXDEV'`: cross device link
- `'ENOTEMPTY'`: directory not empty
- `'EAFNOSUPPORT'`: address family not supported

Note that the error descriptions above were copied verbatim from apr_errno.h.

## Example: HTTP client

The following Lua script implements a minimal HTTP client which can be used to download a given URL on the command line (comparable to wget and curl):

    $ FILE=lua-5.1.4.tar.gz
    $ URL=http://www.lua.org/ftp/$FILE
    $ time curl -s $URL > $FILE
    0,01s user 0,02s system 6% cpu 0,465 total
    $ time lua examples/download.lua $URL > $FILE
    0,03s user 0,02s system 9% cpu 0,549 total

Note that this script and Lua/APR in general are a bit handicapped in that they don’t support HTTPS because the Apache Portable Runtime does not support encrypted network communication.

    local apr = require 'apr'

    -- Report errors without stack traces.
    local function assert(...)
      local status, message = ...
      if not status then
        io.stderr:write('Error: ', message or '(no message)', '\n')
        os.exit(1)
      end
      return ...
    end

    local function getpage(url)
      local components = assert(apr.uri_parse(url))
      assert(components.scheme == 'http', "invalid protocol!")
      local port = assert(components.port or apr.uri_port_of_scheme(components.scheme))
      local socket = assert(apr.socket_create())
      assert(socket:connect(components.hostname, port))
      local pathinfo = assert(apr.uri_unparse(components, 'pathinfo'))
      assert(socket:write('GET ', pathinfo, ' HTTP/1.0\r\n',
                          'Host: ', components.hostname, '\r\n',
                          '\r\n'))
      local statusline = assert(socket:read(), 'HTTP response missing status line!')
      local protocol, statuscode, reason = assert(statusline:match '^(%S+)%s+(%S+)%s+(.-)$')
      local redirect = statuscode:find '^30[123]$'
      for line in socket:lines() do
        local name, value = line:match '^(%S+):%s+(.-)\r?$'
        if name and value then
          if redirect and name:lower() == 'location' then
            io.stderr:write("Following redirect to ", value, " ..\n")
            return getpage(value)
          end
        else
          return (assert(socket:read '*a', 'HTTP response missing body?!'))
        end
      end
      if statuscode ~= '200' then error(reason) end
    end

    local usage = "Please provide a URL to download as argument"
    io.write(getpage(assert(arg and arg[1], usage)))

    -- vim: ts=2 sw=2 et

## Example: Single threaded webserver

The following script implements a minimalistic webserver on top of Lua/APR. It should work out of the box on Windows and UNIX, although you might get a prompt from your firewall. Once the server is running you can open http://localhost:8080 in your web browser to see the server in action. Because the server is single threaded I was curious how bad it would perform, so I tested it with ApacheBench:

    $ lua examples/webserver.lua &
    $ ab -qt5 http://localhost:8080/ | grep 'Requests per second\|Transfer rate'
    Requests per second:    3672.19 [#/sec] (mean)
    Transfer rate:          2201.88 [Kbytes/sec] received

That’s not too bad for 40 lines of code! Here is the script:

    local port_number = tonumber(arg[1]) or 8080
    local bind_address = arg[2] or '*'

    -- Load the Lua/APR binding.
    local apr = require 'apr'

    -- Initialize the server socket.
    local server = assert(apr.socket_create())
    assert(server:bind(bind_address, port_number))
    assert(server:listen(1))
    print("Running webserver on http://" .. bind_address .. ":" .. port_number .. " ..")

    -- Wait for clients to serve.
    local visitor = 1
    local template = [[
    <html>
      <head>
        <title>Hello from Lua/APR!</title>
        <style type="text/css">
          body { font-family: sans-serif; }
          dt { font-weight: bold; }
          dd { font-family: monospace; margin: -1.4em 0 0 14em; }
        </style>
      </head>
      <body>
        <h1>Hello from Lua/APR!</h1>
        <p><em>You are visitor number %010i.</em></p>
        <p>The headers provided by your web browser:</p>
        <dl>%s</dl>
      </body>
    </html>
    ]]
    while true do
      local status, message = pcall(function()
        local client = assert(server:accept())
        -- Read the HTTP request so that the client can receive data.
        local request = assert(client:read(), "Failed to receive request from client!")
        local method, location, protocol = assert(request:match '^(%w+)%s+(%S+)%s+(%S+)')
        local headers = {}
        for line in client:lines() do
          local name, value = line:match '^(%S+):%s+(.-)$'
          if not name then break end
          table.insert(headers, '<dt>' .. name .. ':</dt><dd>' .. value .. '</dd>')
        end
        -- Generate the HTTP response.
        table.sort(headers)
        content = template:format(visitor, table.concat(headers))
        client:write(protocol, ' 200 OK\r\n',
                     'Content-Type: text/html\r\n',
                     'Content-Length: ' .. #content .. '\r\n',
                     'Connection: close\r\n',
                     '\r\n',
                     content)
        assert(client:close())
        visitor = visitor + 1
      end)
      if not status then
        print('Error while serving request:', message)
      end
    end

    -- vim: ts=2 sw=2 et

## Example: Multi threaded webserver

Thanks to the multi threading and thread queue modules in the Apache Portable Runtime it is possible to improve the performance of the single threaded webserver from the previous example. Here is a benchmark of the multi threaded implementation listed below (again using ApacheBench, but now with the `-c` argument):

    $ NUM_THREADS=4
    $ lua examples/threaded-webserver.lua $NUM_THREADS &
    $ ab -qt5 -c$NUM_THREADS http://localhost:8080/ | grep 'Requests per second\|Transfer rate'
    Requests per second:    9210.72 [#/sec] (mean)
    Transfer rate:          5594.79 [Kbytes/sec] received

Comparing these numbers to the benchmark of the single threaded webserver we can see that the number of requests per second went from 3670 to 9210, more than doubling the throughput of the webserver on a dual core processor.

Note that both benchmarks were run on my Compaq Presario CQ60 laptop (which features an Intel Core 2 Duo T5800 processor clocked at 2 GHz and 3 GB of RAM) and that the Lua/APR binding was compiled without debugging symbols.

    local num_threads = tonumber(arg[1]) or 2
    local port_number = tonumber(arg[2]) or 8080

    local template = [[
    <html>
      <head>
        <title>Hello from Lua/APR!</title>
        <style type="text/css">
          body { font-family: sans-serif; }
          dt { font-weight: bold; }
          dd { font-family: monospace; margin: -1.4em 0 0 14em; }
        </style>
      </head>
      <body>
        <h1>Hello from Lua/APR!</h1>
        <p><em>This web page was served by worker %i.</em></p>
        <p>The headers provided by your web browser:</p>
        <dl>%s</dl>
      </body>
    </html>
    ]]

    -- Load the Lua/APR binding.
    local apr = require 'apr'

    -- Initialize the server socket.
    local server = assert(apr.socket_create())
    assert(server:bind('*', port_number))
    assert(server:listen(num_threads * 2))
    print("Running webserver with " .. num_threads .. " client threads on http://localhost:" .. port_number .. " ..")

    -- Create the thread queue (used to pass sockets between threads).
    local queue = apr.thread_queue(num_threads)

    -- Define the function to execute in each child thread.
    function worker(thread_id, queue, template)
      pcall(require, 'luarocks.require')
      local apr = require 'apr'
      while true do
        local client, msg, code = queue:pop()
        assert(client or code == 'EINTR', msg)
        if client then
          local status, message = pcall(function()
            local request = assert(client:read(), "Failed to receive request from client!")
            local method, location, protocol = assert(request:match '^(%w+)%s+(%S+)%s+(%S+)')
            local headers = {}
            for line in client:lines() do
              local name, value = line:match '^(%S+):%s+(.-)$'
              if not name then
                break
              end
              table.insert(headers, '<dt>' .. name .. ':</dt><dd>' .. value .. '</dd>')
            end
            table.sort(headers)
            local content = template:format(thread_id, table.concat(headers))
            client:write(protocol, ' 200 OK\r\n',
                         'Content-Type: text/html\r\n',
                         'Content-Length: ' .. #content .. '\r\n',
                         'Connection: close\r\n',
                         '\r\n',
                         content)
            assert(client:close())
          end)
          if not status then
            print('Error while serving request:', message)
          end
        end
      end
    end

    -- We could give apr.thread_create() a string of Lua code but by using byte
    -- code instead we enable syntax highlighting and we preserve filename and line
    -- numbers in Lua's traceback messages (this makes debugging less of a pain).
    local bytecode = string.dump(worker)

    -- Create the child threads and keep them around in a table (so that they are
    -- not garbage collected while we are still using them).
    local pool = {}
    for i = 1, num_threads do
      table.insert(pool, assert(apr.thread_create(bytecode, i, queue, template)))
    end

    -- Enter the accept() loop in the parent thread.
    while true do
      local status, message = pcall(function()
        local client = assert(server:accept())
        assert(queue:push(client))
      end)
      if not status then
        print('Error while serving request:', message)
      end
    end

    -- vim: ts=2 sw=2 et