freemind-mindgen/watcher.c

253 lines
4.7 KiB
C

#include <sys/types.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define POLL_TIME_SEC 60
/*
* Prints the usage string
*/
void usage(const char* _name);
/*
* Checks if the filepath is a directory or not
*
* Returns -1 on error; 0 on false; 1 on true
*/
int is_dir(const char* _filepath);
/*
* Executes the generation command
*
* Returns -1 on error;
*/
int execute_mindgen(const char* _dest_dir, const char* _filename, const char* _source_dir);
/*
* Executes the deletion command
*
* Returns -1 on error;
*/
int execute_delete(const char* _dir, const char* _filename);
int main(int argc, char** argv)
{
int notify_fd;
int watch_fd;
int error;
bool deleted;
unsigned int buffer_size;
char* buffer;
int offset;
// [name] [watch dir] [destination dir]
if (argc < 3)
{
usage(argv[0]);
return 1;
}
// Check dirs and permissions
if (1 != is_dir(argv[1]))
{
usage(argv[0]);
printf("Watch directory is not a folder, does not exist or there are not sufficient permissions.\n");
}
if (1 != is_dir(argv[2]))
{
usage(argv[0]);
printf("Destination directory is not a folder, does not exist or there are not sufficient permissions.\n");
}
// inotify init
notify_fd = inotify_init();
if (notify_fd < 0)
{
printf("BAD NOTIFY FD\n");
return -1;
}
// inotify add watch
watch_fd = inotify_add_watch(notify_fd, argv[1], IN_DELETE | IN_DELETE_SELF | IN_CLOSE_WRITE);
if (watch_fd < 0)
{
printf("BAD WATCH FD\n");
close(notify_fd);
return -1;
}
deleted = false;
while (!deleted)
{
// wait for event
buffer_size = 0;
while (0 == buffer_size)
{
sleep(POLL_TIME_SEC);
error = ioctl(notify_fd, FIONREAD, &buffer_size);
if (0 != error)
{
printf("BAD IOCTL\n");
return -1;
}
}
// Create big enough buffer and read all data
buffer = (char*)malloc(buffer_size);
error = read(notify_fd, buffer, buffer_size);
if (error != buffer_size)
{
printf("BAD BUFFER SIZE\n");
free(buffer);
close(notify_fd);
return -1;
}
// Read and process all events
offset = 0;
while (offset < buffer_size)
{
struct inotify_event* event = (struct inotify_event*)(buffer + offset);
// on create/modify - mindgen
if (0 != (event->mask & IN_CLOSE_WRITE))
{
//printf("FILE WRITTEN TO: %s\n", event->name);
execute_mindgen(argv[2], event->name, argv[1]);
}
// on delete - rm
if (0 != (event->mask & IN_DELETE))
{
//printf("DELETE: %s\n", event->name);
execute_delete(argv[2], event->name);
}
// on delete_self - exit
if (0 != (event->mask & IN_DELETE_SELF))
{
printf("Watched folder deleted. Stopping.\n");
deleted = true;
}
offset += sizeof(struct inotify_event) + event->len;
}
free(buffer);
buffer = NULL;
}
return 0;
}
void
usage(const char* name)
{
if (NULL == name)
{
return;
}
printf("%s watch_dir dest_dir\n", name);
}
int
is_dir(const char* filepath)
{
int result;
struct stat file_stat;
if (NULL == filepath)
{
return -1;
}
result = stat(filepath, &file_stat);
if (0 == result)
{
if (S_ISDIR(file_stat.st_mode))
{
result = 1;
}
}
return result;
}
int execute_mindgen(const char* dest_dir, const char* filename, const char* source_dir)
{
int pid;
int child_status;
char source_fullname[strlen(source_dir) + strlen(filename) + 2];
char dest_fullname[strlen(dest_dir) + strlen(filename) + 7];
char* arglist[4];
pid = fork();
if (pid < 0)
{
printf("Error trying to generate html.\n");
return -1;
}
if (0 == pid)
{
strcpy(source_fullname, source_dir);
strcat(source_fullname, "/");
strcat(source_fullname, filename);
strcpy(dest_fullname, dest_dir);
strcat(dest_fullname, "/");
strcat(dest_fullname, filename);
strcat(dest_fullname, ".html");
arglist[0] = "mindgen";
arglist[1] = source_fullname;
arglist[2] = dest_fullname;
arglist[3] = NULL;
//printf("%s %s %s\n", arglist[0], arglist[1], arglist[2]);
execv("./mindgen", arglist);
printf("Error generating html.\n");
return -1;
}
wait(&child_status);
return 0;
}
int execute_delete(const char* dir, const char* filename)
{
int pid;
int child_status;
char fullname[strlen(dir) + strlen(filename) + 7];
char* arglist[3];
pid = fork();
if (pid < 0)
{
printf("Error trying to delete.\n");
return -1;
}
if (0 == pid)
{
strcpy(fullname, dir);
strcat(fullname, "/");
strcat(fullname, filename);
strcat(fullname, ".html");
arglist[0] = "rm";
arglist[1] = fullname;
arglist[2] = NULL;
//printf("%s %s\n", arglist[0], arglist[1]);
execv("/bin/rm", arglist);
printf("Error deleting.\n");
return -1;
}
wait(&child_status);
return 0;
}