changeset 1:e1309515d111

Add README file and manpages
author Guido Berhoerster <guido+libpws@berhoerster.name>
date Wed, 25 Mar 2015 17:10:23 +0100
parents d541e748cfd8
children 97097b4b6bfb
files Makefile README docbook-update-source-data.xsl libpws.3.xml pws3_file_create.3.xml pws_init.3.xml
diffstat 6 files changed, 2042 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Feb 10 11:29:54 2015 +0100
+++ b/Makefile	Wed Mar 25 17:10:23 2015 +0100
@@ -45,6 +45,45 @@
 PAX :=		pax
 GZIP :=		gzip
 SED :=		sed
+XSLTPROC :=	xsltproc
+DOCBOOK5_MANPAGES_STYLESHEET =	http://docbook.sourceforge.net/release/xsl-ns/current/manpages/docbook.xsl
+DOCBOOK5_MANPAGES_FLAGS =	--stringparam funcsynopsis.style 'ansi' \
+				--stringparam man.authors.section.enabled 0 \
+				--stringparam man.copyright.section.enabled 0
+DOCBOOK5_XHTML_STYLESHEET =	http://docbook.sourceforge.net/release/xsl-ns/current/xhtml/docbook.xsl
+DOCBOOK5_XHTML_FLAGS =		--stringparam funcsynopsis.style 'ansi' \
+				--stringparam generate.consistent.ids 1 \
+				--stringparam refentry.generate.name 1 \
+				--stringparam refentry.generate.title 0 \
+				--stringparam refentry.xref.manvolnum 1 \
+				--stringparam generate.id.attributes 1 \
+				--stringparam make.valid.html 1 \
+				--stringparam make.clean.html 1 \
+				--stringparam html.cleanup 1 \
+				--stringparam html.longdesc 0 \
+				--stringparam ulink.target '' \
+				--stringparam docbook.css.source '' \
+				--stringparam css.decoration 0 \
+				--stringparam default.table.width '100%'
+
+define generate-manpage-rule =
+$(addsuffix .%,$(basename $1)): $(addsuffix .%.xml,$(basename $(firstword $1))) docbook-update-source-data.xsl
+	$$(XSLTPROC) \
+	    --xinclude \
+	    --stringparam package $$(PACKAGE) \
+	    --stringparam version $$(VERSION) \
+	    docbook-update-source-data.xsl $$< | \
+	    $$(XSLTPROC) \
+	    --xinclude \
+	    --output $(firstword $1) \
+	    $$(DOCBOOK5_MANPAGES_FLAGS) \
+	    $$(DOCBOOK5_MANPAGES_STYLESHEET) \
+	    -
+	$$(SED) 's,^\.HP \\w.*$$$$,.HP 4n,' $$@ >$$(@).tmp && mv $$(@).tmp $$@
+	for alias in $(wordlist 2,$(words $1),$1); do \
+	    ln -sf $(notdir $(firstword $1)) $$$$alias; \
+	done
+endef
 
 DESTDIR ?=
 prefix ?=	/usr/local
@@ -104,11 +143,78 @@
 
 OBJS =			$(LIBPWS_OBJS)
 
+LIBPWS_MANPAGES =	libpws.3
+
+PWS_INIT_MANPAGES =	pws_init.3 \
+			pws_finalize.3 \
+			pws_set_alloc_functions.3 \
+			pws_generate_uuid.3
+
+PWS3_FILE_CREATE_MANPAGES = pws3_file_create.3 \
+			pws3_file_destroy.3 \
+			pws3_file_get_error_code.3 \
+			pws3_file_get_error_message.3 \
+			pws3_file_read_mem.3 \
+			pws3_file_read_stream.3 \
+			pws3_file_write_mem.3 \
+			pws3_file_write_stream.3 \
+			pws3_file_set_header_field.3 \
+			pws3_file_get_header_field.3 \
+			pws3_file_remove_header_field.3 \
+			pws3_file_insert_empty_group.3 \
+			pws3_file_get_empty_group.3 \
+			pws3_file_remove_empty_group.3 \
+			pws3_file_first_empty_group.3 \
+			pws3_file_last_empty_group.3 \
+			pws3_file_next_empty_group.3 \
+			pws3_file_prev_empty_group.3 \
+			pws3_file_insert_record.3 \
+			pws3_file_get_record.3 \
+			pws3_file_remove_record.3 \
+			pws3_file_first_record.3 \
+			pws3_file_last_record.3 \
+			pws3_file_next_record.3 \
+			pws3_file_prev_record.3 \
+			pws3_field_create.3 \
+			pws3_field_destroy.3 \
+			pws3_field_is_header.3 \
+			pws3_field_get_type.3 \
+			pws3_field_get_data_type.3 \
+			pws3_field_set_uuid.3 \
+			pws3_field_set_text.3 \
+			pws3_field_set_time.3 \
+			pws3_field_set_uint8.3 \
+			pws3_field_set_uint16.3 \
+			pws3_field_set_uint32.3 \
+			pws3_field_set_bytes.3 \
+			pws3_field_get_uuid.3 \
+			pws3_field_get_text.3 \
+			pws3_field_get_time.3 \
+			pws3_field_get_uint8.3 \
+			pws3_field_get_uint16.3 \
+			pws3_field_get_uint32.3 \
+			pws3_field_get_bytes.3 \
+			pws3_record_create.3 \
+			pws3_record_destroy.3 \
+			pws3_record_set_field.3 \
+			pws3_record_get_field.3 \
+			pws3_record_remove_field.3
+
+MANPAGES =		$(LIBPWS_MANPAGES) \
+			$(PWS_INIT_MANPAGES) \
+			$(PWS3_FILE_CREATE_MANPAGES)
+
+XHTML_DOCUMENTATION =	$(addsuffix .xhtml,$(firstword $(LIBPWS_MANPAGES)) \
+			$(firstword $(PWS_INIT_MANPAGES)) \
+			$(firstword $(PWS3_FILE_CREATE_MANPAGES)))
+
 .DEFAULT_TARGET = all
 
 .PHONY: all clean clobber dist install
 
-all: $(LIBPWS_LIB)
+all: $(LIBPWS_LIB) $(MANPAGES)
+
+doc: $(MANPAGES) $(XHTML_DOCUMENTATION)
 
 XCPPFLAGS = -Iinclude
 ifeq ($(HAVE_ARC4RANDOM),1)
@@ -146,6 +252,12 @@
 
 $(LIBPWS_LIB): $(LIBPWS_LIB_MEMBERS)
 
+$(eval $(call generate-manpage-rule,$(LIBPWS_MANPAGES)))
+
+$(eval $(call generate-manpage-rule,$(PWS_INIT_MANPAGES)))
+
+$(eval $(call generate-manpage-rule,$(PWS3_FILE_CREATE_MANPAGES)))
+
 %.o: %.c
 	$(MAKEDEPEND.c) $< | $(SED) -f deps.sed >$*.d
 	$(COMPILE.c) -o $@ $<
@@ -154,16 +266,39 @@
 	$(AR) $(ARFLAGS) $@ $<
 	$(RANLIB) $@
 
+%.xhtml: %.xml docbook-update-source-data.xsl
+	$(XSLTPROC) \
+	    --xinclude \
+	    --stringparam package $(PACKAGE) \
+	    --stringparam version $(VERSION) \
+	    docbook-update-source-data.xsl $< | \
+	    $(XSLTPROC) \
+	    --xinclude \
+	    --output $@ \
+	    $(DOCBOOK5_XHTML_FLAGS) \
+	    $(DOCBOOK5_XHTML_STYLESHEET) \
+	    -
+
 install:
 	for header in include/*.h; do \
 	    $(INSTALL.data) $${header} \
-	        "$(DESTDIR)$(includedir)/$(PACKAGE)/$${header##*/}"; \
+	        "$(DESTDIR)$(includedir)/$${header##*/}"; \
 	done
 	$(INSTALL.lib) $(LIBPWS_LIB) \
 	    "$(DESTDIR)$(libdir)/$(notdir $(LIBPWS_LIB))"
+	for manpage in $(MANPAGES); do \
+	    if [ -L $${manpage} ]; then \
+	        $(INSTALL.link) $${manpage} \
+	            "$(DESTDIR)$(mandir)/man$${manpage##*.}/$${manpage##*/}"; \
+	    else \
+	        $(INSTALL.data) $${manpage} \
+	            "$(DESTDIR)$(mandir)/man$${manpage##*.}/$${manpage##*/}"; \
+	    fi \
+	done
 
 clean:
-	rm -f $(LIBPWS_LIB) $(LIBPWS_OBJS)
+	rm -f $(LIBPWS_LIB) $(LIBPWS_OBJS) $(MANPAGES) \
+	    $(XHTML_DOCUMENTATION)
 
 clobber: clean
 	rm -f $(patsubst %.o,%.d,$(OBJS))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Wed Mar 25 17:10:23 2015 +0100
@@ -0,0 +1,103 @@
+libpws
+=======
+
+Description
+-----------
+
+libpws provides an API for creating, reading, manipulating and writing
+Password Safe files, it currently supports version 3 of the Password Safe file
+format.
+
+Build Instructions
+------------------
+
+libpws requires a POSIX:2004 compatible operating system, it has been tested
+to work on Linux distributions, FreeBSD, Solaris and Illumos-derived
+distributions.  The following tools and shared libraries are required to build
+libpws:
+
+- GNU make >= 3.81
+- GNU or BSD install
+- Nettle
+
+Rebuilding the man pages additionally requires the xsltproc tool from libxml2.
+
+Before building libpws check the commented macros in the Makefile for any
+macros you may need to override depending on the used toolchain and operating
+system.
+
+By default, all files will be installed under the "/usr/local" directory, a
+different installation path prefix can be set via the `prefix` macro.  In
+addition, a second path prefix can be specified via the `DESTDIR` macro which
+will be prepended to any path, incuding the `prefix` macro path prefix.  In
+contrast to `prefix`, the path specified via the `DESTDIR` macro will only be
+prepended to paths during installation and not be used for constructing
+internal paths.
+
+The following instructions assume that `make` is GNU make, on some platforms
+it may be installed under a different name or a non-default path.  In order to
+start the build process run `make all`.  After a successful build, run `make
+install` to install the program, any associated data files and the
+documentation.
+
+Previously built binaries, object files, generated data files and
+documentation can be removed by running `make clean`, any additional,
+generated files which are not removed by the `clean` target can be removed by
+running `make clobber`.
+
+Contact
+-------
+
+Please send any feedback, translations or bug reports via email to
+<guido+libpws@berhoerster.name>.
+
+Bug Reports
+-----------
+
+When sending bug reports, please always mention the exact version of libpws
+with which the issue occurs as well as the version of the operating system you
+are using and make sure that you provide sufficient information to reproduce
+the issue and include any input, output, any error messages.
+
+In case of build issues, please also specify the implementations and versions
+of the tools and shared libraries used to build the program, in particular the
+compiler.
+
+In case of crashes, please generate a stack trace with a suitable debugger
+such as gdb, lldb, dbx, or debug after a crash has occurred either by
+examining the resulting core file or by running the program from the debugger
+and attach it to the bug report.  In order to generate a meaningful stack
+trace the program as well as any dynamically linked libraries need to be built
+with debugging information, see the documentation of the used compiler for the
+required compiler flags.  If any of the dynamically linked shared libraries do
+not contain debugging information, please either install debugging information
+for these libraries using mechanisms provided by your operating system or
+rebuild the libraries accordingly.  Please refer to the documentation of the
+debugger for detailed instructions on generating backtraces.
+
+License
+-------
+
+Except otherwise noted, all files are Copyright (C) 2015 Guido Berhoerster and
+distributed under the following license terms:
+
+Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docbook-update-source-data.xsl	Wed Mar 25 17:10:23 2015 +0100
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<xsl:stylesheet
+  version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:db="http://docbook.org/ns/docbook"
+  xmlns="http://docbook.org/ns/docbook"
+  exclude-result-prefixes="xsl db">
+
+  <xsl:param name="package" select="''" />
+  <xsl:param name="version" select="''" />
+
+  <xsl:template match="db:refmeta/db:refmiscinfo[@class = 'source' or
+    @class = 'version']"/>
+
+  <xsl:template match="db:refmeta">
+    <xsl:copy>
+      <xsl:apply-templates/>
+      <refmiscinfo class="source"><xsl:value-of select="$package"/></refmiscinfo>
+      <refmiscinfo class="version"><xsl:value-of select="$version"/></refmiscinfo>
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="@*|node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpws.3.xml	Wed Mar 25 17:10:23 2015 +0100
@@ -0,0 +1,213 @@
+<?xml version="1.0"?>
+<!--
+
+Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+<refentry xmlns="http://docbook.org/ns/docbook"
+  xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en">
+  <info>
+    <author>
+      <personname>
+        <firstname>Guido</firstname>
+        <surname>Berhoerster</surname>
+      </personname>
+      <email>guido+libpws@berhoerster.name</email>
+      <personblurb/>
+    </author>
+    <date>21 March, 2015</date>
+  </info>
+  <refmeta>
+    <refentrytitle>libpws</refentrytitle>
+    <manvolnum>3</manvolnum>
+    <refmiscinfo class="source"/>
+    <refmiscinfo class="version"/>
+    <refmiscinfo class="manual">Library Functions</refmiscinfo>
+  </refmeta>
+  <refnamediv>
+    <refname>libpws</refname>
+    <refpurpose>library for creating and manipulating Password Safe files</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>cc</command>
+      <arg choice="opt" rep="repeat">
+        <option>flag</option>
+      </arg>
+      <arg choice="plain" rep="repeat">
+        <option>file</option>
+      </arg>
+      <arg choice="plain">
+        <option>-lpws</option>
+      </arg>
+      <arg choice="plain">
+        <option>-lnettle</option>
+      </arg>
+      <arg choice="opt" rep="repeat">
+        <option>library</option>
+      </arg>
+    </cmdsynopsis>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;pws.h&gt;
+</funcsynopsisinfo>
+    </funcsynopsis>
+  </refsynopsisdiv>
+  <refsect1>
+    <title>Description</title>
+    <para>libpws provides an API for creating, reading, manipulating and
+    writing Password Safe files. The Password Safe file format is intended
+    for the platform-independent secure storage of passwords and associated
+    metadata and offers protection from unauthorized access to the file by
+    encrypting it using a key derived from a master password. Its design
+    ensures both confidentiality and integrity of its contents.</para>
+    <para>libpws currently supports version 3 of the Password Safe file
+    format.</para>
+    <para>The <literal>&lt;<filename
+    class="header">pws.h</filename>&gt;</literal> header provides type and
+    function declarations for all library services.</para>
+    <para>With the exception of <function>pws_set_alloc_functions</function>
+    all functions are reentrant. Functions operating on a Password Safe file
+    structure, a header field structure, a record field structure, and a record
+    structure provide no locking. A multithreaded application must either
+    provide its own synchronization mechanisms or restrict operations on any of
+    the above structures to a single thread.</para>
+  </refsect1>
+  <refsect1>
+    <title>Interfaces</title>
+    <para>The static library <filename class="libraryfile">libpws.a</filename>
+    provides following the public interfaces:
+    <simplelist type="vert" columns="2">
+      <member><function>pws_init</function></member>
+      <member><function>pws_finalize</function></member>
+      <member><function>pws_set_alloc_functions</function></member>
+      <member><function>pws_generate_uuid</function></member>
+      <member><function>pws3_field_create</function></member>
+      <member><function>pws3_field_destroy</function></member>
+      <member><function>pws3_field_is_header</function></member>
+      <member><function>pws3_field_get_type</function></member>
+      <member><function>pws3_field_get_data_type</function></member>
+      <member><function>pws3_field_set_uuid</function></member>
+      <member><function>pws3_field_set_text</function></member>
+      <member><function>pws3_field_set_time</function></member>
+      <member><function>pws3_field_set_uint8</function></member>
+      <member><function>pws3_field_set_uint16</function></member>
+      <member><function>pws3_field_set_uint32</function></member>
+      <member><function>pws3_field_set_bytes</function></member>
+      <member><function>pws3_field_get_uuid</function></member>
+      <member><function>pws3_field_get_text</function></member>
+      <member><function>pws3_field_get_time</function></member>
+      <member><function>pws3_field_get_uint8</function></member>
+      <member><function>pws3_field_get_uint16</function></member>
+      <member><function>pws3_field_get_uint32</function></member>
+      <member><function>pws3_field_get_bytes</function></member>
+      <member><function>pws3_file_create</function></member>
+      <member><function>pws3_file_destroy</function></member>
+      <member><function>pws3_file_get_error_code</function></member>
+      <member><function>pws3_file_get_error_message</function></member>
+      <member><function>pws3_file_read_mem</function></member>
+      <member><function>pws3_file_read_stream</function></member>
+      <member><function>pws3_file_write_mem</function></member>
+      <member><function>pws3_file_write_stream</function></member>
+      <member><function>pws3_file_set_header_field</function></member>
+      <member><function>pws3_file_get_header_field</function></member>
+      <member><function>pws3_file_remove_header_field</function></member>
+      <member><function>pws3_file_insert_empty_group</function></member>
+      <member><function>pws3_file_get_empty_group</function></member>
+      <member><function>pws3_file_remove_empty_group</function></member>
+      <member><function>pws3_file_first_empty_group</function></member>
+      <member><function>pws3_file_last_empty_group</function></member>
+      <member><function>pws3_file_next_empty_group</function></member>
+      <member><function>pws3_file_prev_empty_group</function></member>
+      <member><function>pws3_file_insert_record</function></member>
+      <member><function>pws3_file_get_record</function></member>
+      <member><function>pws3_file_remove_record</function></member>
+      <member><function>pws3_file_first_record</function></member>
+      <member><function>pws3_file_last_record</function></member>
+      <member><function>pws3_file_next_record</function></member>
+      <member><function>pws3_file_prev_record</function></member>
+    </simplelist></para>
+    <para>It defines the following C preprocessor macros which are documented
+        in the
+        <citerefentry><refentrytitle>pws_init</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+        manual page:
+    <simplelist type="vert">
+      <member><function>LIBPWS_VERSION_MAJOR</function></member>
+      <member><function>LIBPWS_VERSION_MINOR</function></member>
+      <member><function>LIBPWS_VERSION_MICRO</function></member>
+      <member><function>PWS3_VERSION</function></member>
+      <member><function>PWS3_MAX_FIELD_SIZE</function></member>
+      <member><function>PWS3_MAX_PASSWORD_LEN</function></member>
+      <member><function>PWS3_UUID_SIZE</function></member>
+    </simplelist></para>
+  </refsect1>
+  <refsect1>
+    <title>Types</title>
+    <para>libpws provides the following data structures:
+    <variablelist>
+      <varlistentry>
+        <term>struct pws3_file</term>
+        <listitem>
+          <para>Opaque data structure representing a Password Safe version 3
+          file.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>struct pws3_record</term>
+        <listitem>
+          <para>Opaque data structure representing a Password Safe version 3
+          record.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>struct pws3_field</term>
+        <listitem>
+          <para>Opaque data structure representing a Password Safe version 3
+            typed field belonging to the header or a record, depending on the
+            type it may hold a UUID, string, time, 8-bit, 16-bit, or 32-bit
+            wide unsigned integer or raw data.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist></para>
+  </refsect1>
+  <refsect1>
+    <title>Security</title>
+    <para>The aforementioned protection of confidentiality and integrity of
+    the file contents only applies to the stored file. When reading a Password
+    Safe file using libpws, the file contents are decrypted and stored in
+    memory where they might be compromised, e.g. by a malicious application or
+    a privileged user. Furthermore, parts of the process memory may be paged to
+    the swap area by the operating system.</para>
+    <para>libpws provides hooks for allocating and freeing memory used to
+    store sensitive information which may be used to mitigate such issues
+    using operating system specific facilities.</para>
+    <para>libpws has not been formally audited, use at your own risk.</para>
+  </refsect1>
+  <refsect1>
+    <title>See Also</title>
+    <para><citerefentry><refentrytitle>pws_init</refentrytitle>
+      <manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>pws3_file_create</refentrytitle>
+      <manvolnum>3</manvolnum></citerefentry>, <link
+      xlink:href="https://pwsafe.org/"/></para>
+  </refsect1>
+</refentry>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pws3_file_create.3.xml	Wed Mar 25 17:10:23 2015 +0100
@@ -0,0 +1,1400 @@
+<?xml version="1.0"?>
+<!--
+
+Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+<refentry xmlns="http://docbook.org/ns/docbook"
+  xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en">
+  <info>
+    <author>
+      <personname>
+        <firstname>Guido</firstname>
+        <surname>Berhoerster</surname>
+      </personname>
+      <email>guido+libpws@berhoerster.name</email>
+      <personblurb/>
+    </author>
+    <date>21 March, 2015</date>
+  </info>
+  <refmeta>
+    <refentrytitle>libpws</refentrytitle>
+    <manvolnum>3</manvolnum>
+    <refmiscinfo class="source"/>
+    <refmiscinfo class="version"/>
+    <refmiscinfo class="manual">Library Functions</refmiscinfo>
+  </refmeta>
+  <refnamediv>
+    <refname>pws3_file_create</refname>
+    <refname>pws3_file_destroy</refname>
+    <refname>pws3_file_get_error_code</refname>
+    <refname>pws3_file_get_error_message</refname>
+    <refname>pws3_file_read_mem</refname>
+    <refname>pws3_file_read_stream</refname>
+    <refname>pws3_file_write_mem</refname>
+    <refname>pws3_file_write_stream</refname>
+    <refname>pws3_file_set_header_field</refname>
+    <refname>pws3_file_get_header_field</refname>
+    <refname>pws3_file_remove_header_field</refname>
+    <refname>pws3_file_insert_empty_group</refname>
+    <refname>pws3_file_get_empty_group</refname>
+    <refname>pws3_file_remove_empty_group</refname>
+    <refname>pws3_file_first_empty_group</refname>
+    <refname>pws3_file_last_empty_group</refname>
+    <refname>pws3_file_next_empty_group</refname>
+    <refname>pws3_file_prev_empty_group</refname>
+    <refname>pws3_file_insert_record</refname>
+    <refname>pws3_file_get_record</refname>
+    <refname>pws3_file_remove_record</refname>
+    <refname>pws3_file_first_record</refname>
+    <refname>pws3_file_last_record</refname>
+    <refname>pws3_file_next_record</refname>
+    <refname>pws3_file_prev_record</refname>
+    <refname>pws3_field_create</refname>
+    <refname>pws3_field_destroy</refname>
+    <refname>pws3_field_is_header</refname>
+    <refname>pws3_field_get_type</refname>
+    <refname>pws3_field_get_data_type</refname>
+    <refname>pws3_field_set_uuid</refname>
+    <refname>pws3_field_set_text</refname>
+    <refname>pws3_field_set_time</refname>
+    <refname>pws3_field_set_uint8</refname>
+    <refname>pws3_field_set_uint16</refname>
+    <refname>pws3_field_set_uint32</refname>
+    <refname>pws3_field_set_bytes</refname>
+    <refname>pws3_field_get_uuid</refname>
+    <refname>pws3_field_get_text</refname>
+    <refname>pws3_field_get_time</refname>
+    <refname>pws3_field_get_uint8</refname>
+    <refname>pws3_field_get_uint16</refname>
+    <refname>pws3_field_get_uint32</refname>
+    <refname>pws3_field_get_bytes</refname>
+    <refname>pws3_record_create</refname>
+    <refname>pws3_record_destroy</refname>
+    <refname>pws3_record_set_field</refname>
+    <refname>pws3_record_get_field</refname>
+    <refname>pws3_record_remove_field</refname>
+    <refpurpose>create and manipulate Password Safe File Version 3
+    files</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>cc</command>
+      <arg choice="opt" rep="repeat">
+        <option>flag</option>
+      </arg>
+      <arg choice="plain" rep="repeat">
+        <option>file</option>
+      </arg>
+      <arg choice="plain">
+        <option>-lpws</option>
+      </arg>
+      <arg choice="plain">
+        <option>-lnettle</option>
+      </arg>
+      <arg choice="opt" rep="repeat">
+        <option>library</option>
+      </arg>
+    </cmdsynopsis>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;pws.h&gt;
+</funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>struct pws3_file
+        *<function>pws3_file_create</function></funcdef>
+        <void/>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws3_file_destroy</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>enum pws_error_code
+        <function>pws3_file_get_error_code</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>const char *
+        <function>pws3_file_get_error_message</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_file_read_mem</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const char
+        *<parameter><replaceable>password</replaceable></parameter></paramdef>
+        <paramdef>unsigned char
+        *<parameter><replaceable>s</replaceable></parameter></paramdef>
+        <paramdef>size_t
+        <parameter><replaceable>n</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_file_read_stream</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const char
+        *<parameter><replaceable>password</replaceable></parameter></paramdef>
+        <paramdef>FILE
+        *<parameter><replaceable>fp</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_file_write_mem</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const char
+        *<parameter><replaceable>password</replaceable></parameter></paramdef>
+        <paramdef>uint32_t
+        <parameter><replaceable>n_iter</replaceable></parameter></paramdef>
+        <paramdef>unsigned char
+        **<parameter><replaceable>memp</replaceable></parameter></paramdef>
+        <paramdef>size_t
+        *<parameter><replaceable>mem_sizep</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_file_write_stream</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const char
+        *<parameter><replaceable>password</replaceable></parameter></paramdef>
+        <paramdef>uint32_t
+        <parameter><replaceable>n_iter</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws3_file_set_header_field</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_get_header_field</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>uint8_t
+        <parameter><replaceable>field_type</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_remove_header_field</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>uint8_t
+        <parameter><replaceable>field_type</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void
+        <function>pws3_file_insert_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_get_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const char
+        *<parameter><replaceable>group_name</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_remove_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const char
+        *<parameter><replaceable>group_name</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_first_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_last_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_next_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_file_prev_empty_group</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws3_file_insert_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_record
+        *<parameter><replaceable>record</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_record *
+        <function>pws3_file_get_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const unsigned char
+        <parameter><replaceable>uuid</replaceable>[static
+        PWS3_UUID_SIZE]</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_record *
+        <function>pws3_file_remove_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>const unsigned char
+        <parameter><replaceable>uuid</replaceable>[static
+        PWS3_UUID_SIZE]</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_record *
+        <function>pws3_file_first_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_record *
+        <function>pws3_file_last_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_record *
+        <function>pws3_file_next_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_record
+        *<parameter><replaceable>record</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_record *
+        <function>pws3_file_prev_record</function></funcdef>
+        <paramdef>struct pws3_file
+        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
+        <paramdef>struct pws3_record
+        *<parameter><replaceable>record</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>struct pws3_field *
+        <function>pws3_field_create</function></funcdef>
+        <paramdef>int
+        <parameter><replaceable>is_header</replaceable></parameter></paramdef>
+        <paramdef>uint8_t
+        <parameter><replaceable>field_type</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws3_field_destroy</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int
+        <function>pws3_field_is_header</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>uint8_t *
+        <function>pws3_field_get_type</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>enum pws_data_type *
+        <function>pws3_field_get_data_type</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_uuid</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>const unsigned char
+        <parameter><replaceable>uuid</replaceable>[static
+        PWS3_UUID_SIZE]</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_text</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>const char
+        <parameter><replaceable>s</replaceable>[static 1]</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_time</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>time_t
+        <parameter><replaceable>time</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_uint8</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>uint8_t
+        <parameter><replaceable>u8</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_uint16</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>uint16_t
+        <parameter><replaceable>u16</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_uint32</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>uint32_t
+        <parameter><replaceable>u32</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws3_field_set_bytes</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>const unsigned char
+        <parameter><replaceable>s</replaceable>[static 1]</parameter></paramdef>
+        <paramdef>size_t
+        <parameter><replaceable>n</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>const unsigned char *
+        <function>pws3_field_get_uuid</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>const char *
+        <function>pws3_field_get_text</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>time_t
+        <function>pws3_field_get_time</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>uint8_t
+        <function>pws3_field_get_uint8</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>uint16_t
+        <function>pws3_field_get_uint16</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>uint32_t
+        <function>pws3_field_get_uint32</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws3_field_get_bytes</function></funcdef>
+        <paramdef>struct pws3_field
+        *<parameter><replaceable>field</replaceable></parameter></paramdef>
+        <paramdef>const unsigned char
+        **<parameter><replaceable>pp</replaceable></parameter></paramdef>
+        <paramdef>size_t
+        *<parameter><replaceable>np</replaceable></parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+    <synopsis>
+<constant>PWS3_VERSION</constant>
+
+<constant>PWS3_MAX_FIELD_LEN</constant>
+
+<constant>PWS3_MAX_PASSWORD_LEN</constant>
+
+<constant>PWS3_UUID_SIZE</constant>
+
+struct pws3_field;
+
+struct pws3_record;
+
+struct pws3_file;
+
+enum pws_error_code;
+
+enum pws_data_type;
+
+enum pws3_header_field_type;
+
+enum pws3_record_field_type;
+</synopsis>
+  </refsynopsisdiv>
+  <refsect1>
+    <title>Description</title>
+    <refsect2>
+      <title>Introduction</title>
+      <para>The <function>pws3_*()</function> family of functions allows
+      creating, reading, writing, and manipulating Password Safe version 3
+      files. Password Safe version 3 files consist of a header and a body part.
+      The header is comprised of both mandatory and optional typed header
+      fields which hold file-wide metadata. The body consists of records which
+      in turn hold passwords and associated metadata in typed record
+      fields.</para>
+      <para>A header or record field value can be of one of seven basic data
+      types defined below:
+      <table xml:id="table-data-types">
+        <title>Header and Record Field Value Data Types</title>
+        <tgroup cols="3" align="left" colsep="1" rowsep="1">
+          <thead>
+            <row>
+              <entry>Data Type</entry>
+              <entry>C Type</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_UUID</constant></entry>
+              <entry><code>unsigned char [PWS3_UUID_SIZE]</code></entry>
+              <entry>UUID</entry>
+            </row>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_TEXT</constant></entry>
+              <entry><code>char *</code></entry>
+              <entry>NUL-delimited UTF-8 encoded string</entry>
+            </row>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_TIME</constant></entry>
+              <entry><code>time_t</code></entry>
+              <entry>system-specific representation of time</entry>
+            </row>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_UINT8</constant></entry>
+              <entry><code>uint8_t</code></entry>
+              <entry>8-bit wide unsigned integer</entry>
+            </row>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_UINT16</constant></entry>
+              <entry><code>uint16_t</code></entry>
+              <entry>16-bit wide unsigned integer</entry>
+            </row>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_UINT32</constant></entry>
+              <entry><code>uint32_t</code></entry>
+              <entry>32-bit wide unsigned integer</entry>
+            </row>
+            <row>
+              <entry><constant>PWS_DATA_TYPE_BYTES</constant></entry>
+              <entry><code>unsigned char *</code></entry>
+              <entry>array of bytes</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+      </para>
+      <para>The data type of each header field is defined in
+      <xref linkend="table-header-fields"/> and the data type of each record
+      field is defined in <xref linkend="table-record-fields"/>. Each header
+      field, with the exception of the empty groups header field, can only
+      occur once. The version header field
+      (<constant>PWS3_HEADER_FIELD_VERSION</constant>) is mandatory and must
+      not be removed. When reading a file its value is checked and an error is
+      returned if the file format version newer than the one supported by
+      <citerefentry><refentrytitle>libpws</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+      The supported version is defined by the <constant>PWS3_VERSION</constant>
+      macro, when creating a new file structure the version header field will be
+      set to its value by default. Non-standard header and record fields will
+      be preserved when a file is read and subsequently written again, they may
+      be read and manipulated as if they had
+      <constant>PWS_DATA_TYPE_BYTES</constant> data type. All strings are
+      expected to be in UTF-8 encoding.</para>
+      <para>The only mandatory record field is the UUID field which uniquely
+      identifies a record in the file.</para>
+      <para>The complete and authoritative specification of the file format is
+      included with the original Password Safe application available from <link
+      xlink:href="https://pwsafe.org/"/>.</para>
+    </refsect2>
+    <refsect2>
+      <title>Password Safe File Data Structure</title>
+      <para>The <function>pws3_file_create()</function> function allocates and
+      intializes a Password Safe file data structure representing a Password
+      Safe version 3 file. It automatically creates the mandatory version header
+      field and initializes it to the value of the
+      <constant>PWS3_VERSION</constant> macro.</para>
+      <para>The <function>pws3_file_destroy()</function> function deallocates
+      all header fields and records of the file structure passed to it and then
+      deallocates the file structure itself.</para>
+      <para>The <function>pws3_file_read_mem()</function> and
+      <function>pws3_file_read_stream()</function> functions read and parse a
+      Password Safe file into the given data structure passed via the
+      <parameter>pws_file</parameter> argument, replacing any existing header
+      fields and records. The key used to decrypt the file is derived from the
+      given <parameter>password</parameter> parameter. The
+      <function>pws3_file_read_mem()</function> function reads the file from a
+      block of memory <parameter>s</parameter> with the size of
+      <parameter>n</parameter> bytes. The
+      <function>pws3_file_read_stream()</function> reads the file from the
+      stream of the <parameter>fp</parameter> file pointer.</para>
+      <para>The <function>pws3_file_write_mem()</function> and
+      <function>pws3_file_write_stream()</function> functions write a new
+      Password Safe file from the given datat structure. The key used to
+      encrypt the file is derived from the <parameter>password</parameter>
+      argument using the number of iterations to stretch the key determined by
+      the <parameter>n_iter</parameter> argument. The
+      <function>pws3_file_write_mem()</function> will allocate and place the
+      file contents into memory and return the location and size to the
+      locations <parameter>sp</parameter> and <parameter>np</parameter>
+      point to. The <function>pws3_file_write_stream()</function> will write the
+      file contents to the stream of the <parameter>fp</parameter> file
+      pointer.</para>
+    </refsect2>
+    <refsect2>
+      <title>Fields</title>
+      <para>Both header and record fields are stored in
+      <varname>pws3_field</varname> structures which are allocated and
+      initialized with the <function>pws3_field_create()</function> function.
+      Depending on whether <parameter>is_header</parameter> is non-zero either
+      a header field or a record field data structure of the given field type
+      will be created.</para>
+      <para>The <function>pws3_field_destroy()</function> function
+      deallocates the given field data structure and its content.</para>
+      <para>The <function>pws3_field_is_header()</function> function
+      can be used to test whether the given field data structure refers to a
+      header field or a record field.</para>
+      <para>The <function>pws3_field_get_type()</function> function
+      returns the field type of the given field data structure.</para>
+      <para>The <function>pws3_field_get_data_type()</function> function
+      returns the data type of the given field structure.</para>
+      <para>The <function>pws3_field_set_uuid()</function>,
+      <function>pws3_field_set_text()</function>,
+      <function>pws3_field_set_time()</function>,
+      <function>pws3_field_set_uint8()</function>,
+      <function>pws3_field_set_uint16()</function>,
+      <function>pws3_field_set_uint32()</function>, and
+      <function>pws3_field_set_bytes()</function> functions set the
+      content of the given field. The given data is always copied and
+      existing content is replaced. The data type used by the function must
+      match the data type of the field specified in <xref
+      linkend="table-header-fields"/> in case of header fields or that in <xref
+      linkend="table-record-fields"/> in case of record fields.</para>
+      <para>The <function>pws3_field_get_time()</function>,
+      <function>pws3_field_get_uint8()</function>,
+      <function>pws3_field_get_uint16()</function>, and
+      <function>pws3_field_get_uint32()</function> functions return the
+      value of the given field. The
+      <function>pws3_field_get_uuid()</function>,
+      <function>pws3_field_get_text()</function>, and
+      <function>pws3_field_get_bytes()</function> functions return a
+      pointer to the data of the given field if it has been set. The data type
+      used by the function must match the data type of the field specified in
+      <xref linkend="table-header-fields"/> in case of header fields and that
+      in <xref linkend="table-record-fields"/> in case of record fields.
+      Returned pointers are only valid until a field is modified or
+      deallocated.</para>
+    </refsect2>
+    <refsect2>
+      <title>Header Fields</title>
+      <para>Header fields are used to store metadata for the whole file, each
+      type of header field with the exception of the empty groups header field
+      only occurs once. The following header fields are supported:
+      <table xml:id="table-header-fields">
+        <title>Header Fields</title>
+        <tgroup cols="4" align="left" colsep="1" rowsep="1">
+          <thead>
+            <row>
+              <entry>Header Field Type</entry>
+              <entry>Numeric Value</entry>
+              <entry>Data Type</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;VERSION</constant></entry>
+              <entry><literal>0x00</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UINT16</constant></entry>
+              <entry>file format version</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;UUID</constant></entry>
+              <entry><literal>0x01</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UUID</constant></entry>
+              <entry>UUID</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;NON_&#8203;DEFAULT_&#8203;PREFERENCES</constant></entry>
+              <entry><literal>0x02</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>non-default preferences</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;TREE_&#8203;DISPLAY_&#8203;STATUS</constant></entry>
+              <entry><literal>0x03</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>expandended/&#8203;collapsed state of the tree of groups</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;TIMESTAMP</constant></entry>
+              <entry><literal>0x04</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
+              <entry>time when the file was last saved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;USER_&#8203;HOST</constant></entry>
+              <entry><literal>0x05</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>name of the user who last saved the file and name of the host where the file was saved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;APPLICATION</constant></entry>
+              <entry><literal>0x06</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>name of the application used to save the file</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;USER</constant></entry>
+              <entry><literal>0x07</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>name of the user who last saved the file</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;HOST</constant></entry>
+              <entry><literal>0x08</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>name of the host where the file was last saved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;DATABASE_&#8203;NAME</constant></entry>
+              <entry><literal>0x09</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>logical name for referring to the file</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;DATABASE_&#8203;DESCRIPTION</constant></entry>
+              <entry><literal>0x0a</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>description of the file</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;DATABASE_&#8203;FILTERS</constant></entry>
+              <entry><literal>0x0b</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>filters for this file</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RESERVED_&#8203;1</constant></entry>
+              <entry><literal>0x0c</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>reserved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RESERVED_&#8203;2</constant></entry>
+              <entry><literal>0x0d</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>reserved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RESERVED_&#8203;3</constant></entry>
+              <entry><literal>0x0e</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>reseved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RECENTLY_&#8203;USED_&#8203;ENTRIES</constant></entry>
+              <entry><literal>0x0f</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>list of recently used entries</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;NAMED_&#8203;PASSWORD_&#8203;POLICIES</constant></entry>
+              <entry><literal>0x10</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>named password policies</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;EMPTY_&#8203;GROUPS</constant></entry>
+              <entry><literal>0x11</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>empty groups which contain no entries</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;YUBICO</constant></entry>
+              <entry><literal>0x12</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>reserved</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+      </para>
+      <para>The <function>pws3_file_set_header_field()</function> function sets
+      the header field on the given file. An existing field of the same type is
+      replaced with the exception of fields of type
+      <constant>PWS3_HEADER_FIELD_EMPTY_GROUPS</constant> for which
+      <function>pws3_file_set_header_field()</function> has the same effect as
+      calling the <function>pws3_file_insert_empty_group()</function>
+      function.</para>
+      <para>The <function>pws3_file_get_header_field()</function> function
+      returns a pointer to the header field data structure of the given header
+      field type. In case of the
+      <constant>PWS3_HEADER_FIELD_EMPTY_GROUPS</constant> field type a pointer
+      to the first empty group field is returned.</para>
+      <para>The <function>pws3_file_remove_header_field()</function> function
+      removes the header field from the given file and returns a pointer to it.
+      It is the responsibility of the caller to deallocate the header field
+      data structure. In case of the
+      <constant>PWS3_HEADER_FIELD_EMPTY_GROUPS</constant> field type the first
+      empty group is removed.</para>
+      <para>The <function>pws3_file_insert_empty_group()</function> function
+      inserts the given empty groups field into the file, an existing field for
+      a group of the same name is replaced.</para>
+      <para>The <function>pws3_file_get_empty_group()</function> function
+      returns a pointer to the header field datat structure representing an
+      empty group of the given name.</para>
+      <para>The <function>pws3_file_remove_empty_group()</function> function
+      removes the field representing the empty group of the given name from the
+      file and returns a pointer to the header field data structure. It is the
+      responsibility of the caller to deallocate the header field data
+      structure.</para>
+      <para>The <function>pws3_file_first_empty_group()</function> function
+      returns a pointer to the first empty group header field.</para>
+      <para>The <function>pws3_file_last_empty_group()</function> function
+      returns a pointer to the last empty group header field.</para>
+      <para>The <function>pws3_file_next_empty_group()</function> function
+      returns a pointer to the next empty group header filed data structure
+      following the given <parameter>field</parameter>.</para>
+      <para>The <function>pws3_file_prev_empty_groupious()</function> function
+      returns a pointer to the previous empty group header filed data structure
+      preceding the given <parameter>field</parameter>.</para>
+    </refsect2>
+    <refsect2>
+      <title>Records</title>
+      <para>Records consist of at least one or more typed fields, they are
+      identified by an UUID which is the only mandatory field and must not be
+      removed. For presentational purposes records may be organized in
+      hierarchical groups. The following record fields are supported:
+      <table xml:id="table-record-fields">
+        <title>Record Fields</title>
+        <tgroup cols="4" align="left" colsep="1" rowsep="1">
+          <thead>
+            <row>
+              <entry>Record Field Type</entry>
+              <entry>Numeric Value</entry>
+              <entry>Data Type</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;UUID</constant></entry>
+              <entry><literal>0x01</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UUID</constant></entry>
+              <entry>UUID identifying the record</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;GROUP</constant></entry>
+              <entry><literal>0x02</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>group name the record is a member of</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;TITLE</constant></entry>
+              <entry><literal>0x03</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>title</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;USERNAME</constant></entry>
+              <entry><literal>0x04</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>username</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;NOTES</constant></entry>
+              <entry><literal>0x05</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>notes</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD</constant></entry>
+              <entry><literal>0x06</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>password</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;CREATION_&#8203;TIME</constant></entry>
+              <entry><literal>0x07</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
+              <entry>time when the record was created</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;MODIFICATION_&#8203;TIME</constant></entry>
+              <entry><literal>0x08</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
+              <entry>time when the password was last modified</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;ACCESS_&#8203;TIME</constant></entry>
+              <entry><literal>0x09</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
+              <entry>time when the record was last accessed</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;EXPIRY_&#8203;TIME</constant></entry>
+              <entry><literal>0x0a</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
+              <entry>time when the password expires</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;RESERVED_&#8203;1</constant></entry>
+              <entry><literal>0x0b</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>reserved</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;MODIFICATION_&#8203;TIME</constant></entry>
+              <entry><literal>0x0c</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
+              <entry>time at whcih the record was last modified</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;URL</constant></entry>
+              <entry><literal>0x0d</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>URL</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;AUTOTYPE</constant></entry>
+              <entry><literal>0x0e</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>text to be typed when using the autotype feature</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;HISTORY</constant></entry>
+              <entry><literal>0x0f</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>creation time and values of previously used passwords</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;POLICY</constant></entry>
+              <entry><literal>0x10</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>password policy</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;EXPIRY_&#8203;INTERVAL</constant></entry>
+              <entry><literal>0x11</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UINT32</constant></entry>
+              <entry>days until the password expires</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;RUN_&#8203;COMMAND</constant></entry>
+              <entry><literal>0x12</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>command</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;DOUBLE_&#8203;CLICK_&#8203;ACTION</constant></entry>
+              <entry><literal>0x13</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>action on double clicking</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;EMAIL_&#8203;ADDRESS</constant></entry>
+              <entry><literal>0x14</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>email address</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PROTECTED</constant></entry>
+              <entry><literal>0x15</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UINT8</constant></entry>
+              <entry>flag whether the record is protected from modification</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;ALLOWED_&#8203;PASSWORD_&#8203;SYMBOLS</constant></entry>
+              <entry><literal>0x16</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>allowed symbols for generating passwords</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;SHIFT_&#8203;DOUBLE_&#8203;CLICK_&#8203;ACTION</constant></entry>
+              <entry><literal>0x17</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>action on pressing shift and double clicking</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;POLICY_&#8203;NAME</constant></entry>
+              <entry><literal>0x18</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
+              <entry>name of password policy saved in the header</entry>
+            </row>
+            <row>
+              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;KEYBOARD_&#8203;SHORTCUT</constant></entry>
+              <entry><literal>0x19</literal></entry>
+              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
+              <entry>keyboard shortcut</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+      </para>
+      <para>The <function>pws3_record_create()</function> function allocates
+      and creates a record data structure, generates an UUID record field and
+      adds it to the record.</para>
+      <para>The <function>pws3_record_destroy()</function> function deallocates
+      the given record data structure and all its record fields.</para>
+      <para>The <function>pws3_file_record_field_set()</function> function sets
+      the record field on the given record, replacing an existing field of the
+      same type.</para>
+      <para>The <function>pws3_file_record_field_get()</function> function
+      returns a pointer to the record field data structure of the given record
+      field type.</para>
+      <para>The <function>pws3_file_record_field_remove()</function> function
+      removes the record field from the given record and returns a pointer to
+      it. It is the responsibility of the caller to deallocate the record field
+      data structure.</para>
+      <para>The <function>pws3_file_insert_record()</function> function inserts
+      the given record into the file, an existing record with the same UUID is
+      replaced.</para>
+      <para>The <function>pws3_file_get_record()</function> function returns a
+      pointer to the record structure representing a record with the given
+      UUID.</para>
+      <para>The <function>pws3_file_remove_record()</function> function removes
+      the record with the given UUID from the file and returns a pointer to the
+      record data structure. It is the responsibility of the caller to
+      deallocate the record data structure.</para>
+      <para>The <function>pws3_file_first_record()</function> function returns a
+      pointer to the first record.</para>
+      <para>The <function>pws3_file_last_record()</function> function returns a
+      pointer to the last record.</para>
+      <para>The <function>pws3_file_next_record()</function> function returns a
+      pointer to the next record following the given
+      <parameter>record</parameter>.</para>
+      <para>The <function>pws3_file_prev_record()</function>
+      function returns a pointer to the previous group preceding the given
+      <parameter>record</parameter>.</para>
+    </refsect2>
+    <refsect2>
+      <title>Macros</title>
+      <para>The macro <constant>PWS3_VERSION</constant> contains the supported
+      version of the Password Safe version 3 file format.</para>
+      <para>The macro <constant>PWS3_MAX_FIELD_SIZE</constant> contains the
+      maxium size for header and record fields in bytes and
+      <constant>PWS3_MAX_PASSWORD_LEN</constant> contains the maxium password
+      length in bytes.</para>
+      <para>The macro <constant>PWS3_UUID_SIZE</constant> contains the size of
+      UUIDs in bytes.</para>
+    </refsect2>
+  </refsect1>
+  <refsect1>
+    <title>Return Values</title>
+    <para>The <function>pws3_file_create()</function> function returns a
+    pointer to a Password Safe file data structure if successful and
+    <constant>NULL</constant> in case of an error.</para>
+    <para>The <function>pws3_file_read_mem()</function>,
+    <function>pws3_file_read_stream()</function>,
+    <function>pws3_file_write_mem()</function>, and
+    <function>pws3_file_write_stream()</function> functions return
+    <returnvalue>0</returnvalue> on success and <returnvalue>-1</returnvalue>
+    to indicate an error.</para>
+    <para>The <function>pws3_file_get_header_field()</function> function
+    returns a pointer to the header field data structure of the requested type
+    and <constant>NULL</constant> if such a field does not exist.</para>
+    <para>The <function>pws3_file_remove_header_field()</function> function
+    returns a pointer to the header field data structure which was removed from
+    the file or <constant>NULL</constant> if such a field does not exist.</para>
+    <para>The <function>pws3_file_get_empty_group()</function> function returns
+    a pointer to the header field data structure corresponding to the requested
+    empty group and <constant>NULL</constant> if a group of that name does not
+    exist.</para>
+    <para>The <function>pws3_file_remove_empty_group()</function> function
+    returns a pointer to the header field data structure of the empty group
+    which was removed from the file or <constant>NULL</constant> if a group of
+    that name does not exist.</para>
+    <para>The <function>pws3_file_first_empty_group()</function> function
+    returns a pointer to the first of the empty group header fields or
+    <constant>NULL</constant> if there are no such fields.</para>
+    <para>The <function>pws3_file_last_empty_group()</function> function
+    returns a pointer to the last of the empty group header fields or
+    <constant>NULL</constant> if there are no such fields.</para>
+    <para>The <function>pws3_file_next_empty_group()</function> function
+    returns a pointer to the next empty group header field or
+    <constant>NULL</constant> if there are no more such fields.</para>
+    <para>The <function>pws3_file_prev_empty_group()</function> function
+    returns a pointer to the previous empty group header field or
+    <constant>NULL</constant> if there are no more such fields.</para>
+    <para>The <function>pws3_file_get_record()</function> function returns a
+    pointer to the record data structure of the requested record or
+    <constant>NULL</constant> if that record does not exist.</para>
+    <para>The <function>pws3_file_remove_record()</function> function returns a
+    pointer to the record data structure which was removed from the file or
+    <constant>NULL</constant> if no such record exists.</para>
+    <para>The <function>pws3_file_first_record()</function> function returns a
+    pointer to the record data structure of the first record or
+    <constant>NULL</constant> if no records exist.</para>
+    <para>The <function>pws3_file_last_record()</function> function returns a
+    pointer to the record data structure of the last record or
+    <constant>NULL</constant> if no records exist.</para>
+    <para>The <function>pws3_file_next_record()</function> function returns a
+    pointer to the record data structure of the next record or
+    <constant>NULL</constant> if no records exist.</para>
+    <para>The <function>pws3_file_prev_record()</function> function returns a
+    pointer to the record data structure of the previous record or
+    <constant>NULL</constant> if no records exist.</para>
+    <para>The <function>pws3_field_create()</function> function returns a
+    pointer to the new header field data structure on success and
+    <constant>NULL</constant> on failure.</para>
+    <para>The <function>pws3_field_get_type()</function> function returns
+    the field type of the header field structure.</para>
+    <para>The <function>pws3_field_get_data_type()</function> function
+    returns the data type of the header field structure.</para>
+    <para>The <function>pws3_field_set_uuid()</function>,
+    <function>pws3_field_set_text()</function>,
+    <function>pws3_field_set_time()</function>,
+    <function>pws3_field_set_uint8()</function>,
+    <function>pws3_field_set_uint16()</function>,
+    <function>pws3_field_set_uint32()</function>, and
+    <function>pws3_field_set_bytes()</function> functions return
+    <returnvalue>0</returnvalue> on success and <returnvalue>-1</returnvalue>
+    on failure.</para>
+    <para>The <function>pws3_field_get_time()</function>,
+    <function>pws3_field_get_uint8()</function>,
+    <function>pws3_field_get_uint16()</function>, and
+    <function>pws3_field_get_uint32()</function> functions return a
+    value of the type corresponding to the type of header field.</para>
+    <para>The <function>pws3_field_get_uuid()</function> function
+    returns a pointer to a UUID.</para>
+    <para>The <function>pws3_field_get_text()</function> function
+    returns a pointer to a string or <constant>NULL</constant> if no value has
+    been set.</para>
+    <para>The <function>pws3_record_create()</function> function returns a
+    pointer to a record data structure if successful and
+    <constant>NULL</constant> on failure.</para>
+    <para>The <function>pws3_record_get_field()</function> function returns a
+    pointer to the record field data structure of the requested type or
+    <constant>NULL</constant> if such a field does not exist.</para>
+    <para>The <function>pws3_record_remove_field()</function> function returns
+    a pointer to the record field data structure which was removed from the
+    record or <constant>NULL</constant> if such a field does not exist.</para>
+  </refsect1>
+  <refsect1>
+    <title>Errors</title>
+    <para>If the <function>pws3_file_read_mem()</function>,
+    <function>pws3_file_read_stream()</function>,
+    <function>pws3_file_write_mem()</function>, and
+    <function>pws3_file_write_stream()</function> functions fail, an error code
+    indicating the nature of the error may be obtained using the
+    <function>pws3_file_get_error_code()</function> function and a pointer to a
+    detailed error message may be retrieved using the
+    <function>pws3_file_get_error_message()</function> function. The above
+    functions may fail if:</para>
+    <variablelist>
+      <varlistentry>
+        <term><errorname>PWS_ERR_GENERIC_ERROR</errorname></term>
+        <listitem>
+          <para>An unknown error occurred.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_NO_MEMORY</errorname></term>
+        <listitem>
+          <para>There was not enough space to allocate memory.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_IO_ERROR</errorname></term>
+        <listitem>
+          <para>An I/O error occurred.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_TRUNCATED_FILE</errorname></term>
+        <listitem>
+          <para>The file appears to be truncated.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_INVALID_CHECKSUM</errorname></term>
+        <listitem>
+          <para>The calculated checksum does not match the checksum of the
+          file.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_INVALID_RECORD</errorname></term>
+        <listitem>
+          <para>A record is invalid.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_INVALID_HEADER</errorname></term>
+        <listitem>
+          <para>A header is invalid.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><errorname>PWS_ERR_UNSUPPORTED_VERSION</errorname></term>
+        <listitem>
+          <para>The file format version is not supported.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1>
+    <title>Examples</title>
+    <example>
+      <title>Creating a Password Safe file</title>
+      <para>The following code creates a new Password Safe file and sets the
+      save application header field:</para>
+      <programlisting>
+<![CDATA[
+#include <pws.h>
+
+/* ... */
+
+struct pws3_file *file;
+struct pws3_field *application_field;
+
+/* ... */
+
+/* initialize libpws */
+if (pws_init() != 0) {
+	/* handle error */
+}
+
+/* ... */
+
+/* create a new empty file structure */
+file = pws3_file_create();
+if (file == NULL) {
+	/* handle error */
+}
+/* create new empty save application field */
+application_field = pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_APPLICATION);
+if (application_field == NULL) {
+	/* handle error */
+}
+/* set the value of the field */
+if (pws3_field_set_text(application_field, "PasswordManager 2.0") != 0) {
+	/* handle error */
+}
+/* set the header save application field in the file to the new field */
+pws3_file_set_field(file, application_field);
+]]>
+</programlisting>
+    </example>
+    <example>
+      <title>Print the title of each record</title>
+      <para>The following code loops over each record of an existing Password
+      Safe file and prints the content of the title field if it exists:</para>
+      <programlisting>
+<![CDATA[
+#include <stdio.h>
+#include <pws.h>
+
+/* ... */
+
+struct pws3_file *file;
+struct pws3_record *record;
+struct pws3_field *title_field;
+
+/* ... */
+
+/* interate over each record */
+for (record = pws3_file_first_record(file); record != NULL;
+    record = pws3_file_next_record(file, record)) {
+	/* retrieve title field */
+	title_field = pws3_record_get_field(record, PWS3_RECORD_FIELD_TITLE);
+	/* print the title field or "No title" if it does not exitst */
+	printf("Title: %s\n", (title_field != NULL) ?
+	    pws3_record_field_get_text(PWS3_RECORD_FIELD_TITLE) : "No title");
+}
+]]>
+</programlisting>
+    </example>
+    <example>
+      <title>Add a new record to a file</title>
+      <para>The following code creates a new record with a password field, a
+      title field, and a creation time field and adds it to an existing
+      Password Safe file:</para>
+      <programlisting>
+<![CDATA[
+#include <time.h>
+#include <pws.h>
+
+/* ... */
+
+struct pws3_file *file;
+struct pws3_record *record;
+struct pws3_field *password_field;
+struct pws3_field *title_field;
+struct pws3_field *ctime_field;
+time_t		now;
+
+/* ... */
+
+/* create new record */
+record = pws3_record_create();
+if (record == NULL) {
+	/* handle error */
+}
+
+/* create a password field */
+password_field = pws3_record_field_create(PWS3_RECORD_FIELD_PASSWORD);
+if (password_field == NULL) {
+	/* handle error */
+}
+/* set the value of the password field to "PaSsWoRd" */
+if (pws3_record_field_set_text(password_field, "PaSsWoRd") != 0) {
+	/* handle error */
+}
+/* set the password field of the record to the new field */
+pws3_record_set_field(record, password_field);
+
+/* create a title field */
+title_field = pws3_record_field_create(PWS3_RECORD_FIELD_TITLE);
+if (title_field == NULL) {
+	/* handle error */
+}
+/* set the value of the title field to "Foo Bar" */
+if (pws3_record_field_set_text(title_field, "Foo Bar") != 0) {
+	/* handle error */
+}
+/* set the title field of the record to the new field */
+pws3_record_set_field(record, title_field);
+
+/* create a new creation time field */
+ctime_field = pws3_record_field_create(PWS3_RECORD_FIELD_CREATION_TIME);
+if (ctime_field == NULL) {
+	/* handle error */
+}
+/* set the value of the creation time field to the current time */
+pws3_record_field_set_time(ctime_field, time(NULL));
+/* set the creation time field of the record to the new field */
+pws3_record_set_field(record, ctime_field);
+
+/* insert the new record into the file */
+pws3_file_insert_record(file, record);
+]]>
+</programlisting>
+    </example>
+    <example>
+      <title>Reading a Password Safe file</title>
+      <para>The following code opens a Password Safe file named
+      <filename>example.pwsafe3</filename> and parses it:</para>
+      <programlisting>
+<![CDATA[
+#include <stdio.h>
+#include <pws.h>
+
+/* ... */
+
+FILE		*fp;
+struct pws3_file *file;
+
+/* ... */
+
+/* initialize libpws */
+if (pws_init() != 0) {
+	/* handle error */
+}
+
+/* ... */
+
+/* create a new empty file structure */
+file = pws3_file_create();
+if (file == NULL) {
+	/* handle error */
+}
+
+/* open the file */
+fp = fopen("example.pwsafe3", "r");
+if (fp == NULL) {
+	/* handle error */
+}
+
+/* read and parse the file contents into the file structure */
+if (pws3_file_read_stream(file, "PaSsWoRd", fp) != 0) {
+	fprintf(stderr, "error: %s\n",
+	   pws3_file_get_error_message(file));
+	/* handle error */
+}
+]]>
+</programlisting>
+    </example>
+    <example>
+      <title>Writing a Password Safe file</title>
+      <para>The following code writes a Password Safe file to a file
+      named <filename>example.pwsafe3</filename>:</para>
+      <programlisting>
+<![CDATA[
+#include <stdio.h>
+#include <pws.h>
+
+/* ... */
+
+FILE		*fp;
+struct pws3_file *file;
+
+/* ... */
+
+fp = fopen("example.pwsafe3", "w");
+if (fp == NULL) {
+	/* handle error */
+}
+
+if (pws3_file_write_stream(file, "FoOBaR", 10000, fp) != 0) {
+	/* handle error */
+}
+
+fflush(fp);
+fclose(fp);
+]]>
+</programlisting>
+    </example>
+  </refsect1>
+  <refsect1>
+    <title>See Also</title>
+    <para><citerefentry><refentrytitle>libpws</refentrytitle>
+    <manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>pws_init</refentrytitle>
+    <manvolnum>3</manvolnum></citerefentry>,
+    <link xlink:href="https://pwsafe.org/"/></para>
+  </refsect1>
+</refentry>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pws_init.3.xml	Wed Mar 25 17:10:23 2015 +0100
@@ -0,0 +1,159 @@
+<?xml version="1.0"?>
+<!--
+
+Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+<refentry xmlns="http://docbook.org/ns/docbook" xml:lang="en">
+  <info>
+    <author>
+      <personname>
+        <firstname>Guido</firstname>
+        <surname>Berhoerster</surname>
+      </personname>
+      <email>guido+libpws@berhoerster.name</email>
+      <personblurb/>
+    </author>
+    <date>21 March, 2015</date>
+  </info>
+  <refmeta>
+    <refentrytitle>libpws</refentrytitle>
+    <manvolnum>3</manvolnum>
+    <refmiscinfo class="source"/>
+    <refmiscinfo class="version"/>
+    <refmiscinfo class="manual">Library Functions</refmiscinfo>
+  </refmeta>
+  <refnamediv>
+    <refname>pws_init</refname>
+    <refname>pws_finalize</refname>
+    <refname>pws_set_alloc_functions</refname>
+    <refname>pws_generate_uuid</refname>
+    <refpurpose>initalize and deinitialize libpws</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>cc</command>
+      <arg choice="opt" rep="repeat">
+        <option>flag</option>
+      </arg>
+      <arg choice="plain" rep="repeat">
+        <option>file</option>
+      </arg>
+      <arg choice="plain">
+        <option>-lpws</option>
+      </arg>
+      <arg choice="plain">
+        <option>-lnettle</option>
+      </arg>
+      <arg choice="opt" rep="repeat">
+        <option>library</option>
+      </arg>
+    </cmdsynopsis>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;pws.h&gt;
+</funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>int <function>pws_init</function></funcdef>
+        <void/>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws_finalize</function></funcdef>
+        <void/>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>pws_set_alloc_functions</function></funcdef>
+        <paramdef>void
+        *<funcparams>*<replaceable>alloc_function</replaceable></funcparams><funcparams>size_t</funcparams></paramdef>
+        <paramdef>void
+        *<funcparams>*<replaceable>realloc_function</replaceable></funcparams><funcparams>void *, size_t</funcparams></paramdef>
+        <paramdef>void <funcparams>*<replaceable>free_function</replaceable></funcparams><funcparams>void
+        *, size_t</funcparams></paramdef>
+        <paramdef>void
+        *<funcparams>*<replaceable>secure_alloc_function</replaceable></funcparams><funcparams>size_t</funcparams></paramdef>
+        <paramdef>void
+        *<funcparams>*<replaceable>secure_realloc_function</replaceable></funcparams><funcparams>void *, size_t</funcparams></paramdef>
+        <paramdef>void <funcparams>*<replaceable>secure_free_function</replaceable></funcparams><funcparams>void
+        *, size_t</funcparams></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>pws_generate_uuid</function></funcdef>
+        <paramdef>unsigned char [static PWS3_UUID_SIZE]</paramdef>
+      </funcprototype>
+    </funcsynopsis>
+    <synopsis>
+<constant>LIBPWS_VERSION_MAJOR</constant>
+
+<constant>LIBPWS_VERSION_MINOR</constant>
+
+<constant>LIBPWS_VERSION_MICRO</constant>
+    </synopsis>
+  </refsynopsisdiv>
+  <refsect1>
+    <title>Description</title>
+    <para>The <function>pws_init()</function> function initializes
+    <citerefentry><refentrytitle>libpws</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    and must be called before any other function from this library.</para>
+    <para>The <function>pws_finalize()</function> function deinitializes
+    <citerefentry><refentrytitle>libpws</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    after which no other function from this library may be called.</para>
+    <para>The <function>pws_set_alloc_functions()</function> function specifies
+    the functions which are used by
+    <citerefentry><refentrytitle>libpws</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    to allocate, reallocate or free memory allowing for the use of custom
+    allocators. <function>pws_secure_alloc</function>,
+    <function>pws_secure_realloc</function>, and
+    <function>pws_secure_free</function> are used to allocate, reallocate, and
+    free memory containing potentially sensitive information such as passwords,
+    this e.g. allows for wrapping the acutal allocation using operating system
+    specific facilities to prevent memory from being paged to the swap area or
+    to overwrite memory before deallocating it. Any argument set to
+    <constant>NULL</constant> will result in the default function being used,
+    these are <function>malloc</function>, <function>realloc</function>, and a
+    wrapper around <function>free</function>. This function must be called
+    after <function>pws_init</function> and before calling any other function
+    from this library. It is not reentrant.</para>
+    <para>The <function>pws_uuid_create()</function> function generates a new
+    random UUID following RFC4122 and places it in the array passed to
+    it.</para>
+    <para>The macros <constant>LIBPWS_VERSION_MAJOR</constant>,
+    <constant>LIBPWS_VERSION_MINOR</constant>, and
+    <constant>LIBPWS_VERSION_MICRO</constant> can be used to check the major,
+    minor, and micro version of the library.</para>
+  </refsect1>
+  <refsect1>
+    <title>Return Values</title>
+    <para>The <function>pws_init()</function> function returns
+    <returnvalue>0</returnvalue> if the library was initialized successfully and
+    <returnvalue>-1</returnvalue> on failure.</para>
+    <para>The <function>pws_generate_uuid()</function> returns
+    <returnvalue>0</returnvalue> if a new random UUID has been generated and
+    <returnvalue>-1</returnvalue> on failure.</para>
+  </refsect1>
+  <refsect1>
+    <title>See Also</title>
+    <para><citerefentry><refentrytitle>libpws</refentrytitle>
+    <manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>pws3_file_create</refentrytitle>
+    <manvolnum>3</manvolnum></citerefentry>, RFC4122</para>
+  </refsect1>
+</refentry>