brctl: tweak help text, fix comments
[oweals/busybox.git] / coreutils / date.c
index 0fb9f1f00cecb0e17f80fa6959b85df08a6b3358..731241536956d18f60a4707cd2fc13faf22dcad3 100644 (file)
@@ -19,7 +19,7 @@
    much as possible, missed out a lot of bounds checking */
 
 //config:config DATE
-//config:      bool "date (7.1 kb)"
+//config:      bool "date (7 kb)"
 //config:      default y
 //config:      help
 //config:      date is used to set the system date or display the
@@ -36,8 +36,8 @@
 //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  # syscall(__NR_clock_gettime)
+//config:      default n  # syscall(__NR_clock_gettime) or syscall(__NR_clock_gettime64)
+//config:      depends on DATE
 //config:      select PLATFORM_LINUX
 //config:      help
 //config:      Support %[num]N format specifier. Adds ~250 bytes of code.
 //config:      date -s (and other commands like touch -d) use more sensible
 //config:      formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
 //config:
-//config:      With this option off, 'date DATE' is 'date -s DATE' support
+//config:      With this option off, 'date DATE' and 'date -s DATE' support
 //config:      the same format. With it on, 'date DATE' additionally supports
 //config:      MMDDhhmm[[YY]YY][.ss] format.
 
-//applet:IF_DATE(APPLET(date, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_DATE(APPLET_NOEXEC(date, date, BB_DIR_BIN, BB_SUID_DROP, date))
+/* bb_common_bufsiz1 usage here is safe wrt NOEXEC: not expecting it to be zeroed. */
 
 //kbuild:lib-$(CONFIG_DATE) += date.o
 
@@ -66,7 +67,7 @@
  * date [OPTION]... [+FORMAT]
  * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
  * -d, --date=STRING
- *      display time described by STRING, not `now'
+ *      display time described by STRING, not 'now'
  * -f, --file=DATEFILE
  *      like --date once for each line of DATEFILE
  * -r, --reference=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:     "\n       -D FMT          Use FMT (strptime format) for -d TIME conversion"
 //usage:       )
 //usage:     "\n"
 //usage:     "\nRecognized TIME formats:"
@@ -152,12 +153,6 @@ enum {
        OPT_HINT      = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
 };
 
-static void maybe_set_utc(int opt)
-{
-       if (opt & OPT_UTC)
-               putenv((char*)"TZ=UTC0");
-}
-
 #if ENABLE_LONG_OPTS
 static const char date_longopts[] ALIGN1 =
                "rfc-822\0"   No_argument       "R"
@@ -170,6 +165,19 @@ static const char date_longopts[] ALIGN1 =
                ;
 #endif
 
+/* We are a NOEXEC applet.
+ * Obstacles to NOFORK:
+ * - we change env
+ * - xasprintf result not freed
+ * - after xasprintf we use other xfuncs
+ */
+
+static void maybe_set_utc(int opt)
+{
+       if (opt & OPT_UTC)
+               putenv((char*)"TZ=UTC0");
+}
+
 int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int date_main(int argc UNUSED_PARAM, char **argv)
 {
@@ -184,14 +192,18 @@ int date_main(int argc UNUSED_PARAM, char **argv)
        char *filename;
        char *isofmt_arg = NULL;
 
-       opt_complementary = "d--s:s--d"
-               IF_FEATURE_DATE_ISOFMT(":R--I:I--R");
-       IF_LONG_OPTS(applet_long_options = date_longopts;)
-       opt = getopt32(argv, "Rs:ud:r:"
-                       IF_FEATURE_DATE_ISOFMT("I::D:"),
+       opt = getopt32long(argv, "^"
+                       "Rs:ud:r:"
+                       IF_FEATURE_DATE_ISOFMT("I::D:")
+                       "\0"
+                       "d--s:s--d"
+                       IF_FEATURE_DATE_ISOFMT(":R--I:I--R"),
+                       date_longopts,
                        &date_str, &date_str, &filename
-                       IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt));
+                       IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt)
+       );
        argv += optind;
+
        maybe_set_utc(opt);
 
        if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) {
@@ -259,10 +271,17 @@ int date_main(int argc UNUSED_PARAM, char **argv)
                 */
 #endif
        } else {
-#if ENABLE_FEATURE_DATE_NANO
+#if ENABLE_FEATURE_DATE_NANO && defined(__NR_clock_gettime)
                /* libc has incredibly messy way of doing this,
                 * typically requiring -lrt. We just skip all this mess */
                syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
+#elif ENABLE_FEATURE_DATE_NANO && __TIMESIZE == 64
+               /* Let's only support the 64 suffix syscalls for 64-bit time_t.
+                * This simplifies the code for us as we don't need to convert
+                * between 64-bit and 32-bit. We also don't have a way to
+                * report overflow errors here.
+                */
+               syscall(__NR_clock_gettime64, CLOCK_REALTIME, &ts);
 #else
                time(&ts.tv_sec);
 #endif
@@ -290,11 +309,9 @@ int date_main(int argc UNUSED_PARAM, char **argv)
                        tm_time.tm_isdst = -1;
                ts.tv_sec = validate_tm_time(date_str, &tm_time);
 
-               maybe_set_utc(opt);
-
                /* if setting time, set it */
                if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
-                       bb_perror_msg("can't set date");
+                       bb_simple_perror_msg("can't set date");
                }
        }