C언어 파일 생성/삭제 이벤트 확인
inotify - monitoring filesystem events, inotify 를 이용하여 파일시스템 이벤트를 모니터링하는 프로그램을 만들어보자.
응용 또는 질문은 댓글에 남겨주면 성실하게 답장해주겠다.
이번에도 늘 그렇듯 완성된 동작의 소스코드를 동작한다.
이번 소스코드에서는 생성(IN_CREATE)와 삭제(IN_DELETE)만 사용하였지만 더 많은 event trigger가 존재한다.
inotify의 man page 일부 발췌
IN_ACCESS (+)
File was accessed (e.g., read(2), execve(2)).
IN_ATTRIB (*)
Metadata changed—for example, permissions (e.g., chmod(2)), timestamps (e.g., utimensat(2)), extended attributes
(setxattr(2)), link count (since Linux 2.6.25; e.g., for the target of link(2) and for unlink(2)), and
user/group ID (e.g., chown(2)).
IN_CLOSE_WRITE (+)
File opened for writing was closed.
IN_CLOSE_NOWRITE (*)
File or directory not opened for writing was closed.
IN_CREATE (+)
File/directory created in watched directory (e.g., open(2) O_CREAT, mkdir(2), link(2), symlink(2), bind(2) on a
UNIX domain socket).
IN_DELETE (+)
File/directory deleted from watched directory.
IN_DELETE_SELF
Watched file/directory was itself deleted. (This event also occurs if an object is moved to another filesystem,
since mv(1) in effect copies the file to the other filesystem and then deletes it from the original filesystem.)
In addition, an IN_IGNORED event will subsequently be generated for the watch descriptor.
IN_MODIFY (+)
File was modified (e.g., write(2), truncate(2)).
IN_MOVE_SELF
Watched file/directory was itself moved.
IN_MOVED_FROM (+)
Generated for the directory containing the old filename when a file is renamed.
IN_MOVED_TO (+)
Generated for the directory containing the new filename when a file is renamed.
IN_OPEN (*)
File or directory was opened.
IN_MOVE
Equates to IN_MOVED_FROM | IN_MOVED_TO.
IN_CLOSE
Equates to IN_CLOSE_WRITE | IN_CLOSE_NOWRITE.
The following further bits can be specified in mask when calling inotify_add_watch(2):
IN_DONT_FOLLOW (since Linux 2.6.15)
Dont dereference pathname if it is a symbolic link.
IN_EXCL_UNLINK (since Linux 2.6.36)
By default, when watching events on the children of a directory, events are generated for children even after
they have been unlinked from the directory. This can result in large numbers of uninteresting events for some
applications (e.g., if watching /tmp, in which many applications create temporary files whose names are immedi‐
ately unlinked). Specifying IN_EXCL_UNLINK changes the default behavior, so that events are not generated for
children after they have been unlinked from the watched directory.
IN_MASK_ADD
If a watch instance already exists for the filesystem object corresponding to pathname, add (OR) the events in
mask to the watch mask (instead of replacing the mask).
IN_ONESHOT
Monitor the filesystem object corresponding to pathname for one event, then remove from watch list.
IN_ONLYDIR (since Linux 2.6.15)
Only watch pathname if it is a directory. Using this flag provides an application with a race-free way of
ensuring that the monitored object is a directory.
The following bits may be set in the mask field returned by read(2):
IN_IGNORED
Watch was removed explicitly (inotify_rm_watch(2)) or automatically (file was deleted, or filesystem was unmounted). See also BUGS.
IN_ISDIR
Subject of this event is a directory.
IN_Q_OVERFLOW
Event queue overflowed (wd is -1 for this event).
IN_UNMOUNT
Filesystem containing watched object was unmounted. In addition, an IN_IGNORED event will subsequently be gen‐erated for the watch descriptor.
(*)는 파일 및 디렉토리까지 적용되는 플래그이고, (+)디렉토리 내에 있는 파일을 대상으로하는 플래그다.
그 외에는 additional mask flag인데 딱히 써본적이 없어서 모르겠다.
소스코드
- 이벤트 모니터링 대상을 변경하고 싶으면 PATH_TARGET_DIR 부분을 변경하면 된다.
define 하지 않고 getopt를 통해 인자로 받아도 되고 자유롭게 수정해서 사용하자.
- inotify_add_watch() 3번째 인자에 | 를 통해 event mask 를 추가하면 더욱 다양한 옵션을 사용 가능하다.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/inotify.h>
#define INTY_MAX_EVENTS 1024 /* Max. number of events to process at one go */
#define INTY_LEN_NAME 16 /* Assuming that the length of the filename won't exceed 16 bytes */
#define INTY_EVENT_SIZE (sizeof (struct inotify_event)) /* size of one event */
#define INTY_BUF_SIZE (INTY_MAX_EVENTS * (INTY_EVENT_SIZE + INTY_LEN_NAME)) /* buffer to store the data of events */
#define PATH_TARGET_DIR "/tmp"
int main(int _argc, char *_argv[]) {
int inty_fd, inty_wd;
int inty_length, inty_idx = 0;
char inty_buffer[INTY_BUF_SIZE];
bool is_noty_evt_status = false;
if( (inty_fd = inotify_init()) < 0 ) {
printf("inotify_init() failed : [%02d] %s\n", errno, strerror(errno));
return -1;
}
if( (inty_wd = inotify_add_watch(inty_fd, PATH_TARGET_DIR, IN_CREATE | IN_DELETE)) == -1 ) {
printf("inotify_add_watch() failed [%s] : [%02d] %s \n", PATH_TARGET_DIR, errno, strerror(errno));
return -1;
}
printf("inotify_add_watch() watching : [%s]\n", PATH_TARGET_DIR);
while( true ) {
inty_idx = 0;
if( (inty_length = read(inty_fd, inty_buffer, INTY_BUF_SIZE)) < 0 ) {
printf("read() failed : [%02d] %s\n", errno, strerror(errno));
}
while( inty_idx < inty_length ) {
struct inotify_event *event = (struct inotify_event *)&inty_buffer[inty_idx];
if( event->len ) {
if( event->mask & IN_CREATE || event->mask & IN_DELETE ) {
printf("inotify event status: [%s], file: [%s]\n", (event->mask == 256 ? "create" : "remove"), event->name);
is_noty_evt_status = true;
}
}
inty_idx += INTY_EVENT_SIZE + event->len;
}
}
return 0;
}
컴파일 및 결과
- /tmp 를 타겟으로 이벤트 모니터링 를 실행하였다.
- system에서 생성하고 삭제하는 파일들과 본인이 touch /tmp/a 하여 생성한 파일과 rm /tmp/a하여 삭제한 파일의 이벤트가 catch되는 것을 확인할 수 있다.
muabow@muabow-WorkSpace:~/dev/inotify$ gcc inotify_test.c -o inotify_test ; ./inotify_test
inotify_add_watch() watching : [/tmp]
inotify event status: [create], file: [tmpf5EaiiE]
inotify event status: [remove], file: [tmpf5EaiiE]
inotify event status: [create], file: [sh-thd-1196864159]
inotify event status: [remove], file: [sh-thd-1196864159]
inotify event status: [create], file: [sh-thd-2339961226]
inotify event status: [remove], file: [sh-thd-2339961226]
inotify event status: [create], file: [a]
inotify event status: [remove], file: [a]
inotify event status: [create], file: [tmpfxaiGkH]
inotify event status: [remove], file: [tmpfxaiGkH]
inotify event status: [create], file: [sh-thd-4583039949]
inotify event status: [remove], file: [sh-thd-4583039949]
inotify event status: [create], file: [sh-thd-9513632609]
inotify event status: [remove], file: [sh-thd-9513632609]
inotify event status: [create], file: [aa]
inotify event status: [remove], file: [aa]
끝.
'IT > programming' 카테고리의 다른 글
[PYTHON] nested JSON 변환 / comparing two nested JSON (2) | 2022.01.27 |
---|---|
[PYTHON] 유효한 날짜 포맷 확인 / datetime (1) | 2022.01.27 |
[C/C++] C언어 mmap, msync, munmap 설명 (4) | 2022.01.19 |
[C/C++] C언어 프로그램/함수 실행 시간 측정, us 마이크로초 기준 (4) | 2022.01.18 |
[C/C++] C++ 프로그램/함수 실행 시간 측정, ms 밀리초 기준 (0) | 2022.01.18 |
댓글