I want to display my two attributes from the structure stat
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
Here is my code that i try to display the last time access and the last time of last modification of folder/file
struct tm *time;
char buffer[200];
time = localtime(file_info.st_atime);
strftime(buffer, sizeof(buffer), "%d.%m.%Y %H:%M:%S", time);
printf("%s\n", buffer);
time = localtime(file_info.st_mtime);
strftime(buffer, sizeof(buffer), "%d.%m.%Y %H:%M:%S", time);
printf("%s\n", buffer);
I want to display like human readble time and date like 15.03.1952 23:11:34 of a folder/file info that has been last modifed or access in linux
This deviates a bit from your code in terms of style, but perhaps it's helpful?
#include <time.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
char* formatdate(char* str, time_t val)
{
strftime(str, 36, "%d.%m.%Y %H:%M:%S", localtime(&val));
return str;
}
int main()
{
int errno;
const char* filename;
filename = "stat.c";
errno = 0;
struct stat *file_info = malloc(sizeof(struct stat));
if (lstat(filename, file_info) != 0) {
perror("Error");
exit(1);
}
char date[36];
printf("Access: %s\n", formatdate(date, file_info->st_atime));
printf("Modify: %s\n", formatdate(date, file_info->st_mtime));
printf("Change: %s\n", formatdate(date, file_info->st_ctime));
free(file_info);
return 0;
}
char buffer[200];
printf("Access : %s\n", formatdate(buffer, file_info.st_atime));
printf("Modify : %s\n", formatdate(buffer, file_info.st_mtime));
printf("\n\n");
char *formatdate(char *buff, time_t val)
{
strftime(buff,200, "%d.%m.%Y %H:%M:%S", localtime(&val));
return buff;
}
And this is the answer that i was looking for thanks again.
Try this: printf("%s", asctime(localtime(&buffer.st_mtime)));
Related
I tried to search that in many words, but for some reason I am solely given references to questions like "How to check if file or directory exists".
Instead, I would like to check if a given file is located in a given directory.
The problem is that the file, the directory or both can and sometimes have to be passed as a relative path, instead of absolute path.
Is there any windows/unix function that checks on that?
here is an example of using the stat() function regardless if the 'filename' is a full path or just the file name
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#if 0
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
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 */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
#endif
bool doesFileExistInDir( char *path, char *filename )
{
struct stat myStat;
int statStatus;
char pathname[ strlen(path) + strlen( filename ) + 1];
if( !strchr( filename, '/' ) )
{
pathname[0] = '\0';
strcat( pathname, path );
// strcat( pathname, "/" );
strcat( pathname, filename );
}
else
{
strcpy( pathname, filename );
}
if( (statStatus = stat( pathname, &myStat )) != 0 )
{
// then file not accessible -or- directory not readable -or- file does not exist
perror( "stat failed" );
return false;
}
return true;
}
This function can be used to determine if dirname is the directory of filename.
int file_is_in_directory (char *filename, char *dirname) /* [!] Windows-specific */
{
char filename_full[MAX_PATH] = {'\0'};
char dirname_full[MAX_PATH] = {'\0'};
char* file = NULL;
GetFullPathNameA(filename, MAX_PATH, filename_full, NULL); /* [!] Check rval */
GetFullPathNameA(dirname, MAX_PATH, dirname_full, NULL); /* [!] Check rval */
if(!strncmp(dirname_full, filename_full, strlen(dirname_full)))
{
return 1; /* File is located in directory */
}
return 0; /* File not contained */
}
I'm trying to detect text file is empty or not in C.
(values are initialized in NULL)
Whenever read first in value(using fscanf), it always returns file has zero,
even if it has value "0" or "empty".
How can I know the target text file is empty or not?
(it should be distinguished even it has "0" in first letter)
If the file was successfully open for read, as per fopen(filename, "r"), you can verify if it is empty before any read operation this way:
int is_empty_file(FILE *fp) {
int c = getc(fp);
if (c == EOF)
return 1;
ungetc(c, fp);
return 0;
}
ungetc() is guaranteed to work for at least one character. The above function will return 1 if the file is empty or if it cannot be read, due to an I/O error. You can tell which by testing ferr(fp) or feof(fp).
If the file is a stream associated to a device or a terminal, the test code will block until at least one byte can be read, or end of file is signaled.
If the file is a regular file, you could also use a system specific API to determine the file size, such as stat, lstat, fstat (on Posix systems).
If you're under Linux, you can use stat or fstat:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
Will give you this information:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
To check for the size using stat:
struct stat info;
if(stat(filepath, &info) < 0) {
/* error */
}
if(info.st_size == 0) {
/* file is empty */
}
Or using fstat:
int fd = open(filepath, O_RDONLY);
struct stat info;
if(fstat(fd, &info) < 0) {
/* error */
}
if(info.st_size == 0) {
/* file is empty */
}
you can do using ftell
#include <stdio.h>
int get_file_size (char *filename) {
FILE *fp;
int len;
fp = fopen(filename, "r");
if( fp == NULL ) {
perror ("Error opening file");
return(-1);
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
fclose(fp);
return(len);
}
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
}
I am working with the stat struct in C and I want to output each of the fields. When I try to output st_atime, st_mtime, and st_ctime I am using the following lines:
printf("Last file change: %s\n", ctime(sb.st_ctime));
printf("Last file access time: %s\n", ctime(sb.st_atime));
printf("Last file mod time: %s\n", ctime(sb.st_mtime));
For some reason, I am getting a Segmentation Fault(Core Dump) error. My declaration for the stat struct is:
struct stat sb;
#include <stdio.h>
#include <sys/stat.h>
char file[128];
int main(int argc, char *argv[]){
struct stat sb;
sprintf(file, "%s", argv[1]);
if(stat(file, &sb) == 0)
{
printf("Last change: %s\n", ctime(sb.st_ctime));
printf("Last File access: %s\n", ctime(sb.st_atime));
printf("Last file mod: %s\n", ctime(sb.st_mtime));
}
else
{
printf("File name does not exist!\n");
}
return 0;
}
EDIT:
To use the function ctime you should include time.h library using
#include <time.h>
The function ctime receives a pointer to a time_t.
char* ctime (const time_t * timer);
You are passing the time_t itself. You should pass the address of your struct or change the time to time_t * in your struct. This approach is dangerous depending where you are declaring your struct.
printf("Last file change: %s\n", ctime(&(sb.st_ctime)));
or change the declaration to
time_t* st_ctime; /* time of last status change */
You should pass reference to ctime according to its documentation so I suggest to use:
printf("Last file change: %s\n", ctime(&sb.st_ctime));
printf("Last file access time: %s\n", ctime(&sb.st_atime));
printf("Last file mod time: %s\n", ctime(&sb.st_mtime));
I am writing a character device that will be given a processes pid and return the parent process id, start time, and number of siblings. I am using this site: http://tldp.org/LDP/lkmpg/2.6/html/x892.html#AEN972 as a guide.
I would like to add an argument into the read call of the character driver but it is not letting me do that. My code looks like this:
/*
* chardev.c - Create an input/output character device
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/fs.h>
#include <asm/uaccess.h> /* for get_user and put_user */
#include "chardev.h"
#define SUCCESS 0
#define DEVICE_NAME "char_dev"
#define BUF_LEN 80
struct procinfo {
pid_t pid;
pid_t ppid;
struct timespec start_time;
int num_sib;
};
/*
* Is the device open right now? Used to prevent
* concurent access into the same device
*/
static int Device_Open = 0;
/*
* The message the device will give when asked
*/
static char Message[BUF_LEN];
/*
* How far did the process reading the message get?
* Useful if the message is larger than the size of the
* buffer we get to fill in device_read.
*/
static char *Message_Ptr;
/*
* This is called whenever a process attempts to open the device file
*/
static int device_open(struct inode *inode, struct file *file)
{
#ifdef DEBUG
printk(KERN_INFO "device_open(%p)\n", file);
#endif
/*
* We don't want to talk to two processes at the same time
*/
if (Device_Open)
return -EBUSY;
Device_Open++;
/*
* Initialize the message
*/
Message_Ptr = Message;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
#ifdef DEBUG
printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
#endif
/*
* We're now ready for our next caller
*/
Device_Open--;
module_put(THIS_MODULE);
return SUCCESS;
}
/*
* This function is called whenever a process which has already opened the
* device file attempts to read from it.
*/
static ssize_t device_read(struct file *file, /* see include/linux/fs.h */
char __user * buffer, /* buffer to be
* filled with data */
pid_t pid,
size_t length, /* length of the buffer */
loff_t * offset)
{
/*
* Number of bytes actually written to the buffer
*/
int bytes_read = 0;
#ifdef DEBUG
printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
#endif
/*
* If we're at the end of the message, return 0
* (which signifies end of file)
*/
if (*Message_Ptr == 0)
return 0;
/*
* Actually put the data into the buffer
*/
while (length && *Message_Ptr) {
/*
* Because the buffer is in the user data segment,
* not the kernel data segment, assignment wouldn't
* work. Instead, we have to use put_user which
* copies data from the kernel data segment to the
* user data segment.
*/
put_user(*(Message_Ptr++), buffer++);
length--;
bytes_read++;
}
#ifdef DEBUG
printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
#endif
/*
* Read functions are supposed to return the number
* of bytes actually inserted into the buffer
*/
return bytes_read;
}
/*
* This function is called when somebody tries to
* write into our device file.
*/
static ssize_t
device_write(struct file *file,
const char __user * buffer, size_t length, loff_t * offset)
{
int i;
#ifdef DEBUG
printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
#endif
for (i = 0; i < length && i < BUF_LEN; i++)
get_user(Message[i], buffer + i);
Message_Ptr = Message;
/*
* Again, return the number of input characters used
*/
return i;
}
/*
* This function is called whenever a process tries to do an ioctl on our
* device file. We get two extra parameters (additional to the inode and file
* structures, which all device functions get): the number of the ioctl called
* and the parameter given to the ioctl function.
*
* If the ioctl is write or read/write (meaning output is returned to the
* calling process), the ioctl call returns the output of this function.
*
*/
long device_ioctl(struct file *file, /* see include/linux/fs.h */
unsigned int ioctl_num, /* number and param for ioctl */
unsigned long ioctl_param)
{
int i;
char *temp;
char ch;
/*
* Switch according to the ioctl called
*/
switch (ioctl_num) {
case IOCTL_SET_MSG:
/*
* Receive a pointer to a message (in user space) and set that
* to be the device's message. Get the parameter given to
* ioctl by the process.
*/
temp = (char *)ioctl_param;
/*
* Find the length of the message
*/
get_user(ch, temp);
for (i = 0; ch && i < BUF_LEN; i++, temp++)
get_user(ch, temp);
device_write(file, (char *)ioctl_param, i, 0);
break;
case IOCTL_GET_MSG:
/*
* Give the current message to the calling process -
* the parameter we got is a pointer, fill it.
*/
i = device_read(file, (char *)ioctl_param, 99, 0);
/*
* Put a zero at the end of the buffer, so it will be
* properly terminated
*/
put_user('\0', (char *)ioctl_param + i);
break;
case IOCTL_GET_NTH_BYTE:
/*
* This ioctl is both input (ioctl_param) and
* output (the return value of this function)
*/
return Message[ioctl_param];
break;
}
return SUCCESS;
}
/* Module Declarations */
/*
* This structure will hold the functions to be called
* when a process does something to the device we
* created. Since a pointer to this structure is kept in
* the devices table, it can't be local to
* init_module. NULL is for unimplemented functions.
*/
struct file_operations Fops = {
.read = device_read,
.write = device_write,
.unlocked_ioctl = device_ioctl,
.open = device_open,
.release = device_release, /* a.k.a. close */
};
/*
* Initialize the module - Register the character device
*/
int init_module()
{
int ret_val;
/*
* Register the character device (atleast try)
*/
ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
/*
* Negative values signify an error
*/
if (ret_val < 0) {
printk(KERN_ALERT "%s failed with %d\n",
"Sorry, registering the character device ", ret_val);
return ret_val;
}
printk(KERN_INFO "%s The major device number is %d.\n",
"Registeration is a success", MAJOR_NUM);
printk(KERN_INFO "If you want to talk to the device driver,\n");
printk(KERN_INFO "you'll have to create a device file. \n");
printk(KERN_INFO "We suggest you use:\n");
printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
printk(KERN_INFO "The device file name is important, because\n");
printk(KERN_INFO "the ioctl program assumes that's the\n");
printk(KERN_INFO "file you'll use.\n");
return 0;
}
/*
* Cleanup - unregister the appropriate file from /proc
*/
void cleanup_module()
{
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
#if 0
int ret;
/*
* Unregister the device
*/
ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
/*
* If there's an error, report it
*/
if (ret < 0)
printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
#endif
}
So i'm working on linux and my question is how make a program accept arguments in execution like this one:
./program am i
Also both functions work the same way at the moment, because i'm struggling with getting only this line:
(expected result of show_info_who_am_i)
Kamil pts/0 2015-11-12 10:14 (:0)
instead of both of them:
(result of show_info_who)
Kamil tty2 2015-11-12 10:13 (:0)
Kamil pts/0 2015-11-12 10:14 (:0)
#include <stdio.h>
#include <utmp.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#define SHOWHOST /* include remote machine on output */
show_info_who( struct utmp *utbufp )
{
if(utbufp->ut_type > 4){
time_t czas = utbufp->ut_time;
char buf[80];
struct tm* timeinfo = localtime(&czas);
printf("%-8.8s", utbufp->ut_name); /* the logname */
printf(" "); /* a space */
printf("%-8.8s", utbufp->ut_line); /* the tty */
printf(" "); /* a space */
strftime(buf, 80, "%F %R" , timeinfo);
printf("%s", buf);
printf(" "); /* a space */
#ifdef SHOWHOST
printf("(%s)", utbufp->ut_host); /* the host */
#endif
printf("\n"); /* newline */
}
}
show_info_who_am_i( struct utmp *utbufp )
{
if(utbufp->ut_type > 4){
time_t czas = utbufp->ut_time;
char buf[80];
struct tm* timeinfo = localtime(&czas);
printf("%-8.8s", utbufp->ut_name); /* the logname */
printf(" "); /* a space */
printf("%-8.8s", utbufp->ut_line); /* the tty */
printf(" "); /* a space */
strftime(buf, 80, "%F %R" , timeinfo);
printf("%s", buf);
printf(" "); /* a space */
#ifdef SHOWHOST
printf("(%s)", utbufp->ut_host); /* the host */
#endif
printf("\n"); /* newline */
}
}
int main(int argc, char *argv[])
{
struct utmp current_record; /* read info into here */
int utmpfd; /* read from this descriptor */
int reclen = sizeof(current_record);
if ( (utmpfd = open(UTMP_FILE, O_RDONLY)) == -1 ){
perror( UTMP_FILE ); /* UTMP_FILE is in utmp.h */
exit(1);
}
//char am[22] = "am"; /* test */
//char i[22] = "i"; /* test */
//printf("%s,%s\n\n", am,i); /* test */
//printf("%s", argv[1]);
if(argv[1]== "am"){
if(argv[2]== "i"){
while ( read(utmpfd, ¤t_record, reclen) == reclen )
show_info_who_am_i(¤t_record);
}
}
else{
while ( read(utmpfd, ¤t_record, reclen) == reclen )
show_info_who(¤t_record);
}
//printf("%s,%s", argv[1], argv[2]); /* test */
close(utmpfd);
return 0; /* went ok */
}