253 lines
4.6 KiB
C
253 lines
4.6 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();
|
|
|
|
/*
|
|
* 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(source_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;
|
|
}
|