Portability: Use fcntl instead of flock
- POSIX file locking mechanism, eliminating platform-specific code.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
- TW-1605 Japanese translation for Taskwarrior (thanks to Oota Toshiya).
|
- TW-1605 Japanese translation for Taskwarrior (thanks to Oota Toshiya).
|
||||||
- TW-1606 scheduled.any filter (thanks to Peter Rochen).
|
- TW-1606 scheduled.any filter (thanks to Peter Rochen).
|
||||||
- The 'obfuscate' setting, if set to '1' will replace all text with 'xxx'.
|
- The 'obfuscate' setting, if set to '1' will replace all text with 'xxx'.
|
||||||
|
- POSIX file locking mechanism, eliminating platform-specific code.
|
||||||
|
|
||||||
------ current release ---------------------------
|
------ current release ---------------------------
|
||||||
|
|
||||||
|
|||||||
48
src/File.cpp
48
src/File.cpp
@@ -28,14 +28,10 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef SOLARIS
|
#include <stdio.h>
|
||||||
#include <fcntl.h> // for flock() replacement
|
#include <fcntl.h>
|
||||||
#include <string.h> // for memset()
|
|
||||||
#else
|
|
||||||
#include <sys/file.h>
|
|
||||||
#endif
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <text.h>
|
#include <text.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
@@ -151,6 +147,9 @@ void File::close ()
|
|||||||
{
|
{
|
||||||
if (_fh)
|
if (_fh)
|
||||||
{
|
{
|
||||||
|
if (_locked)
|
||||||
|
unlock ();
|
||||||
|
|
||||||
fclose (_fh);
|
fclose (_fh);
|
||||||
_fh = NULL;
|
_fh = NULL;
|
||||||
_h = -1;
|
_h = -1;
|
||||||
@@ -161,38 +160,31 @@ void File::close ()
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool File::lock ()
|
bool File::lock ()
|
||||||
{
|
{
|
||||||
|
_locked = false;
|
||||||
if (_fh && _h != -1)
|
if (_fh && _h != -1)
|
||||||
{
|
{
|
||||||
// Try three times before failing.
|
// l_type l_whence l_start l_len l_pid
|
||||||
int retry = 0;
|
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0 };
|
||||||
while (flock (_h, LOCK_NB | LOCK_EX) && ++retry <= 3)
|
fl.l_pid = getpid ();
|
||||||
;
|
if (fcntl (_h, F_SETLKW, &fl) == 0)
|
||||||
|
|
||||||
if (retry <= 3)
|
|
||||||
{
|
|
||||||
_locked = true;
|
_locked = true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_locked = false;
|
return _locked;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool File::waitForLock ()
|
void File::unlock ()
|
||||||
{
|
{
|
||||||
if (_locked)
|
if (_locked)
|
||||||
return true;
|
{
|
||||||
|
// l_type l_whence l_start l_len l_pid
|
||||||
|
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0 };
|
||||||
|
fl.l_pid = getpid ();
|
||||||
|
|
||||||
if (_fh && _h != -1)
|
fcntl (_h, F_SETLK, &fl);
|
||||||
if (flock (_h, LOCK_EX) == 0)
|
_locked = false;
|
||||||
{
|
}
|
||||||
_locked = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
void close ();
|
void close ();
|
||||||
|
|
||||||
bool lock ();
|
bool lock ();
|
||||||
bool waitForLock ();
|
void unlock ();
|
||||||
|
|
||||||
void read (std::string&);
|
void read (std::string&);
|
||||||
void read (std::vector <std::string>&);
|
void read (std::vector <std::string>&);
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ void TF2::commit ()
|
|||||||
if (_file.open ())
|
if (_file.open ())
|
||||||
{
|
{
|
||||||
if (context.config.getBoolean ("locking"))
|
if (context.config.getBoolean ("locking"))
|
||||||
_file.waitForLock ();
|
_file.lock ();
|
||||||
|
|
||||||
// Write out all the added tasks.
|
// Write out all the added tasks.
|
||||||
std::vector <Task>::iterator task;
|
std::vector <Task>::iterator task;
|
||||||
@@ -258,7 +258,7 @@ void TF2::commit ()
|
|||||||
if (_file.open ())
|
if (_file.open ())
|
||||||
{
|
{
|
||||||
if (context.config.getBoolean ("locking"))
|
if (context.config.getBoolean ("locking"))
|
||||||
_file.waitForLock ();
|
_file.lock ();
|
||||||
|
|
||||||
// Truncate the file and rewrite.
|
// Truncate the file and rewrite.
|
||||||
_file.truncate ();
|
_file.truncate ();
|
||||||
@@ -358,7 +358,7 @@ void TF2::load_lines ()
|
|||||||
if (_file.open ())
|
if (_file.open ())
|
||||||
{
|
{
|
||||||
if (context.config.getBoolean ("locking"))
|
if (context.config.getBoolean ("locking"))
|
||||||
_file.waitForLock ();
|
_file.lock ();
|
||||||
|
|
||||||
_file.read (_lines);
|
_file.read (_lines);
|
||||||
_file.close ();
|
_file.close ();
|
||||||
|
|||||||
35
src/util.cpp
35
src/util.cpp
@@ -42,7 +42,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -228,40 +227,6 @@ const std::string uuid ()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// On Solaris no flock function exists.
|
|
||||||
#ifdef SOLARIS
|
|
||||||
int flock (int fd, int operation)
|
|
||||||
{
|
|
||||||
struct flock fl;
|
|
||||||
|
|
||||||
switch (operation & ~LOCK_NB)
|
|
||||||
{
|
|
||||||
case LOCK_SH:
|
|
||||||
fl.l_type = F_RDLCK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOCK_EX:
|
|
||||||
fl.l_type = F_WRLCK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOCK_UN:
|
|
||||||
fl.l_type = F_UNLCK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fl.l_whence = 0;
|
|
||||||
fl.l_start = 0;
|
|
||||||
fl.l_len = 0;
|
|
||||||
|
|
||||||
return fcntl (fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &fl);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Run a binary with args, capturing output.
|
// Run a binary with args, capturing output.
|
||||||
int execute (
|
int execute (
|
||||||
|
|||||||
@@ -52,15 +52,6 @@ const std::string uuid ();
|
|||||||
|
|
||||||
int execute (const std::string&, const std::vector <std::string>&, const std::string&, std::string&);
|
int execute (const std::string&, const std::vector <std::string>&, const std::string&, std::string&);
|
||||||
|
|
||||||
#ifdef SOLARIS
|
|
||||||
#define LOCK_SH 1
|
|
||||||
#define LOCK_EX 2
|
|
||||||
#define LOCK_NB 4
|
|
||||||
#define LOCK_UN 8
|
|
||||||
|
|
||||||
int flock (int, int);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const std::string indentProject (
|
const std::string indentProject (
|
||||||
const std::string&,
|
const std::string&,
|
||||||
const std::string& whitespace = " ",
|
const std::string& whitespace = " ",
|
||||||
|
|||||||
Reference in New Issue
Block a user