tis-mkfs Manual

Presentation

The aim of the tis-mkfs tool is to generate C source code that represents a virtual file system. It is useful when analyzing an application that has some interactions with the file system, such as reading and writing files (including special character devices), pipes and sockets. The generated code, added to the analysis, makes it possible to analyze the behavior of an application accessing files, or using other operations related to the file system. Without tis-mkfs, the default behavior of the analyzer is to consider that the filesystem only contains /dev/stdin, /dev/stdout and /dev/stderr.

This manual explains how to use the tis-mkfs tool. It also gives the tool limitations and provides workaround solutions. Some internal details are provided to help customizing the virtual file system content and/or behavior if needed.

Quick start

Starting from a file hello.txt that holds the string Hello! the following command generates the mkfs_filesystem.c file that implements a virtual file system containing one input.txt file with the same content than hello.txt:

$ tis-mkfs -local "input.txt:hello.txt"

This is a micro application that open and read the input file:

#include <stdio.h>
int main(void)
{
  FILE *f = fopen("input.txt", "r");
  if (f) {
    int c = fgetc(f);
    if (c != EOF)
      printf("First char = '%c'\n", (char)c);
    fclose(f);
  }
}

The command to run the analyzer on this function using the generated file system is:

$ tis-analyzer -fs mkfs_filesystem.c test.c -val

As expected, the following line is part of the output:

First char = 'H'

Building the virtual file system

This section shows all the possible options that can be used to build a virtual file system with tis-mkfs.

Specification

In order to build the virtual file system, the structure and the content of the file system that needs to be seen from the analyzed application first have to be determined.

This is an example of files and directories that may be expected from the application:

 /
 ├── etc/
 │   └── profile                     # known data
 ├── home/
 │   ├── .bashrc                     # known data
 │   ├── alice/
 │   │   └── data.txt                # specified content
 │   ├── bob/
 │   │   └── .bashrc                 # unknown content
 │   └── Documents/                  # empty directory
 └── usr/
     └── share/
         └── input_file.txt          # known data

For the analysis purposes, the files may have a fully defined content, a totally unknown content, or may be partially specified (number of elements and their range).

Because this model is built to represent the entire file system expected by the application, trying to read a file that does not exist in the virtual file system is analyzed as an error, as it would be in a real file system.

Preparation

The files with a known content are created from files in the real file system. Parts of the directory organization may also be created from there.

For instance, the model above may be built from the following directories and files in the real file system:

 .
 ├── filesystem
 │   ├── etc
 │   │   └── profile                 # content for /etc/profile
 │   └── home
 │       └── .bashrc                 # content for /home/.bashrc
 ├── main_input_file.txt             # content for /usr/share/input_file.txt

In this example, the content of the virtual file /usr/share/input_file.txt is generated from the real ./main_input_file.txt file. It could also have been generated from ./filesystem/usr/share/input_file.txt.

File Generation

This section shows how to choose the options to build the tis-mkfs command to generate a C file holding the virtual file system presented above.

The first option specifies that the local directory filesystem shown above has to be duplicated in the virtual file system, in the path /:

-local "/:filesystem"

Then the file main_input_file.txt is used to give the content of /usr/share/input_file.txt in the virtual file system:

-local "/usr/share/input_file.txt:main_input_file.txt"

More generally, the -local internal_name:local_name option is used to specify that the element local_name must be seen as internal_name in the analyzed program. The internal_name name does not have to specify absolute paths, but it must match exactly the ones used in the analyzed application since there are no path translation (see Perimeter). The local_name object must exist in the real file system:

  • if it is a file, its internal representation has the same content,
  • if it is a directory, the internal_name directory is added to the internal file system together with all its hierarchy. In this case, the files have the same name in the analyzed program than on the machine, but the root is renamed internal_dir.

The empty directory /home/Documents is created with:

-add-dir "/home/Documents"

The /home/bob/.bashrc file is created with an unknown content, and the /home/bob directory is automatically generated:

-add-file "/home/bob/.bashrc"

The /home/alice/data.txt is created as a file having 100 elements between 5 and 50:

-generic "/home/alice/data.txt:100:5:50"

The special filename tis-mkfs-stdin may be used with the -local, -generic and -add-file options to specify the content of the stdin stream.

The virtual file system is generated in a main_filesystem.c output file (and a main_filesystem.h header file is also created):

-o main_filesystem.c

So the full command to generate the virtual file system of the above example in a main_filesystem.c output file is:

$ tis-mkfs -local "/:filesystem" \
        -local "/usr/share/input_file.txt:main_input_file.txt" \
        -add-dir "/home/Documents" \
        -add-file "/home/bob/.bashrc" \
        -generic "/home/alice/data.txt:100:5:50" \
        -o main_filesystem.c \
        -print

The generated file system, showed thanks to the -print option, is the one specified above.

For more options, refer to the complete list in the help message below. All the options to add elements to the file system can be used together, and several times in the same command.

Help

This is the list of all the currently available options:

$ tis-mkfs -help

Generate a virtual file system for TrustInSoft analyzer.
More information in the User Manual.

Options are:
  -local <c_name:local_name> add an element <c_name> in the virtual file system
    that is similar to the <local_name> element.
    - if <local_name> is a file, <c_name> has the same content;
    - if <local_name> is a directory, <c_name> has recursively
      the same tree structure with the same files.
  -content-as-array when some content is specified by a local file,
    generate an array in the file system model
    instead of using the tis_inject_file builtin.
  -add-file <c_name> add a file named <c_name> in the file system.
    The name may include a path to specify where to put it,
    and in that case, the intermediate directories are created.
    The content of the file is unknown.
  -add-fifo similar to -add-file, but for a fifo (named pipe).
  -add-char-device similar to -add-file, but for a character special file (device).
   The device_id is not handled at the moment. It is set to 0,
   but can be changed from the user code if needed.
  -add-dir <c_name> add a directory named <c_name> in the file system.
    The name may include a path to specify where to put it.
    It is empty except is the -add-file option is also used.
  -nb-max-created-files <n> if the analyzed program creates new files, in addition of
   the one given to tis-mkfs, the file system array must be bigger
   than the initial number of files.
   This option sets the maximum number of new files that can be created.
   (default: 100)
  -nb-max-created-dirs <n> is similar to the -nb-max-created-files option, but for directories.
   (default: 10)
  -sep <separator> to change the separator in options (default: ':')
  -o <output_filename> (default: mkfs_filesystem.c)
  -generic <c_name:size:min:max> generates a virtual file of name <c_name>
    of size <size> and containing any values in the interval [<min>;<max>].
    Both bounds must be between 0 and 255.
  -print print the generated file system to stdout
  -quiet do not print helper message to stdout
  -help  Display this list of options
  --help  Display this list of options

Analysis

This section present how to use the generated file system when analyzing an application. It also shows several customizations that may be needed for special purposes.

Notice that the default behavior of the analyzer, when tis-mkfs is not used, is to consider that the filesystem only contains /dev/stdin, /dev/stdout and /dev/stderr. The -no-fs option can be used to change this behavior and to provide no filesystem model at all to the analyzer, but beware that this may lead to imprecise results when analyzing functions related to filesystem operations.

Simple Analysis

To use tis-analyzer to analyze the studied application with the virtual file system, the generated file (named main_filesystem.c in the above example) has to be added with the -fs option. This adds the generated file to the source files to analyse, and also adds the __tis_mkfs.c file that comes with the tis-mkfs tool and that holds specific implementations for some standard library functions that are able to use the generated information. This file is located in the $TIS_HOME/share/tis directory (also called $TIS_SHARE).

So the command line to run the analysis has to be modified like this:

$ tis-analyzer ...  -fs main_filesystem.c

Modifying the Behavior

No Error Mode

Trying to open a file for reading if does not exist in the file system always returns an error, which is the normal behavior of the standard library functions. However these functions may also return errors that may come from the system, for example when the maximum number of open files is reached.

These errors may be ignored during the first steps of the analysis in order to first study the application in its nominal behavior. For that purpose, tis-mkfs provides a macro __TIS_MKFS_NO_ERR or the -no-fs-error option. When using it, the command line is modified with:

$ tis-analyzer ...  -D __TIS_MKFS_NO_ERR ...

or:

$ tis-analyzer … -no-fs-error …

The final analysis must be realized without defining the macro in order to check that all the possible errors are correctly handled.

Pre-Allocate Mode

tis-mkfs stores the files data in memory, and may be instructed to use either static or dynamic allocation.

By default, tis-mkfs use the __TIS_MKFS_STATIC_ALLOCATE mode which stores the file contents in one large statically allocated array. This means that the maximum memory size cannot be changed. Since it does not involve dynamic allocations, it is the easiest mode to use to get precise results.

But two other modes are provided in cases where this array is too small. They may be selected by defining one of the following macros: __TIS_MKFS_PREALLOCATE or __TIS_MKFS_DYNAMIC_ALLOCATE.

When __TIS_MKFS_PREALLOCATE is defined, the maximum size of the larger files has to be given by __mkfs_preallocate_size. This global variable of type size_t must be defined and initialized by the user in one of the source files. For instance:

#include <stdlib.h>
size_t __mkfs_preallocate_size = 100000;

Then the memory that holds the data is allocated only once for each opened file, so it may be adapted according to the needs. The analysis checks that no file grows beyond its pre-allocated size.

When __TIS_MKFS_DYNAMIC_ALLOCATE is defined, tis-mkfs uses realloc calls to expand the files content. In case of heavy use of dynamic allocations, this may lead to accuracy problems in the analyzer.

Precise File Descriptor

The opened files are identified by their file descriptor. It is important to make the analyzer compute a precise value for the file descriptors to keep the exact relation between them and the file information. It means that each call to the internal function __mkfs_get_next_file_desc should return a single value.

Because the standard specifies that, when a new file descriptor is needed, it must always be the smallest available, this function has a loop to find it. It might be needed to unroll it, or to give enough precision (slevel) to this function.

But in some cases, even if the analysis is precise, it might not be possible to have a precise value for a file descriptor when there are several paths opening and closing files. For instance, in the following example, fd2 might be 3 or 4:

// no files opened yet.
int fd1 = open("input1.txt", O_RDONLY);
//@ assert fd1 == 3;
if (c)
  close(fd1);
int fd2 = open("input2.txt", O_RDONLY);

In these case, the __TIS_MKFS_NO_CLOSE macro can be used to tell to the tool to never re-use an already used file descriptor. So no matter if fd1 is closed or not, it does not get re-used, and the analyzed value for fd2 is always 4.

Warning

When using the __TIS_MKFS_NO_CLOSE macro, it might be necessary to increase the value of __TIS_FOPEN_MAX - refer to Overloading some libc Macros; also, the following code pattern, commonly used to force a specific file descriptor value:

close(fd);
dup(otherfd, fd);

will not work, as dup will fail since fd is not reusable when __TIS_MKFS_NO_CLOSE is defined.

Modifying the Generated Information

In some cases, it might be useful to deeper customize the file system content and/or the function behavior. Some examples are given below.

The header file $TIS_SHARE/__tis_mkfs.h may be included when needed for customization as it declares internal data structures and functions. For more details, refer to the Internal Details section.

Modifying the Library

As mentioned before, the __tis_mkfs.c library file that comes with the tis-mkfs tool holds a specific implementation of some standard library functions.

Because there is always a trade-off between the precision and the generality of the analysis, some choices have had to be been made. The section Perimeter gives more information about the limitations of the implemented function.

In some cases, custom implementation of one or more of these functions might be preferred. Some macros are available to exclude the predefined functions that is just a call to an internal version of the function.

For instance, the read function is defined by:

#ifndef __TIS_USER_READ
ssize_t read(int fd, void * buf, size_t count)
{ return __mkfs_read(fd, buf, count); }
#endif // __TIS_USER_READ

To use a specific read function, one has to:

  • define the __TIS_USER_READ macro;
  • write a custom read function (for instance in a read.c file);
  • include that new file in the analysis.

So the modified command looks like:

$ tis-analyzer ... -fs -D__TIS_USER_READ read.c ...

The custom file probably needs to include __tis_mkfs.h, and the custom function may still use the standard __mkfs_read function if needed. Some other functions, such as __check_fd_file_ok_for_reading for instance, might also help writing specific implementations (see Internal Details for more information).

The functions which may be provided by the user are: access, bind, close, closedir, connect, creat, dirfd, dup, dup2, fcntl, fdopendir, fstat, ftruncate, getcwd, getegid, geteuid, getgid, getsocketname, getuid, link, lseek, lstat, mmap, msync, munmap, open, opendir, pipe, pipe2, pread, pwrite, read, readdir, readlink, recv, recvfrom, rewinddir, rmdir, seekdir, socket, stat, telldir, truncate, unlink, write.

Modifying the Generated Header File

Some of the fields in the generated structures are initialized either with information coming from the local file system, or with default values according to the generated configuration file. This header file is named after the generated C file. For instance, if the asked name is main_filesystem.c, then the configuration file is named main_filesystem.h.

Initially generated, this file can be modified, for instance to change the default permission of the virtual files. Have a look in it to see what can be customized there. It can be safely modified since it is not overridden if it exists, so the modifications are not lost in case of a regeneration.

Overloading the Generated Data

Another way to modify the generated values is to modify them from the entry point function that defines the context. It enables to modify the information for one file only, or to give a range of values and even a totally undetermined value.

For instance to analyze the application with the "input_file.txt" having both 0644 or 0600 permission, the entry point can be modified to first retrieve the file information with the __mkfs_get_file function, and to modify the corresponding field in the file array (see the Internal Details section for more information about the data structures):

#include <__tis_mkfs.h>

void main (void) {
  ...
  struct __fc_fs_file * fs = __mkfs_get_file("input_file.txt");
  if (i != -1) {
    t_mode mode1 = S_IFREG | S_IRUSR | S_IWUSR;
    t_mode mode2 = mode1   | S_IRGRP | S_IROTH;
    fs->__fc_stat->st_mode = tis_nondet(mode1, mode2);
    }
  ...
}

Overloading some libc Macros

Because tis-mkfs relies on some libc definitions (mainly from stdio.h), it can be useful to redefine some macros, such as __TIS_FOPEN_MAX which gives the value of FOPEN_MAX. According to the ISO/IEC 9899:2011 standard, this constant is:

the minimum number of files that the implementation guarantees can be open simultaneously

Because its the default value may be too low for some applications (especially when using __TIS_MKFS_NO_CLOSE as explained in Precise File Descriptor), this constant can be overridden by the user from the command line:

$ tis-analyzer ...  -D __TIS_FOPEN_MAX=100

Perimeter

As mentioned before, there is a trade-off between the precision and the generality of the analysis, and moreover, the support is only partial at the moment. In order to warn the user when some unsupported features might be needed to analyze the application, or when a choice has been make that breaks the over-approximation of the results, annotations have been added to the library. These annotations have a _mkfs_niy suffix for tis-mkfs Not Implemented Yet feature. If all these annotations are valid, it means that the library has been used within tis-mkfs perimeter.

Limitations

Testing Permissions

When a file is known in the virtual file system, the access function is implemented to test the stat information according to the uid and gid. In the __TIS_MKFS_NO_ERR mode, it returns either 0 or -1 in case of error, and in this case errno is set to EACCES. Otherwise, the behavior is over-approximated and it returns either 0 or -1 with the errno variable set to an undetermined value.

At the moment, only the permission of the file is tested, not the one of the intermediate directories of the path.

Existing files

As said before, only the files and directory that appear in the virtual file system are supposed to exist. It is not possible at the moment to specify that a file may exist or not.

Path computation

There is no name resolution (such as realpath). It means that the file and directory names in the virtual file system must match the names that are use in the application.

Directories

There is a limited support fr the directory management at the moment. The current directory is the root of the file system, and it is not possible to change directory yet (chdir).

Moreover, there is no name resolution as said before, so directories such as . or .. are meaningless. They are used as is in the file names.

Supported Functions

Some header files declaring functions related to file system operations have been selected:

  • dirent.h,
  • fcntl.h,
  • stdio.h,
  • sys/mman.h,
  • sys/socket.h,
  • sys/stat.h,
  • unistd.h,

All the functions that are declared in these header files - according to The Open Group Base Specifications Issue 7 - are listed below, excluding the ones which are declared as extensions, or obsolescent in the document.

For each function, the third column tells if:

  • it is implemented (ok),
  • it is partially implemented (part),
  • it has not been implemented yet (niy),
  • it will not be implemented (wbi).

When a function is not implemented, the last column provides more information about the reason. Some abbreviations are used:

  • sc-exec: functions related with processes execution are not in tis-mkfs scope;
  • sc-string: functions like sprintf are about strings, so they are not in tis-mkfs scope;
  • lim-scan: scaning functions using format (such as in fscanf) are not handled in tis-mkfs yet;
  • lim-link: links are not handled yet;
  • lim-dir: there is a limited support for directory management at the moment, so some related functions are not implemented yet;
Function Header Source Implem. Comment
_exit unistd.h POSIX.1-2004 wbi builtin
accept sys/socket.h POSIX.1-2008 ok  
access unistd.h POSIX.1-2004 ok  
alarm unistd.h POSIX.1-2004 wbi sc-exec
bind sys/socket.h POSIX.1-2004 ok  
chdir unistd.h POSIX.1-2004 niy lim-dir
chmod sys/stat.h POSIX.1-2004 niy  
chown unistd.h POSIX.1-2004 niy  
clearerr stdio.h C99:7.19.10.1 ok  
close unistd.h POSIX.1-2004 ok  
closedir dirent.h POSIX.1-2004 ok  
confstr unistd.h POSIX.1-2004 niy  
connect sys/socket.h POSIX.1-2004 ok  
creat fcntl.h POSIX.1-2004 ok  
ctermid stdio.h POSIX.1-2004 niy  
dirfd dirent.h POSIX.1-2008 ok  
dup unistd.h POSIX.1-2004 ok  
dup2 unistd.h POSIX.1-2004 ok  
execl unistd.h POSIX.1-2004 wbi sc-exec
execle unistd.h POSIX.1-2004 wbi sc-exec
execlp unistd.h POSIX.1-2004 wbi sc-exec
execv unistd.h POSIX.1-2004 wbi sc-exec
execve unistd.h POSIX.1-2004 wbi sc-exec
execvp unistd.h POSIX.1-2004 wbi sc-exec
faccessat unistd.h POSIX.1-2008 niy  
fchdir unistd.h POSIX.1-2004 niy lim-dir
fchmod sys/stat.h POSIX.1-2004 niy  
fchmodat sys/stat.h POSIX.1-2008 niy  
fchown unistd.h POSIX.1-2004 niy  
fchownat unistd.h POSIX.1-2008 niy  
fclose stdio.h C99:7.19.5.1 ok  
fcntl fcntl.h POSIX.1-2004 niy  
fdatasync unistd.h POSIX.1-2004 niy  
fdopen stdio.h POSIX.1-2004 ok  
fdopendir dirent.h POSIX.1-2008 ok  
feof stdio.h C99:7.19.10.2 ok  
ferror stdio.h C99:7.19.10.3 ok  
fexecve unistd.h POSIX.1-2008 niy  
fflush stdio.h C99:7.19.5.2 ok  
fgetc stdio.h C99:7.19.7.1 ok  
fgetpos stdio.h C99:7.19.9.1 ok  
fgets stdio.h C99:7.19.7.2 ok  
fileno stdio.h POSIX.1-2004 ok  
fopen stdio.h C99:7.19.5.3 ok  
fork unistd.h POSIX.1-2004 wbi sc-exec
fpathconf unistd.h POSIX.1-2004 niy  
fprintf stdio.h C99:7.19.6.1 ok  
fputc stdio.h C99:7.19.7.3 ok  
fputs stdio.h C99:7.19.7.4 ok  
fread stdio.h C99:7.19.8.1 ok  
freopen stdio.h C99:7.19.5.4 niy  
fscanf stdio.h C99:7.19.6.2 niy lim-scan
fseek stdio.h C99:7.19.9.2 ok  
fsetpos stdio.h C99:7.19.9.3 ok  
fstat sys/stat.h POSIX.1-2004 ok  
fstatat sys/stat.h POSIX.1-2008 niy  
ftell stdio.h C99:7.19.9.4 ok  
ftruncate unistd.h POSIX.1-2004 ok  
futimens sys/stat.h POSIX.1-2008? niy  
fwrite stdio.h C99:7.19.8.2 ok  
getc stdio.h C99:7.19.7.5 ok  
getchar stdio.h C99:7.19.7.6 ok  
getcwd unistd.h POSIX.1-2004 part lim-dir
getegid unistd.h POSIX.1-2004 ok  
geteuid unistd.h POSIX.1-2004 ok  
getgid unistd.h POSIX.1-2004 ok  
getgroups unistd.h POSIX.1-2004 niy  
gethostname unistd.h POSIX.1-2004 niy  
getlogin unistd.h POSIX.1-2004 niy  
getlogin_r unistd.h POSIX.1-2004 niy  
getopt unistd.h POSIX.1-2004 wbi not in scope
getpeername sys/socket.h POSIX.1-2001 niy  
getpgid unistd.h POSIX.1-2004 wbi sc-exec
getpgrp unistd.h POSIX.1-2004 wbi sc-exec
getpid unistd.h POSIX.1-2004 niy  
getppid unistd.h POSIX.1-2004 niy  
gets stdio.h C99:7.19.7.7 ok  
getsid unistd.h POSIX.1-2004 niy  
getsockname sys/socket.h POSIX.1-2004 ok  
getsockopt sys/socket.h POSIX.1-2001 niy  
getuid unistd.h POSIX.1-2004 ok  
getwd unistd.h POSIX.1-2004 wbi legacy
isatty unistd.h POSIX.1-2004 niy  
lchown unistd.h POSIX.1-2004 niy  
link unistd.h POSIX.1-2004 niy lim-link
linkat unistd.h POSIX.1-2008 niy lim-link
listen sys/socket.h POSIX.1-2001 niy  
lseek unistd.h POSIX.1-2004 ok  
lstat sys/stat.h POSIX.1-2004 part lim-link
mkdir sys/stat.h POSIX.1-2004 ok lim-dir
mkdirat sys/stat.h POSIX.1-2008 niy lim-dir
mkfifo sys/stat.h POSIX.1-2004 niy lim-dir
mkfifoat sys/stat.h POSIX.1-2008 niy lim-dir
mknod sys/stat.h POSIX.1-2004 niy lim-dir
mmap sys/mman.h POSIX.1-2001 part  
mprotect sys/mman.h POSIX.1-2001 niy  
msync sys/mman.h POSIX.1-2001 niy  
munmap sys/mman.h POSIX.1-2001 part  
open fcntl.h POSIX.1-2004 ok  
openat fcntl.h POSIX.1-2008 niy  
opendir dirent.h POSIX.1-2004 ok  
pathconf unistd.h POSIX.1-2004 niy  
pause unistd.h POSIX.1-2004 wbi sc-exec
perror stdio.h C99:7.19.10.4 wbi not in scope
pipe unistd.h POSIX.1-2004 ok  
pread unistd.h POSIX.1-2004 ok  
printf stdio.h C99:7.19.6.3 ok  
putc stdio.h C99:7.19.7.8 ok  
putchar stdio.h C99:7.19.7.9 ok  
puts stdio.h C99:7.19.7.10 ok  
pwrite unistd.h POSIX.1-2004 ok  
read unistd.h POSIX.1-2004 ok  
readdir dirent.h POSIX.1-2004 ok  
readdir_r dirent.h POSIX.1-2008 niy  
readlink unistd.h POSIX.1-2004 ok  
readlinkat unistd.h POSIX.1-2008 niy  
recv sys/socket.h POSIX.1-2004 ok  
recvfrom sys/socket.h POSIX.1-2004 ok  
recvmsg sys/socket.h POSIX.1-2001 niy  
remove stdio.h C99:7.19.4.2 part rely on unlink
rename stdio.h C11:7.21.4.2 niy lim-name
rewind stdio.h C99:7.19.9.5 ok  
rewinddir dirent.h POSIX.1-2004 ok  
rmdir unistd.h POSIX.1-2004 part lim-dir
scandir dirent.h POSIX.1-2008 niy lim-dir
scanf stdio.h C99:7.19.6.4 niy lim-scan
seekdir dirent.h POSIX.1-2004 ok  
send sys/socket.h POSIX.1-2008 niy  
sendmsg sys/socket.h POSIX.1-2008 niy  
sendto sys/socket.h POSIX.1-2008 niy  
setbuf stdio.h C11:7.21.5.5 ok  
setegid unistd.h POSIX.1-2004 niy  
seteuid unistd.h POSIX.1-2004 niy  
setgid unistd.h POSIX.1-2004 niy  
setpgid unistd.h POSIX.1-2004 niy  
setsid unistd.h POSIX.1-2004 niy  
setsocketopt sys/socket.h POSIX.1-2004 niy  
setuid unistd.h POSIX.1-2004 niy  
setvbuf stdio.h C99:7.19.5.5 ok  
shutdown sys/socket.h ? niy  
sleep unistd.h POSIX.1-2004 wbi sc-exec
snprintf stdio.h C99:7.19.6.5 wbi sc-string
sockatmark sys/socket.h POSIX.1-2001 niy  
socket sys/socket.h POSIX.1-2004 ok  
socketpair sys/socket.h POSIX.1-2001 niy  
sprintf stdio.h C99:7.19.6.6 wbi sc-string
sscanf stdio.h C99:7.19.6.7 wbi sc-string
stat sys/stat.h POSIX.1-2004 ok  
symlink unistd.h POSIX.1-2004 niy lim-link
symlinkat unistd.h POSIX.1-2008 niy lim-link
sysconf unistd.h POSIX.1-2004 niy  
tcgetpgrp unistd.h POSIX.1-2004 niy  
tcsetpgrp unistd.h POSIX.1-2004 niy  
telldir dirent.h POSIX.1-2004 ok  
tmpfile stdio.h C99:7.19.4.3 ok  
tmpnam stdio.h C99:7.19.4.4 ok  
truncate unistd.h POSIX.1-2004 ok  
ttyname unistd.h POSIX.1-2004 niy  
ttyname_r unistd.h POSIX.1-2004 niy  
ualarm unistd.h POSIX.1-2004 wbi sc-exec
umask sys/stat.h POSIX.1-2004 ok  
ungetc stdio.h C99:7.19.7.11 ok  
unlink unistd.h POSIX.1-2004 part lim-dir
unlinkat unistd.h POSIX.1-2008 niy lim-dir
utimensat sys/stat.h POSIX.1-2008 niy  
vfprintf stdio.h C99:7.19.6.8 ok  
vfscanf stdio.h C99:7.19.6.9 niy lim-scan
vprintf stdio.h C99:7.19.6.10 ok  
vscanf stdio.h C99:7.19.6.11 niy lim-scan
vsnprintf stdio.h C99:7.19.6.12 wbi sc-string
vsprintf stdio.h C99:7.19.6.13 wbi sc-string
vsscanf stdio.h C99:7.19.6.14 wbi sc-string
write unistd.h POSIX.1-2004 ok  

Internal Details

This section is useful only when heavy customization is needed, so that may be skipped by casual users.

Generated File Content

The generated C file holds two arrays, one for the file and the other for the directories, that store information about them:

struct __fc_fs_file __fc_fs_files[] = { ... };
struct __fc_fs_dir __fc_fs_dirs[] = { ... };

Each file element includes the stat structure, and a pointer on a function that return an array holding the file content:

struct __fc_fs_file {
  char *__fc_fullpath;
  struct stat *__fc_stat;
  char *(*__fc_content)(void);
};

Each directory element includes also a stat structure, and a dirent array to hold the list of its content:

struct __fc_fs_dir {
  char *__fc_fullpath;
  struct stat *__fc_stat;
  struct dirent *__fc_dir_entries;
};

Moreover, some other variables are set to hold more information to deal with access rights:

uid_t __mkfs_uid = ... ;
uid_t __mkfs_gid = ...;

Helper Functions

The only two generated functions are provided to find the index of an element in the file or directory arrays given its name. If the name does not match any of the known elements, they return -1:

int __mkfs_get_file(const char *path);
int __mkfs_get_dir(const char *path);

Some more function might be helpful to write custom implementations such as:

__mkfs_file_info *__mkfs_get_file_info(int fd);
__mkfs_dir_info *__mkfs_get_dir_info(int fd);
__mkfs_socket_info *__mkfs_get_socket_info(int fd);

int __check_fd_dir_ok(int fd);
int __check_fd_file_ok_for_reading(int fd);
...

See in $TIS_SHARE/__tis_mkfs.h for a complete list of the types and available functions.