/* * ntp-time.c * * Copyright (C) 2013 Krzysztof Mazur * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include static const char *file = "/dev/mtd/data"; static unsigned int offset = 0x40000; static void show_usage(char *name) { printf("ntp-time " PACKAGE_VERSION ".\n" "Copyright (C) 2013 Krzysztof Mazur .\n"); printf("usage: %s [options] [FILE]\n" "Options:\n" " -h, --help show this help\n" " -o, --offset=OFFSET offset in the FILE\n" "\n" "Report bugs to krzysiek@podlesie.net.\n", (name == NULL) ? "ntp-time" : name); exit(EXIT_SUCCESS); } static void parse_command_line(int argc, char **argv) { static const struct option long_options[] = { {"help", 0, 0, 'h'}, {"offset", 1, 0, 'o'}, {"version", 0, 0, 'V'}, {0, 0, 0, 0}, }; int option_index = 0; int c; while (1) { c = getopt_long(argc, argv, "ho:", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': show_usage(argv[0]); exit(EXIT_SUCCESS); case 'o': offset = atoi(optarg); break; default: fprintf(stderr, "Unknown option.\n"); exit(EXIT_FAILURE); } } if (optind >= argc) return; file = strdup(argv[optind++]); if (optind >= argc) return; fprintf(stderr, "warning: unknown parameters detected.\n"); } #define DSP_MAGIC 0x3467ABDD struct dsp_timex { uint32_t magic; uint32_t seq; uint32_t status; uint32_t esterror; uint32_t tv_sec; uint32_t tv_nsec; } __attribute__((packed)); static void pwrite_or_die(int fd, const void *buf, size_t count, off_t offset) { ssize_t ret; ret = pwrite(fd, buf, count, offset); if (ret < count) { fprintf(stderr, "pwrite error: %s\n", (ret < 0) ? strerror(errno) : "short write"); exit(EXIT_FAILURE); } } int main(int argc, char **argv) { struct dsp_timex dsp_timex; struct timex timex; struct timespec ts; int ret; int fd; parse_command_line(argc, argv); fd = open(file, O_WRONLY); if (fd == -1) { fprintf(stderr, "open(%s): %s\n", file, strerror(errno)); exit(EXIT_FAILURE); } dsp_timex.magic = DSP_MAGIC; dsp_timex.seq = 0; for (;;) { memset(&timex, 0, sizeof(timex)); ret = adjtimex(&timex); if (ret == -1) { perror("adjtimex"); exit(EXIT_FAILURE); } if (!(timex.status & STA_NANO)) timex.time.tv_usec *= 1000; dsp_timex.seq++; pwrite_or_die(fd, &dsp_timex, sizeof(dsp_timex), offset); dsp_timex.status = timex.status; dsp_timex.esterror = timex.esterror; dsp_timex.tv_sec = timex.time.tv_sec; dsp_timex.tv_nsec = timex.time.tv_usec; pwrite_or_die(fd, &dsp_timex, sizeof(dsp_timex), offset); dsp_timex.seq++; pwrite_or_die(fd, &dsp_timex, sizeof(dsp_timex), offset); ts.tv_sec = 0; ts.tv_nsec = 1000000000 - timex.time.tv_usec; nanosleep(&ts, NULL); } return EXIT_SUCCESS; }