how to print name of newly created file(s) within a directory in C? - c

This code scans for newly created files within a directory, however where "%s" should contain the name of the new file(s) this does not occur.
I can imagine there are unnecessary pieces of code written here, however being quite unfamiliar with C I'm simply happy it compiles at this point (and actually recognizes new files) !
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
int main (int argc, char *argv[])
{
char target[FILENAME_MAX];
int result;
int fd;
int wd; /* watch descriptor */
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
fd = inotify_init();
if (fd < 0) {
perror("inotify_init");
}
wd = inotify_add_watch(fd, "/home/joe/Documents", IN_CREATE);
while (1) {
char buff[buf_len];
int no_of_events, count = 0;
no_of_events = read (fd, buff, buf_len);
while (count < no_of_events) {
struct inotify_event *event = (struct inotify_event *)&buff[count];
if (event->len) {
if (event->mask & IN_CREATE)
if(!(event->mask & IN_ISDIR)) {
printf("The file %s has been created\n", target);
fflush(stdout);
}
}
count += event_size + event->len;
}
}
return 0;
}

You're printing out target when you get an event, however target is never modified.
The name of the created file is stored in event->name. That's what you want to print.
printf("The file %s has been created\n", event->name);

Related

my read functions reads data out of my file

so I'm working on a project where I have to read BUFFER_SIZE bytes (which will be defined as a macro during the compilation) from a file on each call, and the allowed functions are {read(),malloc()} and when I use my code in the case below it reads the file plus some data I don't know where it came from, BUFFER_SIZE = 10 in this case
file contains :
01234567890123456789012345678901234567890
1
code :
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd;
char *buff;
int r;
buff=(char *) malloc((BUFFER_SIZE + 1) * sizeof(char));
fd = open("test", O_RDONLY);
r = 1;
while (r)
{
printf("BEFORE : %d\n",r);
r = read(fd, buff, BUFFER_SIZE);
printf("AFTER : %d\n",r);
buff[r] = '\0';
printf("%s\n",buff);
}
}

Monitor continuously in my directory using Inotify in c language

I am trying to monitor continuously in my directory to know when a file is created, deleted, modified using Inotify in C language.
I have done like below :
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>
#define EVENT_SIZE (sizeof(struct inotify_event))
#define BUF_LEN (1024 * (EVENT_SIZE + 16))
int main(int argc, char **argv) {
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];
fd = inotify_init();
if (fd < 0) {
perror("inotify_init");
}
wd = inotify_add_watch(fd, ".",
IN_MODIFY | IN_CREATE | IN_DELETE);
length = read(fd, buffer, BUF_LEN);
if (length < 0) {
perror("read");
}
while (i < length) {
struct inotify_event *event =
(struct inotify_event *) &buffer[i];
if (event->len) {
if (event->mask & IN_CREATE) {
printf("The file %s was created.\n", event->name);
} else if (event->mask & IN_DELETE) {
printf("The file %s was deleted.\n", event->name);
} else if (event->mask & IN_MODIFY) {
printf("The file %s was modified.\n", event->name);
}
}
i += EVENT_SIZE + event->len;
}
(void) inotify_rm_watch(fd, wd);
(void) close(fd);
return 0;
}
but here after a new file is created, it is immediately coming out, but I am trying watch continuously what is happening in my directory.

Trying to write a buffer to a file, but keep getting segmentation faults and I can't figure out why

I have some code whose goal is to open/create a file, read in messages, and then write those messages to the opened/created file. Everything up to the writing to the file seems to work just fine. Here is my code.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include "message-lib.h"
int usage( char name[] );
void * recv_log_msgs( void * arg );
sem_t mutex;
int log_fd;
void * recv_log_msgs( void * arg ){
sleep(1);
sem_wait(&mutex);
char buffer[1024];
int number_bytes_read;
FILE *fp = log_fd;
do{
number_bytes_read = read_msg(arg, buffer, 1024);
printf("in recv\n");
printf(buffer);
fwrite(&buffer, 1, sizeof(buffer)/sizeof(buffer[0]), fp);
}while(number_bytes_read > 0);
if(number_bytes_read == 0){
close_connection(arg);
}
sem_post(&mutex);
return NULL;
}
int usage( char name[] ){
printf( "Usage:\n" );
printf( "\t%s <log-file-name> <UDS path>\n", name );
return 1;
}
int main( int argc, char * argv[] )
{
int connection;
pthread_t tid;
if ( argc != 3 )
return usage( argv[0] );
log_fd = creat(argv[1], S_IRUSR | S_IWUSR);
if(log_fd == -1){
perror(argv[1]);
return 1;
}
int listener = permit_connections(argv[2]);
if(listener == -1){
return -1;
}
sem_init(&mutex, 0, 1);
do{
connection = accept_next_connection(listener);
if(connection == -1){
return -1;
}
pthread_create(&tid, NULL, recv_log_msgs, connection);
}while(connection != -1);
close_connection(connection);
close_listener(listener);
fclose(log_fd);
return 0;
}
permit_connections, accept_next_connection, and read_msg are all from a library that was provided to me. I'm guessing my problem is in recv_log_msgs, but I'm not sure what it would be.
Here's the root of your problem:
FILE *fp = log_fd;
log_fd is a file descriptor, fp is a FILE pointer.
The two are not interchangeable, and what you need to do is use the write(...) system call for writing to the log file, or create the log file in some other fashion to get a hold of a FILEpointer to it.
FILE *fp = fopen(argv[1], "w"), might do the trick.
EDIT: As #DarrenSmith pointed out to me in the comments, you can also use
fp = fdopen(log_fd, "w")
and keep the rest of the code as is.

Hashing program not returning identical values for the same file

This hashing function I've created (that scans for new files, and computes their hashes) seemingly functions, however once removing a file, for example test.c, and then replacing it with the exact same file it returns 2 different hash values. By this I mean that whilst the program is running the first calculation might return a hash of 1234, for example, and once deleting and placing the same file within the folder the it then returns 2345.
There seems to be no order, as 1234 could be the result 5 times in a row. I wondered whether there's any strikingly obvious reason in this code?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
#include <openssl/sha.h>
int main (int argc, char *argv[])
{
int fd;
unsigned char c[SHA512_DIGEST_LENGTH];
int i;
SHA512_CTX mdContext;
int bytes;
unsigned char data[1024];
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
char *directory = "/home/joe/Documents/";
char *hashDirectory = "/home/joe/Documents/_Hash/";
char hashInBuf[100];
char hashOutBuf[100];
fd = inotify_init();
if (fd < 0) {
perror("inotify_init");
}
while (1) {
char buff[buf_len];
int no_of_events, count = 0;
//SEARCH FOR NEW FILES WITHIN DIRECTORY
no_of_events = read (fd, buff, buf_len);
while (count < no_of_events) {
struct inotify_event *event = (struct inotify_event *)&buff[count];
if (event->len) {
if ((event->mask & IN_CREATE))
if(!(event->mask & IN_ISDIR)) {
printf("\n%s has been created\n", event->name);
//CONJOIN DIRECTORY AND FILENAME / EXTENSION
snprintf(hashInBuf, sizeof(hashInBuf), "%s/%s", directory, event->name);
snprintf(hashOutBuf, sizeof(hashOutBuf), "%s/%s.txt", hashDirectory, event->name);
FILE *ftest=fopen(hashInBuf, "rb");
FILE *ftest2=fopen(hashOutBuf, "wt");
//HASH FUNCTION
SHA512_Init (&mdContext);
while ((bytes = fread (data, 1, 1024, ftest)) != 0)
SHA512_Update (&mdContext, data, bytes);
SHA512_Final (c,&mdContext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++){
fprintf(ftest2, "%02x", c[i]);
printf("%02x", c[i]);
}
fclose (ftest);
fclose (ftest2);
fflush (stdout);
}
}
count += event_size + event->len;
}
}
return 0;
}
Thank you in advance!
In this line
if ((event->mask & IN_CREATE))
you wait for the event that a file is created. Then, your hashing function immediately starts running!
This may lead to the situation that the file is not fully written yet, so you only hashed a part of the file.
You should use the event IN_CLOSE_WRITE to make sure, that the file has already been completely written.
Another option is to not create the files in this directory, but creating them in a temporary directory and subsequently moving them into the target directory. The corresponding event is IN_MOVED_TO then.

Convert Linux C Char Array to Int

need some advice on this one as im struggling abit and cannot figure it out.
i have a file that gets updated on a PC to indicate a system ran and what time it ran. i am writing a very simple linux console app (will eventually be a nagios plugin). that reads this file and responds depending on what it found within the file.
i am a total newbie to programming on Linux and using C so please be patient and if you would explain any answers it would really be appreciated.
basically i want to convert a char array containing 5 characters into an integer, however the 5th char in the array is always a letter. so technically all i want to-do is convert the first 4 chars in the array to a integer... how?? ive tried multiple ways with no success, my problem is that presently i do not have a good grasp of the language so have no real ideas on what it can and cannot do.
here is the source to my program.
basically the buf array will be holding a string taken from the file that will look something like this
3455Y (the number will be random but always 4 chars long).
Sorry for the poor formatting of the code, but i cannot get this stupid window for love nor money to format it correctly....
include <fcntl.h>
include <unistd.h>
include <stdio.h>
include <stdlib.h>
include <time.h>
include <string.h>
define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
}
else
{
return STATE_OK;
}
time_t ltime; /* calendar time */
struct tm *Tm;
ltime=time(NULL); /* get current cal time */
Tm=localtime(&ltime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d", test);
printf("%d", strtoi(buf));
}
You can use sscanf to do the job:
int num = 0;
sscanf(buf, "%4d", &num);
Then num should hold the number from the line in the file.
You can use atoi
atoi requires one char * argument and returns an int.
If the string is empty, or first character isn't a number or a minus sign, then atoi returns 0.If atoi encounters a non-number character, it returns the number formed up until that point
int num = atoi(buf);
if you want to convert the first four characters of a string to an integer do this:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
uint8_t convertFirstFourChars(char * str, uint32_t *value){
char tmp[5] = {0};
strncpy((char *) tmp, str, 4);
*value = strtoul(tmp);
return errno;
}
then call / test this function like this
#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv){
char test1[5] = "1234A";
char test2[5] = "ABCDE";
uint32_t val = 0;
if(convertFirstFourChars((char *) test1, &val) == 0){
printf("conversion of %s succeeded, value = %ld\n", test1, val);
}
else{
printf("conversion of %s failed!\n", test1);
}
if(convertFirstFourChars((char *) test2, &val) == 0){
printf("conversion succeeded of %s, value = %ld\n", test2, val);
}
else{
printf("conversion of %s failed!\n", test2);
}
return 0;
}
FWIW, don't use atoi(...) because it converts any string to an integer regardless of its validity as a number. atoi("foo") === 0.
this is as much of your code as I was able to recover from the formatting:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
} else {
return STATE_OK;
}
time_t ltime; /* calendar time /
struct tm Tm;
ltime=time(NULL); / get current cal time */
Tm=localtime(&ltime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d", test);
printf("%d", strtoi(buf));
}
this is the version that does what you specified:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
}/* else {
return STATE_OK;
buf[4] = 0;
} */
time_t ltime; /* calendar time */
struct tm *Tm;
ltime=time(NULL); /* get current cal time */
Tm=localtime(&ltime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d\n", test);
printf("%d\n", atoi(buf));
}
The biggest problem with your code was the if statement with the returns in each branch, insuring that nothing after the if statement was ever executed.

Resources