From 11871830c5e904fd0bfa1706cccb3c481ca1da45 Mon Sep 17 00:00:00 2001 From: randomdan Date: Wed, 23 Feb 2011 00:30:48 +0000 Subject: Minor tidy up to address extra picky GCC warnings Explicit early unlocking of session after variables have been copied out so that the session isn't locked during IO --- netfs/Jamfile.jam | 19 +++++++++-------- netfs/daemon.cpp | 32 ++++++++++++++++++++++++---- netfs/daemon.h | 13 ++++++++---- netfs/daemonDirs.cpp | 22 ++++++++++++------- netfs/daemonFiles.cpp | 34 ++++++++++++++++++------------ netfs/daemonMisc.cpp | 56 +++++++++++++++++++++++++++++++++---------------- netfs/daemonService.cpp | 2 +- netfs/daemonSystem.cpp | 6 ++++-- netfs/fuse.cpp | 2 +- netfs/fuseDirs.cpp | 3 ++- netfs/fuseFiles.cpp | 5 +++-- netfs/fuseapp.cpp | 4 ++-- 12 files changed, 133 insertions(+), 65 deletions(-) diff --git a/netfs/Jamfile.jam b/netfs/Jamfile.jam index f9939e0..83a86cb 100644 --- a/netfs/Jamfile.jam +++ b/netfs/Jamfile.jam @@ -1,8 +1,8 @@ import package ; -alias libxmlpp : : : : - "`pkg-config --cflags libxml++-2.6`" - "`pkg-config --libs libxml++-2.6`" ; +alias libxml2 : : : : + "`pkg-config --cflags libxml-2.0`" + "`pkg-config --libs libxml-2.0`" ; lib boost_regex : : boost_regex ; lib boost_filesystem : : boost_filesystem ; @@ -11,44 +11,45 @@ lib boost_thread : : boost_thread ; lib Ice : : Ice ; lib fuse : : fuse ; -alias static_misc : ../libmisc//misc : static ; - lib netfsComms : netfsComms.ice : ; lib netfsCommon : - entCache.cpp : + entCache.cpp ../libmisc/xml.cpp : _FILE_OFFSET_BITS=64 + ../libmisc + libxml2 netfsComms - static_misc ; exe netfs : [ glob fuse*.cpp ] : _FILE_OFFSET_BITS=64 + ../libmisc netfsComms - static_misc netfsComms netfsCommon boost_thread fuse Ice + libxml2 ; lib netfsd : [ glob daemon*.cpp ] : _FILE_OFFSET_BITS=64 + ../libmisc netfsComms - static_misc netfsComms netfsCommon boost_random boost_thread boost_filesystem Ice + libxml2 ; explicit install ; diff --git a/netfs/daemon.cpp b/netfs/daemon.cpp index 3c8fdcc..cd30b18 100644 --- a/netfs/daemon.cpp +++ b/netfs/daemon.cpp @@ -39,7 +39,7 @@ NetFSDaemon::stop() extern "C" { IceBox::Service * - createNetFSDaemon(Ice::CommunicatorPtr communicator) + createNetFSDaemon(Ice::CommunicatorPtr) { return new NetFSDaemon(); } @@ -97,14 +97,38 @@ DaemonGlobalState::Session::~Session() { } -SessionPtr::SessionPtr(boost::intrusive_ptr s) : +SessionPtr::SessionPtr(boost::intrusive_ptr s, bool lock) : ptr(s), - lg(s->lock) + doUnlock(lock) { + if (lock) { + ptr->lock.lock(); + } +} + +SessionPtr::~SessionPtr() +{ + if (doUnlock) { + ptr->lock.unlock(); + } +} + +void +SessionPtr::lock() const +{ + ptr->lock.lock(); + doUnlock = true; +} + +void +SessionPtr::unlock() const +{ + ptr->lock.unlock(); + doUnlock = false; } DaemonGlobalState::Session * -SessionPtr::operator->() +SessionPtr::operator->() const { return ptr.get(); } diff --git a/netfs/daemon.h b/netfs/daemon.h index f3499c0..1f4fc64 100644 --- a/netfs/daemon.h +++ b/netfs/daemon.h @@ -55,11 +55,16 @@ class NetFSDaemon : public IceBox::Service { class SessionPtr { public: - SessionPtr(boost::intrusive_ptr ptr); - DaemonGlobalState::Session * operator->(); + SessionPtr(boost::intrusive_ptr ptr, bool lock); + ~SessionPtr(); + + DaemonGlobalState::Session * operator->() const; + + void lock() const; + void unlock() const; private: - boost::intrusive_ptr ptr; - boost::lock_guard lg; + const boost::intrusive_ptr ptr; + mutable bool doUnlock; }; class TempPrivs { diff --git a/netfs/daemonDirs.cpp b/netfs/daemonDirs.cpp index 01d976b..3d2cd3f 100644 --- a/netfs/daemonDirs.cpp +++ b/netfs/daemonDirs.cpp @@ -8,10 +8,12 @@ Ice::Int FileSystemServer::opendir(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - DIR * od = ::opendir((sess->exportCfg->root / path).string().c_str()); + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + DIR * od = ::opendir(p.string().c_str()); if (!od) { throw NetFSComms::SystemError(errno); } @@ -22,7 +24,7 @@ FileSystemServer::opendir(const NetFSComms::ReqEnv & re, const std::string & pat void FileSystemServer::closedir(Ice::Long tok, Ice::Int id, const Ice::Current&) { - SessionPtr sess(dgs->getSession(tok)); + SessionPtr sess(dgs->getSession(tok), false); try { errno = 0; if (::closedir(sess->dirs.get(id)) != 0) { @@ -39,7 +41,7 @@ FileSystemServer::closedir(Ice::Long tok, Ice::Int id, const Ice::Current&) NetFSComms::NameList FileSystemServer::readdir(Ice::Long tok, Ice::Int id, const Ice::Current&) { - SessionPtr sess(dgs->getSession(tok)); + SessionPtr sess(dgs->getSession(tok), false); try { errno = 0; dirent * d; @@ -61,10 +63,12 @@ FileSystemServer::readdir(Ice::Long tok, Ice::Int id, const Ice::Current&) void FileSystemServer::mkdir(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::mkdir((sess->exportCfg->root / path).string().c_str(), mode) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::mkdir(p.string().c_str(), mode) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -73,10 +77,12 @@ FileSystemServer::mkdir(const NetFSComms::ReqEnv & re, const std::string & path, void FileSystemServer::rmdir(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::rmdir((sess->exportCfg->root / path).string().c_str()) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::rmdir(p.string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; diff --git a/netfs/daemonFiles.cpp b/netfs/daemonFiles.cpp index 2686f20..c78be9b 100644 --- a/netfs/daemonFiles.cpp +++ b/netfs/daemonFiles.cpp @@ -7,10 +7,12 @@ void FileSystemServer::truncate(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Long size, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::truncate((sess->exportCfg->root / path).string().c_str(), size) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::truncate(p.string().c_str(), size) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -19,7 +21,7 @@ FileSystemServer::truncate(const NetFSComms::ReqEnv & re, const std::string & pa void FileSystemServer::ftruncate(const NetFSComms::ReqEnv & re, Ice::Int id, Ice::Long size, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), false); TempPrivs tp(re, &uentries, &gentries); try { errno = 0; @@ -36,7 +38,7 @@ FileSystemServer::ftruncate(const NetFSComms::ReqEnv & re, Ice::Int id, Ice::Lon NetFSComms::Attr FileSystemServer::fgetattr(const NetFSComms::ReqEnv & re, Ice::Int id, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), false); TempPrivs tp(re, &uentries, &gentries); try { struct stat s; @@ -67,10 +69,12 @@ FileSystemServer::fgetattr(const NetFSComms::ReqEnv & re, Ice::Int id, const Ice void FileSystemServer::unlink(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::unlink((sess->exportCfg->root / path).string().c_str()) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::unlink(p.string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -79,10 +83,12 @@ FileSystemServer::unlink(const NetFSComms::ReqEnv & re, const std::string & path Ice::Int FileSystemServer::open(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int flags, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - int fd = ::open((sess->exportCfg->root / path).string().c_str(), flags); + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + int fd = ::open(p.string().c_str(), flags); if (fd == -1) { throw NetFSComms::SystemError(errno); } @@ -93,10 +99,12 @@ FileSystemServer::open(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int FileSystemServer::create(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int flags, Ice::Int mode, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - int fd = ::open((sess->exportCfg->root / path).string().c_str(), O_CREAT | flags, mode); + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + int fd = ::open(p.string().c_str(), O_CREAT | flags, mode); if (fd == -1) { throw NetFSComms::SystemError(errno); } @@ -107,7 +115,7 @@ FileSystemServer::create(const NetFSComms::ReqEnv & re, const std::string & path void FileSystemServer::close(Ice::Long tok, Ice::Int id, const Ice::Current&) { - SessionPtr sess(dgs->getSession(tok)); + SessionPtr sess(dgs->getSession(tok), false); try { errno = 0; if (::close(sess->files.get(id)) != 0) { @@ -124,7 +132,7 @@ FileSystemServer::close(Ice::Long tok, Ice::Int id, const Ice::Current&) NetFSComms::Buffer FileSystemServer::read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const Ice::Current&) { - SessionPtr sess(dgs->getSession(tok)); + SessionPtr sess(dgs->getSession(tok), false); try { NetFSComms::Buffer buf; buf.resize(size); @@ -146,7 +154,7 @@ FileSystemServer::read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long s void FileSystemServer::write(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const NetFSComms::Buffer & data, const Ice::Current&) { - SessionPtr sess(dgs->getSession(tok)); + SessionPtr sess(dgs->getSession(tok), false); try { errno = 0; if (pwrite(sess->files.get(id), &data[0], size, offset) != size) { diff --git a/netfs/daemonMisc.cpp b/netfs/daemonMisc.cpp index 37c38c5..9b76d8e 100644 --- a/netfs/daemonMisc.cpp +++ b/netfs/daemonMisc.cpp @@ -11,18 +11,22 @@ extern std::map files; Ice::Int FileSystemServer::access(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); - return ::access((sess->exportCfg->root / path).string().c_str(), mode); + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + return ::access(p.string().c_str(), mode); } NetFSComms::Attr FileSystemServer::getattr(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); struct stat s; - if (::lstat((sess->exportCfg->root / path).string().c_str(), &s) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::lstat(p.string().c_str(), &s) != 0) { throw NetFSComms::SystemError(errno); } NetFSComms::Attr a; @@ -45,10 +49,12 @@ FileSystemServer::getattr(const NetFSComms::ReqEnv & re, const std::string & pat void FileSystemServer::symlink(const NetFSComms::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::symlink(path1.c_str(), (sess->exportCfg->root / path2).string().c_str()) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path2; + sess.unlock(); + if (::symlink(path1.c_str(), p.string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -57,10 +63,13 @@ FileSystemServer::symlink(const NetFSComms::ReqEnv & re, const std::string & pat void FileSystemServer::link(const NetFSComms::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::link((sess->exportCfg->root / path1).string().c_str(), (sess->exportCfg->root / path2).string().c_str()) != 0) { + boost::filesystem::path p1 = sess->exportCfg->root / path1; + boost::filesystem::path p2 = sess->exportCfg->root / path2; + sess.unlock(); + if (::link(p1.string().c_str(), p2.string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -69,10 +78,13 @@ FileSystemServer::link(const NetFSComms::ReqEnv & re, const std::string & path1, void FileSystemServer::rename(const NetFSComms::ReqEnv & re, const std::string & from, const std::string & to, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::rename((sess->exportCfg->root / from).string().c_str(), (sess->exportCfg->root / to).string().c_str()) != 0) { + boost::filesystem::path f = sess->exportCfg->root / from; + boost::filesystem::path t = sess->exportCfg->root / to; + sess.unlock(); + if (::rename(f.string().c_str(), t.string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -81,11 +93,13 @@ FileSystemServer::rename(const NetFSComms::ReqEnv & re, const std::string & from std::string FileSystemServer::readlink(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; char buf[PATH_MAX]; - ssize_t rc = ::readlink((sess->exportCfg->root / path).string().c_str(), buf, PATH_MAX); + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + ssize_t rc = ::readlink(p.string().c_str(), buf, PATH_MAX); if (rc == -1) { throw NetFSComms::SystemError(errno); } @@ -95,10 +109,12 @@ FileSystemServer::readlink(const NetFSComms::ReqEnv & re, const std::string & pa void FileSystemServer::chmod(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::chmod((sess->exportCfg->root / path).string().c_str(), mode) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::chmod(p.string().c_str(), mode) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -107,10 +123,12 @@ FileSystemServer::chmod(const NetFSComms::ReqEnv & re, const std::string & path, void FileSystemServer::chown(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int uid, Ice::Int gid, const Ice::Current &) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; - if (::chown((sess->exportCfg->root / path).string().c_str(), uid, gid) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::chown(p.string().c_str(), uid, gid) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; @@ -120,7 +138,7 @@ void FileSystemServer::utimens(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Long s0, Ice::Long ns0, Ice::Long s1, Ice::Long ns1, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; struct timespec times[2]; @@ -128,7 +146,9 @@ FileSystemServer::utimens(const NetFSComms::ReqEnv & re, const std::string & pat times[0].tv_nsec = ns0; times[1].tv_sec = s1; times[1].tv_nsec = ns1; - if (::utimensat(0, (sess->exportCfg->root / path).string().c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::utimensat(0, p.string().c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; diff --git a/netfs/daemonService.cpp b/netfs/daemonService.cpp index 04ff9da..0daf992 100644 --- a/netfs/daemonService.cpp +++ b/netfs/daemonService.cpp @@ -7,7 +7,7 @@ ServiceServer::ServiceServer(int16_t hs, DaemonGlobalStatePtr dgs) : } Ice::Long -ServiceServer::connect(const std::string & share, const std::string & auth, const Ice::Current &) +ServiceServer::connect(const std::string & share, const std::string &, const Ice::Current &) { DaemonGlobalState::NSP s = dgs->newSession(hostseed, share); return s.get<0>(); diff --git a/netfs/daemonSystem.cpp b/netfs/daemonSystem.cpp index 2fcba7f..0e89e51 100644 --- a/netfs/daemonSystem.cpp +++ b/netfs/daemonSystem.cpp @@ -6,11 +6,13 @@ NetFSComms::VFS FileSystemServer::statfs(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { - SessionPtr sess(dgs->getSession(re.tok)); + SessionPtr sess(dgs->getSession(re.tok), true); TempPrivs tp(re, &uentries, &gentries); errno = 0; struct statvfs s; - if (::statvfs((sess->exportCfg->root / path).string().c_str(), &s) != 0) { + boost::filesystem::path p = sess->exportCfg->root / path; + sess.unlock(); + if (::statvfs(p.string().c_str(), &s) != 0) { throw NetFSComms::SystemError(errno); } NetFSComms::VFS t; diff --git a/netfs/fuse.cpp b/netfs/fuse.cpp index d5943e3..7a1e141 100644 --- a/netfs/fuse.cpp +++ b/netfs/fuse.cpp @@ -37,7 +37,7 @@ NetFS::init(struct fuse_conn_info *) } int -NetFS::opt_parse(void *, const char * arg, int key, struct fuse_args *) +NetFS::opt_parse(void *, const char * arg, int, struct fuse_args *) { if (strncmp(arg, "--Ice.", 6) == 0) { return 0; diff --git a/netfs/fuseDirs.cpp b/netfs/fuseDirs.cpp index b75ab5c..3f80331 100644 --- a/netfs/fuseDirs.cpp +++ b/netfs/fuseDirs.cpp @@ -10,6 +10,7 @@ NetFS::OpenDir::OpenDir(Ice::Int rid, const std::string & p) : int NetFS::getNextDirID() { + LOCK; while (openDirs.find(++openDirID) != openDirs.end()) ; return openDirID; } @@ -30,8 +31,8 @@ NetFS::opendir(const char * p, struct fuse_file_info * fi) { try { Ice::Int remoteID = filesystem->opendir(reqEnv(), p); - LOCK; fi->fh = getNextDirID(); + LOCK; openDirs[fi->fh] = new OpenDir(remoteID, p); return 0; } diff --git a/netfs/fuseFiles.cpp b/netfs/fuseFiles.cpp index 6a59492..d8aa55f 100644 --- a/netfs/fuseFiles.cpp +++ b/netfs/fuseFiles.cpp @@ -11,6 +11,7 @@ NetFS::OpenFile::OpenFile(Ice::Int rid, const std::string & p, int f) : int NetFS::getNextFileID() { + LOCK; while (openFiles.find(++openFileID) != openFiles.end()) ; return openFileID; } @@ -31,8 +32,8 @@ NetFS::open(const char * p, struct fuse_file_info * fi) { try { Ice::Int remoteID = filesystem->open(reqEnv(), p, fi->flags); - LOCK; fi->fh = getNextFileID(); + LOCK; openFiles[fi->fh] = new OpenFile(remoteID, p, fi->flags); return 0; } @@ -46,8 +47,8 @@ NetFS::create(const char * p, mode_t m, struct fuse_file_info * fi) { try { Ice::Int remoteID = filesystem->create(reqEnv(), p, fi->flags, m); - LOCK; fi->fh = getNextFileID(); + LOCK; openFiles[fi->fh] = new OpenFile(remoteID, p, fi->flags); return 0; } diff --git a/netfs/fuseapp.cpp b/netfs/fuseapp.cpp index 13d8bdf..39718d1 100644 --- a/netfs/fuseapp.cpp +++ b/netfs/fuseapp.cpp @@ -304,8 +304,8 @@ FuseAppBase::run(int & argc, char** & argv, FuseAppBase * fa) fuseCall, fuseCall, fuseCall, - NULL, - NULL, + 0, + 0, NULL, NULL }; -- cgit v1.2.3