diff -up rsyslog-8.2102.0/plugins/imfile/imfile.c.state-file-leaking rsyslog-8.2102.0/plugins/imfile/imfile.c --- rsyslog-8.2102.0/plugins/imfile/imfile.c.state-file-leaking 2021-01-18 11:21:14.000000000 +0100 +++ rsyslog-8.2102.0/plugins/imfile/imfile.c 2022-03-28 12:51:03.572554843 +0200 @@ -259,6 +259,7 @@ struct modConfData_s { Must be manually reset to 0 if desired. Helper for polling mode. */ + sbool deleteStateOnFileMove; }; static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL;/* modConf ptr to use for run process */ @@ -305,7 +306,8 @@ static struct cnfparamdescr modpdescr[] { "sortfiles", eCmdHdlrBinary, 0 }, { "statefile.directory", eCmdHdlrString, 0 }, { "normalizepath", eCmdHdlrBinary, 0 }, - { "mode", eCmdHdlrGetWord, 0 } + { "mode", eCmdHdlrGetWord, 0 }, + { "deletestateonfilemove", eCmdHdlrBinary, 0 } }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, @@ -545,11 +547,20 @@ static int in_setupWatch(act_obj_t *const act, const int is_file) { int wd = -1; + int flags; if(runModConf->opMode != OPMODE_INOTIFY) goto done; - wd = inotify_add_watch(ino_fd, act->name, - (is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO); + // wd = inotify_add_watch(ino_fd, act->name, + // (is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO); + if(is_file) + flags = IN_MODIFY|IN_DONT_FOLLOW; + else if(runModConf->deleteStateOnFileMove) + flags = IN_CREATE|IN_DELETE|IN_MOVED_TO; + else + flags = IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO; + wd = inotify_add_watch(ino_fd, act->name, flags); + if(wd < 0) { if (errno == EACCES) { /* There is high probability of selinux denial on top-level paths */ DBGPRINTF("imfile: permission denied when adding watch for '%s'\n", act->name); @@ -713,7 +724,7 @@ act_obj_add(fs_edge_t *const edge, const char basename[MAXFNAME]; DEFiRet; int fd = -1; - + DBGPRINTF("act_obj_add: edge %p, name '%s' (source '%s')\n", edge, name, source? source : "---"); for(act = edge->active ; act != NULL ; act = act->next) { if(!strcmp(act->name, name)) { @@ -977,9 +988,18 @@ act_obj_destroy(act_obj_t *const act, co if(act == NULL) return; - DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n", - act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted, - act->in_move); + // DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n", + // act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted, + // act->in_move); + if (runModConf->deleteStateOnFileMove) { + DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d\n", + act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted); + } else { + DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n", + act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, + is_deleted, act->in_move); + } + if(act->is_symlink && is_deleted) { act_obj_t *target_act; for(target_act = act->edge->active ; target_act != NULL ; target_act = target_act->next) { @@ -996,13 +1016,15 @@ act_obj_destroy(act_obj_t *const act, co pollFile(act); /* get any left-over data */ if(inst->bRMStateOnDel) { statefn = getStateFileName(act, statefile, sizeof(statefile)); - getFullStateFileName(statefn, "", toDel, sizeof(toDel)); // TODO: check! + // getFullStateFileName(statefn, "", toDel, sizeof(toDel)); // TODO: check! + getFullStateFileName(statefn, act->file_id, toDel, sizeof(toDel)); // TODO: check! statefn = toDel; } persistStrmState(act); strm.Destruct(&act->pStrm); /* we delete state file after destruct in case strm obj initiated a write */ - if(is_deleted && !act->in_move && inst->bRMStateOnDel) { + // if(is_deleted && !act->in_move && inst->bRMStateOnDel) { + if(is_deleted && inst->bRMStateOnDel && (runModConf->deleteStateOnFileMove || !act->in_move)) { DBGPRINTF("act_obj_destroy: deleting state file %s\n", statefn); unlink((char*)statefn); } @@ -1012,6 +1034,7 @@ act_obj_destroy(act_obj_t *const act, co } #ifdef HAVE_INOTIFY_INIT if(act->wd != -1) { + inotify_rm_watch(ino_fd, act->wd); wdmapDel(act->wd); } #endif @@ -2026,6 +2049,7 @@ CODESTARTbeginCnfLoad loadModConf->timeoutGranularity = 1000; /* default: 1 second */ loadModConf->haveReadTimeouts = 0; /* default: no timeout */ loadModConf->normalizePath = 1; + loadModConf->deleteStateOnFileMove = 0; loadModConf->sortFiles = GLOB_NOSORT; loadModConf->stateFileDirectory = NULL; loadModConf->conf_tree = calloc(sizeof(fs_node_t), 1); @@ -2085,6 +2109,8 @@ CODESTARTsetModCnf loadModConf->stateFileDirectory = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "normalizepath")) { loadModConf->normalizePath = (sbool) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "deletestateonfilemove")) { + loadModConf->deleteStateOnFileMove = (sbool) pvals[i].val.d.n; } else if(!strcmp(modpblk.descr[i].name, "mode")) { if(!es_strconstcmp(pvals[i].val.d.estr, "polling")) loadModConf->opMode = OPMODE_POLLING; @@ -2388,16 +2414,35 @@ in_processEvent(struct inotify_event *ev DBGPRINTF("in_processEvent process Event %x is_file %d, act->name '%s'\n", ev->mask, etry->act->edge->is_file, etry->act->name); - if((ev->mask & IN_MOVED_FROM)) { - flag_in_move(etry->act->edge->node->edges, ev->name); - } - if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO)) { - fs_node_walk(etry->act->edge->node, poll_tree); - } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) { - in_handleFileEvent(ev, etry); // esentially poll_file()! + // if((ev->mask & IN_MOVED_FROM)) { + // flag_in_move(etry->act->edge->node->edges, ev->name); + // } + // if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO)) { + // fs_node_walk(etry->act->edge->node, poll_tree); + // } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) { + // in_handleFileEvent(ev, etry); // esentially poll_file()! + // } else { + // fs_node_walk(etry->act->edge->node, poll_tree); + // } + if(!runModConf->deleteStateOnFileMove) { + if((ev->mask & IN_MOVED_FROM)) { + flag_in_move(etry->act->edge->node->edges, ev->name); + } + if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO)) { + fs_node_walk(etry->act->edge->node, poll_tree); + } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) { + in_handleFileEvent(ev, etry); // esentially poll_file()! + } else { + fs_node_walk(etry->act->edge->node, poll_tree); + } } else { - fs_node_walk(etry->act->edge->node, poll_tree); + if((ev->mask & IN_MODIFY) && etry->act->edge->is_file && !(etry->act->is_symlink)) { + in_handleFileEvent(ev, etry); // esentially poll_file()! + } else { + fs_node_walk(etry->act->edge->node, poll_tree); + } } + done: return; }