2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2N/A * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved 2N/A * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 2N/A * Openvision retains the copyright to derivative works of 2N/A * this source code. Do *NOT* create a derivative of this 2N/A * source code before consulting with your legal department. 2N/A * Do *NOT* integrate *ANY* of this source code into another 2N/A * product before consulting with your legal department. 2N/A * For further information, read the top-level Openvision 2N/A * copyright which is contained in the top-level MIT Kerberos 2N/A * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 2N/A /* only create the lock file if we successfully created the db */ 2N/A /* the admin databases do not contain security-critical data */ 2N/A /* make sure todb exists */ 2N/A * Do not release the lock on fromdb because it is being renamed 2N/A * out of existence; no one can ever use it again. 2N/A * A process is allowed to open the same database multiple times 2N/A * and access it via different handles. If the handles use 2N/A * distinct lockinfo structures, things get confused: lock(A), 2N/A * lock(B), release(B) will result in the kernel unlocking the 2N/A * lock file but handle A will still think the file is locked. 2N/A * Therefore, all handles using the same lock file must share a 2N/A * single lockinfo structure. 2N/A * It is not sufficient to have a single lockinfo structure, 2N/A * however, because a single process may also wish to open 2N/A * multiple different databases simultaneously, with different 2N/A * lock files. This code used to use a single static lockinfo 2N/A * structure, which means that the second database opened used 2N/A * the first database's lock file. This was Bad. 2N/A * We now maintain a linked list of lockinfo structures, keyed by 2N/A * lockfilename. An entry is added when this function is called 2N/A * with a new lockfilename, and all subsequent calls with that 2N/A * lockfilename use the existing entry, updating the refcnt. 2N/A * When the database is closed with fini_db(), the refcnt is 2N/A * decremented, and when it is zero the lockinfo structure is 2N/A * freed and reset. The entry in the linked list, however, is 2N/A * never removed; it will just be reinitialized the next time 2N/A * init_db is called with the right lockfilename. 2N/A /* find or create the lockinfo structure for lockfilename */ 2N/A /* doesn't exist, create it, add to list */ 2N/A /* now initialize lockp->lockinfo if necessary */ 2N/A * needs be open read/write so that write locking can work with 2N/A /* Solaris Kerberos */ 2N/A * maybe someone took away write permission so we could only 2N/A /* Solaris Kerberos */ 2N/A /* lockp is set, lockinfo is initialized, update the reference count */ 2N/A /* barry says this can't happen */ 2N/A * Don't free db->lock->filename, it is used as a key to 2N/A * find the lockinfo entry in the linked list. If the 2N/A * lockfile doesn't exist, we must be closing the database 2N/A * after trashing it. This has to be allowed, so don't 2N/A * generate an error. 2N/A /* No need to upgrade lock, just incr refcnt and return */ 2N/A /* tried to exclusive-lock something we don't have */ 2N/A /* write access to */ 2N/A /* test for all the likely "can't get lock" error codes */ 2N/A * If the file no longer exists, someone acquired a permanent 2N/A * lock. If that process terminates its exclusive lock is lost, 2N/A * but if we already had the file open we can (probably) lock it 2N/A * even though it has been unlinked. So we need to insist that 2N/A /* somehow we can't delete the file, but we already */ 2N/A /* have the lock, so release it and return */ 2N/A /* maybe we should return CANTLOCK_DB.. but that would */ 2N/A /* look just like the db was already locked */ 2N/A /* this releases our exclusive lock.. which is okay because */ 2N/A /* now no one else can get one either */ 2N/A /* now we need to create the file since it does not exist */ 2N/A /* Solaris Kerberos */