home *** CD-ROM | disk | FTP | other *** search
- //
- // Copyright (c) 1997 Vermeer Technologies, Inc., a wholly owned
- // subsidiary of Microsoft Corp. All Rights Reserved
-
- // CVote implementation
- #include "votefile.h"
-
- #ifdef WIN32
- #include <windows.h>
- #include <io.h>
- #include <share.h>
- #endif
-
- #ifdef UNIX
- #include <signal.h>
- #include <unistd.h>
- #include <sys/types.h>
- #endif
-
- #include <errno.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- CVote::CVote(const char *filename, BOOL create)
- {
-
- // Assume the worst
- m_vote1count = 1;
- m_vote2count = 1;
- error = TRUE;
-
- MakeWritable(filename);
-
- // Open the file and lock it. Timeout for waiting for lock is 10 sec
- if (!OpenAndLock(filename, 10, create))
- return;
-
- m_vote1count = ReadVoteCount("vote1type");
- m_vote2count = ReadVoteCount("vote2type");
- error = FALSE;
- }
-
- CVote::~CVote()
- {
- WriteVoteCount("vote1type", m_vote1count);
- WriteVoteCount("vote2type", m_vote2count);
- Close(); // Closes and unlocks the file
- }
-
- long CVote::GetVoteCount(const char* votetype)
- {
- if (!strcmp(votetype,"vote1type"))
- { return m_vote1count; }
- else if (!strcmp(votetype,"vote2type"))
- { return m_vote2count; };
-
- // if votetype is something else, this function doesn't support it
- // so return a 0.
- return 0;
- }
-
- void CVote::SetVoteCount(const char* votetype, long votecount)
- {
- if (!strcmp(votetype,"vote1type"))
- { m_vote1count = votecount; }
- else if (!strcmp(votetype,"vote2type"))
- { m_vote2count = votecount; };
- }
-
- void CVote::Increment(const char* votetype, long amount)
- {
- if (!strcmp(votetype,"vote1type"))
- { m_vote1count += amount; }
- else if (!strcmp(votetype,"vote2type"))
- { m_vote2count += amount; };
- }
-
-
- #ifdef UNIX
-
- #ifdef SGI
- void alarm_handler(...)
- #else
- void alarm_handler(int /*sig*/)
- #endif
- {
- // catch alarm signal and ignore
- }
- #endif
-
- void CVote::MakeWritable(const char *filename)
- {
- #ifdef WIN32
- chmod(filename, _S_IREAD | _S_IWRITE);
- #endif
- #ifdef UNIX
- struct stat statBuf;
-
- if (stat(filename, &statBuf))
- return;
-
- int fileMode = statBuf.st_mode;
- fileMode |= S_IWUSR;
-
- if (fileMode & S_IRGRP)
- fileMode |= S_IWGRP;
- if (fileMode & S_IROTH)
- fileMode |= S_IWOTH;
-
- chmod(filename, fileMode);
- #endif
- }
-
-
- BOOL CVote::OpenAndLock(const char *filename, int nTimeoutSec, BOOL create)
- {
-
- #ifdef WIN32
- DWORD startTime = GetTickCount();
- DWORD nTimeout = nTimeoutSec * 1000; // Timeout in milleseconds
- for (fd = -1; nTimeoutSec == 0 || GetTickCount() - startTime < nTimeout;)
- {
- // Try to open the file in locked mode
- fd = _sopen(filename, _O_RDWR, _SH_DENYWR);
-
- // Success, exit the for loop
- if (fd != -1)
- break;
-
- // No success. If file was not found, and create is specified, then
- // create it, lock it, and write a 0 to it
- if (errno == ENOENT && create)
- {
- fd = _sopen(filename, _O_RDWR | _O_CREAT, _SH_DENYWR, _S_IREAD | _S_IWRITE);
-
- InitializeFile();
-
- break;
- }
-
- // Otherwise, delay half a second, and try again.
- Sleep(500);
- }
- if (fd == -1)
- return FALSE; // Timed out
-
- #endif /* WIN32 */
-
-
- #ifdef UNIX
- fd = open(filename, O_RDWR);
- if (fd == -1)
- {
- if (errno == ENOENT && create)
- {
- // If it's okay to create it, try to do so
- fd = open(filename, O_RDWR | O_CREAT, 0666);
- if (fd == -1) // still failed, abort
- return FALSE;
- InitializeFile(); // Fill in with count of 0
- }
- else
- return FALSE;
- }
-
- // Setup the alarm handler
- #ifdef SGI
- void (*func)(...) = 0;
- #else
- void (*func)(int) = 0;
- #endif
- func = signal(SIGALRM, alarm_handler);
- if ((void *)(func) == (void *)(SIG_ERR))
- {
- close(fd);
- fd = -1;
- return FALSE;
- }
-
- // Set number of seconds for alarm:
- alarm(nTimeoutSec);
-
- // Setup the lock to be the whole file
- struct flock sflock;
- sflock.l_type = F_WRLCK;
- sflock.l_whence = 0;
- sflock.l_start = 0;
- sflock.l_len = 0;
-
- // Try to do the lock. This blocks until lock is achieved
- // or the alarm goes off.
- int ret = fcntl(fd, F_SETLKW, &sflock);
-
- // If ret=-1, it failed
- if (ret == -1)
- {
- close(fd);
- fd = -1;
- return FALSE;
- }
- #endif /* UNIX */
-
- // Check validity of the count file
- if (!IsValid())
- {
- fd = -1;
- return FALSE;
- }
- return TRUE;
- }
-
- void CVote::InitializeFile()
- {
- // called whenever the votefile needs to be created from scratch
- // (when file is first saved w/ votebot on it, or when a recalc
- // links occurs and .vot file isn't found
- lseek(fd, 0, SEEK_SET);
-
- write (fd, KEY1_STR, KEY_LEN);
- write (fd, "=", 1);
- char buffer[MAX_NUM];
- sprintf(buffer, "%011ld", 0L);
- int nStrLen = strlen(buffer);
- write(fd, buffer, nStrLen);
-
- #ifdef UNIX
- write (fd, "\r", 1);
- #endif
-
- write (fd, "\n", 1);
-
- write(fd, KEY2_STR, KEY_LEN);
- write(fd, "=", 1);
- sprintf(buffer, "%011ld", 0L);
- write(fd, buffer, nStrLen);
-
- };
-
-
- void CVote::Close()
- {
- // close the .vot file
- close(fd);
- }
-
-
- long CVote::ReadVoteCount(const char* votetype)
- {
-
- char buffer[MAX_NUM];
- int nBytesRead;
-
- // go to the beginning of the file represented by handle fd
- long pos = lseek( fd, 0L, SEEK_SET );
-
- if( pos == -1L ) // file has been corrupted. Give up.
- { error = TRUE; return 0; }
-
- // position the file pointer according to the key we've received.
- if (!strcmp(votetype,"vote1type"))
- {
- lseek(fd, KEY_LEN + 1, SEEK_SET);
- }
- else if (!strcmp(votetype,"vote2type"))
- {
- lseek(fd, (KEY_LEN*2) + 3 + MAX_NUM, SEEK_SET);
- }
-
- // file pointer should be at location of VoteCount for corresponding
- // key, so read it into the buffer and return it.
- nBytesRead = read(fd, buffer, MAX_NUM);
- if (nBytesRead == -1) // no VoteCount? file is corrupted!
- {
- error = TRUE;
- return 0;
- }
-
- buffer[nBytesRead] = '\0'; // Close off the string
-
- return atol(buffer); // convert to number
- //delete[] buffer;
- }
-
- void CVote::WriteVoteCount(const char* votetype, long count)
- {
-
- // before we do any file parsing,
- // go to the beginning of the file (handle fd)
- lseek( fd, 0L, SEEK_SET );
-
- // position the file pointer according to the key we've received.
- if (!strcmp(votetype,"vote1type"))
- {
- lseek(fd, KEY_LEN + 1, SEEK_SET);
- }
- else if (!strcmp(votetype,"vote2type"))
- {
- lseek(fd, (KEY_LEN*2) + 3 + MAX_NUM, SEEK_SET);
- }
-
- // file pointer has been positioned; write count to the file.
- char buffer[MAX_NUM];
- sprintf(buffer, "%011ld", count);
- int nStrLen = strlen(buffer);
- write(fd, buffer, nStrLen);
- }
-
-
-
- BOOL CVote::IsValid()
- {
- // determine whether or not .vot file is a valid one.
- // if it's corrupted, calling function should create a new one.
- lseek(fd, 0, SEEK_SET);
- char buffer[KEY_LEN];
- int nBytesRead = read(fd, buffer, KEY_LEN);
- if (nBytesRead == -1)
- {
- error = TRUE;
- return FALSE;
- }
- return (strncmp(buffer, KEY1_STR, KEY_LEN) == 0);
- }
-
-
-