2015-04-18 18 views
1

嗨,我使用iNotify來檢測目錄中的更改。我正在使用的標誌是IN_CLOSE_WRITE | IN_MOVED_FROM | IN_MOVED_TO | IN_CREATEiNotify如何檢測移出

我想區分IN_MOVED_FROM重命名時,和IN_MOVED_FROM當一個文件被移出文件夾。

  • 我想在用戶將文件移出時檢查cookie字段是否不爲0。正如我以爲cookie只是爲了重命名程序。但即使我將文件移出目錄,它仍然有一個cookie。
  • 我也儘管檢查IN_MODIFY,因爲我希望那將在那裏重新命名,但不是在移動,但它不存在。

有沒有人有任何想法如何檢測,如果它只是「移出」或它是「從oldfilename」重命名?

感謝

回答

2

您需要檢查的IN_MOVED_FROM事件和隨後IN_MOVED_TO事件。如果cookie相同,則該文件已在同一個文件夾中重命名。如果您沒有收到具有相同Cookie的IN_MOVED_TO事件,則該文件已移至觀看文件夾之外。

+0

感謝@ HEK2!所以,但我的問題是IN_MOVED_TO沒有進入相同的緩衝區,所以當我得到IN_MOVED_FROM時,我應該等待幾毫秒,然後如果沒有IN_MOVED_TO,然後聲明它是一個移動? – Noitidart

+0

基本上重命名文件是一個原子操作,無論它是否發生在同一個文件夾中。我期望'IN_MOVED_TO'緊隨其後。我需要重現這個給你一些可靠的東西。 – hek2mgl

+0

謝謝@ hek2mgl!所以,如果我得到一個'IN_MOVED_TO',我會檢查一下是否有一個具有相同cookie的前一個'IN_MOVED_FROM',如果沒有,那麼我會聲明這個項目已經被移動到了文件夾中。所以這是假設,如果重命名,那麼'IN_MOVED_FROM'總是首先發生。如果首先發生'IN_MOVED_FROM',我不應該立即假定它已經被移出了文件夾,但是如果在同一個cookie之後有一個'IN_MOVED_TO',如果它在同一個緩衝區中,我應該檢查同一個緩衝區,並且在'IN_MOVED_FROM'之後,我可以聲明從那裏移動。只是想在這裏大聲:)Thx! – Noitidart

1

我應用了@ 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'; 
}