📄 filefolderc.c
字号:
/* * $Id: FileFolderC.C,v 1.7 2000/08/07 11:05:16 evgeny Exp $ * * Copyright (c) 1994 HAL Computer Systems International, Ltd. * * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. * 1315 Dell Avenue * Campbell, CA 95008 * * Author: Greg Hilton * Contributors: Tom Lang, Frank Bieser, and others * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * http://www.gnu.org/copyleft/gpl.html * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include "FileFolderC.h"#include "FileMisc.h"#include "FilePartMsgC.h"#include "IshAppC.h"#include "AppPrefC.h"#include "MainWinC.h"#include "SortMgrC.h"#include "UndelWinC.h"#include "MsgListC.h"#include "LoginWinC.h"#include <hgl/SysErr.h>#include <hgl/System.h>#include <hgl/VBoxC.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <utime.h>#include <signal.h>#include <errno.h>#include <sys/stat.h>// FIXME: more fs access types should be here#ifdef HAVE_STATVFS // SOLARIS || SVR4 || OSF1 || MIPS# include <sys/statvfs.h># define FSTATFS(fd, bufp) fstatvfs(fd, bufp)# define STATFS statvfs#else# include <sys/vfs.h># define FSTATFS(fd, bufp) fstatfs(fd, bufp)# define STATFS statfs#endif#ifdef HAVE___VAL_IN_F_FSID# define GET_FS_ID(fsid) (fsid.__val[0]) #else# define GET_FS_ID(fsid) (fsid)#endifextern int debuglev;/*------------------------------------------------------------------------ * FileFolderC constructor */FileFolderC::FileFolderC(const char *n, FolderTypeT t, Boolean create): FolderC(n, t, create){ openLevel = 0; lockLevel = 0; lockFile = name + ".lock"; fp = NULL; changedWhileSleeping = False;//// Get the date of the file// if ( stat(name, &stats) != 0 ) {//// Create the file if necessary// if ( errno == ENOENT && create ) { if ( debuglev > 0 ) cout <<"Creating folder: " <<name <<endl; if ( !MakeFile(name) ) return; stat(name, &stats); } else { StringC errmsg = "Could not stat "; errmsg += name; errmsg += "\n" + SystemErrorMessage(errno); halApp->PopupMessage(errmsg); return; } }//// Make sure this is a file// if ( !S_ISREG(stats.st_mode) && name != "/dev/null" ) { StringC errmsg = name; errmsg += " is not a folder."; halApp->PopupMessage(errmsg); return; }//// See if file is writable// writable = (access(name, W_OK) == 0); if ( !writable ) { StringC errmsg = "Folder \""; errmsg += name; errmsg += "\" is not writable and will be opened read-only"; halApp->PopupMessage(errmsg, XmDIALOG_WARNING); }//// See if lock file can be created// if ( !Lock(True) ) { int err = errno; StringC errmsg = "Folder \""; errmsg += name; errmsg += "\" cannot be locked and will be opened read-only."; errmsg += "\n"; errmsg += SystemErrorMessage(err); halApp->PopupMessage(errmsg, XmDIALOG_WARNING); } // End if lock file not created else { Lock(False); } opened = True;} // End FileFolderC constructor/*------------------------------------------------------------------------ * FileFolderC destructor */FileFolderC::~FileFolderC(){ if ( lockLevel > 0 ) unlink(lockFile); CloseFile(True/*force*/); if ( delFiles ) unlink(name);}/*------------------------------------------------------------------------ * Method to create mail lock on folder */BooleanFileFolderC::Lock(Boolean val){ if ( !isInBox ) return True; static SIG_PF oldhup = (SIG_PF)SIG_DFL; static SIG_PF oldint = (SIG_PF)SIG_DFL; static SIG_PF oldquit = (SIG_PF)SIG_DFL; static SIG_PF oldterm = (SIG_PF)SIG_DFL; static SIG_PF oldtstp = (SIG_PF)SIG_DFL; if ( !writable ) return True; if ( val ) { lockLevel++; if ( lockLevel > 1 && access(lockFile, F_OK) == 0 ) return True; // Already locked } else { if ( lockLevel < 1 ) return True; // Not locked lockLevel--; if ( lockLevel > 0 ) return True; // Not ready to unlock } if ( val ) { oldhup = signal(SIGHUP, (SIG_PF)SIG_IGN); oldint = signal(SIGINT, (SIG_PF)SIG_IGN); oldquit = signal(SIGQUIT, (SIG_PF)SIG_IGN); oldterm = signal(SIGTERM, (SIG_PF)SIG_IGN); oldtstp = signal(SIGTSTP, (SIG_PF)SIG_IGN); Boolean success = CreateLock(lockFile); if ( !success ) { lockLevel--; signal(SIGHUP, oldhup); signal(SIGINT, oldint); signal(SIGQUIT, oldquit); signal(SIGTERM, oldterm); signal(SIGTSTP, oldtstp); } return success; } else { unlink(lockFile); signal(SIGHUP, oldhup); signal(SIGINT, oldint); signal(SIGQUIT, oldquit); signal(SIGTERM, oldterm); signal(SIGTSTP, oldtstp); } return True;} // End Lock/*------------------------------------------------------------------------ * Method to create a lock file */BooleanFileFolderC::CreateLock(const char *file){ Boolean retVal = True;//// Loop while file exists. Try for 60 seconds before giving up.// int count = 60; struct stat statbuf; while ( (stat(file, &statbuf) >= 0) && (count > 0) ) { sleep(1); count--; }//// If we timed out, this is probably an old lock file, so just use it.// if ( count > 0 ) { int fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0); if ( fd < 0 ) { retVal = False; } else close(fd); } return retVal;} // End CreateLock/*--------------------------------------------------------------- * Method to open file */BooleanFileFolderC::OpenFile(){ openLevel++; if ( fp ) return True; char *mode; if ( writable ) { if ( access(name, F_OK) != 0 && errno == ENOENT ) mode = "w+"; else mode = "r+"; } else mode = "r";//// Open the file// if ( debuglev > 1 ) cout <<"Opening folder file " <<name <<endl; fp = fopen(name, mode); if ( !fp ) { StringC errmsg("Could not open file: "); errmsg += name; errmsg += "\n" + SystemErrorMessage(errno); halApp->PopupMessage(errmsg); openLevel = 0; return False; } return True;}/*--------------------------------------------------------------- * Method to close file */voidFileFolderC::CloseFile(Boolean force){ if ( !fp ) return; if ( force ) openLevel = 0; else openLevel--; if ( openLevel > 0 ) return; if ( openLevel < 0 ) openLevel = 0; if ( debuglev > 1 ) cout <<"Closing folder file " <<name <<endl; fclose(fp); fp = NULL;//// Get new stats. This can cause loss of new mail!!// // An unconditional update of the stats can lose new mail in the // following scenario: // 1. stats updated // 2. new mail arrives // 3. folder action results in close, stats updated *without* // checking for new mail // 4. mailcheck now will fail to see the new mail //stat(name, &stats);} // End CloseFile/*------------------------------------------------------------------------ * Method to check for new mail */BooleanFileFolderC::NewMail(){ if ( debuglev > 1 ) cout <<"Checking for new mail in folder " <<name <<endl; Boolean newMail = False;//// If the external mods flag is set and we're not sleeping, this is the first// check since we woke up. We need to reread the folder.// if ( changedWhileSleeping && !ishApp->sleeping ) { if ( debuglev > 1 ) cout <<"Incorporating changes made while asleep." <<endl; Rescan(); newMail = HasNewMessages(); if ( newMail && !ishApp->exiting ) UpdateIcon(); changedWhileSleeping = False; return newMail; }//// If there is a POP server specified, run popclient to suck over new mail// if ( isInBox && ishApp->appPrefs->usingPop ) { StringC cmd = ishApp->appPrefs->popclientCmd; Boolean doPop = True; if ( cmd.Contains("%user") || cmd.Contains("%pass") ) { StringC user, pass; if ( GetLogin(ishApp->appPrefs->popServer, user, pass) ) { cmd.Replace("%user", user); cmd.Replace("%pass", pass); } else { doPop = False; } } if ( doPop ) { cmd += ' '; cmd += ishApp->appPrefs->popServer; StringC msg("Checking for mail on POP server "); msg += ishApp->appPrefs->popServer; msg += "..."; ishApp->Broadcast(msg); System(cmd); ishApp->Broadcast(""); } } // End if using pop//// Open, read the last byte and close the file so that the stat() call// works over NFS.// int fd = open(name, O_RDWR); if ( fd >= 0 ) { lseek(fd, 1, SEEK_END); char buf; read(fd, &buf, 1); close(fd); }//// Get the stats of the mail file// struct stat newStats; if ( stat(name, &newStats) != 0 ) { int err = errno; if ( ishApp->sleeping ) changedWhileSleeping = True; else if ( err == ENOENT && stats.st_size > 0 ) {//// If the file is gone but was there before, this is a problem.// StringC errmsg = "Mail folder "; errmsg += name; errmsg += " has disappeared.\n"; errmsg += "The last time we checked, it had a size of "; errmsg += (int)stats.st_size; errmsg += " bytes."; halApp->PopupMessage(errmsg, XmDIALOG_WARNING); Lock(True); Reset(); MakeFile(name); stat(name, &stats); Lock(False); } // End if file was there before else if ( err != ENOENT ) { StringC errmsg = "Mail folder "; errmsg += name; errmsg += " could not be checked:\n"; errmsg += SystemErrorMessage(err); halApp->PopupMessage(errmsg, XmDIALOG_ERROR); } else if ( debuglev > 1 ) cout <<"Folder not present" <<endl; return False; } // End if folder can't be stat'd if ( debuglev > 1 ) cout <<"Folder is " <<newStats.st_size <<" bytes at time " <<newStats.st_mtime <<endl;//// Check file times// if ( newStats.st_mtime == stats.st_mtime && newStats.st_size == stats.st_size ) { if ( debuglev > 1 ) cout <<"No change." <<endl; return False; }//// Something changed. Let's find out what...// if ( newStats.st_size < stats.st_size ) { // File shrunk! if ( ishApp->sleeping ) changedWhileSleeping = True; else { StringC errmsg = "Mail folder "; errmsg += name; errmsg += " has shrunk from "; errmsg += (int)stats.st_size; errmsg += " bytes to "; errmsg += (int)newStats.st_size; errmsg += " bytes."; halApp->PopupMessage(errmsg, XmDIALOG_WARNING); Rescan(); newMail = HasNewMessages(); if ( newMail && !ishApp->exiting ) UpdateIcon(); stats = newStats; } // End if not sleeping return newMail; } // End if mail file shrunk if ( debuglev > 1 ) cout <<"Folder changed." <<endl; stats = newStats; if ( ishApp->sleeping ) { changedWhileSleeping = True; return True; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -