For a computer security assignment, I have to modify the time function in order to return a specific date. I need the time function to return a date between Jan 1st, 2016 and June 15th, 2018. I then use these commands to overload and hook into the time function:
gcc -Wall -fPIC -shared -o newtime.so newtime.c -ldl
export LD_PRELOAD=$PWD/newtime.so
Here is my modified version of the time function:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <time.h>
time_t time (time_t *t)
{
long int seconds = 1485907200;
time_t modifiedTime = (time_t) seconds;
return modifiedTime;
}
Whenever I run this implementation, it says that the date being returned is December 31, 1969 19:00:00. Am I just formatting the time since the Linux Epoch incorrectly or am I making a more serious mistake? I have tried using a regular int instead of a long int, and still experience the same issues. Some insight into my mistake would be very helpful.
You're not implementing the entire functionality of time(). The code your interposing on may use functionality that you have not implemented.
Per the C standard:
7.27.2.4 The time function (note the bolded part):
Synopsis
#include <time.h>
time_t time(time_t *timer);
Description
The time function determines the current calendar time. The encoding
of the value is unspecified.
Returns
The time function returns the implementation's best approximation to
the current calendar time. The value (time_t)(-1) is returned if the
calendar time is not available. If timer is not a null pointer, the
return value is also assigned to the object it points to.
A full implementation, based on your code:
time_t time (time_t *t)
{
long int seconds = 1485907200;
time_t modifiedTime = (time_t) seconds;
if ( t )
{
*t = modifiedTime;
}
return modifiedTime;
}
In fact, there is no problem in the code that you presented. I tested it with the following basic program:
#include <stdio.h>
#include <time.h>
int main(void)
{
printf("%ld\n", (long) time(NULL));
}
So I just run LD_PRELOAD=./newtime.so ./test and I get the expected result.
However, the date command doesn't make call to the time function. It calls instead int clock_gettime(clockid_t clk_id, struct timespec *tp). So you should better re-implement them both if you would like to cover this case.
May be a simple implementation like the following one (It works fine with date):
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
if(tp) {
tp->tv_sec = 1485907200;
tp->tv_nsec = 0;
}
return 0;
}
If you get a date different from your expectation, it could be related to your time zone.
Related
I compile C using the C99 version, and I want to try and output the timezone of the given time.
The IDE I use gives GMT+0 as the timezone, but I want to somehow output it with struct tm.
So I followed the instructions from this answer and made this program:
#include <stdio.h>
#include <time.h>
int main()
{
time_t present = time(NULL);
struct tm now = *localtime(&present);
now.tm_mon += 1;
now.tm_year += 1900;
struct tm t = {0};
localtime_r(&present, &t);
printf("%i/%i/%i %i:%i:%i from %s\n", now.tm_mon, now.tm_mday, now.tm_year, now.tm_hour, now.tm_min, now.tm_sec, t.tm_zone);
}
And it seems like I got 2 errors here:
implicit declaration of function 'localtime_r' is invalid in C99
no member named 'tm_zone' in 'struct tm'
So I checked the IDE Manual, and find that localtime_r actually exists, and is part of the <time.h> library.
So now I'm wondering if the IDE's confused or something. I don't know how to fix it either.
This might get closed as it might "need debugging details", but read more.
Because of this whole situation, how can I get the timezone (maybe even the offset) in C99 and get it to be outputted with printf()?
First, localtime_r is not part of the standard library - it's an extension offered by some implementations, and by default its declaration is not exposed in those implementations. To make it available, you'll have to define the macro _POSIX_SOURCE before including time.h to make it available. An easy way to do that is on the command line, like so:
gcc -o tz -D_POSIX_SOURCE -std=c11 -pedantic -Wall -Werror tz.c
otherwise, just define it in your source before including time.h:
#define _POSIX_SOURCE
#include <stdio.h>
#include <time.h>
Secondly, if all you're interested in is the local time zone then there's an easier way to do this - get the current time:
time_t t = time( NULL );
then use both localtime and gmtime to get the broken down time for the current time zone and UTC:
struct tm *local = localtime( &t );
struct tm *zulu = gmtime( &t );
Then compute the difference between the tm_hour members of local and zulu, and that's your time zone.
int tz = zulu->tm_hour - local->tm_hour;
You'll want to check local->tm_isdst to account for daylight savings, but that should at least get you started.
Incomprehensible behavior of the function strptime():
#define _XOPEN_SOURCE
#include <stdio.h>
#include <time.h>
double getPeriod(char * dateStart, char * dateStop) {
struct tm tmStart, tmStop;
time_t timeStampStart, timeStampStop;
strptime(dateStart, "%Y-%m-%d %H:%M:%S", &tmStart);
strptime(dateStop, "%Y-%m-%d %H:%M:%S", &tmStop);
timeStampStart = mktime(&tmStart);
timeStampStop = mktime(&tmStop);
printf("%d\t%d\n", tmStart.tm_hour, tmStop.tm_hour);
}
int main()
{
getPeriod("2016-12-05 18:14:35", "2016-12-05 18:18:34");
return 0;
}
Output:
17 18
Why does this happen?
Compiler gcc (GCC) 6.2.1
OS Linux
tmStart and tmStop are not initialized, so some fields will be uninitialized when passed to mktime. Thus, the behavior is technically undefined.
From the strptime man page (note the first two sentences):
In principle, this function does not initialize tm but only stores the values specified. This means that tm should be initialized before the call. Details differ a bit between different UNIX systems. The glibc implementation does not touch those fields which are not explicitly specified, except that it recomputes the tm_wday and tm_yday field if any of the year, month, or day elements changed.
How to write current time in printf on Minix 3.2.1?
I try to use gmtime like below but it gives error on time(&nowtime).
#include <sys/time.h>
#include <time.h>
struct tm *now;
time_t nowtime;
time(&nowtime);
now=gmtime(&nowtime);
printf("TIME is NOW %s",now);
Moreover, I try to recall that in kernel (/usr/src/kernel/main.c) because I need that time on the booting of minix to say when the kernel process is finished and switch to user.
I take some errors on above code like when rebuild the kernel like below;
Not that familiar with minix, but it is similar to Unix & Linux, so maybe something from that platform may be present on minix... so A couple of approaches
Run a man on ctime
the man page on Linux's time() command contains this example code (which you may have to modify for minix, but it shows how to use asctime() localtime() and time() ):
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t result;
result = time(NULL);
printf("%s%ju secs since the Epoch\n",
asctime(localtime(&result)),
(uintmax_t)result);
return(0);
}
Working on an Ubuntu 12.04.3 LTS box, I just noticed that localtime() and localtime_r() behave differently when the system's timezone changes during the lifetime of a process: localtime() picks up the timezone change immediately, whereas localtime_r() does not, it seems to stick to what was the timezone at the launch of the process. Is this expected behavior? I haven't seen this covered anywhere.
More precisely, when I use the following code ...
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
int main() {
while (1) {
time_t t = time(NULL);
struct tm *tm = localtime(&t);
printf("localtime:%02d/%02d/%02d-%02d:%02d:%02d\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(1);
}
return 0;
}
... and change the timezone from UTC via ...
# echo 'Europe/Berlin' > /etc/timezone
# sudo dpkg-reconfigure --frontend noninteractive tzdata
... then the code produces the following, ...
localtime:10/04/2013-01:11:33
localtime:10/04/2013-01:11:34
localtime:10/04/2013-01:11:35
localtime:10/03/2013-23:11:36
localtime:10/03/2013-23:11:37
localtime:10/03/2013-23:11:38
... but if I use:
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
int main() {
while (1) {
time_t t = time(NULL);
struct tm local_tm;
struct tm *tm = localtime_r(&t, &local_tm);
printf("localtime_r:%02d/%02d/%02d-%02d:%02d:%02d\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(1);
}
return 0;
}
... then there's no change when doing a similar timezone change:
localtime_r:10/04/2013-01:15:37
localtime_r:10/04/2013-01:15:38
localtime_r:10/04/2013-01:15:39
localtime_r:10/04/2013-01:15:40
localtime_r:10/04/2013-01:15:41
localtime_r:10/04/2013-01:15:42
UPDATE: adding a call to tzset() before invoking localtime_r() produces the expected behavior. Whether that's clear from the spec/manpage or not (see discussion below) is a question for mentalhealth.stackexchange.com...
See this following documentation:
The localtime() function converts the calendar time timep to
broken-down time representation, expressed relative to the user's
specified timezone. The function acts as if it called tzset(3) and
sets the external variables tzname with information about the current
timezone, timezone with the difference between Coordinated Universal
Time (UTC) and local standard time in seconds, and daylight to a
nonzero value if daylight savings time rules apply during some part of
the year. The return value points to a statically allocated struct
which might be overwritten by subsequent calls to any of the date and
time functions. The localtime_r() function does the same, but stores
the data in a user-supplied struct. It need not set tzname, timezone,
and daylight.
From: http://linux.die.net/man/3/localtime_r
So as far as I can tell, it appears that the code is working as I'd expect.
Edited to add more from the same documentation:
According to POSIX.1-2004, localtime() is required to behave as though
tzset(3) was called, while localtime_r() does not have this
requirement. For portable code tzset(3) should be called before
localtime_r().
I've got a problem.
I need to get things like day of year, day of month, month of year etc.
I use this code:
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t liczba_sekund;
struct tm strukt;
time(&liczba_sekund);
localtime_r(&liczba_sekund, &strukt);
printf("today is %d day of year\nmonth is %d, month's day %d\n", strukt.tm_yday+1, strukt.tm_mon+1, strukt.tm_mday);
return 0;
}
First thing: why does gcc -std=c99 -pedantic -Wall return this warning:
My input: gcc test_data.c -o test_data.out -std=c99 -pedantic -Wall
Output:
test_data.c: In function ‘main’:
test_data.c:11:3: warning: implicit declaration of function ‘localtime_r’ [-Wimplicit-function-declaration]
Second thing: how to make it work on windows? While trying to compile it using Dev-C, I got this:
http://imgur.com/U7dyE
##EDIT --------------------
I have found an example for your localtime suggestion:
#include <stdio.h>
#include <time.h>
int main ()
{
time_t time_raw_format;
struct tm * ptr_time;
time ( &time_raw_format );
ptr_time = localtime ( &time_raw_format );
printf ("Current local time and date: %s", asctime(ptr_time));
return 0;
}
How can I change this to date format like this: 5.12.2012 or 5-12-2012? And how to get the day of the year?
I would love if the solution worked both on windows and linux.
localtime_r is not part of the C standard. Maybe you were looking for localtime?
localtime_r is really available on many linux systems:
Thread-safe versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are specified by SUSv2, and available since libc 5.2.5
However, since it isn't part of the standard you cannot use it on Windows.
How can I change this to date format like this: 5.12.2012 or 5-12-2012? And how to get the day of the year?
You have to use strftime instead of asctime:
int main ()
{
time_t time_raw_format;
struct tm * ptr_time;
char buffer[50];
time ( &time_raw_format );
ptr_time = localtime ( &time_raw_format );
if(strftime(buffer,50,"%d.%m.%Y",ptr_time) == 0){
perror("Couldn't prepare formatted string");
} else {
printf ("Current local time and date: %s", buffer);
}
return 0;
}
localtime on Windows should be thread-safe per: http://msdn.microsoft.com/en-us/library/bf12f0hc%28VS.80%29.aspx
Both the 32-bit and 64-bit versions ofgmtime, mktime, mkgmtime, and
localtimeall use a single tm structure per thread for the conversion.
Each call to one of these routines destroys the result of the previous
call.