Exercises
Chapter 2. UNIX Standardization and Implementations
2.5. Limits
2.5.4. sysconf , pathconf , and fpathconf Functions
We've listed various minimum values that an implementation must support, but how do we find out the limits that a particular system actually supports? As we mentioned earlier, some of these limits might be available at compile time; others must be determined at runtime. We've also mentioned that some don't change in a given system, whereas others can change because they are associated with a file or directory. The runtime limits are obtained by calling one of the following three functions.
#include <unistd.h>
long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathconf(int filedes, int name);
All three return: corresponding value if OK, 1 on error (see later)
The difference between the last two functions is that one takes a pathname as its argument and the other takes a file descriptor argument.
Figure 2.10 lists the name arguments that sysconf uses to identify system limits. Constants beginning with _SC_ are used as arguments to sysconf to identify the runtime limit. Figure 2.11 lists the name arguments that are used by pathconf and fpathconf to identify system limits.
Constants beginning with _PC_ are used as arguments to pathconf and fpathconf to identify the runtime limit.
Figure 2.10. Limits and name arguments to
sysconfName of limit Description name argument
ARG_MAX maximum length, in bytes, of arguments to the exec functions _SC_ARG_MAX
ATEXIT_MAX maximum number of functions that can be registered with the atexit function
_SC_ATEXIT_MAX
CHILD_MAX maximum number of processes per real user ID _SC_CHILD_MAX
clock ticks/second number of clock ticks per second _SC_CLK_TCK
COLL_WEIGHTS_MAX maximum number of weights that can be assigned to an entry of the LC_COLLATE order keyword in the locale definition file
_SC_COLL_WEIGHTS_MAX
HOST_NAME_MAX maximum length of a host name as returned by gethostname _SC_HOST_NAME_MAX
IOV_MAX maximum number of iovec structures that can be used with readv or writev
_SC_IOV_MAX
LINE_MAX maximum length of a utility's input line _SC_LINE_MAX
LOGIN_NAME_MAX maximum length of a login name _SC_LOGIN_NAME_MAX
NGROUPS_MAX maximum number of simultaneous supplementary process group IDs per process
_SC_NGROUPS_MAX
OPEN_MAX maximum number of open files per process _SC_OPEN_MAX
PAGESIZE system memory page size, in bytes _SC_PAGESIZE
PAGE_SIZE system memory page size, in bytes _SC_PAGE_SIZE
RE_DUP_MAX number of repeated occurrences of a basic regular expression permitted by the regexec and regcomp functions when using the interval notation \{m,n\}
_SC_RE_DUP_MAX
STREAM_MAX maximum number of standard I/O streams per process at any given time; if defined, it must have the same value as FOPEN_MAX
_SC_STREAM_MAX
SYMLOOP_MAX number of symbolic links that can be traversed during pathname resolution
_SC_SYMLOOP_MAX
TTY_NAME_MAX length of a terminal device name, including the terminating null _SC_TTY_NAME_MAX
TZNAME_MAX maximum number of bytes for the name of a time zone _SC_TZNAME_MAX
This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks
.
Figure 2.11. Limits and name arguments to
pathconfand
fpathconfName of limit Description name argument
FILESIZEBITS minimum number of bits needed to represent, as a signed integer value, the maximum size of a regular file allowed in the specified directory
_PC_FILESIZEBITS
LINK_MAX maximum value of a file's link count _PC_LINK_MAX
MAX_CANON maximum number of bytes on a terminal's canonical input queue _PC_MAX_CANON
MAX_INPUT number of bytes for which space is available on terminal's input queue
_PC_MAX_INPUT
NAME_MAX maximum number of bytes in a filename (does not include a null at end)
_PC_NAME_MAX
PATH_MAX maximum number of bytes in a relative pathname, including the terminating null
_PC_PATH_MAX
PIPE_BUF maximum number of bytes that can be written atomically to a pipe
_PC_PIPE_BUF
SYMLINK_MAX number of bytes in a symbolic link _PC_SYMLINK_MAX
We need to look in more detail at the different return values from these three functions.
All three functions return 1 and set errno to EINVAL if the name isn't one of the appropriate constants. The third column in Figures 2.10 and 2.11 lists the limit constants we'll deal with throughout the rest of this book.
1.
Some names can return either the value of the variable (a return value 0) or an indication that the value is indeterminate.
An indeterminate value is indicated by returning 1 and not changing the value of errno. 2.
The value returned for _SC_CLK_TCK is the number of clock ticks per second, for use with the return values from the times function (Section 8.16).
3.
There are some restrictions for the pathname argument to pathconf and the filedes argument to fpathconf. If any of these restrictions isn't met, the results are undefined.
The referenced file for _PC_MAX_CANON and _PC_MAX_INPUT must be a terminal file.
1.
The referenced file for _PC_LINK_MAX can be either a file or a directory. If the referenced file is a directory, the return value applies to the directory itself, not to the filename entries within the directory.
2.
The referenced file for _PC_FILESIZEBITS and _PC_NAME_MAX must be a directory. The return value applies to filenames within the directory.
3.
The referenced file for _PC_PATH_MAX must be a directory. The value returned is the maximum length of a relative pathname when the specified directory is the working directory. (Unfortunately, this isn't the real maximum length of an absolute pathname, which is what we want to know. We'll return to this problem in Section 2.5.5.)
4.
The referenced file for _PC_PIPE_BUF must be a pipe, FIFO, or directory. In the first two cases (pipe or FIFO) the return value is the limit for the referenced pipe or FIFO. For the other case (a directory) the return value is the limit for any FIFO created in that directory.
5.
The referenced file for _PC_SYMLINK_MAX must be a directory. The value returned is the maximum length of the string that a symbolic link in that directory can contain.
6.
Example
The awk(1) program shown in Figure 2.12 builds a C program that prints the value of each pathconf and sysconf symbol.
The awk program reads two input filespathconf.sym and sysconf.symthat contain lists of the limit name and symbol, separated by tabs. All symbols are not defined on every platform, so the awk program surrounds each call to pathconf and sysconf with the necessary #ifdef statements.
For example, the awk program transforms a line in the input file that looks like
NAME_MAX _PC_NAME_MAX
into the following C code:
#ifdef NAME_MAX
printf("NAME_MAX is defined to be %d\n", NAME_MAX+0);
#else
printf("no symbol for NAME_MAX\n");
#endif
#ifdef _PC_NAME_MAX
pr_pathconf("NAME_MAX =", argv[1], _PC_NAME_MAX);
#else
printf("no symbol for _PC_NAME_MAX\n");
#endif
The program in Figure 2.13, generated by the awk program, prints all these limits, handling the case in which a limit is not defined.
Figure 2.14 summarizes results from Figure 2.13 for the four systems we discuss in this book. The entry "no symbol" means that the system doesn't provide a corresponding _SC or _PC symbol to query the value of the constant. Thus, the limit is undefined in this case. In contrast, the entry "unsupported" means that the symbol is defined by the system but unrecognized by the sysconf or pathconf functions.
The entry "no limit" means that the system defines no limit for the constant, but this doesn't mean that the limit is infinite.
We'll see in Section 4.14 that UFS is the SVR4 implementation of the Berkeley fast file system. PCFS is the MS-DOS FAT file system implementation for Solaris.
Figure 2.12. Build C program to print all supported configuration limits
BEGIN {
printf("#include \"apue.h\"\n") printf("#include <errno.h>\n") printf("#include <limits.h>\n") printf("\n")
printf("static void pr_sysconf(char *, int);\n") printf("static void pr_pathconf(char *, char *, int);\n") printf("\n")
printf("int\n")
printf("main(int argc, char *argv[])\n") printf("{\n")
This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks
.
printf("\tif (argc != 2)\n")
printf("\t\terr_quit(\"usage: a.out <dirname>\");\n\n") FS="\t+"
while (getline <"sysconf.sym" > 0) { printf("#ifdef %s\n", $1)
printf("\tprintf(\"%s defined to be %%d\\n\", %s+0);\n", $1, $1) printf("#else\n")
printf("\tprintf(\"no symbol for %s\\n\");\n", $1) printf("#endif\n")
printf("#ifdef %s\n", $2)
printf("\tpr_sysconf(\"%s =\", %s);\n", $1, $2) printf("#else\n")
printf("\tprintf(\"no symbol for %s\\n\");\n", $2) printf("#endif\n")
}
close("sysconf.sym")
while (getline <"pathconf.sym" > 0) { printf("#ifdef %s\n", $1)
printf("\tprintf(\"%s defined to be %%d\\n\", %s+0);\n", $1, $1) printf("#else\n")
printf("\tprintf(\"no symbol for %s\\n\");\n", $1) printf("#endif\n")
printf("#ifdef %s\n", $2)
printf("\tpr_pathconf(\"%s =\", argv[1], %s);\n", $1, $2) printf("#else\n")
printf("\tprintf(\"no symbol for %s\\n\");\n", $2) printf("#endif\n")
}
close("pathconf.sym") exit
} END {
printf("\texit(0);\n") printf("}\n\n") printf("static void\n")
printf("pr_sysconf(char *mesg, int name)\n") printf("{\n")
printf("\tlong val;\n\n") printf("\tfputs(mesg, stdout);\n") printf("\terrno = 0;\n")
printf("\tif ((val = sysconf(name)) < 0) {\n") printf("\t\tif (errno != 0) {\n")
printf("\t\t\tif (errno == EINVAL)\n")
printf("\t\t\t\tfputs(\" (not supported)\\n\", stdout);\n") printf("\t\t\telse\n")
printf("\t\t\t\terr_sys(\"sysconf error\");\n") printf("\t\t} else {\n")
printf("\t\t\tfputs(\" (no limit)\\n\", stdout);\n") printf("\t\t}\n")
printf("\t} else {\n")
printf("\t\tprintf(\" %%ld\\n\", val);\n") printf("\t}\n")
printf("}\n\n") printf("static void\n")
printf("pr_pathconf(char *mesg, char *path, int name)\n") printf("{\n")
printf("\tlong val;\n") printf("\n")
printf("\tfputs(mesg, stdout);\n") printf("\terrno = 0;\n")
printf("\tif ((val = pathconf(path, name)) < 0) {\n") printf("\t\tif (errno != 0) {\n")
printf("\t\t\tif (errno == EINVAL)\n")
printf("\t\t\t\tfputs(\" (not supported)\\n\", stdout);\n") printf("\t\t\telse\n")
printf("\t\t\t\terr_sys(\"pathconf error, path = %%s\", path);\n") printf("\t\t} else {\n")
printf("\t\t\tfputs(\" (no limit)\\n\", stdout);\n") printf("\t\t}\n")
printf("\t} else {\n")
printf("\t\tprintf(\" %%ld\\n\", val);\n") printf("\t}\n")
printf("}\n") }
Figure 2.13. Print all possible
sysconfand
pathconfvalues
#include "apue.h"
#include <errno.h>
#include <limits.h>
static void pr_sysconf(char *, int);
static void pr_pathconf(char *, char *, int);
int
main(int argc, char *argv[]) {
if (argc != 2)
err_quit("usage: a.out <dirname>");
#ifdef ARG_MAX
printf("ARG_MAX defined to be %d\n", ARG_MAX+0);
#else
printf("no symbol for ARG_MAX\n");
#endif
#ifdef _SC_ARG_MAX
pr_sysconf("ARG_MAX =", _SC_ARG_MAX);
#else
printf("no symbol for _SC_ARG_MAX\n");
#endif
/* similar processing for all the rest of the sysconf symbols... */
#ifdef MAX_CANON
printf("MAX_CANON defined to be %d\n", MAX_CANON+0);
#else
printf("no symbol for MAX_CANON\n");
#endif
#ifdef _PC_MAX_CANON
pr_pathconf("MAX_CANON =", argv[1], _PC_MAX_CANON);
#else
printf("no symbol for _PC_MAX_CANON\n");
#endif
/* similar processing for all the rest of the pathconf symbols... */
exit(0);
} static void
pr_sysconf(char *mesg, int name) {
long val;
fputs(mesg, stdout);
errno = 0;
if ((val = sysconf(name)) < 0) { if (errno != 0) {
This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks
.
if (errno == EINVAL)
fputs(" (not supported)\n", stdout);
else
err_sys("sysconf error");
} else {
fputs(" (no limit)\n", stdout);
} } else {
printf(" %ld\n", val);
} }
static void
pr_pathconf(char *mesg, char *path, int name) {
long val;
fputs(mesg, stdout);
errno = 0;
if ((val = pathconf(path, name)) < 0) { if (errno != 0) {
if (errno == EINVAL)
fputs(" (not supported)\n", stdout);
else
err_sys("pathconf error, path = %s", path);
} else {
fputs(" (no limit)\n", stdout);
} } else {
printf(" %ld\n", val);
} }
Figure 2.14. Examples of configuration limits
Limit FreeBSD 5.2.1 Linux 2.4.22 Mac OS X 10.3
Solaris 9
UFS file system
PCFS file system
ARG_MAX 65,536 131,072 262,144 1,048,320 1,048,320
ATEXIT_MAX 32 2,147,483,647 no symbol no limit no limit
CHARCLASS_NAME_MAX no symbol 2,048 no symbol 14 14
CHILD_MAX 867 999 100 7,877 7,877
clock ticks/second 128 100 100 100 100
COLL_WEIGHTS_MAX 0 255 2 10 10
FILESIZEBITS unsupported 64 no symbol 41 unsupported
HOST_NAME_MAX 255 unsupported no symbol no symbol no symbol
IOV_MAX 1,024 no limit no symbol 16 16
LINE_MAX 2,048 2,048 2,048 2,048 2,048
LINK_MAX 32,767 32,000 32,767 32,767 1
LOGIN_NAME_MAX 17 256 no symbol 9 9
MAX_CANON 255 255 255 256 256
MAX_INPUT 255 255 255 512 512
NAME_MAX 255 255 765 255 8
NGROUPS_MAX 16 32 16 16 16
OPEN_MAX 1,735 1,024 256 256 256
PAGESIZE 4,096 4,096 4,096 8,192 8,192
PAGE_SIZE 4,096 4,096 no symbol 8,192 8,192
PATH_MAX 1,024 4,096 1,024 1,024 1,024
PIPE_BUF 512 4,096 512 5,120 5,120
RE_DUP_MAX 255 32,767 255 255 255
STREAM_MAX 1,735 16 20 256 256
SYMLINK_MAX unsupported no limit no symbol no symbol no symbol
SYMLOOP_MAX 32 no limit no symbol no symbol no symbol
TTY_NAME_MAX 255 32 no symbol 128 128
TZNAME_MAX 255 6 255 no limit no limit
This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks