iNotify 如何检测移出

iNotify how to detect move-out

您好,我正在使用 iNotify 来检测目录中的更改。我使用的标志是 IN_CLOSE_WRITE | IN_MOVED_FROM | IN_MOVED_TO | IN_CREATE

我试图区分重命名时的 IN_MOVED_FROM 和文件移出文件夹时的 IN_MOVED_FROM

有没有人知道如何检测它是 "moved-out" 还是 "renamed-from-oldfilename"?

谢谢

您需要检查 IN_MOVED_FROM 事件和后续的 IN_MOVED_TO 事件。如果 cookie 相同,则文件已在同一文件夹中重命名。如果您没有收到具有相同 cookie 的 IN_MOVED_TO 事件,则文件已移出监视文件夹。

我应用了@hek2mgl 提到的逻辑,感谢他,它的工作如此重要。这是 js-ctypes 代码:

while (true) {
    let length = ostypes.API('read')(fd, buf, count);

    length = parseInt(cutils.jscGetDeepest(length));

    if (length == -1) {
        throw new Error({
            name: 'os-api-error',
            message: 'Failed to read during poll',
            uniEerrno: ctypes.errno
        });
    } else if (!length==0) {
        // then its > 0 as its not -1
        // something happend, read struct
        let FSChanges = [];
        var i = 0;
        var numElementsRead = 0;

        length = parseInt(cutils.jscGetDeepest(length));
        var _cache_aRenamed_local = {}; // local means per buffer
        do {
            let iHoisted = i;
            numElementsRead++;
            var casted = ctypes.cast(buf.addressOfElement(iHoisted), ostypes.TYPE.inotify_event.ptr).contents;

            var fileName = casted.addressOfField('name').contents.readString();
            var mask = casted.addressOfField('mask').contents;
            var len = casted.addressOfField('len').contents;
            var cookie = cutils.jscGetDeepest(casted.addressOfField('cookie').contents)
            var wd = casted.addressOfField('wd').contents;

            var aEvent = convertFlagsToAEventStr(mask);



            if (aEvent == 'renamed-to') {
                if (cookie in _cache_aRenamed_local) { // assuming that renamed-from must happen before rename-to otherwise its a added
                    if (_cache_aRenamed_local[cookie].aExtra.aOSPath_parentDir_identifier == wd) { // aOSPath_parentDir_identifier is a wd if its different then the current wd then it was added/removed from that watched dir
                        var rezObj = {
                            aFileName: fileName,
                            aEvent: 'renamed',
                            aExtra: {
                                nixInotifyFlags: mask, // i should pass this, as if user did modify the flags, they might want to figure out what exactly changed
                                aOSPath_parentDir_identifier: wd,
                                aOld: {
                                    aFileName: _cache_aRenamed_local[cookie].aFileName,
                                    aExtra: {
                                        nixInotifyFlags: _cache_aRenamed_local[cookie].aExtra.nixInotifyFlags
                                    }
                                }
                            }
                        }
                        FSChanges.push(rezObj);
                    } else {
                        // the one in cache was removed from its parent folder, this one here was added to parent folder. so this is detect as file moved from one watched dir to another watched dir
                        if (_cache_aRenamed_local[cookie].aFileName != fileName) {
                            console.error('whaaaaa wd\'s are differnt and got renamed-to so names should be same');
                            _cache_aRenamed_local[cookie].aEvent = 'haaa names are different?? im just going to say REMOVED as a guess i have never encoutnered this situation yet and i dont think we ever should';
                            FSChanges.push(_cache_aRenamed_local[cookie]);
                        } else {
                            _cache_aRenamed_local[cookie].aEvent = 'removed';
                            FSChanges.push(_cache_aRenamed_local[cookie]);
                        }
                    }
                    delete _cache_aRenamed_local[cookie];
                } else {
                    var rezObj = {
                        aFileName: fileName,
                        aEvent: 'added',
                        aExtra: {
                            aOSPath_parentDir_identifier: wd
                        }
                    }
                    FSChanges.push(rezObj);
                }
            } else if (aEvent == 'renamed-from') {
                var rezObj = {
                    aFileName: fileName,
                    aEvent: aEvent,
                    aExtra: {
                        aOSPath_parentDir_identifier: wd
                    }
                }
                _cache_aRenamed_local[cookie] = rezObj;
            } else {
                var rezObj = {
                    aFileName: fileName,
                    aEvent: aEvent,
                    aExtra: {
                        aOSPath_parentDir_identifier: wd
                    }
                }
                FSChanges.push(rezObj);
            }

            if (len == 0) {
                break;
            };
            i += nixStuff.sizeField0 + nixStuff.sizeField1 + nixStuff.sizeField2 + nixStuff.sizeField3 + parseInt(len);
        } while (i < length);
        for (var cookieLeft in _cache_aRenamed_local) {
            // whatever is left in _cache_aRenamed_local is `removed` things
            _cache_aRenamed_local[cookieLeft].aEvent = 'removed';
            FSChanges.push(rezObj);
        }
        console.error('loop ended:', 'numElementsRead:', numElementsRead);

        if (FSChanges.length > 0) {
            return FSChanges;
        } // else dont return and continue loop
    }
}

我使用此函数将标志转换为类似 renamed-fromrenamed-to

的字符串
function convertFlagsToAEventStr(flags) {
    var default_flags = {
        IN_CLOSE_WRITE: 'contents-modified',
        IN_MOVED_TO: 'renamed-to', // can also be a added
        IN_DELETE: 'removed',
        IN_MOVED_FROM: 'renamed-from', // can also be a removed
        IN_CREATE: 'added'
    };


    for (var f in default_flags) {
        if (flags & ostypes.CONST[f]) {
            return default_flags[f];
        }
    }
    return 'UNKNOWN FLAG';
}