view toys.h @ 1512:7afd32673a5c draft 0.5.0

Workaround for musl's faccessat bug (the rm -r "error: is a directory" thing). The Linux man page says I can use AT_SYMLINK_NOFOLLOW. It works in glibc, uclibc, and klibc, but musl returns -EINVAL any time you pass in that flag and the maintainer says that's not a bug and insists the man page and those other libraries all change to match musl's behavior. Toybox uses it to avoid scheduling unnecessary metadata writes for things we're about to delete (have to chmod unreadable directories so we can descend into them to delete their contents, the chmod happens before we descend so the disk I/O has plenty of time to be scheduled) because the extra writes wear out SSD faster. It's just an optimization and I don't really care if it works _well_ (the fchmodat call _also_ takes AT_SYMLINK_NOFOLLOW so that's covered), but musl's behavior uniquely makes the check always error and thus breaks normal "rm -r". Yes this workaround is checking #ifdef __MUSL__ which the library does not supply (because its code is perfect and will thus never need to be worked around). You can CFLAGS=-D__MUSL__ if you don't echo "#define __MUSL__" >> include/features.h when installing the library.
author Rob Landley <rob@landley.net>
date Thu, 02 Oct 2014 07:24:38 -0500
parents 84922376d15c
children 83cac28515a3
line wrap: on
line source

/* Toybox infrastructure.
 *
 * Copyright 2006 Rob Landley <rob@landley.net>
 */

// Stuff that needs to go before the standard headers

#include "generated/config.h"
#include "lib/portability.h"

// General posix-2008 headers
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <grp.h>
#include <inttypes.h>
#include <limits.h>
#include <libgen.h>
#include <math.h>
#include <pwd.h>
#include <regex.h>
#include <sched.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include <utmpx.h>

// Posix networking

#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/un.h>

// Internationalization support (also in POSIX and LSB)

#include <locale.h>
#include <wchar.h>
#include <wctype.h>

// LSB 4.1 headers
#include <pty.h>
#include <sys/ioctl.h>
#include <sys/statfs.h>
#include <sys/sysinfo.h>

#include "lib/lib.h"
#include "toys/e2fs.h"

// Get list of function prototypes for all enabled command_main() functions.

#define NEWTOY(name, opts, flags) void name##_main(void);
#define OLDTOY(name, oldname, opts, flags) void oldname##_main(void);
#include "generated/newtoys.h"
#include "generated/oldtoys.h"
#include "generated/flags.h"
#include "generated/globals.h"

// These live in main.c

struct toy_list *toy_find(char *name);
void toy_init(struct toy_list *which, char *argv[]);
void toy_exec(char *argv[]);

// Flags describing command behavior.

#define TOYFLAG_USR      (1<<0)
#define TOYFLAG_BIN      (1<<1)
#define TOYFLAG_SBIN     (1<<2)
#define TOYMASK_LOCATION ((1<<4)-1)

// This is a shell built-in function, running in the same process context.
#define TOYFLAG_NOFORK   (1<<4)

// Start command with a umask of 0 (saves old umask in this.old_umask)
#define TOYFLAG_UMASK    (1<<5)

// This command runs as root.
#define TOYFLAG_STAYROOT (1<<6)
#define TOYFLAG_NEEDROOT (1<<7)
#define TOYFLAG_ROOTONLY (TOYFLAG_STAYROOT|TOYFLAG_NEEDROOT)

// Call setlocale to listen to environment variables.
// This invalidates sprintf("%.*s", size, string) as a valid length constraint.
#define TOYFLAG_LOCALE   (1<<8)

// Array of available commands

extern struct toy_list {
  char *name;
  void (*toy_main)(void);
  char *options;
  int flags;
} toy_list[];

// Global context shared by all commands.

extern struct toy_context {
  struct toy_list *which;  // Which entry in toy_list is this one?
  char **argv;             // Original command line arguments
  char **optargs;          // Arguments left over from get_optflags()
  unsigned optflags;       // Command line option flags from get_optflags()
  int exitval;             // Value error_exit feeds to exit()
  int optc;                // Count of optargs
  int exithelp;            // Should error_exit print a usage message first?
  int old_umask;           // Old umask preserved by TOYFLAG_UMASK
  int toycount;            // Total number of commands in this build
  int signal;              // generic_signal() records what signal it saw here
  int signalfd;            // and writes signal to this fd, if set
  int recursion;           // How many nested calls to toy_exec()

  // This is at the end so toy_init() doesn't zero it.
  jmp_buf *rebound;        // longjmp here instead of exit when do_rebound set
} toys;

// Two big temporary buffers: one for use by commands, one for library functions

extern char toybuf[4096], libbuf[4096];

extern char **environ;

#define GLOBALS(...)

#define ARRAY_LEN(array) (sizeof(array)/sizeof(*array))