簡體   English   中英

linux C ++通知文件類型創建

[英]linux C++ notify file type creation

我需要監視Linux中特定文件夾中特定文件類型(具有已知擴展名)的創建。 我了解inotify只會監視現有文件。 我理解正確嗎?

是否有inotify的替代方法(或類似的程序包),可以讓我按文件類型監視文件創建?

編輯:我需要的是通過掩碼監視文件創建。 我需要監視* .json的路徑,而忽略其他文件類型。

這聽起來像是inotify的好用例。 手冊頁上有一個很好的例子,可以輕松地將其轉移到您的問題上。

這是一個小程序,可以像

$ myprog /tmp '*.o' '*.a'

監視目錄/tmp來創建*.o*.a文件。 請注意,對模式進行了引用以防止外殼擴展。 該程序將永遠運行直到被SIGINT中斷(按Ctrl + C )。

我正在使用fnmatch將創建的文件的名稱與模式進行匹配,並為SIGINT安裝設置全局標志的信號處理程序。

#include <assert.h>
#include <errno.h>
#include <fnmatch.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>

我定義了一個小的預處理器宏,以使用GCC的__attribute__擴展名對齊緩沖區。 稍后當我們實際使用此宏時會對此進行更多介紹。

#ifdef __GNUC__
#  define ALIGNAS(TYPE) __attribute__ ((aligned(__alignof__(TYPE))))
#else
#  define ALIGNAS(TYPE) /* empty */
#endif

這是一個全局標志,我們將在信號處理程序中設置該標志,以指示程序應正常退出。

static volatile int interrupted = 0;

這就是信號處理程序本身。

static void
interruption_handler(const int s)
{
  if (s == SIGINT)
    interrupted = 1;
}

該功能是程序的主要功能。

static int
monitor_directory(const char *const directory,
                  const char *const *const patterns,
                  const size_t pattern_count)
{
  int notifyfd = -1;
  int watchfd = -1;
  int ret = 0;
  const char * errmsg = "unknown error";

首先,我們初始化inotify inotify_init將返回一個文件描述符,我們可以從中read()通知。 我使用阻塞的I / O,因此read()會阻塞直到事件發生。

  notifyfd = inotify_init();
  if (notifyfd < 0)
    {
      errmsg = "inotify_init";
      goto catch;
    }

現在我們注冊要觀看的文件。 在我們的例子中,我們要監視一個目錄( directory )以創建新文件( IN_CREATE )。 返回的文件描述符可用於告訴(如果發生事件)其所屬的受監視文件。 但是由於無論如何我們只觀看單個文件(恰好是目錄),因此我們實際上不需要此信息。

  watchfd = inotify_add_watch(notifyfd, directory, IN_CREATE);
  if (watchfd < 0)
    {
      errmsg = "inotify_add_watch";
      goto catch;
    }

現在一切都已正確設置,我們可以從通知文件描述符開始read()了。

  while (1)
    {

事先不知道從inotify描述符讀取的調用將read多少,因此我們必須讀入char緩沖區。 我們希望正確,艱難地進行調整。 有關更多評論,請參見手冊頁。

      char buffer[sizeof(struct inotify_event) + NAME_MAX + 1] ALIGNAS(struct inotify_event);
      const struct inotify_event * event_ptr;

從文件描述符read() 如果我們被打斷,則read()將解除阻塞並返回–1,就像發生錯誤時一樣。

      ssize_t count = read(notifyfd, buffer, sizeof(buffer));
      if (count < 0)
        {
          if (interrupted)
            goto finally;
          errmsg = "read";
          goto catch;
        }

我們有一個新事件,請處理。

      event_ptr = (const struct inotify_event *) buffer;
      assert(event_ptr->wd == watchfd);
      assert(event_ptr->mask & IN_CREATE);
      if (event_ptr->len)
        {
          size_t i;

嘗試根據我們的每個模式匹配文件名。

          for (i = 0; i < pattern_count; ++i)
            {
              switch (fnmatch(patterns[i], event_ptr->name, FNM_PATHNAME))
                {
                case 0:
                  /* Your application logic here... */
                  if (printf("%s\n", event_ptr->name) < 0)
                    {
                      errmsg = "printf";
                      goto catch;
                    }
                  break;
                case FNM_NOMATCH:
                  break;
                default:
                  errmsg = "fnmatch";
                  goto catch;
                }
            }
        }
    }

最后,我們必須進行一些清理。 使用inotify創建的文件描述符的close()會導致其釋放所有關聯的資源。

 finally:
  if (watchfd >= 0)
    {
      int status = close(watchfd);
      watchfd = -1;
      if (status < 0)
        {
          errmsg = "close(watchfd)";
          goto catch;
        }
    }
  if (notifyfd >= 0)
    {
      int status = close(notifyfd);
      notifyfd = -1;
      if (status < 0)
        {
          errmsg = "close(notifyfd)";
          goto catch;
        }
    }
  return ret;
 catch:
  if (errmsg && errno)
    perror(errmsg);
  ret = -1;
  goto finally;
}

這就是我們將所有內容連接在一起並運行程序的方式。

int
main(const int argc, const char *const *const argv)
{
  if (argc < 3)
    {
      fprintf(stderr, "usage: %s DIRECTORY PATTERN...\n", argv[0]);
      return EXIT_FAILURE;
    }
  {
    struct sigaction sa;
    sa.sa_handler = interruption_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
  }
  if (monitor_directory(argv[1], argv + 2, argc - 2) < 0)
    return EXIT_FAILURE;
  return EXIT_SUCCESS;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM