Example #1
0
int main(int argc, char *argv[]) {
    int err, i;
    struct ibc_opts ibc_opts;
    struct inotify_event *evt;
    char buf[BUF_LEN], output[FILEPATH_BUF_SZ];
    const char *fp;

    memset(&ibc, 0, sizeof(struct ibc));
    err = hcreate_r(HTAB_SIZE, &ibc.htab);
    if (err == 0) {
        perror("hcreate_r");
        goto hcreate_error;
    }

    err = parse_opts(&ibc_opts, argc, argv);
    if (err == -1) {
        goto parsing_error;
    }

    for (i = 0; i < argc; i++)
        memset(argv[i], 0, strlen(argv[i]));


    err = ibc.fd = inotify_init();
    if (err == -1) {
        perror("inotify_init");
        goto inotify_init_error;
    }

    err = add_watches(&ibc_opts);
    if (err == -1) {
        goto add_watches_error;
    }

    while(read(ibc.fd, buf, BUF_LEN) > 0) {
        evt = (struct inotify_event *) buf;
        fp = get_inotify_event_path(evt->wd, evt->name);
        if (fp) {
            snprintf(output, FILEPATH_BUF_SZ, "%s/%s", ibc_opts.output_dir,
                    evt->name);
            cp(output, fp);
        }
    }

add_watches_error:
    close(ibc.fd);
inotify_init_error:
    free_opts(&ibc_opts);
parsing_error:
hcreate_error:
    hdestroy_r(&ibc.htab);
    return err;
}
Example #2
0
File: main.c Project: l3ib/fsniper
/* handler for HUP. reloads the config file. */
void handle_hup_signal()
{
    char * error;
    log_write("Received SIGHUP, reloading config file.\n");
    keyval_node_free_all(config);
    config = keyval_parse_file(configfile);
    if ((error = keyval_get_error())) {
        fprintf(stderr, "%s", error);
        free(error);
        exit(1);
    }
    close(ifd);
    free_watchnodes();
    ifd = inotify_init();
    g_watchnode = add_watches(ifd);
}
Example #3
0
File: main.c Project: l3ib/fsniper
int main(int argc, char** argv)
{
    int ifd, len = 0, i = 0, selectret = 0, maxfd, retryselect, pid;
    char buf[BUF_LEN]; 
    char *configdir;
    char *pidfilename;
    char *statusfilename;
    char *statusbin;
    char *error_str;
    char *version_str = PACKAGE_STRING;
    char *pbuf;
    char *filename;
    FILE *pidfile;
    FILE *statusfile;
    fd_set set;
    struct inotify_event *event;
    struct argument *argument = argument_new();
    struct pipe_list *pipe_list_cur;
    struct stat file_stat;
    struct watchnode *node;

    /* alloc pipe list */
    pipe_list_head = malloc(sizeof(struct pipe_list));
    pipe_list_head->next = NULL;

    /* set up signals for exiting/reaping */ 
    signal(SIGINT, &handle_quit_signal); 
    signal(SIGTERM, &handle_quit_signal);
    signal(SIGCHLD, &handle_child_signal);
    signal(SIGHUP, &handle_hup_signal);


    /* add command line arguments */
    argument_register(argument, "help", "Prints this help text.", 0);
    argument_register(argument, "version", "Prints version information.", 0);
    argument_register(argument, "daemon", "Run as a daemon.", 0);
    argument_register(argument, "verbose", "Turns on debug text.", 0);
    argument_register(argument, "sync", "Sync mode (for debugging).", 0);
    argument_register(argument, "log-to-stdout", "Deprecated, use \"--log-to=stdout\" instead", 0);
    argument_register(argument, "log-to", "Log messages with specified way. "
#ifdef USE_SYSLOG
                                "Can be: stdout, file, syslog. \"file\" by default.", 1);
#else
                                "Can be: stdout, file. \"file\" by default.", 1);
#endif

    if ((error_str = argument_parse(argument, argc, argv))) {
	fprintf(stderr, "Error in arguments: %s", error_str);
	free(error_str);
	return -1;
    }

    if (argument_exists(argument, "help")) {
	char *help_txt = argument_get_help_text(argument);
	printf("%s", help_txt);
	free(help_txt);
	return 0;
    }

    if (argument_exists(argument, "version")) {
	printf("%s\n", version_str);
	return 0;
    }

    if (argument_exists(argument, "verbose")) {
	verbose = 1;
    }

    if (argument_exists(argument, "daemon") && fork())
	return 0;

    if (argument_exists(argument, "sync"))
	syncmode = 1;


    if (argument_exists(argument, "log-to-stdout"))
        fprintf(stderr, "Warning, this option is deprecated, " \
                        "please use new syntax: \"--log-to=stdout\".\n");

    logtype = LOG_FILE;
    if (argument_exists(argument, "log-to") && \
        (log_arg = argument_get_value(argument, "log-to")) != NULL)
    {
        if      (strcmp(log_arg, "stdout") == 0)
            logtype = LOG_STDOUT;
#ifdef USE_SYSLOG
        else if (strcmp(log_arg, "syslog") == 0)
            logtype = LOG_SYS;
#endif
        else /* logtype already set to 'file' above */
            fprintf(stderr, "Warning, selected unknown logging type. " \
                            "Will use \"--log-to=file\" instead.\n");
    }

    /* get config dir (must free this) */
    configdir = get_config_dir();	

    /* if a config file has not been specified, use default */
    if (argument_get_extra(argument))
    {
	configfile = strdup(argument_get_extra(argument));
    }
    else
    {
	configfile = malloc (strlen(configdir) + strlen ("/config") + 1);
	sprintf(configfile, "%s/config", configdir);
    }

    argument_free(argument);
    free(configdir);

    if (access(configfile, R_OK) != 0)
    {
	fprintf(stderr, "error: could not open config file: %s\n", configfile);
	return -1;
    }

    /* create a pid file */
    pidfilename = get_pid_filename();
	
    if (stat(pidfilename, &file_stat) == 0) /* pidfile exists */
    {
	pidfile = fopen(pidfilename, "r");
		
	if (fscanf(pidfile, "%d", &pid) == 1) /* pidfile has a pid inside */
	{
	    char *binaryname;
	    char *scanformat; 
	    if ((binaryname = strrchr(argv[0], '/')) != NULL)
	    {
		binaryname++;
	    }
	    else
	    {
		binaryname = argv[0];
	    }

	    scanformat = malloc(strlen("Name:   %") + strlen(binaryname) + strlen("s") + 1);
	    statusfilename = malloc(strlen("/proc/") + 6 + strlen("/status") + 1);
	    sprintf(statusfilename, "/proc/%d/status", pid);

	    if (stat(statusfilename, &file_stat) != 0) /* write pid file if the process no longer exists */
	    {
		write_pid_file(pidfilename);
	    }
	    else /* process exists, so check owner and binary name */
	    {
		statusfile = fopen(statusfilename, "r");
		statusbin = malloc(strlen(binaryname) + 2); /* the binary name may start with "fsniper" but be longer */
		sprintf(scanformat, "Name:   %%%ds", strlen(binaryname) + 1);
		fscanf(statusfile, scanformat, statusbin);
		free(statusfilename);
		fclose(statusfile);
		fclose(pidfile);
				
		if (strcmp(binaryname, statusbin) == 0 && file_stat.st_uid == getuid())
		    /* exit if the process is fsniper and is owned by the current user */
		{
		    printf("%s: already running instance found with pid %d. exiting.\n", binaryname, pid);
		    exit(1);
		}
		else /* the pid file contains an old pid, one that isn't fsniper, or one not owned by the current user */
		{
		    write_pid_file(pidfilename);
		}
	    }
	}
	else /* pidfile is invalid */
	{
	    fclose(pidfile);
	    write_pid_file(pidfilename);
	}
    }
    else /* the pidfile doesn't exist */
    {
	write_pid_file(pidfilename);
    }
    free(pidfilename);

    /* start up log */
    if (!log_open())
    {
	fprintf(stderr, "Error: could not start log.\n");
	return -1;
    }

    ifd = inotify_init();
    if (ifd < 0)
    {
	perror("inotify_init");
	return -1;
    }

    if (verbose) log_write("Parsing config file: %s\n", configfile);
    config = keyval_parse_file(configfile);

    if ((error_str = keyval_get_error())) {
        fprintf(stderr, "%s", error_str);
        free(error_str);
        exit(1);
    }

    validate_config(config);

    /* add nodes to the inotify descriptor */
    g_watchnode = add_watches(ifd);

    /* wait for events and then handle them */
    while (1)
    {		
	/* set up fds and max */
	FD_ZERO(&set);
	FD_SET(ifd, &set);
	maxfd = ifd;
	for (pipe_list_cur = pipe_list_head->next; pipe_list_cur; pipe_list_cur = pipe_list_cur->next)
	{
	    FD_SET(pipe_list_cur->pfd[0], &set);
	    if (pipe_list_cur->pfd[0] > maxfd)
		maxfd = pipe_list_cur->pfd[0];
	}

	retryselect = 1;
	while (retryselect)
	{
	    /* use select to get activity on any of the fds */
	    selectret = select(maxfd + 1, &set, NULL, NULL, NULL);

	    if (selectret == -1)
	    {
		if (errno == EINTR)
		    retryselect = 1;
		else
		    handle_quit_signal(-2);
	    } else
		retryselect = 0;
	}
		
	/* handle any events on the inotify fd */
	if (FD_ISSET(ifd, &set))
	{
	    len = read(ifd, buf, BUF_LEN);
	    while (i < len)
	    {
		event = (struct inotify_event *) &buf[i];
		if (event->len && (event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO))
		{
		    /* if sync mode, just call handle_exec */
		    if (syncmode == 1)
		    {
			handle_event(event, fileno(_logfd));
		    }
		    else
		    {
			/* create new pipe_list entry */
			for (pipe_list_cur = pipe_list_head; pipe_list_cur->next != NULL; pipe_list_cur = pipe_list_cur->next) {}

			pipe_list_cur->next = malloc(sizeof(struct pipe_list));
			pipe_list_cur->next->next = NULL;

			/* create pipe */
			pipe(pipe_list_cur->next->pfd);

			if (fork() == 0) 
			{
			    /* child, close 0 */
			    close(pipe_list_cur->next->pfd[0]);					
			    log_close();
			    signal(SIGINT, &handle_child_quit_signal);
			    signal(SIGTERM, &handle_child_quit_signal);
			    handle_event(event, pipe_list_cur->next->pfd[1]);
			} else {
			    /* parent, close 1 */
			    close(pipe_list_cur->next->pfd[1]);
			}
		    }
		}
                else if (event->len && (event->mask & IN_CREATE && event->mask & IN_ISDIR))
                {
                    for (node = g_watchnode->next; node; node = node->next)
                        if (node->wd == event->wd)
                            break;

                    if (node)
                    {
                        /* combine the name inotify gives with the full path to the file */
                        filename = malloc(strlen(node->path) + strlen("/") + strlen(event->name) + 1);
                        sprintf(filename, "%s/%s", node->path, event->name);
                        watch_dir(node, ifd, strdup(filename), node->section);
                        free(filename);
                    }
                }
		else if (event->len && (event->mask & IN_DELETE && event->mask & IN_ISDIR))
                {
                    for (node = g_watchnode->next; node; node = node->next)
                        if (node->wd == event->wd)
                            break;

                    if (node)
                    {
                        /* combine the name inotify gives with the full path to the file */
                        filename = malloc(strlen(node->path) + strlen("/") + strlen(event->name) + 1);
                        sprintf(filename, "%s/%s", node->path, event->name);
                        unwatch_dir(filename, ifd);
                        free(filename);
                    }
                }
                i += EVENT_SIZE + event->len;
            }
	    i = 0;
	}
		
	/* now lets see if we have any pipe activity */
	pipe_list_cur = pipe_list_head->next;
	while (pipe_list_cur)
	{
	    if (FD_ISSET(pipe_list_cur->pfd[0], &set))
	    {
		len = read(pipe_list_cur->pfd[0], buf, BUF_LEN);
		if (len == 0)
		{
		    close(pipe_list_cur->pfd[0]);
		    /* remove this item from the list */
		    pipe_list_cur = pipe_list_remove(pipe_list_head, pipe_list_cur);
					
		} else {
		    /* print it somewhere */
		    pbuf = malloc(len + 1);
		    snprintf(pbuf, len, "%s", buf);
		    log_write("%s\n", pbuf);
		    free(pbuf);
		    pipe_list_cur = pipe_list_cur->next;
		}
	    } else {
		pipe_list_cur = pipe_list_cur->next;

	    }


	}
    }
}
Example #4
0
/* Main routine*/
int main( int argc, char **argv ) 
{
  int length, i = 0;
  int fd;
  char buffer[BUF_LEN], root[MAX_LEN];


  /*Check for supplied path to monitor*/
  switch(argc)
    {
    case 1: printf("No directory specified. Will monitor the entire filesystem...\n\n");
      strcpy(root,"/");
      break;
      
    case 2: strcpy(root,argv[1]);
      if(root[strlen(root)-1]!='/')
	strcat(root,"/");
      puts(root);

      break;
      
    default: printf("Ignoring all other arguments after the first\n");
    }
  

  /* Set up logger*/
  fp_log = fopen("inotify_logger.log","a");
  if (fp_log == NULL)
    {
      printf("Error opening logger. All output will be redirected to the stdout\n");
      fp_log = stdout;
    }

  fd = inotify_init();
  if ( fd < 0 ) {
    perror( "Couldn't initialize inotify");
  }

  /* Read the sub-directories at one level under argv[1] 
   * and monitor them for access */
  add_watches(fd,root);
  
  /* do it forever*/
  while(1)
    {
      i = 0;
      length = read( fd, buffer, BUF_LEN );  

      if ( length < 0 ) {
	perror( "read" );
      }  

      /* Read the events*/
      while ( i < length ) {
	struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
	if ( event->len ) {
	  if ( event->mask & IN_CREATE) {
	    if (event->mask & IN_ISDIR)
	      fprintf(fp_log,"%d DIR::%s CREATED\n", event->wd,event->name );       
	    else
	      fprintf(fp_log, "%d FILE::%s CREATED\n", event->wd, event->name);       
	  }
	  
	  if ( event->mask & IN_MODIFY) {
	    if (event->mask & IN_ISDIR)
	      fprintf(fp_log,"%d DIR::%s MODIFIED\n", event->wd,event->name );       
	    else
	      fprintf(fp_log,"%d FILE::%s MODIFIED\n", event->wd,event->name );       

	  }
	  
	  if ( event->mask & IN_DELETE) {
	    if (event->mask & IN_ISDIR)
	      fprintf(fp_log,"%d DIR::%s DELETED\n", event->wd,event->name );       
	    else
	      fprintf(fp_log,"%d FILE::%s DELETED\n", event->wd,event->name );       
	  }  

	  i += EVENT_SIZE + event->len;
	}
      }
    }
  /* Clean up*/
  ( void ) close( fd );
  
  return 0;
}