I'm writing a C program using nftw() to walk a filesystem and retrieve file modification times for each file.
nftw() calls a supplied function pointer and provides a struct stat as an argument.
man stat(2) states that the time modification fields are:
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
However, whilst man stat(2) provides an example of how to print the time fields, it doesn't tell me how to find information about struct timespec, nor how to query/manipulate the time modification fields.
How should I go about finding that information on my computer alone, without resorting to Google?
Typically one of the man pages describes what these structures contain. If you tell us your platform I can give further details. Otherwise, open up the header /usr/include/time.h to see what struct timespec is defined as.
$ apropos timespec
clock_gettime (2) - Return the current timespec value of tp for the specified clock
$ man 2 clock_gettime
Usually, when I need information on data types or functions, if not included in the man pages, I issue a command like the following:
grep -r "timespec" /usr/include/
in the path where are the header files.
Related
I am making a program to copy files from a source to a destination directory and would like to change the destination file timestamps so they match the source file timestamps.
So far I have discovered the utime() function and have manipulated the utimbuf struct with the times I would like to use.
However, the times do not take into account the nanoseconds.
For example:
If I want to copy "file1" and it has a timestamp of 123.213241, my copy will have 123.000000 when running my current program. I would like to include the nanoseconds .213241 etc.
Here is my code so far:
struct stat buf;
struct utimbuf time;
stat(filename, &buf) // get metadata of file "filename" and then store in buf
time.actime = buf.st_atim.tv_sec; // set times in time struct
time.modtime = buf.st_mtim.tv_sec;
utime(filename_copy, &time); // load file copy with time struct
How can I include nanoseconds in my file timestamps?
According to POSIX, the function you need is utimensat() (or its close relative, futimens()). Both of these take a pair of struct timespec values in an array, which allows you to specify a time to nanoseconds. The first element is the access time; the second is the modification time.
Not all file systems support nanosecond timestamps. Not all systems actually support nanosecond resolution — they might round to the nearest microsecond.
Note that modern versions of the stat() function return a structure with elements st_atim, st_ctim, and st_mtim. These are also struct timespec values. The <sys/stat.h> defines some backwards-compatibility macros:
For compatibility with earlier versions of this standard, the st_atime macro shall be defined with the value st_atim.tv_sec. Similarly, st_ctime and st_mtime shall be defined as macros with the values st_ctim.tv_sec and st_mtim.tv_sec, respectively.
For Linux, see utimensat(2). However, the documentation for stat(2) only mentions subsecond times in the Notes section near the bottom. Be cautious.
Is it possible to get the struct info (that is, the keys) of any struct? Or is required that you go to the manual page to read up what the actual structure is for that object. Take the following example:
struct stat stats;
stat(filepath, &stats);
printf("Size: %lld\n", stats.st_size);
Is it possible to do something like stats.keys(), or whatever a potentially equivalent operation would be to see the inner structure of a struct ?
You can read the man page, or you can read the header; there are no built-in introspection facilities in the C language that will inspect structs for their attributes in any convenient way.
In theory, if you compile the executable with debugging symbols a debugger might be able to tell you some of this (after loading and parsing the executable and its symbols), but that's generally going to be less convenient than just reading the docs.
On Linux, sched.h contains the definition of
int sched_rr_get_interval(pid_t pid, struct timespec * tp);
to get the time slice of a process. However the file shipping with OS X El Capitan doesn't hold that definition.
Is there an alternative for this on OS X?
The API's related to this stuff are pretty byzantine and poorly documented, but here's what I've found.
First, the datatypes related to RR scheduling seem to be in /usr/include/mach/policy.h, around line 155. There's this struct:
struct policy_rr_info {
...
integer_t quantum;
....
};
The quantum is, I think, the timeslice (not sure of units.) Then grepping around for this or related types defined in the same place, I found the file /usr/include/mach/mach_types.def, which says that the type struct thread_policy_t contains a field policy_rr_info_t on line 203.
Next, I found in /usr/include/mach/thread_act.h the public function thread_policy_get, which can retrieve information about a thread's policy into a struct thread_policy_t *.
So, working backwards. I think (but haven't tried at all) that you can
Use the thread_policy_get() routine to return information about the thread's scheduling state into a thread_policy_t
That struct seems to have a policy_rr_info_t sub-substructure
That sub-structure should have a quantum field.
That field appears to be the timeslice, but I don't know about the units.
There are no man pages for this part of the API, but this Apple Developer page explains at least a little bit about how to use this API.
Note that this is all gleaned from just grepping the various kernel headers, and I've definitely not tried to use any of these APIs in any actual code.
I'm trying to print the time within my own custom system call in a human readable format (Jan 29 2015 05:53:12 for example, though any order is fine). I'm using code I know works in a standard C program because I've used it before, but for some reason it doesn't work within a system call.
#include<linux/linkage.h>
#include<linux/kernel.h>
#include<linux/sched.h>
#include<linux/time.h>
asmlinkage long sys_mycall (int someVal)
{
time_t t;
time(&t);
printk("myInt: %d", someVal);
printk("%s", ctime(&t)) ;
return 0 ;
}
I'm getting errors on implicit declaration of functions 'time' and 'ctime', even though I included linux/time.h (I also tried just time.h).
And an error on ctime returning type int when I specified %s.
I know this means that something is going wrong with the time.h, but what exactly is it? Am I not allowed to include that in a sys call?
Thanks!
The kernel coding environment is not a "hosted" implementation of C, which implies that various standard C functions like ctime() might not exist, or if they do, might not behave in the same way as the standard functions. In fact, ctime() does not exist inside the kernel at all.
Instead, you can use time_to_tm() from <linux/time.h> to convert a time_t to a broken-down time in a struct tm, and then print the components of struct tm individually.
Note that you have to supply a timezone offset to time_to_tm(), because there is no overall "current timezone" for the kernel - timezone is a display setting and is therefore handled entirely in userspace. This is one reason why the kernel typically doesn't format times to be "human-readable" itself. If you don't have a good value to supply for the timezone offset, you can use zero which will mean that the broken-down time is in UTC.
Instead of time(), to obtain the current time to seconds granuality inside the kernel use get_seconds().
The ctime() function is not available in the kernel.
In fact, there are very few date/time formatting functions available in the kernel; most of these functions are only available in user space. If you want to generate a timestamp in the kernel, don't try to format it; just return a time_t and let userspace applications handle the formatting.
If that isn't enough and you really want a readable timestamp, you'll need to define the necessary functions yourself.
In the 2nd edition of "The C Programming Language" by Kernighan and Ritchie they implement a simplified version of the UNIX command ls (section 8.6 "Example - Listing Directories", p. 179). For this purpose they create the following interface which provides a system-independent access to the name and inode number of the files stored in a directory.
#define NAME_MAX 14 /* longest filename component; */
/* system dependent */
typedef struct { /* portable director-entry */
long ino; /* inode number */
char name[NAME_MAX+1]; /* name + '\0' terminator */
} Dirent;
typedef struct { /* minimal DIR: no buffering, etc. */
int fd; /* file descriptor for directory */
Dirent d; /* the directory entry */
} DIR;
DIR *opendir(char *dirname);
Dirent *readdir(DIR *dfd);
void closedir(DIR *dfd);
Then they implement this interface for Version 7 and System V UNIX systems.
opendir() basically uses the system
call open() to open a directory and
malloc() to allocate space for a
DIR structure. The file descriptor
returned by open() is then stored
in the variable fd of that DIR.
Nothing is stored in the Dirent
component.
readdir() uses the system call
read() to get the next
(system-dependent) directory entry of
an opened directory and copies the so
obtained inode number and filename
into a static Dirent structure (to
which a pointer is returned). The
only information needed by
readdir() is the file descriptor
stored in the DIR structure.
Now to my question: What is the point of having a DIR structure? If my understanding of this program is correct, the Dirent component of DIR is never used, so why not replace the whole structure with a file descriptor and directly use open() and close()?
Thanks.
Ps: I am aware that on modern UNIX systems read() can no longer be used on directories (I have tried out this program on Ubuntu 10.04), but I still want to make sure that I have not overlooked something important in this example.
From K&R:
Regrettably, the format and precise contents of a directory are not the same on all
versions of the system. So we will divide the task into two pieces to try to isolate
the non-portable parts. The outer level defines a structure called a Dirent and three routines opendir, readdir, and closedir to provide system-independent access to the name and inode number in a directory entry.
So the reason is portability. They want to define an interface that can survive on systems that have different stat structs or nonstandard open() and close(). They go on to build a bunch of reusable tools around it, which don't even care if they're on a Unix-like system. That's the point of wrappers.
Maybe it's not used because they started out by defining their data structures (with a Dirent inside DIR) but ended up not using it. Keeping data structures grouped like that is good design.
It is so they don't have to allocate memory for the Dirent structure that is returned by readdir. This way they can reuse the Dirent between subsiquent calls to readdir.