⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directory.c++

📁 好东东。linux下面的文件节点、文件状态的变化监听代码
💻 C++
字号:
//  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.//  //  This program is free software; you can redistribute it and/or modify it//  under the terms of version 2 of the GNU General Public License as//  published by the Free Software Foundation.////  This program is distributed in the hope that it would be useful, but//  WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any//  license provided herein, whether implied or otherwise, is limited to//  this program in accordance with the express provisions of the GNU//  General Public License.  Patent licenses, if any, provided herein do not//  apply to combinations of this program with other product or programs, or//  any other product whatsoever.  This program is distributed without any//  warranty that the program is delivered free of the rightful claim of any//  third person by way of infringement or the like.  See the GNU General//  Public License for more details.////  You should have received a copy of the GNU General Public License along//  with this program; if not, write the Free Software Foundation, Inc., 59//  Temple Place - Suite 330, Boston MA 02111-1307, USA.#include "Directory.h"#include <assert.h>#include <errno.h>#include <string.h>#include <stdio.h>#include <sys/dir.h>#include <sys/stat.h>#include <sys/wait.h>#include <unistd.h>#include "Client.h"#include "DirEntry.h"#include "DirectoryScanner.h"#include "Event.h"#include "FileSystem.h"#include "Log.h"#include "Scheduler.h"Directory *Directory::current_dir;Directory::Directory(const char *name, Client *c, Request r, const Cred& cr)    : ClientInterest(name, c, r, cr, DIRECTORY), entries(NULL), unhangPid(-1){    dir_bits() = 0;    if (exported_to_host())    {        dir_bits() = SCANNING;        DirectoryScanner *scanner = new DirectoryScanner(*this,						         Event::Exists, false,						         new_done_handler, this);        if (scanner->done()) {            delete scanner;        } else {	    client()->enqueue_scanner(scanner);        }    }}voidDirectory::new_done_handler(void *closure){    Directory *dir = (Directory *) closure;    dir->dir_bits() &= ~SCANNING;    dir->post_event(Event::EndExist);}Directory::~Directory(){    assert(!(dir_bits() & SCANNING));    if (dir_bits() & RESCAN_SCHEDULED)	Scheduler::remove_onetime_task(scan_task, this);    DirEntry *q, *p = entries;    if (p)    {   (void) chdir();	while (p)	{   q = p->next;	    delete p;	    p = q;	}    }    if (current_dir == this)	chdir_root();}ClientInterest::TypeDirectory::type() const{    assert(!(dir_bits() & SCANNING));    return DIRECTORY;}voidDirectory::resume(){    assert(!(dir_bits() & SCANNING));    ClientInterest::resume();    for (DirEntry *ep = entries; ep; ep = ep->next)	if (ep->needs_scan())	    ep->scan();}Interest *Directory::find_name(const char *name){    assert(!(dir_bits() & SCANNING));    if (name[0] == '/')        // I don't know why this happens, but just in case ...	return this;    else	for (DirEntry *ep = entries; ep; ep = ep->next)	    if (!strcmp(name, ep->name()))		return ep;    return NULL;}//  Directory::do_scan() scans a Directory.  There are several cases.////  If monitoring is suspended, do nothing.////  If the Directory is actually not a directory (e.g., a file, a//  device or nonexistent), then it is lstat'd once, and a Changed,//  Deleted or Created event is written if appropriate.////  If a Directory changes from a directory to something else, then//  all its entries are deleted and Deleted events are sent.////  If it is a real directory, then it is lstat'd repeatedly and read//  repeatedly until it stops changing.  This prevents fam from//  missing files in race conditions (I hope).boolDirectory::do_scan(){    if (!active() || !needs_scan() || (dir_bits() & SCANNING))	return false;     become_user();    bool stat_changed = do_stat();    if (stat_changed && !isdir())   // Seems like a bug to send Changed after	post_event(Event::Changed); // Deleted, but what would fixing it break?    bool scan_entries = filesystem()->dir_entries_scanned();    dir_bits() |= SCANNING;    DirectoryScanner *scanner = new DirectoryScanner(*this, Event::Created,						     scan_entries,						     scan_done_handler,						     this);    if (scanner->done()) {        delete scanner;    } else {	client()->enqueue_scanner(scanner);    }    return stat_changed;}voidDirectory::scan_task(void *closure){    Directory *dir = (Directory *) closure;    dir->dir_bits() &= ~RESCAN_SCHEDULED;    dir->scan();}voidDirectory::scan_done_handler(void *closure){    Directory *dir = (Directory *) closure;    dir->dir_bits() &= ~SCANNING;}boolDirectory::chdir(){    if (current_dir == this)	return true;    int rc = ::chdir(name());    Log::debug("+chdir to \"%s\"", name());    if (rc < 0)    {   Log::info("can't chdir(\"%s\"): %m", name());	if ((errno == EACCES) && (client() != NULL))        {            client()->suggest_insecure_compat(name());        }	return false;    }    current_dir = this;    return true;}boolDirectory::chdir_root(){    int rc = 0;    if (current_dir)    {        rc = ::chdir("/");        Log::debug("-chdir to \"/\"");	current_dir = NULL;    }    return rc == 0;}////  void//  Directory::unhang()////  Description://      This gets called after a system call has failed with oserror()//      set to ETIMEDOUT.  This means that we can't contact the nfs//      server.  In order to reconnect when the server becomes visible//      again, a process has to acually hang on the mount.  We fork and//      exec nfsunhang to do this for us.  We don't care about//      nfsunhang's exit status because we poll nfs mounts anyway.//#if HAVE_SGI_NOHANGvoidDirectory::unhang(){    int status;    if (unhangPid == -1	|| waitpid(unhangPid, &status, WNOHANG) != 0) {	if (access("/usr/lib/nfsunhang", X_OK) == -1) {	    return;	}	unhangPid = fork();	if (unhangPid == 0) {	    for (int fd = getdtablesize() - 1; fd > 2; fd--) {		close(fd);	    }	    execl("/usr/lib/nfsunhang", "nfsunhang", name(), NULL);	    exit(1);	}	Log::debug("unhangPid: %d", unhangPid);    }}#endif // HAVE_SGI_NOHANG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -