aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2016-08-29 08:26:36 -0700
committerElliott Hughes <enh@google.com>2016-08-29 08:47:36 -0700
commit5d83f7a6f9363143b51d778a22e0d7f34dcade36 (patch)
tree03d114a28aa8c12d34bf0e38d90fcb8f7559da45
parente9452d6abed3389259420a18b4f62f77a60faa65 (diff)
parent7b7fec9cc6c67382ab4144d98e72c881858281f4 (diff)
downloadandroid_external_toybox-5d83f7a6f9363143b51d778a22e0d7f34dcade36.tar.gz
android_external_toybox-5d83f7a6f9363143b51d778a22e0d7f34dcade36.tar.bz2
android_external_toybox-5d83f7a6f9363143b51d778a22e0d7f34dcade36.zip
Merge remote-tracking branch 'toybox/master' into HEAD
Change-Id: Ib0b86bedbf7b9a4370533847ac0acad5aa478795
-rw-r--r--.config2
-rw-r--r--Android.mk2
-rw-r--r--generated/config.h4
-rw-r--r--generated/flags.h52
-rw-r--r--generated/globals.h14
-rw-r--r--generated/help.h10
-rw-r--r--generated/newtoys.h2
-rw-r--r--toys/net/tunctl.c53
-rw-r--r--toys/pending/chrt.c92
-rw-r--r--toys/pending/dd.c149
-rw-r--r--toys/posix/ls.c65
11 files changed, 320 insertions, 125 deletions
diff --git a/.config b/.config
index ce30a8ed..17b55dfe 100644
--- a/.config
+++ b/.config
@@ -117,6 +117,7 @@ CONFIG_XARGS=y
# CONFIG_BOOTCHARTD is not set
# CONFIG_BRCTL is not set
# CONFIG_COMPRESS is not set
+CONFIG_CHRT=y
# CONFIG_GZIP is not set
# CONFIG_GZIP_D is not set
# CONFIG_DECOMPRESS is not set
@@ -267,6 +268,7 @@ CONFIG_TAC=y
CONFIG_TASKSET=y
CONFIG_TIMEOUT=y
CONFIG_TRUNCATE=y
+CONFIG_TUNCTL=y
CONFIG_UPTIME=y
CONFIG_USLEEP=y
CONFIG_VCONFIG=y
diff --git a/Android.mk b/Android.mk
index 7738dc46..7e49a6fd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -84,6 +84,7 @@ LOCAL_SRC_FILES := \
toys/net/netcat.c \
toys/net/netstat.c \
toys/net/rfkill.c \
+ toys/net/tunctl.c \
toys/other/acpi.c \
toys/other/base64.c \
toys/other/blkid.c \
@@ -138,6 +139,7 @@ LOCAL_SRC_FILES := \
toys/other/which.c \
toys/other/xxd.c \
toys/other/yes.c \
+ toys/pending/chrt.c \
toys/pending/dd.c \
toys/pending/expr.c \
toys/pending/getfattr.c \
diff --git a/generated/config.h b/generated/config.h
index 8669a306..6cda122a 100644
--- a/generated/config.h
+++ b/generated/config.h
@@ -212,6 +212,8 @@
#define USE_BRCTL(...)
#define CFG_COMPRESS 0
#define USE_COMPRESS(...)
+#define CFG_CHRT 1
+#define USE_CHRT(...) __VA_ARGS__
#define CFG_GZIP 0
#define USE_GZIP(...)
#define CFG_GZIP_D 0
@@ -504,6 +506,8 @@
#define USE_TIMEOUT(...) __VA_ARGS__
#define CFG_TRUNCATE 1
#define USE_TRUNCATE(...) __VA_ARGS__
+#define CFG_TUNCTL 1
+#define USE_TUNCTL(...) __VA_ARGS__
#define CFG_UPTIME 1
#define USE_UPTIME(...) __VA_ARGS__
#define CFG_USLEEP 1
diff --git a/generated/flags.h b/generated/flags.h
index 3363e244..c95a5de3 100644
--- a/generated/flags.h
+++ b/generated/flags.h
@@ -232,6 +232,22 @@
#undef FOR_chroot
#endif
+// chrt mp#bfiorR[!bfior] mp#bfiorR[!bfior]
+#undef OPTSTR_chrt
+#define OPTSTR_chrt "mp#bfiorR[!bfior]"
+#ifdef CLEANUP_chrt
+#undef CLEANUP_chrt
+#undef FOR_chrt
+#undef FLAG_R
+#undef FLAG_r
+#undef FLAG_o
+#undef FLAG_i
+#undef FLAG_f
+#undef FLAG_b
+#undef FLAG_p
+#undef FLAG_m
+#endif
+
// chvt <1
#undef OPTSTR_chvt
#define OPTSTR_chvt "<1"
@@ -2817,6 +2833,18 @@
#undef FLAG_s
#endif
+// tunctl <1>1t|d|u:T[!td] <1>1t|d|u:T[!td]
+#undef OPTSTR_tunctl
+#define OPTSTR_tunctl "<1>1t|d|u:T[!td]"
+#ifdef CLEANUP_tunctl
+#undef CLEANUP_tunctl
+#undef FOR_tunctl
+#undef FLAG_T
+#undef FLAG_u
+#undef FLAG_d
+#undef FLAG_t
+#endif
+
// ulimit >1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc] >1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]
#undef OPTSTR_ulimit
#define OPTSTR_ulimit ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]"
@@ -3315,6 +3343,20 @@
#endif
#endif
+#ifdef FOR_chrt
+#ifndef TT
+#define TT this.chrt
+#endif
+#define FLAG_R (1<<0)
+#define FLAG_r (1<<1)
+#define FLAG_o (1<<2)
+#define FLAG_i (1<<3)
+#define FLAG_f (1<<4)
+#define FLAG_b (1<<5)
+#define FLAG_p (1<<6)
+#define FLAG_m (1<<7)
+#endif
+
#ifdef FOR_chvt
#ifndef TT
#define TT this.chvt
@@ -5492,6 +5534,16 @@
#define FLAG_s (1<<0)
#endif
+#ifdef FOR_tunctl
+#ifndef TT
+#define TT this.tunctl
+#endif
+#define FLAG_T (1<<0)
+#define FLAG_u (1<<1)
+#define FLAG_d (1<<2)
+#define FLAG_t (1<<3)
+#endif
+
#ifdef FOR_ulimit
#ifndef TT
#define TT this.ulimit
diff --git a/generated/globals.h b/generated/globals.h
index 8a9be047..e94633d1 100644
--- a/generated/globals.h
+++ b/generated/globals.h
@@ -162,6 +162,12 @@ struct netstat_data {
int wpad;
};;
+// toys/net/tunctl.c
+
+struct tunctl_data {
+ char *user;
+};
+
// toys/other/acpi.c
struct acpi_data {
@@ -426,6 +432,12 @@ struct brctl_data {
int sockfd;
};
+// toys/pending/chrt.c
+
+struct chrt_data {
+ long pid;
+};
+
// toys/pending/compress.c
struct compress_data {
@@ -1376,6 +1388,7 @@ extern union global_union {
struct ifconfig_data ifconfig;
struct netcat_data netcat;
struct netstat_data netstat;
+ struct tunctl_data tunctl;
struct acpi_data acpi;
struct base64_data base64;
struct blockdev_data blockdev;
@@ -1407,6 +1420,7 @@ extern union global_union {
struct arping_data arping;
struct bootchartd_data bootchartd;
struct brctl_data brctl;
+ struct chrt_data chrt;
struct compress_data compress;
struct crond_data crond;
struct crontab_data crontab;
diff --git a/generated/help.h b/generated/help.h
index 62277f1b..3e3c339f 100644
--- a/generated/help.h
+++ b/generated/help.h
@@ -104,7 +104,9 @@
#define HELP_dmesg "usage: dmesg [-c] [-r|-t] [-n LEVEL] [-s SIZE]\n\nPrint or control the kernel ring buffer.\n\n-c Clear the ring buffer after printing\n-n Set kernel logging LEVEL (1-9)\n-r Raw output (with <level markers>)\n-s Show the last SIZE many bytes\n-t Don't print kernel's timestamps\n\n"
-#define HELP_rfkill "Usage: rfkill COMMAND [DEVICE]\n\nEnable/disable wireless devices.\n\nCommands:\nlist [DEVICE] List current state\nblock DEVICE Disable device\nunblock DEVICE Enable device\n\nDEVICE is an index number, or one of:\nall, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm.\n\n\n"
+#define HELP_tunctl "usage: tunctl [-dtT] [-u USER] NAME\n\nCreate and delete tun/tap virtual ethernet devices.\n\n-T Use tap (ethernet frames) instead of tun (ip packets)\n-d Delete tun/tap device\n-t Create tun/tap device\n-u Set owner (user who can read/write device without root access)\n\n\n"
+
+#define HELP_rfkill "Usage: rfkill COMMAND [DEVICE]\n\nEnable/disable wireless devices.\n\nCommands:\nlist [DEVICE] List current state\nblock DEVICE Disable device\nunblock DEVICE Enable device\n\nDEVICE is an index number, or one of:\nall, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm.\n\n"
#define HELP_netstat "usage: netstat [-pWrxwutneal]\n\nDisplay networking information. Default is netsat -tuwx\n\n-r routing table\n-a all sockets (not just connected)\n-l listening server sockets\n-t TCP sockets\n-u UDP sockets\n-w raw sockets\n-x unix sockets\n-e extended info\n-n don't resolve names\n-W wide display\n-p PID/Program name of sockets\n\n"
@@ -408,6 +410,8 @@
#define HELP_compress "usage: compress [-zgLR19] [FILE]\n\nCompress or decompress file (or stdin) using \"deflate\" algorithm.\n\n-1 min compression\n-9 max compression (default)\n-g gzip (default)\n-L zlib\n-R raw\n-z zip\n\n"
+#define HELP_chrt "usage: chrt [-m] [-p PID] [POLICY PRIO] [COMMAND [ARGS...]]\n\nGet/set a process' real-time (scheduling) attributes.\n\n-p Apply to given pid\n-R Set SCHED_RESET_ON_FORK\n-m Show min/max priorities available\n\nPolicies:\n -b SCHED_BATCH -f SCHED_FIFO -i SCHED_IDLE\n -o SCHED_OTHER -r SCHED_RR\n\n"
+
#define HELP_brctl "usage: brctl COMMAND [BRIDGE [INTERFACE]]\n\nManage ethernet bridges\n\nCommands:\nshow Show a list of bridges\naddbr BRIDGE Create BRIDGE\ndelbr BRIDGE Delete BRIDGE\naddif BRIDGE IFACE Add IFACE to BRIDGE\ndelif BRIDGE IFACE Delete IFACE from BRIDGE\nsetageing BRIDGE TIME Set ageing time\nsetfd BRIDGE TIME Set bridge forward delay\nsethello BRIDGE TIME Set hello time\nsetmaxage BRIDGE TIME Set max message age\nsetpathcost BRIDGE PORT COST Set path cost\nsetportprio BRIDGE PORT PRIO Set port priority\nsetbridgeprio BRIDGE PRIO Set bridge priority\nstp BRIDGE [1/yes/on|0/no/off] STP on/off\n\n"
#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nCreate /var/log/bootlog.tgz with boot chart data\n\nstart: start background logging; with PROG, run PROG,\n then kill logging with USR1\nstop: send USR1 to all bootchartd processes\ninit: start background logging; stop when getty/xdm is seen\n (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init\n\n"
@@ -504,9 +508,9 @@
#define HELP_mkdir "usage: mkdir [-vp] [-m mode] [dirname...]\n\nCreate one or more directories.\n\n-m set permissions of directory to mode.\n-p make parent directories as needed.\n-v verbose\n\n"
-#define HELP_ls_color "--color device=yellow symlink=turquoise/red dir=blue socket=purple\n files: exe=green suid=red suidfile=redback stickydir=greenback\n =auto means detect if output is a tty.\n\nusage: ls --color[=auto] [-ACFHLRSZacdfhiklmnpqrstux1] [directory...]\n\nlist files\n\nwhat to show:\n-a all files including .hidden -b escape nongraphic chars\n-c use ctime for timestamps -d directory, not contents\n-i inode number -k block sizes in kilobytes\n-p put a '/' after dir names -q unprintable chars as '?'\n-s size (in blocks) -u use access time for timestamps\n-A list all files but . and .. -H follow command line symlinks\n-L follow symlinks -R recursively list files in subdirs\n-F append /dir *exe @sym |FIFO -Z security context\n\noutput formats:\n-1 list one file per line -C columns (sorted vertically)\n-g like -l but no owner -h human readable sizes\n-l long (show full details) -m comma separated\n-n like -l but numeric uid/gid -o like -l but no group\n-x columns (horizontal sort)\n\nsorting (default is alphabetical):\n-f unsorted -r reverse -t timestamp -S size\n"
+#define HELP_ls_color "--color device=yellow symlink=turquoise/red dir=blue socket=purple\n files: exe=green suid=red suidfile=redback stickydir=greenback\n =auto means detect if output is a tty.\n\nusage: ls --color[=auto] [-ACFHLRSZacdfhiklmnpqrstux1] [directory...]\n\nlist files\n\nwhat to show:\n-a all files including .hidden -b escape nongraphic chars\n-c use ctime for timestamps -d directory, not contents\n-i inode number -p put a '/' after dir names\n-q unprintable chars as '?' -s storage used (1024 byte units)\n-u use access time for timestamps -A list all files but . and ..\n-H follow command line symlinks -L follow symlinks\n-R recursively list in subdirs -F append /dir *exe @sym |FIFO\n-Z security context\n\noutput formats:\n-1 list one file per line -C columns (sorted vertically)\n-g like -l but no owner -h human readable sizes\n-l long (show full details) -m comma separated\n-n like -l but numeric uid/gid -o like -l but no group\n-x columns (horizontal sort)\n\nsorting (default is alphabetical):\n-f unsorted -r reverse -t timestamp -S size\n"
-#define HELP_ls "usage: ls --color[=auto] [-ACFHLRSZacdfhiklmnpqrstux1] [directory...]\n\nlist files\n\nwhat to show:\n-a all files including .hidden -b escape nongraphic chars\n-c use ctime for timestamps -d directory, not contents\n-i inode number -k block sizes in kilobytes\n-p put a '/' after dir names -q unprintable chars as '?'\n-s size (in blocks) -u use access time for timestamps\n-A list all files but . and .. -H follow command line symlinks\n-L follow symlinks -R recursively list files in subdirs\n-F append /dir *exe @sym |FIFO -Z security context\n\noutput formats:\n-1 list one file per line -C columns (sorted vertically)\n-g like -l but no owner -h human readable sizes\n-l long (show full details) -m comma separated\n-n like -l but numeric uid/gid -o like -l but no group\n-x columns (horizontal sort)\n\nsorting (default is alphabetical):\n-f unsorted -r reverse -t timestamp -S size\n--color device=yellow symlink=turquoise/red dir=blue socket=purple\n files: exe=green suid=red suidfile=redback stickydir=greenback\n =auto means detect if output is a tty.\n\n"
+#define HELP_ls "usage: ls --color[=auto] [-ACFHLRSZacdfhiklmnpqrstux1] [directory...]\n\nlist files\n\nwhat to show:\n-a all files including .hidden -b escape nongraphic chars\n-c use ctime for timestamps -d directory, not contents\n-i inode number -p put a '/' after dir names\n-q unprintable chars as '?' -s storage used (1024 byte units)\n-u use access time for timestamps -A list all files but . and ..\n-H follow command line symlinks -L follow symlinks\n-R recursively list in subdirs -F append /dir *exe @sym |FIFO\n-Z security context\n\noutput formats:\n-1 list one file per line -C columns (sorted vertically)\n-g like -l but no owner -h human readable sizes\n-l long (show full details) -m comma separated\n-n like -l but numeric uid/gid -o like -l but no group\n-x columns (horizontal sort)\n\nsorting (default is alphabetical):\n-f unsorted -r reverse -t timestamp -S size\n--color device=yellow symlink=turquoise/red dir=blue socket=purple\n files: exe=green suid=red suidfile=redback stickydir=greenback\n =auto means detect if output is a tty.\n\n"
#define HELP_ln "usage: ln [-sfnv] [FROM...] TO\n\nCreate a link between FROM and TO.\nWith only one argument, create link in current directory.\n\n-s Create a symbolic link\n-f Force the creation of the link, even if TO already exists\n-n Symlink at destination treated as file\n-v Verbose\n\n"
diff --git a/generated/newtoys.h b/generated/newtoys.h
index b541278d..edca9c9c 100644
--- a/generated/newtoys.h
+++ b/generated/newtoys.h
@@ -25,6 +25,7 @@ USE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv[-HLP]", TOYFLAG_BIN))
USE_CHMOD(NEWTOY(chmod, "<2?vRf[-vf]", TOYFLAG_BIN))
USE_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_CHRT(NEWTOY(chrt, "mp#bfiorR[!bfior]", TOYFLAG_USR|TOYFLAG_SBIN))
USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN))
USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
@@ -248,6 +249,7 @@ USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFL
USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP))
USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_BIN))
USE_TTY(NEWTOY(tty, "s", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TUNCTL(NEWTOY(tunctl, "<1>1t|d|u:T[!td]", TOYFLAG_USR|TOYFLAG_BIN))
USE_TCPSVD(OLDTOY(udpsvd, tcpsvd, TOYFLAG_USR|TOYFLAG_BIN))
USE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN))
USE_UMOUNT(NEWTOY(umount, "ndDflrat*v[!na]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
diff --git a/toys/net/tunctl.c b/toys/net/tunctl.c
new file mode 100644
index 00000000..1aafebfd
--- /dev/null
+++ b/toys/net/tunctl.c
@@ -0,0 +1,53 @@
+/* tunctl.c - Control tap/tun network devices.
+ *
+ * Copyright 2016 Rob Landley <rob@landley.net>
+ *
+ * See http://kernel.org/doc/Documentation/networking/tuntap.txt
+ *
+ * This is useful for things like "kvm -netdev tap" and containers.
+ * See https://landley.net/lxc/02-networking.html for example usage.
+ *
+ * todo: bridge mode
+ * -b bridge daemon (forwards packets between NAME and NAME2 interfaces)
+
+
+USE_TUNCTL(NEWTOY(tunctl, "<1>1t|d|u:T[!td]", TOYFLAG_USR|TOYFLAG_BIN))
+
+config TUNCTL
+ bool "tunctl"
+ default y
+ help
+ usage: tunctl [-dtT] [-u USER] NAME
+
+ Create and delete tun/tap virtual ethernet devices.
+
+ -T Use tap (ethernet frames) instead of tun (ip packets)
+ -d Delete tun/tap device
+ -t Create tun/tap device
+ -u Set owner (user who can read/write device without root access)
+*/
+
+#define FOR_tunctl
+#include "toys.h"
+#include <linux/if_tun.h>
+
+GLOBALS(
+ char *user;
+)
+
+void tunctl_main(void)
+{
+ struct ifreq *ifr = (void *)toybuf;
+ uid_t u = TT.user ? xgetuid(TT.user) : 0;
+ int fd = xopen("/dev/net/tun", O_RDWR);
+
+ // Associate filehandle with device
+ ifr->ifr_flags = ((toys.optflags&FLAG_T) ? IFF_TUN : IFF_TAP)|IFF_NO_PI;
+ strncpy(ifr->ifr_name, *toys.optargs, sizeof(ifr->ifr_name));
+ xioctl(fd, TUNSETIFF, toybuf);
+
+ if (toys.optflags&FLAG_t) {
+ xioctl(fd, TUNSETPERSIST, (void *)1);
+ xioctl(fd, TUNSETOWNER, (void *)(long)u);
+ } else xioctl(fd, TUNSETPERSIST, (void *)0);
+}
diff --git a/toys/pending/chrt.c b/toys/pending/chrt.c
new file mode 100644
index 00000000..0c25f484
--- /dev/null
+++ b/toys/pending/chrt.c
@@ -0,0 +1,92 @@
+/* chrt.c - Get/set real-time (scheduling) attributes
+ *
+ * Copyright 2016 The Android Open Source Project
+
+USE_CHRT(NEWTOY(chrt, "mp#bfiorR[!bfior]", TOYFLAG_USR|TOYFLAG_SBIN))
+
+config CHRT
+ bool "chrt"
+ default y
+ help
+ usage: chrt [-m] [-p PID] [POLICY PRIO] [COMMAND [ARGS...]]
+
+ Get/set a process' real-time (scheduling) attributes.
+
+ -p Apply to given pid
+ -R Set SCHED_RESET_ON_FORK
+ -m Show min/max priorities available
+
+ Policies:
+ -b SCHED_BATCH -f SCHED_FIFO -i SCHED_IDLE
+ -o SCHED_OTHER -r SCHED_RR
+*/
+
+#define FOR_chrt
+#include "toys.h"
+
+#include <linux/sched.h>
+
+GLOBALS(
+ long pid;
+)
+
+static char *policy_name(int policy) {
+ char *policy_names[] = { "SCHED_OTHER", "SCHED_FIFO", "SCHED_RR",
+ "SCHED_BATCH", "4", "SCHED_IDLE", "SCHED_DEADLINE" };
+
+ return policy < ARRAY_LEN(policy_names) ? policy_names[policy] : "???";
+}
+
+void chrt_main(void)
+{
+ int policy = SCHED_RR;
+ struct sched_param p;
+
+ // Show min/maxes?
+ if (toys.optflags&FLAG_m) {
+ for (policy = SCHED_OTHER; policy <= SCHED_IDLE; ++policy)
+ if (policy != 4) // There's an unused hole in the priorities.
+ printf("%s min/max priority\t: %d/%d\n", policy_name(policy),
+ sched_get_priority_min(policy), sched_get_priority_max(policy));
+ return;
+ }
+
+ // If we have a pid but no command or policy, we're just querying.
+ if (TT.pid && !*(toys.optargs+1) &&
+ !(toys.optflags&(FLAG_b|FLAG_f|FLAG_i|FLAG_o|FLAG_r))) {
+ policy = sched_getscheduler(TT.pid);
+ if (policy == -1) perror_exit("sched_getscheduler");
+ policy &= ~SCHED_RESET_ON_FORK;
+ printf("pid %ld's current scheduling policy: %s\n",
+ TT.pid, policy_name(policy));
+
+ if (sched_getparam(TT.pid, &p)) perror_exit("sched_getparam");
+ printf("pid %ld's current scheduling priority: %d\n",
+ TT.pid, p.sched_priority);
+
+ return;
+ }
+
+ // Did we get a meaningful combination of arguments?
+ if (!*toys.optargs) help_exit("missing priority");
+ if (TT.pid && *(toys.optargs+1)) help_exit("-p and command");
+ if (!TT.pid && !*(toys.optargs+1)) help_exit("missing command");
+
+ // Translate into policy and priority.
+ if (toys.optflags&FLAG_b) policy = SCHED_BATCH;
+ else if (toys.optflags&FLAG_f) policy = SCHED_FIFO;
+ else if (toys.optflags&FLAG_i) policy = SCHED_IDLE;
+ else if (toys.optflags&FLAG_o) policy = SCHED_OTHER;
+
+ if (toys.optflags&FLAG_R) policy |= SCHED_RESET_ON_FORK;
+
+ p.sched_priority = atolx_range(*toys.optargs, sched_get_priority_min(policy),
+ sched_get_priority_max(policy));
+
+ if (sched_setscheduler(TT.pid, policy, &p)) perror_exit("sched_setscheduler");
+
+ if (*(toys.optargs+1)) {
+ toys.stacktop = 0;
+ xexec(++toys.optargs);
+ }
+}
diff --git a/toys/pending/dd.c b/toys/pending/dd.c
index c3e51cfa..0bb48494 100644
--- a/toys/pending/dd.c
+++ b/toys/pending/dd.c
@@ -4,6 +4,8 @@
* Copyright 2013 Kyungwan Han <asura321@gmail.com>
*
* See http://opengroup.org/onlinepubs/9699919799/utilities/dd.html
+ *
+ * todo: ctrl-c doesn't work, the read() is restarting.
USE_DD(NEWTOY(dd, NULL, TOYFLAG_USR|TOYFLAG_BIN))
@@ -51,20 +53,10 @@ GLOBALS(
} in, out;
);
-#define C_CONV 0x0000
-#define C_BS 0x0001
-#define C_COUNT 0x0002
-#define C_IBS 0x0004
-#define C_OBS 0x0008
-#define C_IF 0x0010
-#define C_OF 0x0020
-#define C_SEEK 0x0040
-#define C_SKIP 0x0080
#define C_SYNC 0x0100
#define C_FSYNC 0x0200
#define C_NOERROR 0x0400
#define C_NOTRUNC 0x0800
-#define C_STATUS 0x1000
struct pair {
char *name;
@@ -85,20 +77,6 @@ static struct pair clist[] = {
{ "sync", C_SYNC },
};
-static struct pair operands[] = {
- // keep the array sorted by name, bsearch() can be used.
- { "bs", C_BS },
- { "conv", C_CONV },
- { "count", C_COUNT },
- { "ibs", C_IBS },
- { "if", C_IF },
- { "obs", C_OBS },
- { "of", C_OF },
- { "seek", C_SEEK },
- { "skip", C_SKIP },
- { "status", C_STATUS},
-};
-
static unsigned long long strsuftoll(char *arg, int def, unsigned long long max)
{
unsigned long long result;
@@ -161,6 +139,17 @@ static void write_out(int all)
if (TT.out.count) memmove(TT.out.buff, TT.out.bp, TT.out.count); //move remainder to front
}
+int strstarteq(char **a, char *b)
+{
+ char *aa = *a;
+
+ if (!strstart(&aa, b)) return 0;
+ if (*aa != '=') return 0;
+ *a = ++aa;
+
+ return 1;
+}
+
static int comp(const void *a, const void *b) //const to shut compiler up
{
return strcmp(((struct pair*)a)->name, ((struct pair*)b)->name);
@@ -169,87 +158,65 @@ static int comp(const void *a, const void *b) //const to shut compiler up
void dd_main()
{
struct pair *res, key;
- char *arg;
- long sz;
+ char **args;
+ unsigned long long bs = 0;
+ int trunc = O_TRUNC;
TT.show_xfer = TT.show_records = 1;
+ TT.c_count = ULLONG_MAX;
TT.in.sz = TT.out.sz = 512; //default io block size
- while (*toys.optargs) {
- if (!(arg = strchr(*toys.optargs, '='))) error_exit("unknown arg %s", *toys.optargs);
- *arg++ = '\0';
- if (!*arg) help_exit(0);
- key.name = *toys.optargs;
- if (!(res = bsearch(&key, operands, ARRAY_LEN(operands), sizeof(struct pair),
- comp))) error_exit("unknown arg %s", key.name);
-
- toys.optflags |= res->val;
- switch (res->val) {
- case C_BS:
- TT.in.sz = TT.out.sz = strsuftoll(arg, 1, LONG_MAX);
- break;
- case C_IBS:
- sz = strsuftoll(arg, 1, LONG_MAX);
- if (!(toys.optflags & C_BS)) TT.in.sz = sz;
- break;
- case C_OBS:
- sz = strsuftoll(arg, 1, LONG_MAX);
- if (!(toys.optflags & C_BS)) TT.out.sz = sz;
- break;
- case C_COUNT:
- TT.c_count = strsuftoll(arg, 0, ULLONG_MAX);
- break;
- case C_IF:
- TT.in.name = arg;
- break;
- case C_OF:
- TT.out.name = arg;
- break;
- case C_SEEK:
- TT.out.offset = strsuftoll(arg, 0, ULLONG_MAX);
- break;
- case C_SKIP:
- TT.in.offset = strsuftoll(arg, 0, ULLONG_MAX);
- break;
- case C_STATUS:
- if (!strcmp(arg, "noxfer")) TT.show_xfer = 0;
- else if (!strcmp(arg, "none")) TT.show_xfer = TT.show_records = 0;
- else error_exit("unknown status '%s'", arg);
- break;
- case C_CONV:
- while (arg) {
- key.name = strsep(&arg, ",");
- if (!(res = bsearch(&key, clist, ARRAY_LEN(clist),
- sizeof(struct pair), comp)))
- error_exit("unknown conversion %s", key.name);
-
- toys.optflags |= res->val;
- }
- break;
- }
- toys.optargs++;
+ for (args = toys.optargs; *args; args++) {
+ char *arg = *args;
+
+ if (strstarteq(&arg, "bs")) bs = strsuftoll(arg, 1, LONG_MAX);
+ else if (strstarteq(&arg, "ibs")) TT.in.sz = strsuftoll(arg, 1, LONG_MAX);
+ else if (strstarteq(&arg, "obs")) TT.out.sz = strsuftoll(arg, 1, LONG_MAX);
+ else if (strstarteq(&arg, "count")) TT.c_count = strsuftoll(arg, 0, ULLONG_MAX-1);
+ else if (strstarteq(&arg, "if")) TT.in.name = arg;
+ else if (strstarteq(&arg, "of")) TT.out.name = arg;
+ else if (strstarteq(&arg, "seek"))
+ TT.out.offset = strsuftoll(arg, 0, ULLONG_MAX);
+ else if (strstarteq(&arg, "skip"))
+ TT.in.offset = strsuftoll(arg, 0, ULLONG_MAX);
+ else if (strstarteq(&arg, "status")) {
+ if (!strcmp(arg, "noxfer")) TT.show_xfer = 0;
+ else if (!strcmp(arg, "none")) TT.show_xfer = TT.show_records = 0;
+ else error_exit("unknown status '%s'", arg);
+ } else if (strstarteq(&arg, "conv")) {
+ while (arg) {
+ key.name = strsep(&arg, ",");
+ if (!(res = bsearch(&key, clist, ARRAY_LEN(clist),
+ sizeof(struct pair), comp)))
+ error_exit("unknown conversion %s", key.name);
+
+ toys.optflags |= res->val;
+ }
+ } else error_exit("bad arg %s", arg);
}
+ if (bs) TT.in.sz = TT.out.sz = bs;
signal(SIGINT, generic_signal);
signal(SIGUSR1, generic_signal);
gettimeofday(&TT.start, NULL);
- /* for C_BS, in/out is done as it is. so only in.sz is enough.
+ /* for bs=, in/out is done as it is. so only in.sz is enough.
* With Single buffer there will be overflow in a read following partial read
*/
- TT.in.buff = TT.out.buff = xmalloc(TT.in.sz
- + ((toys.optflags & C_BS) ? 0 : TT.out.sz));
+ TT.in.buff = TT.out.buff = xmalloc(TT.in.sz + (bs ? 0 : TT.out.sz));
TT.in.bp = TT.out.bp = TT.in.buff;
//setup input
if (!TT.in.name) TT.in.name = "stdin";
else TT.in.fd = xopenro(TT.in.name);
+ if (toys.optflags&C_NOTRUNC) trunc = 0;
+
//setup output
if (!TT.out.name) {
TT.out.name = "stdout";
TT.out.fd = 1;
} else TT.out.fd = xcreate(TT.out.name,
- O_WRONLY|O_CREAT|(O_TRUNC*!(toys.optflags&C_NOTRUNC)), 0666);
+ O_WRONLY|O_CREAT|(trunc*!TT.out.offset), 0666);
// Implement skip=
if (TT.in.offset) {
@@ -269,14 +236,14 @@ void dd_main()
}
}
- if (TT.out.offset)
- xlseek(TT.out.fd, TT.out.offset * (off_t)TT.out.sz, SEEK_CUR);
-
- if ((toys.optflags&C_SEEK) && !(toys.optflags & C_NOTRUNC))
- if (ftruncate(TT.out.fd, TT.out.offset * TT.out.sz))
- perror_exit("ftruncate");
+ // seek/truncate as necessary. We handled position zero truncate with
+ // O_TRUNC on open, so output to /dev/null and such doesn't error.
+ if (TT.out.fd!=1 && (bs = TT.out.offset*TT.out.sz)) {
+ xlseek(TT.out.fd, bs, SEEK_CUR);
+ if (trunc && ftruncate(TT.out.fd, bs)) perror_exit("ftruncate");
+ }
- while (!(toys.optflags & C_COUNT) || (TT.in_full + TT.in_part) < TT.c_count) {
+ while (TT.c_count==ULLONG_MAX || (TT.in_full + TT.in_part) < TT.c_count) {
ssize_t n;
// Show progress and exit on SIGINT or just continue on SIGUSR1.
@@ -310,7 +277,7 @@ void dd_main()
}
TT.out.count = TT.in.count;
- if (toys.optflags & C_BS) {
+ if (bs) {
write_out(1);
TT.in.count = 0;
continue;
diff --git a/toys/posix/ls.c b/toys/posix/ls.c
index 6b181c0a..5d1e0602 100644
--- a/toys/posix/ls.c
+++ b/toys/posix/ls.c
@@ -18,12 +18,12 @@ config LS
what to show:
-a all files including .hidden -b escape nongraphic chars
-c use ctime for timestamps -d directory, not contents
- -i inode number -k block sizes in kilobytes
- -p put a '/' after dir names -q unprintable chars as '?'
- -s size (in blocks) -u use access time for timestamps
- -A list all files but . and .. -H follow command line symlinks
- -L follow symlinks -R recursively list files in subdirs
- -F append /dir *exe @sym |FIFO -Z security context
+ -i inode number -p put a '/' after dir names
+ -q unprintable chars as '?' -s storage used (1024 byte units)
+ -u use access time for timestamps -A list all files but . and ..
+ -H follow command line symlinks -L follow symlinks
+ -R recursively list in subdirs -F append /dir *exe @sym |FIFO
+ -Z security context
output formats:
-1 list one file per line -C columns (sorted vertically)
@@ -126,6 +126,12 @@ static int numlen(long long ll)
return snprintf(0, 0, "%llu", ll);
}
+static int print_with_h(char *s, long long value, int units)
+{
+ if (toys.optflags&FLAG_h) return human_readable(s, value*units, 0);
+ else return sprintf(s, "%lld", value);
+}
+
// Figure out size of printable entry fields for display indent/wrap
static void entrylen(struct dirtree *dt, unsigned *len)
@@ -148,13 +154,10 @@ static void entrylen(struct dirtree *dt, unsigned *len)
// cheating slightly here: assuming minor is always 3 digits to avoid
// tracking another column
len[5] = numlen(dev_major(st->st_rdev))+5;
- } else if (flags & FLAG_h) {
- human_readable(tmp, st->st_size, 0);
- len[5] = strwidth(tmp);
- } else len[5] = numlen(st->st_size);
+ } else len[5] = print_with_h(tmp, st->st_size, 1);
}
- len[6] = (flags & FLAG_s) ? numlen(st->st_blocks) : 0;
+ len[6] = (flags & FLAG_s) ? print_with_h(tmp, st->st_blocks, 512) : 0;
len[7] = (flags & FLAG_Z) ? strwidth((char *)dt->extra) : 0;
}
@@ -219,7 +222,7 @@ static int filter(struct dirtree *new)
if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime;
if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime;
- if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2;
+ new->st.st_blocks >>= 1;
if (flags & (FLAG_a|FLAG_f)) return DIRTREE_SAVE;
if (!(flags & FLAG_A) && new->name[0]=='.') return 0;
@@ -355,10 +358,8 @@ static void listfiles(int dirfd, struct dirtree *indir)
}
totpad = totals[1]+!!totals[1]+totals[6]+!!totals[6]+totals[7]+!!totals[7];
if ((flags&(FLAG_h|FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) && indir->parent) {
- if (flags&FLAG_h) {
- human_readable(tmp, blocks*512, 0);
- xprintf("total %s\n", tmp);
- } else xprintf("total %llu\n", blocks);
+ print_with_h(tmp, blocks, 512);
+ xprintf("total %s\n", tmp);
}
}
@@ -377,7 +378,7 @@ static void listfiles(int dirfd, struct dirtree *indir)
memset(colsizes, 0, columns*sizeof(unsigned));
for (ul=0; ul<dtlen; ul++) {
entrylen(sort[next_column(ul, dtlen, columns, &c)], len);
- *len += totpad;
+ *len += totpad+1;
if (c == columns) break;
// Expand this column if necessary, break if that puts us over budget
if (*len > colsizes[c]) {
@@ -412,20 +413,22 @@ static void listfiles(int dirfd, struct dirtree *indir)
if (flags & FLAG_m) xputc(',');
if (flags & (FLAG_C|FLAG_x)) {
if (!curcol) xputc('\n');
- } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) {
+ } else if ((flags & FLAG_1) || width+2+*len > TT.screen_width) {
xputc('\n');
width = 0;
} else {
- xputc(' ');
- width++;
+ printf(" ");
+ width += 2;
}
}
width += *len;
- if (flags & FLAG_i)
- xprintf("%*lu ", totals[1], (unsigned long)st->st_ino);
- if (flags & FLAG_s)
- xprintf("%*lu ", totals[6], (unsigned long)st->st_blocks);
+ if (flags & FLAG_i) printf("%*lu ", totals[1], (unsigned long)st->st_ino);
+
+ if (flags & FLAG_s) {
+ print_with_h(tmp, st->st_blocks, 512);
+ printf("%*s ", totals[6], tmp);
+ }
if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) {
struct tm *tm;
@@ -459,15 +462,15 @@ static void listfiles(int dirfd, struct dirtree *indir)
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
printf("% *d,% 4d", totals[5]-4, dev_major(st->st_rdev),
dev_minor(st->st_rdev));
- else if (flags&FLAG_h) {
- human_readable(tmp, st->st_size, 0);
- xprintf("%*s", totals[5]+1, tmp);
- } else printf("% *lld", totals[5]+1, (long long)st->st_size);
+ else {
+ print_with_h(tmp, st->st_size, 0);
+ printf("%*s", totals[5]+1, tmp);
+ }
// print time, always in --time-style=long-iso
tm = localtime(&(st->st_mtime));
strftime(tmp, sizeof(tmp), "%F %H:%M", tm);
- xprintf(" %s ", tmp);
+ printf(" %s ", tmp);
} else if (flags & FLAG_Z)
printf("%-*s ", (int)totals[7], (char *)sort[next]->extra);
@@ -478,7 +481,7 @@ static void listfiles(int dirfd, struct dirtree *indir)
ss = sort[next]->name;
crunch_str(&ss, INT_MAX, stdout, TT.escmore, crunch_qb);
- if (color) xprintf("\033[0m");
+ if (color) printf("\033[0m");
if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) {
printf(" -> ");
@@ -500,7 +503,7 @@ static void listfiles(int dirfd, struct dirtree *indir)
// Pad columns
if (flags & (FLAG_C|FLAG_x)) {
curcol = colsizes[curcol]-(*len)-totpad;
- if (curcol < 255) xprintf("%s", toybuf+255-curcol);
+ if (curcol < 255) printf("%s", toybuf+255-curcol);
}
}