ntp-tools / ntpsetfile.c /
a78b58f 2 months ago
1 contributor
106 lines | 2.621kb
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <errno.h>

#define NTP_TIMESTAMP_DELTA 2208988800ull
#define NTP_PORT 123
#define NTP_PACKET_SIZE 48

static long max_delta=120;

int main(int argc, char *argv[]) {
    if ((argc != 2) && (argc != 3)) {
        fprintf(stderr, "Usage: %s <time file> <max delta>\n", argv[0]);
        return 1;
    }

    time_t now = time(NULL);
    if (now == (time_t)-1) {
        perror("Cannot get time");
        return EXIT_FAILURE;
    }
    
    FILE *fp = fopen(argv[1], "r");
    if (!fp) {
        perror("Error opening file, creating it. Please re-run");
        FILE *fp = fopen(argv[1], "w");
        fprintf(fp, "%ld\n", (long)now);
        fclose(fp);
        return EXIT_FAILURE;
    }
    
    if( NULL != argv[2]) {
		max_delta=atoi(argv[2]);
	}
    

    char buffer[64];  // enough for a 32-bit int in ASCII
    if (!fgets(buffer, sizeof(buffer), fp)) {
        fprintf(stderr, "Error reading integer from file\n");
        fclose(fp);
        return EXIT_FAILURE;
    }
    fclose(fp);

    // Convert ASCII string to integer
    char *endptr;
    long value = strtol(buffer, &endptr, 10);

    if (*endptr != '\0' && *endptr != '\n') {
        fprintf(stderr, "Invalid integer in file: %s\n", buffer);
        return EXIT_FAILURE;
    }

    if (value < INT32_MIN || value > INT32_MAX) {
        fprintf(stderr, "Value out of 32-bit range: %ld\n", value);
        return EXIT_FAILURE;
    }
    
    //printf("Max delta : %ld\n", (long)max_delta);
    printf("Epoch time: %ld\n", (long)now);
    long delta=now-value;
    printf("Delta     : %ld\n", (long)delta);
    
    long do_change=0; 
    if(delta<0) {
		//printf("Current time is before file\n");
		if(-delta > max_delta) do_change=1;
	} else {
		//printf("Current time is after file\n");
		if(delta > max_delta) do_change=1;
	}
    
    if(do_change) {	
		// Set system time
		struct timeval tv = {
			.tv_sec = value,
			.tv_usec = 0
		};
		printf("Time difference %ld > %ld, forcing\n",delta,max_delta);
		if (settimeofday(&tv, NULL) < 0) {
			perror("settimeofday (are you root?)");
			return 1;
		}

		//~ printf("System time set successfully to: %s", ctime(&tv.tv_sec));
    } else {
		printf("Time difference is acceptable, updating %s\n",
			argv[1]);
		FILE *fp = fopen(argv[1], "w");
		if (!fp) {
			perror("Error opening file");
			return EXIT_FAILURE;
		}
		fprintf(fp, "%ld\n", (long)now);
        fclose(fp);
	}
    return 0;
}