modprobe-small: fix and simplify rmmod
[oweals/busybox.git] / coreutils / date.c
index c3478fab14310ea0b3fa323c95ec614218a29c93..767e0d4a29296f9c224a1013921f4387b82bdec1 100644 (file)
@@ -7,7 +7,7 @@
  * iso-format handling added by Robert Griebl <griebl@gmx.de>
  * bugfixes and cleanup by Bernhard Reutner-Fischer
  *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
 */
 
 /* This 'date' command supports only 2 time setting formats,
 /* Input parsing code is always bulky - used heavy duty libc stuff as
    much as possible, missed out a lot of bounds checking */
 
-/* Default input handling to save surprising some people */
-
-/* GNU coreutils 6.9 man page:
- * date [OPTION]... [+FORMAT]
- * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
- * -d, --date=STRING
- *      display time described by STRING, not `now'
- * -f, --file=DATEFILE
- *      like --date once for each line of DATEFILE
- * -r, --reference=FILE
- *      display the last modification time of FILE
- * -R, --rfc-2822
- *      output date and time in RFC 2822 format.
- *      Example: Mon, 07 Aug 2006 12:34:56 -0600
- * --rfc-3339=TIMESPEC
- *      output date and time in RFC 3339 format.
- *      TIMESPEC='date', 'seconds', or 'ns'
- *      Date and time components are separated by a single space:
- *      2006-08-07 12:34:56-06:00
- * -s, --set=STRING
- *      set time described by STRING
- * -u, --utc, --universal
- *      print or set Coordinated Universal Time
- *
- * Busybox:
- * long options are not supported
- * -f is not supported
- * -I seems to roughly match --rfc-3339, but -I has _optional_ param
- *    (thus "-I seconds" doesn't work, only "-Iseconds"),
- *    and does not support -Ins
- * -D FMT is a bbox extension for _input_ conversion of -d DATE
- */
+//applet:IF_DATE(APPLET(date, BB_DIR_BIN, BB_SUID_DROP))
 
 //kbuild:lib-$(CONFIG_DATE) += date.o
 
 //config:        Enable option (-I) to output an ISO-8601 compliant
 //config:        date/time string.
 //config:
+//config:# defaults to "no": stat's nanosecond field is a bit non-portable
 //config:config FEATURE_DATE_NANO
 //config:      bool "Support %[num]N nanosecond format specifier"
 //config:      default n
-//config:      depends on DATE
+//config:      depends on DATE  # syscall(__NR_clock_gettime)
+//config:      select PLATFORM_LINUX
 //config:      help
 //config:        Support %[num]N format specifier. Adds ~250 bytes of code.
 //config:
 //config:        the same format. With it on, 'date DATE' additionally supports
 //config:        MMDDhhmm[[YY]YY][.ss] format.
 
+/* GNU coreutils 6.9 man page:
+ * date [OPTION]... [+FORMAT]
+ * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
+ * -d, --date=STRING
+ *      display time described by STRING, not `now'
+ * -f, --file=DATEFILE
+ *      like --date once for each line of DATEFILE
+ * -r, --reference=FILE
+ *      display the last modification time of FILE
+ * -R, --rfc-2822
+ *      output date and time in RFC 2822 format.
+ *      Example: Mon, 07 Aug 2006 12:34:56 -0600
+ * --rfc-3339=TIMESPEC
+ *      output date and time in RFC 3339 format.
+ *      TIMESPEC='date', 'seconds', or 'ns'
+ *      Date and time components are separated by a single space:
+ *      2006-08-07 12:34:56-06:00
+ * -s, --set=STRING
+ *      set time described by STRING
+ * -u, --utc, --universal
+ *      print or set Coordinated Universal Time
+ *
+ * Busybox:
+ * long options are not supported
+ * -f is not supported
+ * -I seems to roughly match --rfc-3339, but -I has _optional_ param
+ *    (thus "-I seconds" doesn't work, only "-Iseconds"),
+ *    and does not support -Ins
+ * -D FMT is a bbox extension for _input_ conversion of -d DATE
+ */
+
+//usage:#define date_trivial_usage
+//usage:       "[OPTIONS] [+FMT] [TIME]"
+//usage:#define date_full_usage "\n\n"
+//usage:       "Display time (using +FMT), or set time\n"
+//usage:       IF_NOT_LONG_OPTS(
+//usage:     "\n       [-s] TIME       Set time to TIME"
+//usage:     "\n       -u              Work in UTC (don't convert to local time)"
+//usage:     "\n       -R              Output RFC-2822 compliant date string"
+//usage:       ) IF_LONG_OPTS(
+//usage:     "\n       [-s,--set] TIME Set time to TIME"
+//usage:     "\n       -u,--utc        Work in UTC (don't convert to local time)"
+//usage:     "\n       -R,--rfc-2822   Output RFC-2822 compliant date string"
+//usage:       )
+//usage:       IF_FEATURE_DATE_ISOFMT(
+//usage:     "\n       -I[SPEC]        Output ISO-8601 compliant date string"
+//usage:     "\n                       SPEC='date' (default) for date only,"
+//usage:     "\n                       'hours', 'minutes', or 'seconds' for date and"
+//usage:     "\n                       time to the indicated precision"
+//usage:       )
+//usage:       IF_NOT_LONG_OPTS(
+//usage:     "\n       -r FILE         Display last modification time of FILE"
+//usage:     "\n       -d TIME         Display TIME, not 'now'"
+//usage:       ) IF_LONG_OPTS(
+//usage:     "\n       -r,--reference FILE     Display last modification time of FILE"
+//usage:     "\n       -d,--date TIME  Display TIME, not 'now'"
+//usage:       )
+//usage:       IF_FEATURE_DATE_ISOFMT(
+//usage:     "\n       -D FMT          Use FMT for -d TIME conversion"
+//usage:       )
+//usage:     "\n"
+//usage:     "\nRecognized TIME formats:"
+//usage:     "\n       hh:mm[:ss]"
+//usage:     "\n       [YYYY.]MM.DD-hh:mm[:ss]"
+//usage:     "\n       YYYY-MM-DD hh:mm[:ss]"
+//usage:     "\n       [[[[[YY]YY]MM]DD]hh]mm[.ss]"
+//usage:       IF_FEATURE_DATE_COMPAT(
+//usage:     "\n       'date TIME' form accepts MMDDhhmm[[YY]YY][.ss] instead"
+//usage:       )
+//usage:
+//usage:#define date_example_usage
+//usage:       "$ date\n"
+//usage:       "Wed Apr 12 18:52:41 MDT 2000\n"
+
 #include "libbb.h"
+#if ENABLE_FEATURE_DATE_NANO
+# include <sys/syscall.h>
+#endif
 
 enum {
        OPT_RFC2822   = (1 << 0), /* R */
@@ -205,12 +253,18 @@ int date_main(int argc UNUSED_PARAM, char **argv)
                ts.tv_sec = statbuf.st_mtime;
 #if ENABLE_FEATURE_DATE_NANO
                ts.tv_nsec = statbuf.st_mtim.tv_nsec;
+               /* Some toolchains use .st_mtimensec instead of st_mtim.tv_nsec.
+                * If you need #define _SVID_SOURCE 1 to enable st_mtim.tv_nsec,
+                * drop a mail to project mailing list please
+                */
 #endif
        } else {
 #if ENABLE_FEATURE_DATE_NANO
-               clock_gettime(CLOCK_REALTIME, &ts);
+               /* libc has incredibly messy way of doing this,
+                * typically requiring -lrt. We just skip all this mess */
+               syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
 #else
-               time(&ts.tv_nsec);
+               time(&ts.tv_sec);
 #endif
        }
        localtime_r(&ts.tv_sec, &tm_time);
@@ -231,7 +285,9 @@ int date_main(int argc UNUSED_PARAM, char **argv)
                }
 
                /* Correct any day of week and day of year etc. fields */
-               tm_time.tm_isdst = -1;  /* Be sure to recheck dst */
+               /* Be sure to recheck dst (but not if date is time_t format) */
+               if (date_str[0] != '@')
+                       tm_time.tm_isdst = -1;
                ts.tv_sec = validate_tm_time(date_str, &tm_time);
 
                maybe_set_utc(opt);
@@ -295,7 +351,7 @@ int date_main(int argc UNUSED_PARAM, char **argv)
                        scale = 1;
                        pres = 9;
                        if (n) {
-                               pres = xatoi_u(p);
+                               pres = xatoi_positive(p);
                                if (pres == 0)
                                        pres = 9;
                                m = 9 - pres;