diff --git a/ChangeLog b/ChangeLog index 54421bfae3..010408a31f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,37 @@ +1998-03-10 17:54 Ulrich Drepper + + * libc.map: Add _dl_debug_message. + * elf/dl-misc.c: Make _dl_debug_message a function. Print the PID + before every line. + * elf/fini.c: Correctly use new _dl_debug_message function. + * elf/init.c: Likewise. + * elf/dl-lookup.c: Likewise. + * sysdeps/unix/sysv/linux/libc-start.c: Likewise. + * elf/dl-load.c: Likewise. Add more debugging prints. + * elf/dl-reloc.c: Likewise. + * elf/dl-version.c: Likewise. + * elf/dl-support.c: Add variables for debugging. + * elf/rtld.c: Likewise. Recognize new debug options. + * elf/link.h: Declare new variables. + + * elf/dl-deps.c (_dl_map_object_deps): Little optimizations. + 1998-03-10 Ulrich Drepper + * sysdeps/unix/sysv/linux/sys/quota.h: Extract information from + kernel headers. Patch by a sun . + +1998-03-11 00:16 Tim Waugh + + * posix/wordexp-test.c (command_line_test): New function to allow + testing of specific cases from the command-line. + +1998-03-10 Ulrich Drepper + + * elf/dl-init.c (_dl_init_next): Print nicer messages. + * elf/dl-fini.c (_dl_fini): Likewise. + * sysdeps/unix/sysv/linux/libc-start.c (__libc_start_main): Likewise. + * elf/dl-lookup.c (_dl_lookup_versioned_symbol): Print version symbol in debug message. (_dl_lookup_versioned_symbol_skip): Likewise. diff --git a/elf/dl-deps.c b/elf/dl-deps.c index c069fab0c8..76e71d78cb 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -139,7 +139,7 @@ _dl_map_object_deps (struct link_map *map, { struct link_map *l = runp->map; - if (l->l_info[AUXTAG] || l->l_info[FILTERTAG] || l->l_info[DT_NEEDED]) + if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG]) { const char *strtab = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); @@ -228,12 +228,11 @@ _dl_map_object_deps (struct link_map *map, newp = alloca (sizeof (struct list)); /* Copy the content of the current entry over. */ - memcpy (newp, orig, sizeof (*newp)); + orig->dup = memcpy (newp, orig, sizeof (*newp)); /* Initialize new entry. */ orig->done = 0; orig->map = args.aux; - orig->dup = newp; /* We must handle two situations here: the map is new, so we must add it in all three lists. If the map @@ -347,7 +346,7 @@ _dl_map_object_deps (struct link_map *map, if (runp->done) do runp = runp->unique; - while (runp && runp->done); + while (runp != NULL && runp->done); } /* Store the search list we built in the object. It will be used for diff --git a/elf/dl-fini.c b/elf/dl-fini.c index 9dcd87ad11..abbd8c878e 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -32,9 +32,9 @@ _dl_fini (void) { /* When debugging print a message first. */ if (_dl_debug_impcalls) - _dl_debug_message ("\n\tcalling fini: ", + _dl_debug_message (1, "\ncalling fini: ", l->l_name[0] ? l->l_name : _dl_argv[0], - "\n", NULL); + "\n\n", NULL); (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) (); } diff --git a/elf/dl-init.c b/elf/dl-init.c index 6fcac75a60..6bdad4e841 100644 --- a/elf/dl-init.c +++ b/elf/dl-init.c @@ -60,7 +60,7 @@ _dl_init_next (struct link_map *map) /* Print a debug message if wanted. */ if (_dl_debug_impcalls) - _dl_debug_message ("\tcalling init: ", + _dl_debug_message (1, "\ncalling init: ", l->l_name[0] ? l->l_name : _dl_argv[0], "\n\n", NULL); diff --git a/elf/dl-load.c b/elf/dl-load.c index 1d700f9da4..06c8ad57b4 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -28,6 +28,7 @@ #include #include #include "dynamic-link.h" +#include /* On some systems, no flag bits are given to specify file mapping. */ @@ -527,6 +528,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, const ElfW(Ehdr) *header; const ElfW(Phdr) *phdr; const ElfW(Phdr) *ph; + size_t maplength; int type; /* Look again to see if the real name matched another already loaded. */ @@ -545,6 +547,10 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, return l; } + /* Print debugging message. */ + if (_dl_debug_files) + _dl_debug_message (1, "file=", name, "; generating link map\n", NULL); + /* Map in the first page to read the header. */ header = map (0, sizeof *header); @@ -663,6 +669,9 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, /* Now process the load commands and map segments into memory. */ c = loadcmds; + /* Length of the sections to be loaded. */ + maplength = loadcmds[nloadcmds - 1].allocend - c->mapstart; + if (type == ET_DYN || type == ET_REL) { /* This is a position-independent shared object. We can let the @@ -678,7 +687,6 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, the OS can do whatever it likes. */ caddr_t mapat; ElfW(Addr) mappref; - size_t maplength = loadcmds[nloadcmds - 1].allocend - c->mapstart; mappref = (ELF_PREFERRED_ADDRESS (loader, maplength, c->mapstart) - MAP_BASE_ADDR (l)); mapat = map_segment (mappref, maplength, c->prot, 0, c->mapoff); @@ -786,6 +794,36 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, l->l_entry += l->l_addr; + if (_dl_debug_files) + { + const size_t nibbles = sizeof (void *) * 2; + char buf1[nibbles + 1]; + char buf2[nibbles + 1]; + char buf3[nibbles + 1]; + + buf1[nibbles] = '\0'; + buf2[nibbles] = '\0'; + buf3[nibbles] = '\0'; + + memset (buf1, '0', nibbles); + memset (buf2, '0', nibbles); + memset (buf3, '0', nibbles); + _itoa_word ((unsigned long int) l->l_ld, &buf1[nibbles], 16, 0); + _itoa_word ((unsigned long int) l->l_addr, &buf2[nibbles], 16, 0); + _itoa_word (maplength, &buf3[nibbles], 16, 0); + + _dl_debug_message (1, " dynamic: 0x", buf1, " base: 0x", buf2, + " size: 0x", buf3, "\n", NULL); + memset (buf1, '0', nibbles); + memset (buf2, '0', nibbles); + memset (buf3, ' ', nibbles); + _itoa_word ((unsigned long int) l->l_entry, &buf1[nibbles], 16, 0); + _itoa_word ((unsigned long int) l->l_phdr, &buf2[nibbles], 16, 0); + _itoa_word (l->l_phnum, &buf3[nibbles], 10, 0); + _dl_debug_message (1, " entry: 0x", buf1, " phdr: 0x", buf2, + " phnum: ", buf3, "\n\n", NULL); + } + elf_get_dynamic_info (l->l_ld, l->l_info); if (l->l_info[DT_HASH]) _dl_setup_hash (l); @@ -800,7 +838,7 @@ print_search_path (struct r_search_path_elem **list, { int first = 1; - _dl_debug_message ("\t search path=", NULL); + _dl_debug_message (1, " search path=", NULL); while (*list != NULL && (*list)->what == what) /* Yes, ==. */ { @@ -809,23 +847,23 @@ print_search_path (struct r_search_path_elem **list, if ((*list)->machdirstatus != nonexisting) { buf[(*list)->machdirnamelen - 1] = '\0'; - _dl_debug_message (first ? "" : ":", buf, NULL); + _dl_debug_message (0, first ? "" : ":", buf, NULL); first = 0; } if ((*list)->dirstatus != nonexisting) { buf[(*list)->dirnamelen - 1] = '\0'; - _dl_debug_message (first ? "" : ":", buf, NULL); + _dl_debug_message (0, first ? "" : ":", buf, NULL); first = 0; } ++list; } if (name != NULL) - _dl_debug_message ("\t\t(", what, " from file ", + _dl_debug_message (0, "\t\t(", what, " from file ", name[0] ? name : _dl_argv[0], ")\n", NULL); else - _dl_debug_message ("\t\t(", what, ")\n", NULL); + _dl_debug_message (0, "\t\t(", what, ")\n", NULL); } /* Try to open NAME in one of the directories in DIRS. @@ -871,7 +909,7 @@ open_path (const char *name, size_t namelen, int preloaded, /* Print name we try if this is wanted. */ if (_dl_debug_libs) - _dl_debug_message ("\t trying file=", buf, "\n", NULL); + _dl_debug_message (1, " trying file=", buf, "\n", NULL); fd = __open (buf, O_RDONLY); if (this_dir->machdirstatus == unknown) @@ -926,7 +964,7 @@ open_path (const char *name, size_t namelen, int preloaded, /* Print name we try if this is wanted. */ if (_dl_debug_libs) - _dl_debug_message ("\t trying file=", buf, "\n", NULL); + _dl_debug_message (1, " trying file=", buf, "\n", NULL); fd = __open (buf, O_RDONLY); if (this_dir->dirstatus == unknown) @@ -1038,6 +1076,12 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, return l; } + /* Display information if we are debugging. */ + if (_dl_debug_files && loader != NULL) + _dl_debug_message (1, "\nfile=", name, "; needed by ", + loader->l_name[0] ? loader->l_name : _dl_argv[0], + "\n", NULL); + if (strchr (name, '/') == NULL) { /* Search for NAME in several places. */ @@ -1045,7 +1089,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, size_t namelen = strlen (name) + 1; if (_dl_debug_libs) - _dl_debug_message ("\tfind library=", name, "; searching\n", NULL); + _dl_debug_message (1, "find library=", name, "; searching\n", NULL); fd = -1; @@ -1109,7 +1153,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, /* Add another newline when we a tracing the library loading. */ if (_dl_debug_libs) - _dl_debug_message ("\n", NULL); + _dl_debug_message (1, "\n", NULL); } else { diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 95399ba0b8..f2cd981883 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -100,7 +100,7 @@ do_lookup (const char *undef_name, unsigned long int hash, /* Print some debugging info if wanted. */ if (_dl_debug_symbols) - _dl_debug_message ("\tsymbol=", undef_name, "; lookup in file=", + _dl_debug_message (1, "symbol=", undef_name, "; lookup in file=", map->l_name[0] ? map->l_name : _dl_argv[0], "\n", NULL); @@ -236,7 +236,7 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, } if (_dl_debug_bindings) - _dl_debug_message ("\tbinding file ", reference_name, " to ", + _dl_debug_message (1, "binding file ", reference_name, " to ", current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], ": symbol `", undef_name, "'\n", NULL); @@ -281,7 +281,7 @@ _dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref, } if (_dl_debug_bindings) - _dl_debug_message ("\tbinding file ", reference_name, " to ", + _dl_debug_message (1, "binding file ", reference_name, " to ", current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], ": symbol `", undef_name, "'\n", NULL); @@ -342,7 +342,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref, } if (_dl_debug_bindings) - _dl_debug_message ("\tbinding file ", reference_name, " to ", + _dl_debug_message (1, "binding file ", reference_name, " to ", current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], ": symbol `", undef_name, "' [", version->name, @@ -396,7 +396,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, } if (_dl_debug_bindings) - _dl_debug_message ("\tbinding file ", reference_name, " to ", + _dl_debug_message (1, "binding file ", reference_name, " to ", current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], ": symbol `", undef_name, "' [", version->name, diff --git a/elf/dl-misc.c b/elf/dl-misc.c index 90288525f4..1e13d0d28a 100644 --- a/elf/dl-misc.c +++ b/elf/dl-misc.c @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #ifndef MAP_ANON /* This is the only dl-sysdep.c function that is actually needed at run-time @@ -89,6 +91,54 @@ _dl_sysdep_output (int fd, const char *msg, ...) size_t len = strlen (msg); __write (fd, msg, len); msg = va_arg (ap, const char *); - } while (msg); + } + while (msg != NULL); + va_end (ap); +} + + +void +_dl_debug_message (int new_line, const char *msg, ...) +{ + /* We print the strings we get passed one after the other but start all + lines using the current PID. */ + static int pid; + va_list ap; + + if (pid == 0) + pid = getpid (); + + va_start (ap, msg); + do + if (msg[0] == '\0') + /* Get the next argument. */ + msg = va_arg (ap, const char *); + else + { + const char *endp; + + /* We actually will print something in this line. So print the + PID now if needed. */ + if (new_line) + { + char buf[7] = "00000:\t"; + __write (_dl_debug_fd, _itoa_word (pid, &buf[5], 10, 0), 7); + new_line = 0; + } + + endp = strchr (msg, '\n'); + if (endp == NULL) + { + __write (_dl_debug_fd, msg, strlen (msg)); + msg = va_arg (ap, const char *); + } + else + { + __write (_dl_debug_fd, msg, endp - msg + 1); + msg = endp + 1; + new_line = 1; + } + } + while (msg != NULL); va_end (ap); } diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 531da9618a..d38c6c13a0 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -32,6 +32,10 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) if (l->l_relocated) return; + if (_dl_debug_reloc) + _dl_debug_message (1, "\nrelocation processing: ", + l->l_name[0] ? l->l_name : _dl_argv[0], "\n", NULL); + if (l->l_info[DT_TEXTREL]) { /* Bletch. We must make read-only segments writable diff --git a/elf/dl-support.c b/elf/dl-support.c index 39fa47cd4d..0f3a4c5f66 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -39,6 +39,9 @@ int _dl_debug_libs; int _dl_debug_impcalls; int _dl_debug_bindings; int _dl_debug_symbols; +int _dl_debug_versions; +int _dl_debug_reloc; +int _dl_debug_files; /* If nonzero print warnings about problematic situations. */ int _dl_verbose; diff --git a/elf/dl-version.c b/elf/dl-version.c index f615bb0cbc..a8bdeef89b 100644 --- a/elf/dl-version.c +++ b/elf/dl-version.c @@ -79,6 +79,12 @@ match_symbol (const char *name, ElfW(Word) hash, const char *string, ElfW(Addr) def_offset; ElfW(Verdef) *def; + /* Display information about what we are doing while debugging. */ + if (_dl_debug_versions) + _dl_debug_message (1, "checking for version `", string, "' in file ", + map->l_name[0] ? map->l_name : _dl_argv[0], + " required by file ", name, "\n", NULL); + if (map->l_info[VERSTAG (DT_VERDEF)] == NULL) { /* The file has no symbol versioning. I.e., the dependent diff --git a/elf/link.h b/elf/link.h index b2eb572d77..bd9b9e476d 100644 --- a/elf/link.h +++ b/elf/link.h @@ -253,6 +253,9 @@ extern int _dl_debug_libs; extern int _dl_debug_impcalls; extern int _dl_debug_bindings; extern int _dl_debug_symbols; +extern int _dl_debug_versions; +extern int _dl_debug_reloc; +extern int _dl_debug_files; /* File deccriptor to write debug messages to. */ extern int _dl_debug_fd; @@ -267,9 +270,10 @@ extern void _dl_sysdep_output (int fd, const char *string, ...); /* OS-dependent function to write a debug message on the specified descriptor for this. All arguments are `const char *'; args until - a null pointer are concatenated to form the message to print. */ -#define _dl_debug_message(string, args...) \ - _dl_sysdep_output (_dl_debug_fd, string, ##args) + a null pointer are concatenated to form the message to print. If + NEW_LINE is nonzero it is assumed that the message starts on a new + line.*/ +extern void _dl_debug_message (int new_line, const char *string, ...); /* OS-dependent function to write a message on the standard output. All arguments are `const char *'; args until a null pointer diff --git a/elf/rtld.c b/elf/rtld.c index 2db6cf3613..8b72d07883 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -78,6 +78,9 @@ int _dl_debug_libs; int _dl_debug_impcalls; int _dl_debug_bindings; int _dl_debug_symbols; +int _dl_debug_versions; +int _dl_debug_reloc; +int _dl_debug_files; /* Set nonzero during loading and initialization of executable and libraries, cleared before the executable's entry point runs. This @@ -927,7 +930,15 @@ process_dl_debug (char *dl_debug) ++dl_debug; if (*dl_debug != '\0') { - if (strncmp (dl_debug, "bindings", 8) == 0 + if (strncmp (dl_debug, "files", 5) == 0 + && (issep (dl_debug[5]) || dl_debug[5] == '\0')) + { + _dl_debug_files = 1; + _dl_debug_impcalls = 1; + any_debug = 1; + dl_debug += 5; + } + else if (strncmp (dl_debug, "bindings", 8) == 0 && (issep (dl_debug[8]) || dl_debug[8] == '\0')) { _dl_debug_bindings = 1; @@ -935,6 +946,25 @@ process_dl_debug (char *dl_debug) any_debug = 1; dl_debug += 8; } + else if (strncmp (dl_debug, "help", 4) == 0 + && (issep (dl_debug[4]) || dl_debug[4] == '\0')) + { + _dl_sysdep_message ("\ +Valid options for the LD_DEBUG environment variable are:\n\ +\n\ + bindings display information about symbol binding\n\ + files display processing of files and libraries\n\ + help display this help message and exit\n\ + libs display library search paths\n\ + reloc display relocation processing\n\ + symbols display symbol table processing\n\ + versions display version dependencies\n\ +\n\ +To direct the debugging output into a file instead of standard output\n\ +a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n", + NULL); + _exit (0); + } else if (strncmp (dl_debug, "libs", 4) == 0 && (issep (dl_debug[4]) || dl_debug[4] == '\0')) { @@ -943,21 +973,13 @@ process_dl_debug (char *dl_debug) any_debug = 1; dl_debug += 4; } - else if (strncmp (dl_debug, "help", 4) == 0 - && (issep (dl_debug[4]) || dl_debug[4] == '\0')) + else if (strncmp (dl_debug, "reloc", 4) == 0 + && (issep (dl_debug[5]) || dl_debug[5] == '\0')) { - _dl_sysdep_message ("\ -Valid options for the LD_DEBUG environment variable are:\n\ -\n\ - bindings display information about symbol binding\n\ - help display this help message and exit\n\ - libs display library search paths\n\ - symbols display symbol table processing\n\ -\n\ -To direct the debugging output into a file instead of standard output\n\ -a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n", - NULL); - _exit (0); + _dl_debug_reloc = 1; + _dl_debug_impcalls = 1; + any_debug = 1; + dl_debug += 5; } else if (strncmp (dl_debug, "symbols", 7) == 0 && (issep (dl_debug[7]) || dl_debug[7] == '\0')) @@ -967,6 +989,14 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n", any_debug = 1; dl_debug += 7; } + else if (strncmp (dl_debug, "versions", 8) == 0 + && (issep (dl_debug[8]) || dl_debug[8] == '\0')) + { + _dl_debug_versions = 1; + _dl_debug_impcalls = 1; + any_debug = 1; + dl_debug += 8; + } else { /* Display a warning and skip everything until next diff --git a/libc.map b/libc.map index 4388fb50b3..dc7037b358 100644 --- a/libc.map +++ b/libc.map @@ -99,6 +99,7 @@ GLIBC_2.0 { _rpc_dtablesize; _null_auth; _seterr_reply; __res_randomid; __getpid; __strcasecmp; __write; _strerror_internal; _dl_sysdep_output; + _dl_debug_message; __ffs; # Exception handling support functions from libgcc diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c index 75cfe5f360..2a94caa367 100644 --- a/posix/wordexp-test.c +++ b/posix/wordexp-test.c @@ -89,8 +89,19 @@ struct test_case_struct static int testit (struct test_case_struct *tc); +void +command_line_test (const char *words) +{ + wordexp_t we; + int i; + int retval = wordexp (words, &we, 0); + printf ("wordexp returned %d\n", retval); + for (i = 0; i < we.we_wordc; i++) + printf ("we_wordv[%d] = \"%s\"\n", i, we.we_wordv[i]); +} + int -main (int argc, char * argv[]) +main (int argc, char *argv[]) { struct passwd *pw; int test; @@ -101,6 +112,12 @@ main (int argc, char * argv[]) if (testit (&test_case[test])) ++fail; + if (argc > 1) + { + command_line_test (argv[1]); + return 0; + } + pw = getpwnam ("root"); if (pw != NULL) { diff --git a/sysdeps/unix/sysv/linux/libc-start.c b/sysdeps/unix/sysv/linux/libc-start.c index 5e089d4ebb..d32e54f162 100644 --- a/sysdeps/unix/sysv/linux/libc-start.c +++ b/sysdeps/unix/sysv/linux/libc-start.c @@ -50,14 +50,14 @@ __libc_start_main (int (*main) (int, char **, char **), int argc, /* Call the initializer of the libc. */ #ifdef PIC if (_dl_debug_impcalls) - _dl_debug_message ("\tinitialize libc\n\n", NULL); + _dl_debug_message (1, "\ninitialize libc\n\n", NULL); #endif __libc_init_first (argc, argv, __environ); /* Call the initializer of the program. */ #ifdef PIC if (_dl_debug_impcalls) - _dl_debug_message ("\tinitialize program: ", argv[0], "\n\n", NULL); + _dl_debug_message (1, "\ninitialize program: ", argv[0], "\n\n", NULL); #endif (*init) (); @@ -66,7 +66,7 @@ __libc_start_main (int (*main) (int, char **, char **), int argc, #ifdef PIC if (_dl_debug_impcalls) - _dl_debug_message ("\ttransferring control: ", argv[0], "\n\n", NULL); + _dl_debug_message (1, "\ntransferring control: ", argv[0], "\n\n", NULL); #endif exit ((*main) (argc, argv, __environ)); diff --git a/sysdeps/unix/sysv/linux/sys/quota.h b/sysdeps/unix/sysv/linux/sys/quota.h index 47e88d7176..bcbbfa5ddb 100644 --- a/sysdeps/unix/sysv/linux/sys/quota.h +++ b/sysdeps/unix/sysv/linux/sys/quota.h @@ -1,3 +1,161 @@ -/* The kernel header file contains all declarations and definitions. */ +/* This just represents the non-kernel parts of . + * + * here's the corresponding copyright: + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * Version: $Id$ + */ + +#ifndef _SYS_QUOTA_H +#define _SYS_QUOTA_H 1 + +#include #include -#include + +/* + * Convert diskblocks to blocks and the other way around. + * currently only to fool the BSD source. :-) + */ +#define dbtob(num) ((num) << 10) +#define btodb(num) ((num) >> 10) + +/* + * Convert count of filesystem blocks to diskquota blocks, meant + * for filesystems where i_blksize != BLOCK_SIZE + */ +#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE) + +/* + * Definitions for disk quotas imposed on the average user + * (big brother finally hits Linux). + * + * The following constants define the amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). The timer is started when the user crosses + * their soft limit, it is reset when they go below their soft limit. + */ +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ + +#define MAXQUOTAS 2 +#define USRQUOTA 0 /* element used for user quotas */ +#define GRPQUOTA 1 /* element used for group quotas */ + +/* + * Definitions for the default names of the quotas files. + */ +#define INITQFNAMES { \ + "user", /* USRQUOTA */ \ + "group", /* GRPQUOTA */ \ + "undefined", \ +}; + +#define QUOTAFILENAME "quota" +#define QUOTAGROUP "staff" + +#define NR_DQHASH 43 /* Just an arbitrary number any suggestions ? */ +#define NR_DQUOTS 256 /* Number of quotas active at one time */ + +/* + * Command definitions for the 'quotactl' system call. + * The commands are broken into a main command defined below + * and a subcommand that is used to convey the type of + * quota that is being manipulated (see above). + */ +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +#define Q_QUOTAON 0x0100 /* enable quotas */ +#define Q_QUOTAOFF 0x0200 /* disable quotas */ +#define Q_GETQUOTA 0x0300 /* get limits and usage */ +#define Q_SETQUOTA 0x0400 /* set limits and usage */ +#define Q_SETUSE 0x0500 /* set usage */ +#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ +#define Q_SETQLIM 0x0700 /* set limits */ +#define Q_GETSTATS 0x0800 /* get collected stats */ + +/* + * The following structure defines the format of the disk quota file + * (as it appears on disk) - the file is an array of these structures + * indexed by user or group number. + */ +struct dqblk + { + u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int32_t dqb_curblocks; /* current block count */ + u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */ + u_int32_t dqb_isoftlimit; /* preferred inode limit */ + u_int32_t dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive files */ + }; + +/* + * Shorthand notation. + */ +#define dq_bhardlimit dq_dqb.dqb_bhardlimit +#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit +#define dq_curblocks dq_dqb.dqb_curblocks +#define dq_ihardlimit dq_dqb.dqb_ihardlimit +#define dq_isoftlimit dq_dqb.dqb_isoftlimit +#define dq_curinodes dq_dqb.dqb_curinodes +#define dq_btime dq_dqb.dqb_btime +#define dq_itime dq_dqb.dqb_itime + +#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) + +struct dqstats + { + u_int32_t lookups; + u_int32_t drops; + u_int32_t reads; + u_int32_t writes; + u_int32_t cache_hits; + u_int32_t pages_allocated; + u_int32_t allocated_dquots; + u_int32_t free_dquots; + u_int32_t syncs; + }; + +__BEGIN_DECLS + +extern int quotactl __P ((int __cmd, const char *__special, int __id, + caddr_t __addr)); + +__END_DECLS + +#endif /* sys/quota.h */