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

📄 filesystem.c++

📁 fax相关的东西
💻 C++
📖 第 1 页 / 共 2 页
字号:
/*	$Id: FileSystem.c++,v 1.11 2006/09/21 09:13:42 aidan Exp $ *//* * Copyright (c) 1995-1996 Sam Leffler * Copyright (c) 1995-1996 Silicon Graphics, Inc. * HylaFAX is a trademark of Silicon Graphics * * Permission to use, copy, modify, distribute, and sell this software and  * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. *  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   *  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE  * OF THIS SOFTWARE. *//* * File commands other than transfer. */#include "HylaFAXServer.h"#include "Sys.h"#include "tiffio.h"#include <limits.h>#include <ctype.h>/* * Delete a file (submitted document or received facsimile). */voidHylaFAXServer::deleCmd(const char* pathname){    struct stat sb;    SpoolDir* dir = fileAccess(pathname, W_OK, sb);    if (dir) {	if (!IS(PRIVILEGED)) {	    if (!S_ISREG(sb.st_mode)) {		reply(550, "%s: not a plain file.", pathname);		return;	    }	    if (!dir->deleAble) {		perror_reply(550, pathname, EPERM);		return;	    }	}	/*	 * XXX must decide what to do with jobs/documents/etc...	 * XXX e.g. should job be treated like jdele; should we	 * XXX cross-check document use for consistency....	 */	if (Sys::unlink(pathname) < 0)	    perror_reply(550, pathname, errno);	else {	    const char* cp = strrchr(pathname, '/');	    logNotice("%s of %s [%s] deleted %s%s"		, (const char*) the_user		, (const char*) remotehost		, (const char*) remoteaddr		, dir->pathname, cp ? cp+1 : pathname	    );	    ack(250, cmdToken(T_DELE));	    FileCache::flush(pathname);	}    }}/* * Set ownership of a file. */voidHylaFAXServer::chownCmd(const char* pathname, const char* user){    struct stat sb;    SpoolDir* dir = fileAccess(pathname, W_OK, sb);    if (dir) {	u_int id;	if (isdigit(user[0]))	    id = (u_int) atoi(user);	else if (!userID(user, id))	    return;	if (!FileCache::chown(pathname, sb.st_uid, (gid_t) id))	    perror_reply(550, pathname, errno);	else	    ack(250, cmdToken(T_CHOWN));    }}/* * Set protection of a file. */voidHylaFAXServer::chmodCmd(const char* pathname, u_int mode){    struct stat sb;    SpoolDir* dir = fileAccess(pathname, W_OK, sb);    if (dir) {	mode = 0600 | (mode&066);	if (!FileCache::chmod(pathname, mode))	    perror_reply(550, pathname, errno);	else	    ack(250, cmdToken(T_CHMOD));    }}/* * Return the last modification time for a file. */voidHylaFAXServer::mdtmCmd(const char* pathname){    struct stat sb;    SpoolDir* dir = fileAccess(pathname, X_OK, sb);    if (dir) {	struct tm* t = cvtTime(sb.st_mtime);	reply(213, "%d%02d%02d%02d%02d%02d"	    , t->tm_year+1900	    , t->tm_mon+1	    , t->tm_mday	    , t->tm_hour	    , t->tm_min	    , t->tm_sec	);    }}/* * NB: this array is ordered by expected frequency of access. */SpoolDir HylaFAXServer::dirs[] = {{ "/status/",	false, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listStatus,	&HylaFAXServer::listStatusFile,  &HylaFAXServer::nlstStatus,	&HylaFAXServer::nlstUnixFile, },{ "/sendq/",	false, false, false, 0,  &HylaFAXServer::isVisibleSendQFile,  &HylaFAXServer::listSendQ,	&HylaFAXServer::listSendQFile,  &HylaFAXServer::nlstSendQ,	&HylaFAXServer::nlstSendQFile, },{ "/doneq/",	false, false, false, 0,  &HylaFAXServer::isVisibleSendQFile,  &HylaFAXServer::listSendQ,	&HylaFAXServer::listSendQFile,  &HylaFAXServer::nlstSendQ,	&HylaFAXServer::nlstSendQFile, },{ "/docq/",	false,  true,  true, 0,  &HylaFAXServer::isVisibleDocQFile,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/tmp/",	false,  true,  true, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/log/",	false, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/recvq/",	false, false,  true, 0,  &HylaFAXServer::isVisibleRecvQFile,  &HylaFAXServer::listRecvQ,	&HylaFAXServer::listRecvQFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/archive/",	false, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/pollq/",	false,  true,  true, 0,  &HylaFAXServer::isVisibleRecvQFile,  &HylaFAXServer::listRecvQ,	&HylaFAXServer::listRecvQFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/",		false, false, false, 0,  &HylaFAXServer::isVisibleRootFile,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/etc/",	 true, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/info/",	false, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/bin/",	 true, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/config/",	false, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },{ "/client/",	 true, false, false, 0,  &HylaFAXServer::isVisibletrue,  &HylaFAXServer::listDirectory,	&HylaFAXServer::listUnixFile,  &HylaFAXServer::nlstDirectory,	&HylaFAXServer::nlstUnixFile, },};#define	N(a)	(sizeof (a) / sizeof (a[0]))/* * Initialize the directory handling. */voidHylaFAXServer::dirSetup(void){    for (u_int i = 0, n = N(dirs); i < n; i++) {	struct stat sb;	if (!FileCache::lookup(dirs[i].pathname, sb) || !S_ISDIR(sb.st_mode)) {	    logError("%s: Not a directory.", dirs[i].pathname);	    continue;	}	dirs[i].ino = sb.st_ino;	if (streq(dirs[i].pathname, "/"))	    cwd = &dirs[i];    }}/* * Return a directory handle given a pathname. */SpoolDir*HylaFAXServer::dirLookup(const char* path){    struct stat sb;    return (!FileCache::lookup(path, sb) || !S_ISDIR(sb.st_mode) ?	(SpoolDir*) NULL : dirLookup(sb.st_ino));}/* * Return a directory handle given an inode number. */SpoolDir*HylaFAXServer::dirLookup(ino_t ino){    for (u_int i = 0, n = N(dirs); i < n; i++)	if (dirs[i].ino == ino)	    return (&dirs[i]);    return (NULL);}/* * Check if the client is permitted to do the * request operation on the specified file. * Operations are: X_OK (list/stat), R_OK (look * at the contents), W_OK (write/delete contents). * * If the operation is permitted the stat result * for the target file is returned to the caller * for use in futher checks (e.g. type of file). */SpoolDir*HylaFAXServer::fileAccess(const char* path, int op, struct stat& sb){    if (!FileCache::lookup(path, sb)) {			// file not found	if (op != W_OK || errno != ENOENT) {	    perror_reply(550, path, errno);	    return (NULL);	}	/*	 * The file does not exist, fake up the	 * information that would result from a	 * successful file creation--for use below.	 */	sb.st_mode = S_IFREG|S_IRGRP|S_IWGRP;	sb.st_gid = (gid_t) uid;	sb.st_ino = 0;					// NB: to be created    }    /*     * Validate containing directory and target file.     * The directory must exist and the client must     * have permission to access it.  The target file     * must not be a directory if the client is about     * to do a read/write-style operation or the target     * file must be owned by the client (other checks     * are left to the caller).     */    struct stat db;    const char* cp = strrchr(path, '/');    if (cp) {	cp++;						// include "/"	if (!FileCache::lookup(fxStr(path, cp-path), db)) {	    perror_reply(550, path, ENOENT);	    return (NULL);	}    } else {	if (!FileCache::lookup(cwd->pathname, db)) {	// implicit ref to "."	    perror_reply(550, path, ENOENT);	    return (NULL);	}	cp = path;    }    SpoolDir* dir = dirLookup(db.st_ino);    if (!dir) {						// no containing dir	perror_reply(550, path, ENOENT);	return (NULL);    } else if (!IS(PRIVILEGED)) {			// unprivileged client	if (dir->adminOnly) {				// requires admin priv's	    perror_reply(550, path, EPERM);	    return (NULL);	} else if (!fileVisible(*dir, cp, sb)) {	// not visible w/o admin	    perror_reply(550, path, EPERM);	    return (NULL);	} else if (op != X_OK) {			// client wants to r/w	    if (S_ISDIR(sb.st_mode)) {			// cannot r/w directory		reply(550, "%s: not a plain file.", path);		return (NULL);	    } else if (sb.st_ino == 0 && !dir->storAble) {		perror_reply(550, path, EPERM);		// cannot stor in dir.		return (NULL);	    }	    /*	     * Check file protection mode; we use the	     * normal ``other'' bits for public access	     * and the group bits for the ``fax uid''.	     */	    if ((sb.st_mode&op) == 0 &&			// !pubicly accessible	      (sb.st_gid != (gid_t) uid ||		// !owner	       ((sb.st_mode>>3)&op) == 0)) {		// !owner acessible		perror_reply(550, path, EPERM);		return (NULL);	    }	}    } else {						// privileged client	if (op != X_OK && S_ISDIR(sb.st_mode)) {	// cannot r/w directory	    reply(550, "%s: not a plain file.", path);	    return (NULL);	}    }    return (dir);}/* * Like fileAccess, but when the target is a directory. * The implicit operation is X_OK and the directory handle * returned is for the target, not the containing directory. */SpoolDir*HylaFAXServer::dirAccess(const char* path){    struct stat sb;    if (!FileCache::lookup(path, sb)) {			// file not found	perror_reply(550, path, errno);	return (NULL);    }    if (!S_ISDIR(sb.st_mode)) {	perror_reply(550, path, ENOTDIR);	return (NULL);    }    // NB: this assumes all directories are top-level    SpoolDir* dir = dirLookup(sb.st_ino);    if (!dir) {						// XXX should not happen	perror_reply(550, path, ENOENT);	return (NULL);    } else if (dir->adminOnly && !IS(PRIVILEGED)) {	// requires admin priv's	perror_reply(550, path, EPERM);	return (NULL);    }    return (dir);}/* * Force the specified file to have the GID setup as * the effective GID of the process.  On System-V-style * filesystems this happens automatically and there is * nothing to do.  On BSD-style filesystems however the * file's GID is set from the GID of the containing * directory so we must explicitly set the value.  Note * that we must auto-detect the appropriate semantics * because some systems support both styles and the * specific scheme is selectable on a per-filesystem * basis (e.g. IRIX). */voidHylaFAXServer::setFileOwner(const char* file){    if (IS(CHECKGID)) {				// auto-detect how GID handled        struct stat sb;        if (!FileCache::lookup(file, sb)) {            fatal("setFileOwner called for non-existent file (check)");        }        if (sb.st_gid != (gid_t) uid) {            state |= S_SETGID;			// not set, must force it        } else {            state &= ~S_SETGID;			// set by OS, no work to do        }        if (TRACE(SERVER)) {

⌨️ 快捷键说明

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