Re: [RFC PATCH] hwclock: --offset: Use offset instead of writing clock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Noé,
 I just submitted a patch on 14-09-27 that adds this functionality
without creating a new state file.

On 10/07/2014 05:15 AM, Noé Rubinstein wrote:
> From: Noé Rubinstein <noe.rubinstein@xxxxxxxxx>
> 
> This option is useful for systems that have a working hardware clock, but do
> not provide a way to write to it. Instead of setting the hardware clock, write
> the difference between hardware and system clock to a file; when getting the
> hardware clock, add the offset from this file to obtain the correct time.
> 
> I have not checked how well this interacts with the adjtime mechanism, so
> this is an RFC patch.
> ---
>  sys-utils/hwclock.8.in |  6 ++++
>  sys-utils/hwclock.c    | 88 ++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 92 insertions(+), 2 deletions(-)
> 
> diff --git a/sys-utils/hwclock.8.in b/sys-utils/hwclock.8.in
> index b11b45c..63fabda 100644
> --- a/sys-utils/hwclock.8.in
> +++ b/sys-utils/hwclock.8.in
> @@ -113,6 +113,12 @@ not reset.
>  .BR \-w , \ \-\-systohc
>  Set the Hardware Clock to the current System Time.
>  .TP
> +.BR \-\-offset[=filename]
> +This option is useful for systems that have a working hardware clock, but do
> +not provide a way to write to it. Instead of setting the hardware clock, write
> +the difference between hardware and system clock to a file; when getting the
> +hardware clock, add the offset from this file to obtain the correct time.
> +.TP
>  .BR \-V , \ \-\-version
>  Display version information and exit.
>  .TP
> diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
> index e780158..c7deab9 100644
> --- a/sys-utils/hwclock.c
> +++ b/sys-utils/hwclock.c
> @@ -98,6 +98,7 @@ struct clock_ops *ur;
>  #define MAX_DRIFT 2145.0
>  
>  const char *adj_file_name = NULL;
> +const char *offset_file_name = NULL;
>  
>  struct adjtime {
>  	/*
> @@ -234,6 +235,35 @@ hw_clock_is_utc(const bool utc, const bool local_opt,
>  	return ret;
>  }
>  
> +static int read_offset(struct timeval *offset)
> +{
> +	FILE *f;
> +	int rc;
> +	f = fopen(offset_file_name, "r");
> +	if (!f)
> +		return -errno;
> +
> +	rc = fread(offset, sizeof(*offset), 1, f);
> +	fclose(f);
> +
> +	return rc == 1 ? 0 : -EINVAL;
> +}
> +
> +static int write_offset(struct timeval offset)
> +{
> +	FILE *f;
> +	int rc;
> +	f = fopen(offset_file_name, "w");
> +	if (!f)
> +		return -errno;
> +
> +	rc = fwrite(&offset, sizeof(offset), 1, f);
> +	fclose(f);
> +
> +	return rc == 1 ? 0 : -EINVAL;
> +}
> +
> +
>  /*
>   * Read the adjustment parameters out of the /etc/adjtime file.
>   *
> @@ -1290,6 +1320,8 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
>  	bool no_auth;
>  	/* The time at which we read the Hardware Clock */
>  	struct timeval read_time;
> +	/* The offset between system time and hardware time */
> +	struct timeval offset = {0};
>  	/*
>  	 * The Hardware Clock gives us a valid time, or at
>  	 * least something close enough to fool mktime().
> @@ -1320,6 +1352,11 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
>  		adjtime.dirty = FALSE;
>  	}
>  
> +	if ((hctosys || show) && offset_file_name)
> +	{
> +		read_offset(&offset);
> +	}
> +
>  	universal = hw_clock_is_utc(utc, local_opt, adjtime);
>  
>  	if ((set || systohc || adjust) &&
> @@ -1328,7 +1365,8 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
>  		adjtime.dirty = TRUE;
>  	}
>  
> -	if (show || adjust || hctosys || (!noadjfile && !systz && !predict)) {
> +	if (show || adjust || hctosys || (!noadjfile && !systz && !predict) ||
> +	    offset_file_name) {
>  		/* data from HW-clock are required */
>  		rc = synchronize_to_clock_tick();
>  
> @@ -1358,8 +1396,20 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
>  	}
>  
>  	if (show) {
> -		display_time(hclock_valid, hclocktime,
> +		display_time(hclock_valid, hclocktime + offset.tv_sec,
>  			     time_diff(read_time, startup_time));
> +	} else if (set && offset_file_name) {
> +		if (!hclock_valid) {
> +			printf(_("Hardware clock invalid, not writing offset.\n"));
> +		} else {
> +			offset.tv_sec = set_time - hclocktime;
> +			rc = write_offset(offset);
> +			if (rc) {
> +				printf(_("Unable to write offset: %s."), strerror(-rc));
> +				return rc;
> +			}
> +		}
> +
>  	} else if (set) {
>  		set_hardware_clock_exact(set_time, startup_time,
>  					 universal, testing);
> @@ -1371,6 +1421,18 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
>  	} else if (adjust) {
>  		do_adjustment(&adjtime, hclock_valid,
>  			      hclocktime, read_time, universal, testing);
> +	} else if (systohc && offset_file_name) {
> +		if (!hclock_valid) {
> +			printf(_("Hardware clock invalid, not writing offset.\n"));
> +		} else {
> +			gettimeofday(&offset, NULL);
> +			offset.tv_sec -= hclocktime;
> +			rc = write_offset(offset);
> +			if (rc) {
> +				printf(_("Unable to write offset: %s."), strerror(-rc));
> +				return rc;
> +			}
> +		}
>  	} else if (systohc) {
>  		struct timeval nowtime, reftime;
>  		/*
> @@ -1390,6 +1452,17 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
>  					    reftime.tv_sec,
>  					    hclock_valid, hclocktime, (double)
>  					    read_time.tv_usec / 1E6);
> +	} else if (hctosys && offset_file_name) {
> +		if (!hclock_valid) {
> +			printf(_("Hardware clock invalid, not setting time.\n"));
> +		} else {
> +			offset.tv_sec += hclocktime;
> +			rc = settimeofday(&offset, NULL);
> +			if (rc) {
> +				printf(_("Unable to set system clock.\n"));
> +				return rc;
> +			}
> +		}
>  	} else if (hctosys) {
>  		rc = set_system_clock(hclock_valid, hclocktime, testing);
>  		if (rc) {
> @@ -1547,6 +1620,7 @@ static void out_version(void)
>  	printf(UTIL_LINUX_VERSION);
>  }
>  
> +#define DEFAULT_OFFSET_FILE "/etc/time_offset"
>  /*
>   * usage - Output (error and) usage information
>   *
> @@ -1577,6 +1651,10 @@ static void usage(const char *fmt, ...)
>  		"     --adjust         adjust the RTC to account for systematic drift since\n"
>  		"                        the clock was last set or adjusted\n"), usageto);
>  	fputs(_(" -c, --compare        periodically compare the system clock with the CMOS clock\n"), usageto);
> +	fprintf(usageto,
> +	      _("     --offset [file]  instead of setting the clock, write an offset to file.\n"
> +	        "                      when reading the time, add this offset to the hardware time.\n"
> +		"                         (default: %s)\n"), DEFAULT_OFFSET_FILE);
>  #ifdef __linux__
>  	fputs(_("     --getepoch       print out the kernel's hardware clock epoch value\n"
>  		"     --setepoch       set the kernel's hardware clock epoch value to the \n"
> @@ -1653,6 +1731,7 @@ int main(int argc, char **argv)
>  	/* Long only options. */
>  	enum {
>  		OPT_ADJFILE = CHAR_MAX + 1,
> +		OPT_OFFSET,
>  		OPT_BADYEAR,
>  		OPT_DATE,
>  		OPT_DIRECTISA,
> @@ -1698,6 +1777,7 @@ int main(int argc, char **argv)
>  		{"test",	0, 0, OPT_TEST},
>  		{"date",	1, 0, OPT_DATE},
>  		{"epoch",	1, 0, OPT_EPOCH},
> +		{"offset",	2, 0, OPT_OFFSET},
>  #ifdef __linux__
>  		{"rtc",		1, 0, 'f'},
>  #endif
> @@ -1837,6 +1917,10 @@ int main(int argc, char **argv)
>  		case OPT_PREDICT_HC:
>  			predict = TRUE;		/* --predict-hc */
>  			break;
> +		case OPT_OFFSET:
> +			offset_file_name =	/* --offset */
> +				optarg ? optarg : DEFAULT_OFFSET_FILE;
> +			break;
>  #ifdef __linux__
>  		case 'f':
>  			rtc_dev_name = optarg;	/* --rtc */
> 
--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux