/*************************************************************************\
* Copyright (C) Michael Kerrisk, 2015. *
* *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation, either version 3 or (at your option) any *
* later version. This program is distributed without any warranty. See *
* the file COPYING.gpl-v3 for details. *
\*************************************************************************/
/* Supplementary program for Chapter 19 */
/* Known limitations
- Pathnames longer than PATH_MAX are not handled.
*/
#define _GNU_SOURCE
#include <sys/select.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/select.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <ftw.h>
#include <signal.h>
#include <stdarg.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
/* logMessage() flags */
#define VB_BASIC 1 /* Basic messages */
#define VB_NOISY 2 /* Verbose messages */
static int verboseMask;
static int checkCache;
static int dumpCache;
static int readBufferSize = 0;
static char *stopFile;
static int abortOnCacheProblem;
static FILE *logfp = NULL;
static int inotifyReadCnt = 0; /* Counts number of read()s from
inotify file descriptor */
static const int INOTIFY_READ_BUF_LEN =
(100 * (sizeof(struct inotify_event) + NAME_MAX + 1));
static void dumpCacheToLog(void);
/* Something went badly wrong. Create a 'stop' file to signal the
'rand_dtree' processes to stop, dump a copy of the cache to the
log file, and abort. */
__attribute__ ((__noreturn__))
static void
createStopFileAndAbort(void)
{
open(stopFile, O_CREAT | O_RDWR, 0600);
dumpCacheToLog();
abort();
}
/* Write a log message. The message is sent to none, either, or both of
stderr and the log file, depending on 'vb_mask' and whether a log file
has been specified via command-line options . */
static void
logMessage(int vb_mask, const char *format, ...)
{
va_list argList;
/* Write message to stderr if 'vb_mask' is zero, or matches one
of the bits in 'verboseMask' */
if ((vb_mask == 0) || (vb_mask & verboseMask)) {
va_start(argList, format);
vfprintf(stderr, format, argList);
va_end(argList);
}
/* If we have a log file, write the message there */
if (logfp != NULL) {
va_start(argList, format);
vfprintf(logfp, format, argList);
va_end(argList);
}
}
/***********************************************************************/
/* Display some information about an inotify event. (Used when
when we are doing verbose logging.) */
static void
displayInotifyEvent(struct inotify_event *ev)
{
logMessage(VB_NOISY, "==> wd = %d; ", ev->wd);
if (ev->cookie > 0)
logMessage(VB_NOISY, "cookie = %4d; ", ev->cookie);
logMessage(VB_NOISY, "mask = ");
if (ev->mask & IN_ISDIR)
logMessage(VB_NOISY, "IN_ISDIR ");
if (ev->mask & IN_CREATE)
logMessage(VB_NOISY, "IN_CREATE ");
if (ev->mask & IN_DELETE_SELF)
logMessage(VB_NOISY, "IN_DELETE_SELF ");
if (ev->mask & IN_MOVE_SELF)
logMessage(VB_NOISY, "IN_MOVE_SELF ");
if (ev->mask & IN_MOVED_FROM)
logMessage(VB_NOISY, "IN_MOVED_FROM ");
if (ev->mask & IN_MOVED_TO)
logMessage(VB_NOISY, "IN_MOVED_TO ");
if (ev->mask & IN_IGNORED)
logMessage(VB_NOISY, "IN_IGNORED ");
if (ev->mask & IN_Q_OVERFLOW)
logMessage(VB_NOISY, "IN_Q_OVERFLOW ");
if (ev->mask & IN_UNMOUNT)
logMessage(VB_NOISY, "IN_UNMOUNT ");
logMessage(VB_NOISY, "\n");
if (ev->len > 0)
logMessage(VB_NOISY, " name = %s\n", ev->name);
}
/***********************************************************************/
/* Data structures and functions for the watch list cache */
/* We use a very simple data structure for caching watched directory
paths: a dynamically sized array that is searched linearly. Not
efficient, but our main goal is to demonstrate the use of inotify. */
struct watch {
int wd; /* Watch descriptor (-1 if slot unused) */
char path[PATH_MAX]; /* Cached pathname */
};
struct watch *wlCache = NULL; /* Array of cached items */
static int cacheSize = 0; /* Current size of the array */
/* Deallocate the watch cache */
static void
freeCache(void)
{
free(wlCache);
cacheSize = 0;
wlCache = NULL;
}
/* Check that all pathnames in the cache are valid, and refer
to directories */
static void
checkCacheConsistency(void)
{
int failures, j;
struct stat sb;
failures = 0;
for (j = 0; j < cacheSize; j++) {
if (wlCache[j].wd >= 0) {
if (lstat(wlCache[j].path, &sb) == -1) {
logMessage(0,
"checkCacheConsistency: stat: "
"[slot = %d; wd = %d] %s: %s\n",
j, wlCache[j].wd, wlCache[j].path, strerror(errno));
failures++;
} else if (!S_ISDIR(sb.st_mode)) {
logMessage(0, "checkCacheConsistency: %s is not a directory\n",
wlCache[j].path);
exit(EXIT_FAILURE);
}
}
}
if (failures > 0)
logMessage(VB_NOISY, "checkCacheConsistency: %d failures\n",
failures);
}
/* Check whether the cache contains the watch descriptor 'wd'.
If found, return the slot number, otherwise return -1. */
static int
findWatch(int wd)
{
int j;
for (j = 0; j < cacheSize; j++)
if (wlCache[j].wd == wd)
return j;
return -1;
}
/* Find and return the cache slot for the watch descriptor 'wd'.
The caller expects this watch descriptor to exist. If it does not,
there is a problem, which is signaled by the -1 return. */
static int
findWatchChecked(int wd)
{
int slot;
slot = findWatch(wd);
if (slot >= 0)
return slot;
logMessage(0, "Could not find watch %d\n", wd);
/* With multiple renamers there are still rare cases where
the cache is missing entries after a 'Could not find watch'
event. It looks as though this is because of races with nftw(),
since the cache is (occasionally) re-created with fewer
entries than there are objects in the tree(s). Returning
-1 to our caller identifies that there's a problem, and the
caller should probably trigger a cache rebuild. */
if (abortOnCacheProblem) {
createStopFileAndAbort();
} else {
return -1;
}
}
/* Mark a cache entry as unused */
static void
markCacheSlotEmpty(int slot)
{
logMessage(VB_NOISY,
" markCacheSlotEmpty: slot = %d; wd = %d; path = %s\n",
slot, wlCache[slot].wd, wlCache[slot].path);
wlCache[slot].wd = -1;
wlCache[slot].path[0] = '\0';
}
/* Find a free slot in the cache */
static int
findEmptyCacheSlot(void)
{
int j;
const int ALLOC_INCR = 200;
for (j = 0; j < cacheSize; j++)
if (wlCache[j].wd == -1)
return j;
/* No free slot found; resize cache */
cacheSize += ALLOC_INCR;
wlCache = realloc(wlCache, cacheSize * sizeof(struct watch));
if (wlCache == NULL)
errExit("realloc");
for (j = cacheSize - ALLOC_INCR; j < cacheSize; j++)
markCacheSlotEmpty(j);
return cacheSize - ALLOC_INCR; /* Return first slot in
newly allocated space */
}
/* Add an item to the cache */
static int
addWatchTo
没有合适的资源?快使用搜索试试~ 我知道了~
Linux-Unix系统编程手册随书源码
1星 需积分: 9 14 下载量 37 浏览量
2016-08-15
14:31:56
上传
评论
收藏 193KB GZ 举报
温馨提示
共485个文件
c:352个
h:60个
makefile:45个
Linux-Unix系统编程经典书籍Linux-Unix系统编程手册的随书源码
资源推荐
资源详情
资源评论
收起资源包目录
Linux-Unix系统编程手册随书源码 (485个子文件)
COPYING.agpl-v3 34KB
fork_whos_on_first.count.awk 776B
longest_line.awk 74B
BUILDING 5KB
inotify_dtree.c 45KB
acl_update.c 13KB
userns_child_exec.c 11KB
simple_init.c 8KB
rand_dtree.c 6KB
demo_clone.c 6KB
execlp.c 6KB
pthread_barrier_demo.c 5KB
test_tty_functions.c 5KB
inet_sockets.c 5KB
inet_sockets.c 5KB
self_pipe.c 4KB
is_seqnum_sv.c 4KB
ttyname.c 4KB
check_password_caps.c 4KB
daemon_SIGHUP.c 4KB
select_mq.c 4KB
svsem_op.c 4KB
scm_cred_recv.c 4KB
scm_cred_send.c 4KB
i_fcntl_locking.c 4KB
thread_multijoin.c 4KB
acct_v3_view.c 4KB
scm_rights_recv.c 4KB
acl_view.c 4KB
real_timer.c 4KB
dnotify.c 4KB
userns_setns_test.c 4KB
chiflag.c 4KB
t_mount.c 4KB
error_functions.c 4KB
epoll_input.c 4KB
t_stat.c 4KB
is_echo_v2_sv.c 4KB
svmsg_file_server.c 4KB
ptmr_sigev_thread.c 3KB
ns_child_exec.c 3KB
thread_lock_speed.c 3KB
pty_fork.c 3KB
pty_fork.c 3KB
script.c 3KB
mq_notify_sigwaitinfo.c 3KB
multi_SIGCHLD.c 3KB
demo_inotify.c 3KB
catch_rtsigs.c 3KB
utmpx_login.c 3KB
is_echo_sv.c 3KB
multi_pidns.c 3KB
acct_view.c 3KB
svsem_good_init.c 3KB
svshm_create.c 3KB
popen_glob.c 3KB
demo_uts_namespaces.c 3KB
prod_condvar.c 3KB
svsem_create.c 3KB
procfs_user_exe.c 3KB
ns_run.c 3KB
t_clock_nanosleep.c 3KB
demo_sched_fifo.c 3KB
t_clone.c 3KB
seek_io.c 3KB
tty_functions.c 3KB
tty_functions.c 3KB
scm_rights_send.c 3KB
unix_sockets.c 3KB
unix_sockets.c 3KB
t_select.c 3KB
job_mon.c 3KB
svmsg_create.c 3KB
thread_cleanup.c 3KB
is_seqnum_cl.c 3KB
create_pid_file.c 3KB
create_pid_file.c 3KB
nftw_dir_tree.c 3KB
change_case.c 3KB
svmsg_file_client.c 3KB
ignore_pending_sig.c 3KB
fork_sig_sync.c 3KB
rusage_wait.c 3KB
orphaned_pgrp_SIGHUP.c 3KB
unbuffer.c 3KB
svmsg_receive.c 3KB
setenv.c 3KB
system.c 3KB
ptmr_sigev_signal.c 3KB
pipe_ls_wc.c 3KB
file_type_stats.c 3KB
prod_no_condvar.c 3KB
demo_sigio.c 3KB
fifo_seqnum_server.c 3KB
is_seqnum_v2_sv.c 3KB
idshow.c 3KB
poll_pipes.c 3KB
t_sigsuspend.c 3KB
memlock.c 3KB
sig_receiver.c 3KB
共 485 条
- 1
- 2
- 3
- 4
- 5
资源评论
- wafbyy2017-10-10上传者修改了源码的
好来一世为红颜
- 粉丝: 1
- 资源: 26
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功