/*
Copyright (c) 2000-2008, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file dksf.h
	Access to system functions.

	Unless otherwise stated, int functions in this module return a positive
	number to indicate success or a true condition, 0 to indicate an error
	or an unfullfilled condition.
	Pointer functions return valid pointers on success, NULL on error.

	The dkstat_xxx() function group can be used to obtain
	information about a file or directory. In a first step information
	about the file is collected and stored in a dk_stat_t data structure.
	The further dkstat_xxx() functions can be used to retrieve details
	from the structure.
	\code
	  dk_stat_t *p;
	  p = dk_stat_open("x.txt");
	  if(p) {
	    ... retrieve information from p ...
	    dkstat_close(p);
	  }
	\endcode

	The dkdir_xxx() function group can be used to traverse directories.
	\code
	  dk_dir_t *p;
	  p = dkdir_open(".");
	  if(p) {
	    while(dkdir_next(p)) {
	      ... yet another entry found ...
	      ... retrieve information from p ...
	    }
	    dkdir_close(p);
	  }
	\endcode

	The dkfne_xxx() function group can be used to expand file name
	patterns (some Windows command interpreters do not expand
	wildcards and leave this up to applications).

	To find all regular file names (1 in dkfne_open()) but no
	directories (0 in dkfne_open()) matching a file name pattern
	n use:
	\code
	char *n = ... file name ... ;
	char *fn = NULL;
	dk_fne_t *fne;
	if(dksf_must_expand_filename(n)) {
	  fne = dkfne_open(n, 1, 0);
	  if(fne) {
	    while(dkfne_next(fne)) {
	      fn = dkfne_get_fullname(fne);
	      ... fn is a file name ...
	    }
	    dkfne_close(fne);
	    ... fn can not longer be used, it pointed into fne ...
	  } else {
	    ... error, failed to create fne ...
	  }
	}
	\endcode

	If file name pattern n should choose exactly one file name use:
	\code
	char *n = ... file name ... ;
	char *fn = NULL;
	dk_fne_t *fne;
	if(dksf_must_expand_filename(n)) {
	  fne = dkfne_open(n, 1, 0);
	  if(fne) {
	    fn = dkfne_get_one(fne);
	    if(fn) {
	      ... fn is a file name ...
	    } else {
	      ... error, not exactly one name matches ...
	    }
	    dkfne_close(fne);
	    ... fn can not longer be used, it pointed into fne ...
	  } else {
	    ... error, failed to create fne ...
	  }
	}
	\endcode

	The dksf_echo_xxx() function group deals with keyboard echo on
	terminals.
	\code
	  dk_echo_t echodata;
	  if(dksf_echo_test_tty()) {
	    ... standard input is connected to terminal ...
	    if(dksf_echo_save(&echodata)) {
	      if(dksf_echo_off(&echodata)) {
	        ... ask user for password ...
		... read password from standard input ...
	      } else {
	        ... error, failed to turn echo off ...
	      }
	      dksf_echo_restore(&echodata);
	    } else {
	      ... error, failed to save current echo state ...
	    }
	  } else {
	    ... error, standard input is not a terminal ...
	  }
	\endcode
*/

#ifndef DK_SYSFCT_INCLUDED

/** Make sure to include file only once. */
#define DK_SYSFCT_INCLUDED 1

#include <dk.h>
#include <dktypes.h>
#include <dksfc.h>

#if defined(EXTERN)
#undef EXTERN
#endif
#ifndef DK_SYSFCT_C
#if !DK_HAVE_PROTOTYPES
#define EXTERN extern
#else
#define EXTERN /* nix */
#endif
#else
#define EXTERN /* nix */
#endif

#if defined(__cplusplus)
extern "C" {
#endif

/**	Create a dk_stat_t structure and collect information about a file.
	The function collects information about the file \a n and stores
	it into a new dk_stat_t structure. Memory for this structure
	is allocated dynamically, call dkstat_close() to release the memory
	after usage.
	@param	n	The file name.
	@return	Pointer to the new structure, NULL on error.
*/
EXTERN dk_stat_t * dkstat_open DK_PR((char *n));

/**	Create a new empty dk_stat_t structure. Memory for this structure
	is allocated dynamically, call dkstat_delete() to release the memory
	after usage. The structure only contains default values, use
	dkstat_get() to load information about a file into the structure.
	@return	Pointer to the new structure, NULL on error.
*/
EXTERN dk_stat_t * dkstat_new DK_PR((void));

/**	Load information about a file into a dk_stat_t structure.
	@param	p	Pointer to dk_stat_t structure.
	@param	n	File name.
	@return	Flag indicating success.
*/
EXTERN int	  dkstat_get DK_PR((dk_stat_t *p, char *n));

/**	Release memory for a structure obtained by dkstat_new().
	@param	p	Pointer to dk_stat_t structure to release.
*/
EXTERN void	  dkstat_delete DK_PR((dk_stat_t *p));

/**	Close a dk_stat_t structure obtained by dkstat_open() and release
	memory.
	@param p	Pointer to dk_stat_t structure to release.
*/
EXTERN void	  dkstat_close DK_PR((dk_stat_t *p));

/**	Get file type.
	The file type is returned as DK_FT_xxx constant. If the
	file name pointed to a symbolic link the result is an or-combination
	of the real file type and DK_FT_SYMLINK.
	@param	p	Pointer to dk_stat_t structure.
	@return	The file type.
*/
EXTERN int	  dkstat_filetype DK_PR((dk_stat_t *p));

/**	Get permissions.
	The permissions are an or-combination of DK_PERM_xxx constants.
	@param  p       Pointer to dk_stat_t structure.
	@return	Permissions to the file.
*/
EXTERN int	  dkstat_permissions DK_PR((dk_stat_t *p));

/**	Get inode number.
	@param  p       Pointer to dk_stat_t structure.
	@return	The inode number.
*/
EXTERN unsigned long  dkstat_inode DK_PR((dk_stat_t *p));

/**	Get device number.
	@param  p       Pointer to dk_stat_t structure.
	@return The device number.
*/
EXTERN unsigned long   dkstat_device DK_PR((dk_stat_t *p));

/**	Get relative device number.
	@param  p       Pointer to dk_stat_t structure.
	@return	The relative device number.
*/
EXTERN unsigned long  dkstat_rdevice DK_PR((dk_stat_t *p));

/**	Get number of links.
	@param  p       Pointer to dk_stat_t structure.
	@return	The number of links.
*/
EXTERN unsigned long  dkstat_nlinks DK_PR((dk_stat_t *p));

/**	Get file size.
	@param  p       Pointer to dk_stat_t structure.
	@return	The file size.
*/
EXTERN dk_long_long_unsigned_t dkstat_size DK_PR((dk_stat_t *p));

/**	Get file size, indicate numeric overflow error if necessary.
	@param  p       Pointer to dk_stat_t structure.
	@param	ok	Pointer to variable to receive the error code.
			The variable is left untouched if no error occures.
			If there was an error while retrieving the file size
			the variable is set to DK_ERR_MATH_OOR.
	@return	The file size.
*/
EXTERN dk_long_long_unsigned_t dkstat_size_ok DK_PR((dk_stat_t *p, int *ok));

/**	Get owner UID.
	@param  p       Pointer to dk_stat_t structure.
	@return	Owner UID.
*/
EXTERN long	  dkstat_uid DK_PR((dk_stat_t *p));

/**	Get owner GID.
	@param  p       Pointer to dk_stat_t structure.
	@return	Owner GID.
*/
EXTERN long	  dkstat_gid DK_PR((dk_stat_t *p));

/**	Get creation time.
	@param  p       Pointer to dk_stat_t structure.
	@return	Pointer to string containing creation time as text.
*/
EXTERN char	 * dkstat_ctime DK_PR((dk_stat_t *p));

/**	Get last access time.
	@param  p       Pointer to dk_stat_t structure.
	@return	Pointer to string containing last access time as text.
*/
EXTERN char	 * dkstat_atime DK_PR((dk_stat_t *p));

/**	Get last modification time.
	@param	p	Pointer to dk_stat_t structure.
	@return	Pointer to string containing last modification time as text.
*/
EXTERN char	 * dkstat_mtime DK_PR((dk_stat_t *p));

/**	Check whether or not the file is a far symbolic link
	(link to a destination outside the current file system).
	@param	p	Pointer to dk_stat_t structure.
	@return	Flag to indicate whether or not the file is a far link.
*/
EXTERN int      dkstat_far_link DK_PR((dk_stat_t *p));

/**	Open a directory.
	@param	n	Name of directory.
	@return	Pointer to directory traversal structure dk_dir_t.
	The dk_dir_t structure must be released after usage calling
	dkdir_close().
*/
EXTERN dk_dir_t  *dkdir_open	DK_PR((char *n));

/**	Close a directory.
	@param	d	Directory to close.
*/
EXTERN void	  dkdir_close	DK_PR((dk_dir_t *d));

/**	Create a new empty dk_dir_t structure.
	A pointer to a the new structure is returned. The memory
	must be release using dkdir_delete() after usage.
	@return	Pointer to the new structure.
*/
EXTERN dk_dir_t  *dkdir_new	DK_PR((void));

/**	Release memory for dk_dir_t structure.
	@param	d	Directory structure.
*/
EXTERN void      dkdir_delete	DK_PR((dk_dir_t *d));

/**	Start traversing directory.
	The function starts a new directory traversal for a
	dk_dir_t structure. This is only necessary for a
	dk_dir_t obtained from dkdir_new().
	@param	d	Directory structure.
	@param	n	Name of directory.
	@return	Flag to indicate success.
*/
EXTERN int	  dkdir_start_search	DK_PR((dk_dir_t *d, char *n));

/**	End traversing a directory.
	The function finishes a directory traversal formerly started
	by dkdir_start_search().
	@param	d	Directory structure.
*/
EXTERN void	  dkdir_end_search	DK_PR((dk_dir_t *d));

/**	Check for next directory entry.
	This function checks whether or not there is yet another entry
	in the directory which was not yet found in the current directory
	traversal.
	If this function returns successfully you can use the functions
	below -- dkdir_get_fullname(), dkdir_get_shortname(), dkdir_uid(),
	dkdir_gid(), dkdir_ctime(), dkdir_atime(), dkdir_mtime(),
	dkdir_filetype(), dkdir_permissions(), dkdir_inode(), dkdir_device(),
	dkdir_rdevice(), dkdir_nlinks(), dkdir_size() and dkdir_size_ok() --
	to obtain information about the entry. The char * functions return
	pointers to elements of \a d, these pointers can not longer
	be used after dkdir_delete() or dkdir_close(). The \a d members
	will change in the next call to dkdir_next().
	@param	d	Directory structure.
	@return	Flag to indicate success.
*/
EXTERN int	  dkdir_next		DK_PR((dk_dir_t *d));

/**	Retrieve full file name.
	@param	d	Directory structure.
	@return	The full file name of the last entry found.
*/
EXTERN char	  *dkdir_get_fullname	DK_PR((dk_dir_t *d));

/**	Retrieve short file name.
	@param	d	Directory structure.
	@return	The short file name of the last entry found.
*/
EXTERN char      *dkdir_get_shortname   DK_PR((dk_dir_t *d));

/**	Get owner UID.
	@param	d	Directory structure.
	@return	The entry owners UID.
*/
EXTERN long	  dkdir_uid DK_PR((dk_dir_t *d));

/**	Get owner GID.
	@param	d	Directory structure.
	@return	The owners GID.
*/
EXTERN long	  dkdir_gid DK_PR((dk_dir_t *d));

/**	Get creation time.
	@param	d	Directory structure.
	@return	The creation time as text.
*/
EXTERN char	 * dkdir_ctime DK_PR((dk_dir_t *d));

/**	Get last access time.
	@param	d	Directory structure.
	@return	The last access time stamp as text.
*/
EXTERN char	 * dkdir_atime DK_PR((dk_dir_t *d));

/**	Get modification time.
	@param	d	Directory structure.
	@return	Modification time stamp as text.
*/
EXTERN char	 * dkdir_mtime DK_PR((dk_dir_t *d));

/**	Get file type.
	@param	d	Directory structure.
	@return	The file type.
*/
EXTERN int	  dkdir_filetype DK_PR((dk_dir_t *d));

/**	Get permissions.
	@param	d	Directory structure.
	@return	The file permissions.
*/
EXTERN int	  dkdir_permissions DK_PR((dk_dir_t *d));

/**	Get inode number.
	@param	d	Directory structure.
	@return	The inode number.
*/
EXTERN unsigned long  dkdir_inode DK_PR((dk_dir_t *d));

/**	Get device number.
	@param	d	Directory structure.
	@return	The device number.
*/
EXTERN unsigned long   dkdir_device DK_PR((dk_dir_t *d));

/**	Get relative device number.
	@param	d	Directory structure.
	@return	The relative device number.
*/
EXTERN unsigned long  dkdir_rdevice DK_PR((dk_dir_t *d));

/**	Get number of links.
	@param	d	Directory structure.
	@return	The number of links.
*/
EXTERN unsigned long  dkdir_nlinks DK_PR((dk_dir_t *d));

/**	Get entry size.
	@param	d	Directory structure.
	@return	The file size of the entry.
*/
EXTERN dk_long_long_unsigned_t dkdir_size DK_PR((dk_dir_t *d));

/**	Get entry size and check for overflow.
	@param	d	Directory structure
	@param	ok	Pointer to variable receiving an error code
			if an error occurs.
	@return	The file size of the entry.
*/
EXTERN dk_long_long_unsigned_t dkdir_size_ok DK_PR((dk_dir_t *d, int *ok));

/**	Retrieve all information about the current entry.
	This function returns a pointer to a member of \a d. Do not attempt
	to release this memory using dkstat_close(). The pointer can not
	be used after the dk_dir_t structure was released using
	dkdir_close() or dkdir_delete().
	@param	d	Directory structure.
	@return	Pointer to file information.
*/
EXTERN dk_stat_t *dkdir_stat DK_PR((dk_dir_t *d));

/**	Check whether file name needs expansion.
	This function checks whether the file name must be expanded.
	A file name must be expanded on Windows systems if the name contains
	wildcards ('*' or '?').
	@param	n	File name to inspect.
	@return	Flag to indicate whether or not the
	file name must be expanded.
*/
EXTERN int	dksf_must_expand_filename DK_PR((char *n));

/**	Open file name expander.
	The file name expander structure (dk_fne_t) is created in
	dynamically allocated memory, you must release it after usage
	calling the dkfne_close() function.
	@param	n	File name pattern containing wildcards ('*', '?').
	@param	f	Flag whether (non-zero value) or not (0) to
			search for files.
	@param	d	Flag whether (non-zero value) nor not (0) to search
			for directories.
	@return	Pointer to new file name expander on success, NULL on error.
*/
EXTERN dk_fne_t	 *dkfne_open DK_PR((char *n, int f, int d));

/**	Close file name expander.
	@param	f	File name expander to close and release.
*/
EXTERN void       dkfne_close	DK_PR((dk_fne_t *f));

/**	Check for next file matching the pattern.
	If the function returns successfully you can use dkfne_get_fullname()
	or dkfne_get_shortname() to retrieve the name of the entry found.
	These functions return pointers to components of \a f, so the pointer
	can not be used after releasing the structure using dkfne_close().
	The components are modified by the next call to dkfne_next() or
	dkfne_get_one().
	@param	f	File name expander.
	@return	Flag to indicate success.
*/
EXTERN int	  dkfne_next	DK_PR((dk_fne_t *f));

/**	Check whether or not the pattern matches exactly one file name.
	If the function returns successfully you can use dkfne_get_fullname()
	or dkfne_get_shortname() to retrieve the name of the entry found.
	These functions return pointers to components of \a f, so the pointer
	can not be used after releasing the structure using dkfne_close().
	The components are modified by the next call to dkfne_next() or
	dkfne_get_one().
	@param	f	File name expander.
	@return	Flag to indicate success.
*/
EXTERN char	 *dkfne_get_one	DK_PR((dk_fne_t * f));

/**	Get full file name.
	@param	f	File name expander.
	@return	Pointer to the file name.
*/
EXTERN char      *dkfne_get_fullname	DK_PR((dk_fne_t *f));

/**	Get short file name.
	@param	f	File name expander.
	@return	Pointer to the file name.
*/
EXTERN char      *dkfne_get_shortname	DK_PR((dk_fne_t *f));

/**	Retrieve error code.
	This function returns the error code for the last error occured.
	Optionally the error code variable can be reset.
	@param	f	File name expander.
	@param	r	Flag to indicate whether (non-zero value) or not (0)
			the error code member variable must be reset.
	@return	The error code of the last error.
*/
EXTERN int	  dkfne_get_error_code DK_PR((dk_fne_t *f, int r));

/**	Make directory.
	@param	p	Path name of the new directory.
	@param	m	Access permissions to the new directory
			(or-combined DK_PERM_...-constants).
	@return	Flag to indicate success.
*/
EXTERN int	  dksf_mkdir DK_PR((char *p, int m));

/**	Change access permissions.
	@param	p	Path name of the file or directory.
	@param	m	New access permissions (or-combination of
			DK_PERM_...-constants).
	@return	Flag to indicate success.
*/
EXTERN int	  dksf_chmod DK_PR((char *p, int m));

/**	Change access permissions of an opened file.
	@param	fd	File descriptor.
	@param	m	New access permissions (or-combination of
	DK_PER_...-constants).
	@return	Flag to indicate success.
*/
EXTERN int	  dksf_fchmod DK_PR((int fd, int m));

/**	Check whether the system supports user IDs.
	@return	Flag to indicate whether the system supports user IDs.
*/
EXTERN int	  dksf_have_getuid DK_PR((void));

/**	Get current user ID.
	@return	The user ID.
*/
EXTERN long	  dksf_getuid DK_PR((void));

/**	Check whether  the system supports dksf_geteuid().
	@return	Flag to indicate whether the system supports dksf_geteuid().
*/
EXTERN int	  dksf_have_geteuid DK_PR((void));

/**	Get effective user ID.
	@return The effective user ID.
*/
EXTERN long	  dksf_geteuid DK_PR((void));

/**	Check whether the system supports group IDs and dksf_getgid().
	@return	Flag to indicate whether the system supports dksf_getgid().
*/
EXTERN int	  dksf_have_getgid DK_PR((void));

/**	Get group ID.
	@return	The group ID.
*/
EXTERN long	  dksf_getgid DK_PR((void));

/**	Check whether the system supports dksf_getegid().
	@return	Flag to indicate whether the system supports dksf_getedid().
*/
EXTERN int	  dksf_have_getegid DK_PR((void));

/**	Get effective group ID.
	@return	The effective group ID.
*/
EXTERN long	  dksf_getegid DK_PR((void));

/**	Check whether the system supports process IDs and dksf_getpid().
	@return	Flag to indicate whether the system supports dksf_getpid().
*/
EXTERN int	  dksf_have_getpid DK_PR((void));

/**	Get process ID.
	@return	The process ID.
*/
EXTERN long	  dksf_getpid DK_PR((void));

/**	Check whether the system supports dksf_getppid().
	@return	Flag to indicate whether the system supports dksf_getppid().
*/
EXTERN int	  dksf_have_getppid DK_PR((void));

/**	Get parent process ID.
	@return	The process ID of the parent process.
*/
EXTERN long	  dksf_getppid DK_PR((void));

/**	Check whether the system supports process group IDs and dksf_getpgrp().
	@return	Flag to indicate whether the system supports dksf_getpgrp().
*/
EXTERN int	  dksf_have_getpgrp DK_PR((void));

/**	Get process group ID.
	@return	The processgroup ID of the current process.
*/
EXTERN long	  dksf_getpgrp DK_PR((void));

/**	Check whether the system supports dksf_getpgid().
	@return	Flag to indicate whether the system supports dksf_getpgid().
*/
EXTERN int	  dksf_have_getpgid DK_PR((void));

/**	Get process group ID of another process.
	@param	p	The process ID of a process.
	@return	The process group id of \a p.
*/
EXTERN long	  dksf_getpgid DK_PR((long p));

/**	Get current user name.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_uname DK_PR((char *b, size_t s));

/**	Get effective user name.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_euname DK_PR((char *b, size_t s));

/**	Get current users home directory.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_home DK_PR((char *b, size_t s));

/**	Get effective users home directory.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_ehome DK_PR((char *b, size_t s));

/**	Get host name.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_hostname DK_PR((char *b, size_t s));

/**	Get DNS domain name of host.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_domainname DK_PR((char *b, size_t s));

/**	Get name of directory for temporary files.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	  dksf_get_tempdir DK_PR((char *b, size_t s));

/**	Get maximum length of a path in characters.
	@return	Maximum path length.
*/
EXTERN long	  dksf_get_maxpathlen	DK_PR((void));

/**	Get maximum number of open files.
	@return	Maximum number of open files.
*/
EXTERN long	  dksf_get_maxfiles	DK_PR((void));

/**	Get current working directory.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@return	Success flag.
*/
EXTERN int	dksf_getcwd DK_PR((char *b, size_t s));

/**	Get full file name (including path) of executable file.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@param	d	Current working directory.
	@param	p	Program name from argv[0].
	@param	w	Flag to allow Windows functions GetModuleFileNameA() and
			GetModuleHandle() on Windows systems.
			Recommended value: 1.
	@return	Success flag.
*/
EXTERN int	dksf_get_executable DK_PR((char *b, size_t s, char *d, char *p, int w));

/**	Combine paths.
	@param	b	Pointer to buffer receiving the result.
	@param	s	Size of \a b.
	@param	c	Base directory (i.e. current directory).
	@param	p	Path name to add.
	@return	Success flag.
*/
EXTERN int	dksf_path_combine DK_PR((char *b, size_t s, char *c, char *p));

/**	Check absolute path name.
	The function checks, whether or not \a p is an absolute path name.
	@param	p	The path name to check
	@return	Flag to indicate whether or not \a p is an absolute path name.
*/
EXTERN int	dksf_is_abs_path DK_PR((char *p));

/**	Find file name suffix.
	The function searches for the suffix of the file name \a p.
	@param	p	Path name.
	@return	Pointer to the dot starting the file name suffix.
*/
EXTERN char	*dksf_get_file_type_dot DK_PR((char *p));

/**	Find last path name component.
	@param	p	Path name.
	@return	Pointer to last component in path name.
*/
EXTERN char	*dksf_get_last_filename DK_PR((char *p));

/**	Convert time stamp to text representation.
	@param	b	Buffer to receive result, must be 21 at least.
	@param	t	Time stamp.
*/
EXTERN void	dksf_time_convert DK_PR((char *b, time_t t));

/**	Correct file name separators.
	Some systems use slashes other systems use backslashes
	to separate parts in a path name.
	This function converts slashes into backslashes or backslashes
	into slashes.
	@param	p	Path name.
*/
EXTERN void	dksf_correct_fnsep DK_PR((char *p));

/**	Remove directory.
	The directory is removed, including all contents.
	@param	p	Path name of directory to delete.
	@return	Success flag.
*/
EXTERN int	dksf_remove_directory DK_PR((char *p));

/**	Remove a file.
	@param	p	Path name of the file.
	@return	Success flag.
*/
EXTERN int      dksf_remove_file DK_PR((char *p));

/**	Security checks before overwriting a file.
	This function checks whether a file can be overwritten.
	Even if file permissions allow writing we should do additional
	checks:
	- The file must not be a directory (DK_SF_SEC_DIR).
	- For symbolic links the following checks are added:
		- The symbolic link owner must be the owner of the
		  link destination (DK_SF_SEC_OWNER).
		- The symbolic link must not reside in a group
		  writable directory (DK_SF_SEC_WG).
		- The symbolic link must not reside in a public writable
		  directory (DK_SF_SEC_WO).
	@param	p	Path name of file to open.
	@param	i	Security checks to ignore (or-combination of
			DK_SF_SEC_xxx constants.
	@param	r	Pointer to a variable to receive the reason if opening
			The file is denied due to failed security checks.
	@return	Flag to indicate whether or not the file can be written.
*/
EXTERN int	dksf_allowed_to_write DK_PR((char *p, int i, int *r));

/**	Open a file, apply security checks.
	Before opening the file this function uses dksf_allowed_to_write()
	for additional security checks.
	@param	p	Path name of file to open
	@param	m	File open mode, i.e. "r", "w",...
	@param	i	Security checks to ignore (or-combination of
	DK_SF_SEC_xxx constants).
	@param	r	Pointer to a variable to receive the reason
			if opening the file is denied due to failed
			security checks.
	@return	Pointer to a FILE structure.

*/
EXTERN FILE	*dksf_msfo DK_PR((char *p, char *m, int i, int *r));

/**	Open a file, apply security checks.
	This function is intended as a replacement for fopen().
	Before calling fopen() all the DK_SF_SEC_xxx security checks are
	applied.
	@param	p	Path name of file to open.
	@param	m	File open mode, i.e. "r", "w"...
	@return	Pointer to FILE structure.
*/
EXTERN FILE	*dksf_fopen DK_PR((char *p, char *m));

/**	Switch file descriptor to binary mode.
	On Windows systems this function switches a file descriptor \a f to
	binary or text mode depending on the \a b flag. On other systems
	this function has no impact.
	@param	f	File descriptor.
	@param	b	Flag to indicate whether to bring the file descriptor
			into binary or text mode.
	@return	Flag to indicate whether or not the file descriptor was
			in binary mode before the function was invoked.
*/
EXTERN int	dksf_fdesk_binary DK_PR((int f, int b));

/**	Get file type.
	This function returns the file type (regular file, directory, socket...)
	as DK_SF_FT_xxx constant.
	@param	p	Path name.
	@return	The file type.
*/
EXTERN int	dksf_get_filetype DK_PR((char *p));

/**	Check whether a path name is a directory.
	@param	p	Path name.
	@return	Flag to indicate whether or not the path is a directory.
*/
EXTERN int	dksf_is_directory DK_PR((char *p));

/**	Deny the creation of core files.
	This functtion sets the allowed size of core files to 0
	if supported by the system.
*/
EXTERN int	dksf_no_core DK_PR((void));

/**	Check whether or not standard input is connected to a terminal.
	@return	Check result.
*/
EXTERN int	dksf_echo_test_tty DK_PR((void));

/**	Save current keyboard echo setting.
	@param	e	Structure to save data to.
	@return	Flag to indicate success.
*/
EXTERN int	dksf_echo_save DK_PR((dk_echo_t *e));

/**	Restore keyboard echo setting.
	@param	e	Structure to restore data from.
	@return	Flag to indicate success.
*/
EXTERN int	dksf_echo_restore DK_PR((dk_echo_t *e));

/**	Check whether the keyboard echo data belongs to a terminal.
	@param	e	Structure for keyboard echo data.
	@return	Check result.
*/
EXTERN int	dksf_echo_is_tty DK_PR((dk_echo_t *e));

/**	Turn keyboard echo off.
	@param	e	Structure for keyboard echo data.
	@return	Flag to indicate success.
*/
EXTERN int	dksf_echo_off DK_PR((dk_echo_t *e));

/**	Get size of file size data type in bytes.
	@return	The size.
*/
EXTERN unsigned long dksf_filesize_bytes DK_PR((void));

/**	Get size of long long type in bytes.
	@return The size.
*/
EXTERN unsigned long dksf_long_long_bytes DK_PR((void));

/**	Check whether a destination file must be rebuild.
	@param	d	Name of destination file.
	@param	s	Name of source file.
	@return	1 for  rebuild, 0 for not necessary.
*/
EXTERN int dksf_must_rebuild DK_PR((char *d, char *s));

#if defined(__cplusplus)
}
#endif

/** Security check: File group writable? */
#define	DK_SF_SEC_WG	1

/** Security check: File writable for others (all)? */
#define DK_SF_SEC_WO	2

/** Security check: For symlinks, do symlink owner and file owner match? */
#define DK_SF_SEC_OWNER	4

/** Security check: Is the path name a directory? */
#define DK_SF_SEC_DIR   8

#endif
/* DK_SYSFCT_INCLUDED */

