Documentation du code de SPIP et de ses plugins

SPIP

nfslock.php

Gestion des verrous NFS

Table of Contents

Constants

_DEFAULT_LOCKTIME  = 60
_NAME_LOCK  = 'spip_nfs_lock'

Functions

spip_nfslock()  : int|bool
Crée un verrou pour NFS
spip_nfsunlock()  : mixed
Unlock an nfslock()ed file
spip_nfslock_test()  : mixed
Test a lock to see if it's still valid.

Constants

Functions

spip_nfslock()

Crée un verrou pour NFS

spip_nfslock(string $fichier[, int $max_age = 0 ]) : int|bool

(Excerpts from Chuck's notes: this becomes complex, due to our dear friend, the NFS mounted mail spool. the netbsd code didn't do this properly, as far as I could tell.

  • you can't trust exclusive creating opens over NFS, the protocol just doesn't support it. so to do a lock you have to create a tmp file and then try and hard link it to your lock file.
  • to detect a stale lock file you have to see how old it is, but you can't use time(0) because that is the time on the local system and the file gets the times of the NFS server. when is a lock file stale? people seem to like 120 or 300 seconds.)

NB: It is critical that nfslock()ed files be unlocked by nfsunlock(). Simply unlinking the lock file is a good way to trash someone else's lock file. All it takes is for the process doing the unlink to get hung for a few minutes when it doesn't expect it. Meanwhile, its lock expires and a second process forces the lock and creates its own. Then the first process comes along and kills the second process' lock while it's still valid.

Security considerations: If we're root, be very careful to see that the temp file we opened is what we think it is. The problem is that we could lose a race with someone who takes our tmp file and replaces it with, say, a hard link to /etc/passwd. Then, if the first lock attempt fails, we'll write a char to the file (see 4. below); this would truncate the passwd file. So we make sure that the link count is 1. We don't really care about any other screwing around since we don't write anything sensitive to the lock file, nor do we change its owner or mode. If someone beats us on a race and replaces our temp file with anything else, it's no big deal- the file may get truncated, but there's no possible security breach. ...Actually the possibility of the race ever happening, given the random name of the file, is virtually nil.

args: path = path to directory of lock file (/net/u/1/a/alexis/.mailspool) namelock = file name of lock file (alexis.lock) max_age = age of lockfile, in seconds, after which the lock is stale. stale locks are always broken. Defaults to DEFAULT_LOCKTIME if zero. Panix mail locks go stale at 300 seconds, the default. notify = 1 if we should tell stdout that we're sleeping on a lock

Returns the time that the lock was created on the other system. This is important for nfsunlock(). If the lock already exists, returns NFSL_LOCKED. If there is some other failure, return NFSL_SYSF. If NFSL_LOCKED is returned, errno is also set to EEXIST. If we're root and the link count on the tmp file is wrong, return NFSL_SECV.

Mods of 7/13/95: Change a bit of code to re-stat the lockfile after closing it. This is to work around a bug in SunOS that appears to to affect some SunOS 4.1.3 machines (but not all). The bug is that close() updates the stat st_ctime field for that file. So use lstat on fullpath instead of fstat on tmpfd. This alteration applies to both nfslock and nfslock1.

Mod of 5/4/95: Change printf's to fprintf(stderr... in nfslock and nfslock1.

Mods of 4/29/95: Fix freeing memory before use if a stat fails. Remove code that forbids running as root; instead, if root, check link count on tmp file after opening it.

Mods of 4/27/95: Return the create time instead of the lockfile's fd, which is useless. Added new routines nfsunlock(), nfslock_test(), nfslock_renew().

Mods of 1/8/95: Eliminate some security checks since this code never runs as root. In particular, we completely eliminate the safeopen routine. But add one check: if we are root, fail immediately.

Change arguments: take a path and a filename. Don't assume a global or macro pointing to a mailspool.

Add notify argument; if 1, tell user when we're waiting for a lock.

Add max_age argument and DEFAULT_LOCKTIME.

Change comments drastically.

Parameters
$fichier : string

Chemin du fichier

$max_age : int = 0

Age maximum du verrou

Tags
author

Chuck Cranor chuck@maria.wustl.edu (original author)

author

Alexis Rosen alexis@panix.com (rewritter)

author

Cedric Morin cedric@yterium.com (rewritter for php&SPIP)

used-by
spip_fopen_lock()

si _SPIP_LOCK_MODE = 2.

Return values
int|bool

Timestamp du verrou, false si erreur

spip_nfsunlock()

Unlock an nfslock()ed file

spip_nfsunlock(string $fichier, int $birth[, int $max_age = 0 ][, bool $test = false ]) : mixed

This can get tricky because the lock may have expired (perhaps even during a process that should be "atomic"). We have to make sure we don't unlock some other process' lock, and return a panic code if we think our lock file has been broken illegally. What's done in reaction to that panic (of anything) is up to the caller. See the comments on nfslock()!

args: path = path to directory of lock file (/net/u/1/a/alexis/.mailspool) namelock = file name of lock file (alexis.lock) max_age = age of lockfile, in seconds, after which the lock is stale. stale locks are always broken. Defaults to DEFAULT_LOCKTIME if zero. Panix mail locks go stale at 300 seconds, the default. birth = time the lock was created (as returned by nfslock()).

Returns NFSL_OK if successful, NFSL_LOST if the lock has been lost legitimately (because more than max_age has passed since the lock was created), and NFSL_STOLEN if it's been tampered with illegally (i.e. while this program is within the expiry period). Returns NFSL_SYSF if another system failure prevents it from even trying to unlock the file.

Note that for many programs, a return code of NFSL_LOST or NFSL_STOLEN is equally disastrous; a NFSL_STOLEN means that some other program may have trashed your file, but a NFSL_LOST may mean that you have trashed someone else's file (if in fact you wrote the file that you locked after you lost the lock) or that you read inconsistent information.

In practice, a return code of NFSL_LOST or NFSL_STOLEN will virtually never happen unless someone is violating the locking protocol.

Parameters
$fichier : string

Chemin du fichier

$birth : int

Timestamp de l'heure de création du verrou

$max_age : int = 0

Age maximum du verrou

$test : bool = false

Mode de test return bool true si déverrouillé, false sinon

Tags
author

Alexis Rosen alexis@panix.com

see
spip_nfslock()

spip_nfslock_test()

Test a lock to see if it's still valid.

spip_nfslock_test(string $fichier, int $birth[, int $max_age = 0 ]) : mixed

Args, return codes, and behavior are identical to nfsunlock except that nfslock_test doesn't remove the lock. NFSL_OK means the lock is good, NFLS_LOST and NFSL_STOLEN means it's bad, and NFSL_SYSF means we couldn't tell due to system failure.

The source for this routine is almost identical to nfsunlock(), but it's coded separately to make things as clear as possible.

Parameters
$fichier : string

Chemin du fichier

$birth : int

Timestamp de l'heure de création du verrou

$max_age : int = 0

Age maximum du verrou return bool true si déverrouillé, false sinon

Tags
author

Alexis Rosen alexis@panix.com

see
spip_nfsunlock()

about lost and stolen locks.


        
On this page

Search results