lockdev-1.0.3/0000755000175000017500000000000010320306166012145 5ustar covencovenlockdev-1.0.3/debian/0000755000175000017500000000000010320276414013371 5ustar covencovenlockdev-1.0.3/debian/foo0000644000175000017500000000000010320276414014065 0ustar covencovenlockdev-1.0.3/Makefile0000644000175000017500000000456510320276711013621 0ustar covencoven-include Rules.mk libname = liblockdev pkgname = lockdev objs = src/lockdev.o shobjs = src/lockdev.z VER = $(shell expr `pwd` : '.*-\([0-9.]*\)') MVER = ${shell expr `pwd` : '.*-\([0-9]*\).[0-9]*'} static = ${libname}.a shared = ${libname}.${VER}.so soname = ${libname}.so.${MVER} # overwritten by caller (e.g.: debian/rules) basedir = /usr/local srcdir=. libdir = ${basedir}/lib incdir = ${basedir}/include mandir = ${basedir}/share/man CC = gcc LCFLAGS = -g -O2 -fPIC -Wall -pipe -D_REENTRANT CFLAGS = -g LDLIBS = -llockdev .PHONY: shared static perl-lib ALL: shared static perl-lib static ${static}: ${objs} $(AR) $(ARFLAGS) ${static} $^ shared ${shared}: ${shobjs} ${CC} ${LCFLAGS} -shared -Wl,-soname,${soname} $^ -lc -o ${shared} src/lockdev.z: src/lockdev.c ${CC} ${CFLAGS} -c -fPIC -o $@ $? perl-lib: static cd LockDev && perl Makefile.PL INSTALLDIRS=vendor cd LockDev && make OPTIMIZE="-O2 -g -Wall" cd LockDev && make test .PHONY: install install_dev install_dbg install_doc install_run install: install_dev install_dbg install_doc install_run install_dev: ${static} src/lockdev.h install -m755 -d ${libdir} install -m644 ${static} ${libdir} install -m755 -d ${incdir} install -m644 src/lockdev.h ${incdir} install -m644 src/ttylock.h ${incdir} install_debug: ${static} ${shared} install -m755 -d ${libdir}/debug install -m644 ${static} ${libdir}/debug install -m644 ${shared} ${libdir}/debug/${soname} install_profile: ${static} ${shared} install -m755 -d ${libdir}/profile install -m644 ${static} ${libdir}/profile install -m644 ${shared} ${libdir}/profile/${soname} install_doc: docs/lockdev.3 install -m755 -d ${mandir}/man3 install -m644 docs/lockdev.3 ${mandir}/man3 install_run: ${shared} install -m755 -d ${libdir} install -m644 ${shared} ${libdir} .PHONY: clean distclean perl-clean mostyclean perl-clean: clean cd LockDev && rm -rf *~ *.o LockDev.bs LockDev.c \ Makefile Makefile.old blib pm_to_blib clean: -find . -name '*~' | xargs --no-run-if-empty rm -f -find . -name '*.o' | xargs --no-run-if-empty rm -f -find . -name '*.z' | xargs --no-run-if-empty rm -f mostyclean: clean -rm -f *.a *.so *.so.* -rm -f shared static debug profile _SRCDIR_ distclean: mostyclean perl-clean .PHONY: distribute dist tarball dist distribute: tarball tarball: distclean cd .. && tar -cvf - ${pkgname}-${VER} | gzip -9c > ${pkgname}_${VER}.tgz lockdev-1.0.3/ChangeLog.old0000644000175000017500000001751107304172415014507 0ustar covencovenlockdev (1.0.0) unstable; urgency=low * added management of pseudo device /dev/tty , thanx to Alan Cox. * added unconditional malloc of supplied device argoment. * changed name of the shared lib to end in .so * changed Makefile.PL because the perl manpage disappeared. * Changed symbols in the API as suggested by Daniel Quinlan and Erik Troan. Changed soname accordingly. * Corrected manpages and added LSB proposal (draft 2). * corrected cua device management: use linux/major.h to determine the cua major number; conditioned to __linux__ * Changed LICENSE file to hold the LGPL 2.1 -- Fabrizio Polacco Wed, 1 Dec 1999 12:59:10 +0200 lockdev (0.11.1) unstable; urgency=low * NMU for the perl upgrade. Closes: #41522 * Corrected the rules files to conform to perl policy 1.0.1. * Compiled with perl-5.005. * Corrected the location of the license. * Upgraded standards-version to 2.5.1 -- Raphael Hertzog Mon, 19 Jul 1999 20:51:00 +0200 lockdev (0.11) unstable; urgency=low * Avoided repetute locking of the semaphore. * Corrected special case of semaphore misbehaviour (found while crosschecking between two instancies running under gdb). * Added modification on-the-fly of major number of device from 4 to 5 in case it was referring to one of the 64 cua devices; it now locks the major+minor numbers of the corresponding ttyS device. The name remains unaffected, as it could be an arbitrary name. (Thanx to Daniel Quinlan ) * Tryed to use fcntl instead of flock, after suggestion of Daniel Quinlan, to permit use on NFS mounted partitions. I wasn't able to make it correctly work, so I conditioned the changes and left the code there, for further (future) investigations. Any help highly appreciated. * changed third file (LCK..) to have three dots, and made it stay there, as a quick reference. It doesn't hurt, and shouw the pid with a simple ls -l * Added full text of LGPL licence instead of GPL one added in the previous version (oops). -- Fabrizio Polacco Wed, 2 Jun 1999 15:58:03 +0300 lockdev (0.10) unstable; urgency=low * Added ttylock.h as Compatibility API to AIX. Programs written for that environment can be linked directly to lockdev library. (On AIX the symbols are in libc, so special care should be used) * changed location of manpages to /usr/share/man. * changed the name of the source to lockdev_0.10.tar.gz * changed address of FSF in Copyright file, added the full GPL text as LICENSE (only in the source), corrected name of the mailing list. * changed name of changelog, just to make lintian happier. * corrected name of docs dir for perl package. -- Fabrizio Polacco Thu, 8 Apr 1999 21:04:53 +0300 liblockdev (0.9a) frozen unstable; urgency=low * Added more tests in postinst of liblockdev0g-dbg, to avoid strange problems encountered by Adam P. Harris (closes: #22565) -- Fabrizio Polacco Mon, 18 May 1998 15:21:12 +0300 liblockdev (0.9) frozen unstable; urgency=low * cleaned symlinks in docs dirs. * changed libs symlinks from /usr/lib to /lib * stripped main shared library. * Corrected wrong shlibs dependency (thanx to Hamish Moffatt, closes: #22282). * Changed dependency of -dev from libc6 to libc6-dev, thanx to James Troup (closes: #16476). * Added -I.. in Makefile.PL to allow compilation of the perl part even when the -dev package isn't installed (thanx to Martin Schulze for the patch) closes: #15834 -- Fabrizio Polacco Tue, 12 May 1998 13:39:27 +0300 liblockdev (0.8) unstable; urgency=low * updated manpage (degugging section). * added environment variable to set debug value, and signals to change those values at runtime (if compiled with -DDEBUG). * avoided symlink to /usr/src changing .stab in asm source file (overwritten implicit rule to produce asm source). Thanx to Martin Schulze for the help. * changed dbg package to install shared debug lib in /usr/lib/debug and profile lib in /usr/lib/profile. * splitted debian/rules in included debian/policy * cleaned Makefile and changed to build debug shared lib. Thanx to Yann Dirson. * added change in umask value to allow full permissions to lock files. (this is questionable: would it be better to add a suid program to check and remove dangling locks?) -- Fabrizio Polacco Tue, 23 Dec 1997 11:26:10 +0200 liblockdev (0.7) unstable; urgency=low * cleaned Makefile and debian/rules * change in Makefile.PL to allow pristine compilation on new systems (closes: #15834, thanx to Martin Schulze). * added -dbg package with debug and profile libs. * problem with lenght of dev_t in glibc for printf: cast needed :-) * corrected ftp address in copyright file. -- Fabrizio Polacco Sun, 30 Nov 1997 01:00:50 +0200 liblockdev (0.6) unstable; urgency=low * added symlink to dirs in /usr/doc (one dir for all packages), now /usr/doc/liblockdev is a symlink installed by -dev package, as the liblockdev.a and liblockdev.so symlinks. Instead, lblockdev-perl installs a copy of the docs because it doesn't depend on the run-time binary package (as -dev does). * cleaned spreading in the distribution: source and run-time to section 'libs', development into 'devel', perl module into 'interpreters' (waiting for a perl section). * created extension perl library LockDev:: with manpage LockDev(3pm) and packaged as liblockdev0-perl. * moved symlink so.0 -> so.0.6 to runtime package. * added unlink of semaphore file (not really needed, just to clean up) * corrected error in Synopsis of manpage (oops). * cleaned source code: changed ANSI-C definition of functions to K&R, as recommended in GNU coding style (but not for indentation). Added ANSI-C prototypes for internal functions (exported one already have them in .h interface file. * cleaned rules file, got rid of unneeded libc5 compatibility. * Moved back include of stdio.h from lockdev.h to .c (closes:Bug#14154) Thanx to Juan Cespedes * Corrected debian/rules to have binary-arch rule (closes:Bug#14062) -- Fabrizio Polacco Wed, 22 Oct 1997 13:45:34 +0300 liblockdev (0.5) unstable; urgency=low * moved to libc6 (glibc2); added a "g" after soname in package name. * added rules to build also compatibility libc5 libs. -- Fabrizio Polacco Thu, 25 Sep 1997 11:51:22 +0300 liblockdev0 (0.4) unstable; urgency=low * Changed priority from extra to optional. * cleaned Makefile and added separate static/debug library. * Cleaned include file. * Added global var liblockdev_debug for debugging level * Added 2 functions to set and reset debugging level (only in static lib) -- Fabrizio Polacco Sat, 6 Sep 1997 02:20:01 +0300 liblockdev0 (0.3) unstable; urgency=low * avoided stripping of static lib (compiled with -DDEBUG) * added semaphore lock to avoid race condition in removing stale locks (thanx to Barak Pearlmutter) * changed unlink of stale lock to a complex and convoluted way to avoid conflicts between us and another process that doesn't use this library. Still exists the possibility of a conflict between two other processes that don't use this library, but we are safe. * cleaned code in lock_dev() -- Fabrizio Polacco Fri, 5 Sep 1997 11:05:21 +0300 liblockdev0 (0.2) unstable; urgency=low * fixed shared lib links. -- Fabrizio Polacco Thu, 4 Sep 1997 19:08:38 +0300 liblockdev0 (0.1) unstable; urgency=low * Initial Release. -- Fabrizio Polacco Thu, 4 Sep 1997 14:13:23 +0300 lockdev-1.0.3/README.debug0000644000175000017500000000360407021200320014102 0ustar covencoven Instructions on how to use the debugging libraries in a debug session. In this directory (/usr/lib/debug) are included shared libraries compiled with debugging symbols, and installed by -dbg binary packages. These packages installs also the sources used to compile this library into a directory under /usr/src . Instructions for gdb are embedded in the shared library, so gdb can automatically list the source code. To use these libraries: set this environment variable: LD_LIBRARY_PATH=/usr/lib/debug; export LD_LIBRARY_PATH and run gdb or directly LD_LIBRARY_PATH=/usr/lib/debug gdb You don't need to recompile or link your program to debug the library (anyway you probably have to recompile it if you want to debug it). Pay attention that gdb ignores the value of that variable when the program is setuid or setgid. In that case, you have to be root to have dbg load the library. These debug shared libraries aren't by itself slower that the stripped version, but they have been compiled using -DDEBUG, which might activate printing of debugging values, so don't use these libraries in a production environment, neither set the LD_LIBRARY_PATH variable in a global profile nor add /usr/lib/debug to /etc/ld.so.conf nor run ldconfig with this path. Otherways _all_ users will use the debugging libraries by default, as well as the system. It is a good idea to leave the -dbg binary installed only for the strict time you need it. Don't install all the -dbg libraries unless you want exactly debug all them together. Use dpkg -r to remove them when you have done with your debugging session. It also occupy less diskspace if you leave them in .deb format (compressed), and even better when you have them handy on a CD :-) [This file (README.debug) Fri, 26 Dec 1997 01:06:14 +0200 (c) 1997 by Fabrizio Polacco Use it under the GPL (see /usr/share/common-licenses/GPL)] lockdev-1.0.3/Rules.mk0000644000175000017500000000325207304172211013572 0ustar covencoven### this fragment of makefile _must_ be included in the makefile ### and this variable ( create_debug_lib ) must be passed to the ### sub-make to activate this rule. Do this in the debug building ifdef create_debug_lib _SRCDIR_: ln -sf . $@ ### How does this work? ### a little explanation: ### the build stage (and all the binary) depends from a file not phony ### named _SRCDIR_ which is created in the current working dir as a ### symlink to . (dot, the current dir), and removed in the clean stage. ### We overwrite the implicit rule to make objects from .c sources, ### producing the asm source file from the .c source seen through the ### _SRCDIR_ symlink. In the rule we change that strange name with the ### absolute pathname where we will store the sources, so that the ### object (and the libraries) will record that name instead that the ### actual one. ### The purpose is to have a default link from the libraries to the ### place where the debugging binary package will put the sources, so that ### gdb will diplay source lines without _any_ need of strange declarations. define compile.c ${COMPILE.c} -S _SRCDIR_/$< -o $*.ss endef define compile.cc ${COMPILE.cc} -S _SRCDIR_/$< -o $*.ss endef define the_rest sed 's,^.stabs \"_SRCDIR_\/,.stabs \"${abs_src}/,' $*.ss > $*.s ${COMPILE.s} -o $@ $*.s ${RM} $*.ss $*.s endef # overwriting implicit rule %.o: %.c _SRCDIR_ @echo "=== overwritten rule .o:.c ($@: $^) ===" ${compile.c} ${the_rest} # overwriting implicit rule %.o: %.cc _SRCDIR_ @echo "=== overwritten rule .o:.cc ($@: $^) ===" ${compile.cc} ${the_rest} endif # create_debug_lib ############################################################################### lockdev-1.0.3/LICENSE0000644000175000017500000006364407004350013013162 0ustar covencoven GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. ^L Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. ^L GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. ^L Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. ^L 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. ^L 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. ^L 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. ^L 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ^L How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! lockdev-1.0.3/src/0000755000175000017500000000000010320301571012727 5ustar covencovenlockdev-1.0.3/src/lockdev.c0000644000175000017500000006317610421756314014552 0ustar covencoven/* * lockdev.c * (c) 1997, 1999 by Fabrizio Polacco * this source program is part of the liblockdev library. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License (LGPL) as published by the Free Software Foundation; * version 2.1 dated February 1999. * * 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. * * You should have received a copy of the GNU Lesser General * Public License (LGPL) along with this program; if not, write * to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * On Debian GNU/Linux systems, the complete text of the * GNU Library General Public License can be found in * `/usr/share/common-licenses/LGPL'. * * * This library provides a stable way to lock devices on a Linux or * Unix system, both following FSSTND 1.2 and SVr4 device locking * methods, and it's built to be portable and to avoid conflicts * with other programs. * It is highly reccommended that all programs that need to lock a * device (or test if it is locked, call the functions defined in * the public interface of this library. * * To use the library on other Operating Systems, with different * lock file name conventions, simply add the proper sprintf in the * conditional statement at the beginning of this source. * * pid_t dev_testlock( const char * devname) * * Given a device name returns zero if the device is not * locked, otherways returns the pid number ( > 0 ) of the * owner of the lock. The owner process is checked for * existance. Stale locks are removed. ( -1 ) is returned * on error (device not exist or has wrong name). * * pid_t dev_lock( const char * devname) * First it makes a very simple check that the device * filename isn't locked, then checks for the lockfile SVr4 * style (these checks are redundant, just to avoid the * rest in case the device was locked properly by another * process. * Then it creates a lock file with a surely unused name, * using the pid number, then it tryes to acquire the lock * doing hardlinks, which are atomic and don't overwrite * existing files. * The lock is considered acquired if both links are * established. Then the function returns zero to mean that * this process owns the lock. Otherways it returns the pid * of the active process that owns the lock or -1 for some * kind of error. * * pid_t dev_relock( const char * devname, const pid_t old_pid) * checks that the locks exist and is owned by the old_pid * (if non zero), and then rewrites the pid in the files, * thus reassigning the ownership of the lock to the * current process, usually a child of the original one. * * pid_t dev_unlock( const char * devname, const pid_t pid) * Given a device name it checks that the lock files be * owned by the process in argument (if non-zero), then * deletes them. Lock files are anyway removed unless they * are owned by a different existing process whose pid is * returned; a null value is returned after the successfull * removal of both files, otherways a -1 value is returned * to indicate an error. The order in which they are * deleted is important, and is the reverse of the order in * which they are created in dev_lock() . * * All these functions use a semaphore (a file named LOCKDEV in the * defined lock directory) locked using flock( LOCK_EX) on the * beginning of the operations and released when returning to the * caller. * A macro insures that the semaphore is released before each * return to the caller (thus the releasing function may be called * several times if nested calls were involved. It is obvious why * we use a macro and not an inline function (return isn't a * function). * * Two functions and a global int are provided for debugging * purpose: when compiling with -DDEBUG some printf are added in * the code to help debug the program. A verbosity value (1 by * default) is stored in a global int that can be incremented * calling liblockdev_incr_debug() and set to zero calling * liblockdev_reset_debug() . The value used are only three: 1 (the * default) is for error conditions and semaphore status, 2 is for * normal conditions checks, and 3 is to check all entries in a * function. * If the library is compiled without -DDEBUG, the global int is * not used in any part, but the symbols still exist so it is * possible to use them safely in your code. * */ #include #include #include #include #include #include #include #include #ifndef _PATH_LOCK # define LOCK_PATH "/var/lock" #else # define LOCK_PATH _PATH_LOCK #endif #ifndef _PATH_DEV # define DEV_PATH "/dev" #else # define DEV_PATH _PATH_DEV #endif #include #include #include #if defined (__GNU_LIBRARY__) # include # define MAJOR(dev) gnu_dev_major (dev) # define MINOR(dev) gnu_dev_minor (dev) #else # error "put here a define for MAJOR and MINOR" #endif #include "lockdev.h" /* * PROTOTYPES for internal functions * all internal functions names start with _dl_ */ static inline int _dl_filename_0 ( char * name, const pid_t pid); static inline int _dl_filename_1 ( char * name, const struct stat * st); static inline int _dl_filename_2 ( char * name, const char * dev); static void _dl_sig_handler ( int sig); static int _dl_get_semaphore ( int flag); static int _dl_unlock_semaphore ( int value); static inline int _dl_lock_semaphore ( void); static inline int _dl_block_semaphore ( void); static pid_t _dl_check_lock ( const char * lockname); static char * _dl_check_devname ( const char * devname); #define SEMAPHORE "LOCKDEV" #define close_n_return( v) return( _dl_unlock_semaphore( v)) #if DEBUG static int liblockdev_debug = DEBUG; /* 1 by default */ # define _debug(val,fmt,arg...) (liblockdev_debug && (liblockdev_debug >= val) && printf(fmt,##arg)) static int env_var_debug = -1; /* record set from env var */ # define _env_var "LIBLOCKDEV_DEBUG" #else static int liblockdev_debug = 0; # define _debug(val,fmt,arg...) do { } while (0) #endif /* exported by the interface file lockdev.h */ void liblockdev_incr_debug (void) { liblockdev_debug++; } /* exported by the interface file lockdev.h */ void liblockdev_reset_debug (void) { liblockdev_debug = 0; } /* * for internal use * * * inline functions that builds the three different filenames that are * used by these routines: * type 0 is the name containing the process ID * type 1 is the name build using the major and minor numbers (as in SVr4) * type 2 is the name containing the device name (as in FSSTND) * All types uses the macro LOCK_PATH */ #if defined (__GNU_LIBRARY__) || defined (__FreeBSD_kernel__) || defined(__NetBSD_kernel__) || defined(__OpenBSD_kernel__) /* for internal use */ static inline int _dl_filename_0 (char *name, const pid_t pid) { int l; _debug( 3, "_dl_filename_0 (pid=%d)\n", (int)pid); /* file of type /var/lock/LCK... */ l = sprintf( name, "%s/LCK...%d", LOCK_PATH, (int)pid); _debug( 2, "_dl_filename_0 () -> len=%d, name=%s<\n", l, name); return l; } /* for internal use */ static inline int _dl_filename_1 (char *name, const struct stat *st) { int l; int add = 0; _debug( 3, "_dl_filename_1 (mode=%d, stat=%d)\n", (int)st->st_mode, (int)st->st_rdev); /* lockfile of type /var/lock/LCK.C.004.064 */ l = sprintf( name, "%s/LCK.%c.%03d.%03d", LOCK_PATH, S_ISCHR(st->st_mode) ? 'C' : S_ISBLK(st->st_mode) ? 'B' : 'X', (int)MAJOR( add+st->st_rdev), (int)MINOR( add+st->st_rdev)); _debug( 2, "_dl_filename_1 () -> len=%d, name=%s<\n", l, name); return l; } /* for internal use */ static inline int _dl_filename_2 (char *name, const char *dev) { int l, i; _debug( 3, "_dl_filename_2 (dev=%s)\n", dev); /* lockfile of type /var/lock/LCK..ttyS2 */ l = sprintf( name, "%s/LCK..%s", LOCK_PATH, dev); _debug( 2, "_dl_filename_2 () -> len=%d, name=%s<\n", l, name); for (i=strlen(LOCK_PATH)+1; name[i] != '\0'; ++i) { if (name[i] == '/') name[i] = ':'; } return l; } #else # error "lock filename build missing" #endif /* handler for signals */ static void _dl_sig_handler (int sig) { signal( sig, _dl_sig_handler); switch( sig ) { #if DEBUG case SIGUSR1: liblockdev_debug++; break; case SIGUSR2: liblockdev_debug = 0; break; #endif default: break; } } /* holds the file descriptor of the lock between the various *_semaphore function calls. * its positive conten doesn't tells that we lock the file. */ static int semaphore= -1; static char sem_name[MAXPATHLEN+1]; static int oldmask= -1; /* for internal use */ static int _dl_get_semaphore (int flag) { int flag2 = flag; sprintf( sem_name, "%s/%s", LOCK_PATH, SEMAPHORE); _debug( 1, "_dl_get_semaphore(name=%s)=%d\n", sem_name, semaphore); while ( semaphore == -1 ) { semaphore = creat( sem_name, (S_IRWXU | S_IRWXG | S_IRWXO)); if ( semaphore == -1 ) { if ( errno == EAGAIN ) { if ( flag-- ) { sleep( 1); continue; } return EAGAIN; } return -1; } #ifdef USE_FCNTL /* this does not work. Why? */ while ( fcntl( semaphore, F_SETLK, (long)F_WRLCK) < 0 ) { if (( errno == EACCES ) || ( errno == EAGAIN )) { if ( flag2-- ) { sleep( 1); continue; } semaphore = -1; return EWOULDBLOCK; } return -1; } #endif /* if USE_FCNTL */ } #ifndef USE_FCNTL while ( flock( semaphore, LOCK_EX | LOCK_NB) < 0 ) { if ( errno == EWOULDBLOCK ) { if ( flag2-- ) { sleep( 1); continue; } return EWOULDBLOCK; } return -1; } #endif /* not USE_FCNTL */ return 0; /* file locked */ } /* for internal use */ static int _dl_unlock_semaphore (int value) { if ( semaphore != -1 ) { _debug( 1, "_dl_unlock_semaphore(return=%d)=%d\n", value, semaphore); unlink( sem_name); close( semaphore); semaphore = -1; } if (oldmask != -1 ) { umask( oldmask); /* restore original mask value */ oldmask = -1; } return( value); } /* for internal use */ static inline int _dl_lock_semaphore (void) { return _dl_get_semaphore( 0); } /* for internal use */ static inline int _dl_block_semaphore (void) { return _dl_get_semaphore( 3); } static pid_t pid_read = 0; /* read also by dev_testlock */ /* for internal use */ /* zero means: we don't own the lock; maybe someone else */ static pid_t _dl_check_lock(const char *lockname) { /* no check on lockname */ FILE *fd = 0; int j = 0; _debug( 3, "_dl_check_lock(lockname=%s)\n", lockname); if ( _dl_block_semaphore() ) { return -1; } if ( ! (fd=fopen( lockname, "r")) ) { if ( errno == ENOENT ) { _debug( 2, "_dl_check_lock() no lock\n"); return 0; /* no file, no lock */ } else { _debug( 1, "_dl_check_lock() fopen error %d\n", errno); return -1; } } j = fscanf( fd, "%d", &pid_read); fclose( fd); _debug( 2, "_dl_check_lock() read %d value = %d\n", j, pid_read); /* checks content's format */ if ( j == 1 ) { /* checks process existence */ if ( ( kill( pid_read, 0) == 0 ) || (errno == EPERM) ) { _debug( 2, "_dl_check_lock() locked by %d\n", (int)pid_read); return pid_read; } } else { pid_read = 0; } /* wrong format or no process */ _debug( 2, "_dl_check_lock() removing stale lock by %d\n", (int)pid_read); /* We own a semaphore lock, so ALL the processes that uses this * library are waiting for us to complete, or are exiting. * But in the world there are several programs that uses only * the "standard" locking method dictated by FSSTND, which * permits to a third process to step in, acquire a lock that is * unlinked by the running process, and therefore fall in a * state where two processes think they own the lock on the same * device. * Therefore, instead of simply unlinking, we rename the * file to a safe name (one with the process id, but different * from that used to create the lock, and we unlink it before, * just for safety); (AFAIK) rename is atomic if the * newpath doesn't exist. Then we check the content again. If it * wasn't changed then we can unlink safely, otherways we should * quickly link it back to the old name (not rename because of * the overwriting). * This is a curtesy we use to a process that uses ths FSSTND * standard, which present natively this possibility. * Our courtesy isn't fully secure: a fourth process could step * in and compete the lock with the "third" one. Both these * processes don't use this library and what happens then is * already possible to happen when we are not running, so ... * ... why should we care more about this? */ { char tpname[MAXPATHLEN+1]; pid_t pid2 = 0; /* make a unique filename, but different from anyone else. * maybe also this sprintf should be added to the * conditional part, as the others */ sprintf( tpname, "%s/.%d", LOCK_PATH, (int)getpid()); unlink( tpname); /* in case there was */ rename( lockname, tpname); if ( ! (fd=fopen( tpname, "r")) ) { return -1; } fscanf( fd, "%d", &pid2); if ( pid2 && (pid2 != pid_read) && ( kill( pid2, 0) == 0 )) { /* lock file was changed! let us quickly * put it back again */ link( tpname, lockname); /* could fail, meaning that there is a fourth * process involved which now owns the lock, but * it is possible that the third process, who * acquired the lock during the race condition, * still thinks it have the lock. * We leave them go lost in their way! */ _debug( 2, "_dl_check_lock() locked by %d\n", (int)pid2); fclose( fd); unlink( tpname); return( pid2); } fclose( fd); unlink( tpname); } _debug( 2, "_dl_check_lock() no lock\n"); return 0; } /* for internal use */ static char * _dl_check_devname (const char *devname) { int l; const char * p; char *m; /* devname can be absolute, relative to PWD or a single * filename, in any case we assume that the file is in /dev; * maybe we should check it and do something if not? */ p = devname; /* only a filename */ /* If the device is located under /dev/, strip off /dev. */ _debug( 3, "_dl_check_devname(%s) strip name = %s\n", devname, DEV_PATH); if (strncmp(DEV_PATH, p, strlen(DEV_PATH)) == 0) { p += 5; _debug( 3, "_dl_check_devname(%s) stripped name = %s\n", devname, p); } else { /* Otherwise, strip off everything but the device name. */ while ( (m=strrchr( p, '/')) != 0 ) { p = m+1; /* was pointing to the slash */ _debug( 3, "_dl_check_devname(%s) name = %s\n", devname, p); } } if ( strcmp( p, "tty") == 0 ) p = ttyname( 0); /* this terminal, if it exists */ if ( ((l=strlen( p)) == 0 ) || ( l > (MAXPATHLEN - strlen(LOCK_PATH)) )) return 0; if ( ! (m = malloc( 1 + l)) ) return 0; return strcpy( m, p); } /* exported by the interface file lockdev.h */ /* ZERO means that the device wasn't locked, but could have been locked later */ pid_t dev_testlock(const char *devname) { const char * p; char device[MAXPATHLEN+1]; char lock[MAXPATHLEN+1]; struct stat statbuf; pid_t pid; #if DEBUG if ( env_var_debug == -1 ) { char *value; if ( value=getenv( _env_var ) ) env_var_debug = liblockdev_debug = atoi( value); signal( SIGUSR1, _dl_sig_handler); signal( SIGUSR2, _dl_sig_handler); } #endif /* DEBUG */ _debug( 3, "dev_testlock(%s)\n", devname); if ( ! (p=_dl_check_devname( devname)) ) close_n_return( -1); strcpy( device, DEV_PATH); strcat( device, p); /* now device has a copy of the pathname */ _debug( 2, "dev_testlock() device = %s\n", device); /* check the device name for existence and retrieve the major * and minor numbers */ if ( stat( device, &statbuf) == -1 ) { close_n_return( -1); } /* first check for the FSSTND-1.2 lock, get the pid of the * owner of the lock and test for its existence; in case, * return the pid of the owner of the lock. */ /* lockfile of type /var/lock/LCK..ttyS2 */ _dl_filename_2( lock, p); if ( (pid=_dl_check_lock( lock)) ) close_n_return( pid); /* and also check if a pid file was left around * do this before the static var is wiped * BUT! we don't fail in case the process exists, as this is not * a lock file, just a pid holder! */ if ( pid_read ) { _dl_filename_0( lock, pid_read); _dl_check_lock( lock); } /* do the check with the new style lock file name (a la SVr4); * the reason for this order is that is much more probable that * another program uses the FSSTND lock without the new one than * the contrary; anyway we do both tests. */ /* lockfile of type /var/lock/LCK.004.064 */ _dl_filename_1( lock, &statbuf); if ( (pid=_dl_check_lock( lock)) ) close_n_return( pid); if ( pid_read ) { _dl_filename_0( lock, pid_read); _dl_check_lock( lock); } close_n_return( 0); } /* exported by the interface file lockdev.h */ pid_t dev_lock (const char *devname) { const char * p; char device[MAXPATHLEN+1]; char lock[MAXPATHLEN+1]; char lock0[MAXPATHLEN+1]; char lock1[MAXPATHLEN+1]; char lock2[MAXPATHLEN+1]; struct stat statbuf; pid_t pid, pid2, our_pid; FILE *fd = 0; #if DEBUG if ( env_var_debug == -1 ) { char *value; if ( value=getenv( _env_var ) ) env_var_debug = liblockdev_debug = atoi( value); signal( SIGUSR1, _dl_sig_handler); signal( SIGUSR2, _dl_sig_handler); } #endif /* DEBUG */ _debug( 3, "dev_lock(%s)\n", devname); if (oldmask == -1 ) oldmask = umask( 0); /* give full permissions to files created */ if ( ! (p=_dl_check_devname( devname)) ) close_n_return( -1); strcpy( device, DEV_PATH); strcat( device, p); /* now device has a copy of the pathname */ _debug( 2, "dev_lock() device = %s\n", device); /* check the device name for existence and retrieve the major * and minor numbers */ if ( stat( device, &statbuf) == -1 ) { close_n_return( -1); } /* now get our own pid */ our_pid = getpid(); _debug( 2, "dev_lock() our own pid = %d\n", (int)our_pid); /* We will use this algorithm: * first we build a file using the pid in the name (garanteed to * be unique), then we try to link to the lockname (atomic * operation which doesn't overwrite existing files). If we * succeed then we link it to the other lockname. Only when both * this operations succeed we own the lock. */ /* file of type /var/lock/LCK.. */ _dl_filename_0( lock0, our_pid); if ( ! (fd=fopen( lock0, "w")) ) close_n_return( -1); /* no file, no lock */ fprintf( fd, "%10d\n", (int)our_pid); fclose( fd); /* first check for the FSSTND-1.2 lock, get the pid of the * owner of the lock and test for its existence; in case, * return the pid of the owner of the lock. */ /* lockfile of type /var/lock/LCK..ttyS2 */ _dl_filename_2( lock2, p); pid = _dl_check_lock( lock2); if ( pid && pid != our_pid ) { unlink( lock0); close_n_return( pid); /* error or locked by someone else */ } if ( pid_read ) { /* modifyed by _dl_check_lock() */ _dl_filename_0( lock, pid_read); _dl_check_lock( lock); /* remove stale pid file */ } /* not locked or already owned by us */ /* test the lock and try to lock; repeat untill an error or a * lock happens */ /* lockfile of type /var/lock/LCK.004.064 */ _dl_filename_1( lock1, &statbuf); while ( ! (pid=_dl_check_lock( lock1)) ) { if (( link( lock0, lock1) == -1 ) && ( errno != EEXIST )) { unlink( lock0); close_n_return( -1); } } if ( pid != our_pid ) { /* error or another one owns it now */ unlink( lock0); close_n_return( pid); } if ( pid_read ) { /* modifyed by _dl_check_lock() */ _dl_filename_0( lock, pid_read); _dl_check_lock( lock); /* remove stale pid file */ } /* from this point lock1 is OUR! */ /* lockfile of type /var/lock/LCK..ttyS2 */ while ( ! (pid=_dl_check_lock( lock2)) ) { if (( link( lock0, lock2) == -1 ) && ( errno != EEXIST )) { unlink( lock0); unlink( lock1); close_n_return( -1); } } if ( pid != our_pid ) { /* error or another one owns it now */ /* this is more probable here, because of the existance * of processes who uses broken lock from FSSTND. * We let them win. */ unlink( lock0); unlink( lock1); close_n_return( pid); } /* quite unlike, but ... */ if ( pid_read ) { /* modifyed by _dl_check_lock() */ _dl_filename_0( lock, pid_read); _dl_check_lock( lock); /* remove stale pid file */ } /* OK, the lock is our! now remove the pid-file */ /* unlink( lock0); No, we leave also the pid-file, to easy * manual check in the /var/lock dir */ /* Paranoid mode on: are we sure we still own the lock? There is * a race condition in removing stale locks that could have let * a fourth process acquire the lock that we beleave is our. * So simply check again for the lock should let us know if we * were so much unlucky. */ pid = _dl_check_lock( lock1); pid2 = _dl_check_lock( lock2); if (( pid == pid2 ) && ( pid == our_pid )) { _debug( 2, "dev_lock() got lock\n"); close_n_return( 0); /* locked by us */ } /* oh, no! someone else stepped in! */ if ( pid == our_pid ) { unlink( lock1); pid = 0; } if ( pid2 == our_pid ) { unlink( lock2); pid2 = 0; } if ( pid && pid2 ) { /* two different processes own the two files: bleah! */ _debug( 1, "dev_lock() process %d owns file %s\n", (int)pid, lock1); _debug( 1, "dev_lock() process %d owns file %s\n", (int)pid2, lock2); _debug( 1, "dev_lock() process %d (we) have no lock!\n", (int)our_pid); close_n_return( -1); } close_n_return( (pid + pid2)); } /* exported by the interface file lockdev.h */ pid_t dev_relock (const char *devname, const pid_t old_pid) { const char * p; char device[MAXPATHLEN+1]; char lock1[MAXPATHLEN+1]; char lock2[MAXPATHLEN+1]; struct stat statbuf; pid_t pid, our_pid; FILE *fd = 0; #if DEBUG if ( env_var_debug == -1 ) { char *value; if ( value=getenv( _env_var ) ) env_var_debug = liblockdev_debug = atoi( value); signal( SIGUSR1, _dl_sig_handler); signal( SIGUSR2, _dl_sig_handler); } #endif /* DEBUG */ _debug( 3, "dev_relock(%s, %d)\n", devname, (int)old_pid); if (oldmask == -1 ) oldmask = umask( 0); /* give full permissions to files created */ if ( ! (p=_dl_check_devname( devname)) ) close_n_return( -1); strcpy( device, DEV_PATH); strcat( device, p); /* now device has a copy of the pathname */ _debug( 2, "dev_relock() device = %s\n", device); /* check the device name for existence and retrieve the major * and minor numbers */ if ( stat( device, &statbuf) == -1 ) { close_n_return( -1); } /* now get our own pid */ our_pid = getpid(); _debug( 2, "dev_relock() our own pid = %d\n", (int)our_pid); /* first check for the FSSTND-1.2 lock, get the pid of the * owner of the lock and test for its existence; in case, * return the pid of the owner of the lock. */ /* lockfile of type /var/lock/LCK..ttyS2 */ _dl_filename_2( lock2, p); pid = _dl_check_lock( lock2); if ( pid && old_pid && pid != old_pid ) close_n_return( pid); /* error or locked by someone else */ /* lockfile of type /var/lock/LCK.004.064 */ _dl_filename_1( lock1, &statbuf); pid = _dl_check_lock( lock1); if ( pid && old_pid && pid != old_pid ) close_n_return( pid); /* error or locked by someone else */ if ( ! pid ) { /* not locked ??? */ /* go and lock it */ return( dev_lock( devname)); } /* we don't rewrite the pids in the lock files untill we're sure * we own all the lockfiles */ if ( ! (fd=fopen( lock1, "w")) ) close_n_return( -1); /* something strange */ fprintf( fd, "%10d\n", (int)our_pid); fclose( fd); /* under normal conditions, this second file is a hardlink of * the first, so we have yet modifyed it also, and this write * seems redundant ... but ... doesn't hurt. */ if ( ! (fd=fopen( lock2, "w")) ) /* potentially a problem */ close_n_return( -1); /* something strange */ fprintf( fd, "%10d\n", (int)our_pid); fclose( fd); _debug( 2, "dev_relock() lock changed\n"); close_n_return( 0); /* locked by us */ } /* exported by the interface file lockdev.h */ pid_t dev_unlock (const char *devname, const pid_t pid) { const char * p; char device[MAXPATHLEN+1]; char lock0[MAXPATHLEN+1]; char lock1[MAXPATHLEN+1]; char lock2[MAXPATHLEN+1]; struct stat statbuf; pid_t wpid; #if DEBUG if ( env_var_debug == -1 ) { char *value; if ( value=getenv( _env_var ) ) env_var_debug = liblockdev_debug = atoi( value); signal( SIGUSR1, _dl_sig_handler); signal( SIGUSR2, _dl_sig_handler); } #endif /* DEBUG */ _debug( 3, "dev_unlock(%s, %d)\n", devname, (int)pid); if (oldmask == -1 ) oldmask = umask( 0); /* give full permissions to files created */ if ( ! (p=_dl_check_devname( devname)) ) close_n_return( -1); strcpy( device, DEV_PATH); strcat( device, p); /* now device has a copy of the pathname */ _debug( 2, "dev_unlock() device = %s\n", device); /* check the device name for existence and retrieve the major * and minor numbers */ if ( stat( device, &statbuf) == -1 ) { close_n_return( -1); } /* first remove the FSSTND-1.2 lock, get the pid of the * owner of the lock and test for its existence; in case, * return the pid of the owner of the lock. */ /* lockfile of type /var/lock/LCK..ttyS2 */ _dl_filename_2( lock2, p); wpid = _dl_check_lock( lock2); if ( pid && wpid && pid != wpid ) close_n_return( wpid); /* error or locked by someone else */ /* lockfile of type /var/lock/LCK.004.064 */ _dl_filename_1( lock1, &statbuf); wpid = _dl_check_lock( lock1); if ( pid && wpid && pid != wpid ) close_n_return( wpid); /* error or locked by someone else */ _dl_filename_0( lock0, wpid); if ( wpid == _dl_check_lock( lock0)) unlink( lock0); /* anyway now we remove the files, in the reversed order than * they have been built. */ unlink( lock2); unlink( lock1); _debug( 2, "dev_unlock() unlocked\n"); close_n_return( 0); /* successfully unlocked */ } lockdev-1.0.3/src/sample.c0000644000175000017500000000166310320267625014375 0ustar covencoven#include #include #include "lockdev.h" void usage (void) { fprintf( stderr, "Usage: sample [-lurd] \n" ); exit( -1 ); } int main (int argc, char *argv[]) { int i, chld; char *p, *dev, ch; ch = '\0'; for( i = argc - 1; i > 0; i-- ) { p = argv[i]; if( *p == '-' ) { switch( *++p ) { case 'l': case 'u': case 'r': ch = *p; break; case 'd': liblockdev_incr_debug(); break; default: usage(); break; } } else dev = p; } fprintf( stderr, "option %c, device %s\n", ch, dev ); i = 0; switch( ch ) { case 'l': i = dev_lock( dev); break; case 'u': i = dev_unlock( dev, 0); break; case 'r': dev_lock( dev); if(( chld = fork()) == 0 ) { sleep(5); } else { sleep( 1); if (( i = dev_relock( dev, chld)) < 0 ) { fprintf( stderr, "Relock failed in parent.\n" ); } } break; default: i = dev_testlock( dev); break; } exit( i); } lockdev-1.0.3/src/ttylock.h0000644000175000017500000000332210320267001014570 0ustar covencoven/* * ttylock.h * (c) 1997 by Fabrizio Polacco * this header file is part of the lockdev library. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; version 2 * dated June, 1991. * * 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. * * You should have received a copy of the GNU Library General * Public License along with this program; if not, write to the * Free Software Foundation, Inc., 675 Mass Ave., Cambridge, MA * 02139, USA. * * This header file provides an alternative API to the services of * the lockdev library, the same API implemented by AIX. * It is intended as a quick help for any program originally * designed for the AIX that wants to move to lockdev. * */ #ifndef _TTYLOCK_H_ #define _TTYLOCK_H_ #ifdef __cplusplus extern "C" { #endif #include /* API of the library */ int ttylock (char * devname); int ttywait (char * devname); int ttyunlock (char * devname); int ttylocked (char * devname); static inline int ttylock(char *devname) { /* should set errno ? */ return dev_lock( devname) == 0 ? 0 : -1; } static inline int ttyunlock (char *devname) { return dev_unlock(devname, 0); } static inline int ttylocked(char *devname) { return dev_testlock( devname) == 0 ? 0 : -1; } static inline int ttywait (char *devname) { while( dev_testlock( devname)) { sleep(1); } } #ifdef __cplusplus }; #endif #endif /* _TTYLOCK_H_ */ lockdev-1.0.3/src/lockdev.h0000644000175000017500000000354310320267001014533 0ustar covencoven/* * lockdev.h * (c) 1997, 1999 by Fabrizio Polacco * this source program is part of the liblockdev library. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License (LGPL) as published by the Free Software Foundation; * version 2.1 dated February 1999. * * 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. * * You should have received a copy of the GNU Lesser General * Public License (LGPL) along with this program; if not, write * to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * On Debian GNU/Linux systems, the complete text of the * GNU Library General Public License can be found in * `/usr/share/common-licenses/LGPL'. * * * * This library provides a stable way to lock devices on a Linux or * Unix system, both following FSSTND 1.2 and SVr4 device locking * methods, and it's built to be portable and to avoid conflicts * with other programs. * It is highly reccommended that all programs that needs to lock a * device (or test if it is locked), call the functions defined in * the public interface of this library. * */ #ifndef _LOCKDEV_H_ #define _LOCKDEV_H_ #ifdef __cplusplus extern "C" { #endif #include /* API of the library */ void liblockdev_incr_debug (void); void liblockdev_reset_debug (void); pid_t dev_testlock (const char *devname); pid_t dev_lock (const char *devname); pid_t dev_relock (const char * devname, const pid_t old_pid); pid_t dev_unlock (const char * devname, const pid_t pid); #ifdef __cplusplus }; #endif #endif /* _LOCKDEV_H_ */ lockdev-1.0.3/docs/0000755000175000017500000000000007021207426013100 5ustar covencovenlockdev-1.0.3/docs/LSB.9912010000600000175000017500000000453507021207426014206 0ustar covencoven------- start of cut text -------------- A dynamically loadable library should be provided with the Operating System for the purpose of locking devices. The library should offer the following API: pid_t dev_testlock ( const char * devname); pid_t dev_lock ( const char * devname); pid_t dev_relock ( const char * devname, pid_t old_pid); pid_t dev_unlock ( const char * devname, pid_t pid); where devname is the full pathname of the device to be locked, old_pid and pid are the ID of the process currently owning the lock (ZERO disables the check of the owner). Return value for success is ZERO (for dev_testlock means that there is no lock on that device), or the process ID of the owner of the lock. Stale locks are always removed by any call to the library. The details of the underlying implementation are left intentionally undefined to permit the development of more robust locking methods than the one described in previous versions of the FHS. The only implementation requirement is that the library must implement the old FHS method to provide backward-compatibility with older programs. Note that future versions of the LSB may drop this requirement. Here is the old FHS device locking method: The naming convention which must be used is "LCK.." followed by the base name of the device. For example, to lock /dev/cua0 the file "LCK..cua0" would be created. The format used for device lock files must be the HDB UUCP lock file format. The HDB format is to store the process identifier (PID) as a ten byte ASCII decimal number, with a trailing newline. For example, if process 1230 holds a lock file, it would contain the eleven characters: space, space, space, space, space, space, one, two, three, zero, and newline. Then, anything wishing to use /dev/cua0 can read the lock file and act accordingly (all locks in /var/lock should be world-readable). A reference implementation of the library can be found at URL: ... ------- end ---------------------------- lockdev-1.0.3/docs/lockdev.30000644000175000017500000001304307021207115014607 0ustar covencoven.TH LOCKDEV 3 "26 Dec 1997" "Linux Manpage" "Linux Programmer's Manual" .SH NAME lockdev, liblockdev, dev_testlock, dev_lock, dev_relock, dev_unlock \- manage device lockfiles .SH SYNOPSIS .B #include .sp .BI "pid_t dev_testlock( const char * " devname ");" .br .BI "pid_t dev_lock( const char * " devname ");" .br .BI "pid_t dev_relock( const char * " devname ", pid_t " pid ");" .br .BI "pid_t dev_unlock( const char * " devname ", pid_t " pid ");" .sp .BI "cc [ "flag " ... ] "file " ... -llockdev [ "library " ] " .SH DESCRIPTION The .B lockdev functions act on device locks normally located in .B /var/lock . The lock is acquired creating a pair of files hardlinked between them and named after the device name (as mandated by FSSTND) and the device's major and minor numbers (as in SVr4 locks). This permits to circumvent a problem using only the FSSTND lock method when the same device exists under different names (for convenience or when a device must be accessable by more than one group of users). .br The lock file names are typically in the form .B LCK..ttyS1 and .B LCK.004.065 , but is provided a way to easily modify them to use the library on different architectures. The content of those files is the pid of the process who owns the lock. .sp The .B dev_testlock() function simply checks if the device is in some way locked and if the owner of the lock is still active (otherwise it removes the lock). It recognise a valid lock even if only one of the two lock files exists (and is owned by an existing process), thus permitting a safe use of this library together with programs using only FSSTND or SVr4 lock style. .sp The .B dev_lock() function first checks if the device is already locked and then tries to acquire the lock building the two lock files. First it creates the file which name contains the major and minor numbers (in SVr4 style), then it creates the file with the device name in its name. This order reduces the clashes with other processes trying to lock the same device (even with a different name) and using this library. It has no problem with processes that uses only the FSSTND algorithm. .sp The .B dev_relock() function changes the owner of an existing lock; if the pid of the old owner is provided, then it checks if the lock was correctly assigned (otherwise there is the possibility of a process acquiring a lock which was owned by another unrelated process). If the device was not locked, locks it. .sp The .B dev_unlock() function removes the existing locks on the device. If the pid of the owner of the lock is provided, then it checks if the lock is assigned to that process, avoiding to remove locks assigned to other existing processes. .SH RETURN VALUES All the functions in .B lockdev library return .B ZERO on successfull completion of the function (dev_testlock returns zero if there is no lock on the device), otherwise, if the device is currently locked by an existing process, they return the pid of the process owner of the lock. They return a negative number when some kind of error happens. Actually they all return only (-1). .SH DEBUGGING The .B API has symbols used only for debugging purposis .sp .BI "int liblockdev_debug" .br .BI "void liblockdev_incr_debug( void );" .br .BI "void liblockdev_reset_debug( void );" .sp which can be used when the liblockdev library is compiled with .B -DDEBUG flag as when using .B make install-dbg , which compiles a debug shared library and installs it under /usr/local/lib/debug (or /usr/lib/debug). .br The value of the global integer is set to 1 by the DEBUG define, and can be set to a different value passing a flag like .B -DDEBUG=3 during compilation of the library, or setting the environment variable .B LIBLOCKDEV_DEBUG to the wanted value before executing your program. .br During execution of your program, the flag's value can be changed from your program or from another terminal, respectively using the function .B liblockdev_incr_debug() , or sending SIGUSR1 to the running process, to increment the value of the integer by one, or using the function .B liblockdev_reset_debug() , or sending SIGUSR2 to the running process, to set to zero the value of the global integer. .br Direct manipulation of the global integer is strongly deprecated, because the data structure of the symbol (actually an integer) could be changed later in some way, or even become a macro. .sp The library prints on stdout some informations like error conditions (level of 1), normal termination conditions (2) or function calling (3). .sp To use the debug shared library, simply define in your environment the variable LD_LIBRARY_PATH=/usr/lib/debug (or /usr/local/lib/debug if built using make install-dbg) and call gdb or directly your program without any need to recompile it. As you can check with ldd, your program will load the debug library instead of the normal one. .br Beware that if your program is setuid or setgid, you must become root to let this work, because ld.so ignores the LD_LIBRARY_PATH variable for security reasons. .sp On .B Debian GNU/Linux systems exists a debug binary package named .B liblockdev1-dbg which installs a shared library built with all debugging options (and the -DDEBUG flag) into /usr/lib/debug . .SH FILES /var/lock/LCK.. .br /var/lock/LCK.. .br /usr/lib/liblockdev.so.1 .br /usr/lib/debug/liblockdev.so.1 .SH HISTORY (c) 1997 by Fabrizio Polacco . .br This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2 dated June, 1991. lockdev-1.0.3/LockDev/0000755000175000017500000000000010320301571013467 5ustar covencovenlockdev-1.0.3/LockDev/Makefile.PL0000644000175000017500000000070610320267435015456 0ustar covencovenuse ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'LockDev', 'VERSION_FROM' => 'LockDev.pm', # finds $VERSION 'LIBS' => [''], 'DEFINE' => '', 'INC' => '-I../src', 'MYEXTLIB' => '../src/lockdev.z', ); sub MY::postamble { ' $(MYEXTLIB): ../src/lockdev.c ../src/lockdev.h cd .. && $(MAKE) static '; } lockdev-1.0.3/LockDev/typemap0000644000175000017500000000006206436645140015107 0ustar covencovenconst char * T_PV pid_t T_IV const pid_t T_IV lockdev-1.0.3/LockDev/test.pl0000644000175000017500000000227307021211344015011 0ustar covencoven# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### We start with some black magic to print on failure. # Change 1..1 below to 1..last_test_to_print . # (It may become useful if the test is moved to ./t subdirectory.) BEGIN { $| = 1; print "1..8\n"; } END {print "not ok 1\n" unless $loaded;} use LockDev; $loaded = 1; print "ok 1\n"; ######################### End of black magic. # Insert your test code below (better if it prints "ok 13" # (correspondingly "not ok 13") depending on the success of chunk 13 # of the test code): # 2 no lock print &LockDev::dev_testlock( "/dev/ttyS3") == 0 ? "ok 2\n" : "not ok 2\n"; print &LockDev::dev_lock( "/dev/ttyS3") == 0 ? "ok 3\n" : "not ok 3\n"; print &LockDev::dev_testlock( "/dev/ttyS3") == $$ ? "ok 4\n" : "not ok 4\n"; print &LockDev::dev_relock( "/dev/ttyS3", 0) == 0 ? "ok 5\n" : "not ok 5\n"; print &LockDev::dev_testlock( "/dev/ttyS3") == $$ ? "ok 6\n" : "not ok 6\n"; print &LockDev::dev_unlock( "/dev/ttyS3", $$) == 0 ? "ok 7\n" : "not ok 7\n"; print &LockDev::dev_testlock( "/dev/ttyS3") == 0 ? "ok 8\n" : "not ok 8\n"; lockdev-1.0.3/LockDev/MANIFEST0000644000175000017500000000010306436645140014632 0ustar covencovenChanges LockDev.pm LockDev.xs MANIFEST Makefile.PL test.pl typemap lockdev-1.0.3/LockDev/LockDev.xs0000644000175000017500000000154707021210714015403 0ustar covencoven#ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef __cplusplus } #endif #include "lockdev.h" static int not_here(s) char *s; { croak("%s not implemented on this architecture", s); return -1; } static double constant(name, arg) char *name; int arg; { errno = 0; switch (*name) { } errno = EINVAL; return 0; not_there: errno = ENOENT; return 0; } MODULE = LockDev PACKAGE = LockDev double constant(name,arg) char * name int arg pid_t dev_testlock ( devname) const char * devname; OUTPUT: RETVAL pid_t dev_lock ( devname) const char * devname; OUTPUT: RETVAL pid_t dev_relock ( devname, old_pid) const char * devname; const pid_t old_pid; OUTPUT: RETVAL pid_t dev_unlock ( devname, pid) const char * devname; const pid_t pid; OUTPUT: RETVAL lockdev-1.0.3/LockDev/LockDev.pm0000644000175000017500000001035607021211645015367 0ustar covencovenpackage LockDev; use strict; use Carp; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD); require Exporter; require DynaLoader; @ISA = qw(Exporter DynaLoader); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. @EXPORT_OK = qw( &dev_testlock &dev_lock &dev_relock &dev_unlock ); $VERSION = '1.0'; sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my $constname; ($constname = $AUTOLOAD) =~ s/.*:://; my $val = constant($constname, @_ ? $_[0] : 0); if ($! != 0) { if ($! =~ /Invalid/) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { croak "Your vendor has not defined LockDev macro $constname"; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } bootstrap LockDev $VERSION; # Preloaded methods go here. # Autoload methods go after =cut, and are processed by the autosplit program. 1; __END__ # Below is the stub of documentation for your module. You better edit it! =head1 NAME LockDev - Perl extension to manage device lockfiles =head1 SYNOPSIS use LockDev; $pid = LockDev::dev_testlock( $device); $pid = LockDev::dev_lock( $device); $pid = LockDev::dev_relock( $device, $oldpid); $pid = LockDev::dev_unlock( $device, $oldpid); =head1 DESCRIPTION The LockDev methods act on device locks normally located in /var/lock . The lock is acquired creating a pair of files hardlinked between them and named after the device name (as mandated by FSSTND) and the device's major and minor numbers (as in SVr4 locks). This permits to circumvent a problem using only the FSSTND lock method when the same device exists under different names (for convenience or when a device must be accessable by more than one group of users). The lock file names are typically in the form LCK..ttyS1 and LCK.004.065 , and their content is the pid of the process who owns the lock. =head1 METHODS $pid = LockDev::dev_testlock( $device); This method simply checks if the device is in some way locked and if the owner of the lock is still active (otherways it removes the lock). It recognise a valid lock even if only one of the two lock files exists (and is owned by an existing process), thus permitting a safe use of this library toghether with programs using only FSSTND or SVr4 lock style. $pid = LockDev::dev_lock( $device); This method first checks if the device is already locked and then tryes to acquire the lock building the two lock files. First it creates the file which name contains the major and minor numbers (in SVr4 style), then it creates the file with the device name in its name. This order reduces the clashes with other processes trying to lock the same device (even with a different name) and using this library. It has no problem with processes that uses only the FSSTND algorithm. $pid = LockDev::dev_relock( $device, $oldpid); This method changes the owner of an existing lock; if the pid of the old owner is provided, then it checks if the lock was correctly assigned (otherways there is the possibility of a process acquiring a lock which was owned by another unrelated process). If the device was not locked, locks it. $pid = LockDev::dev_unlock( $device, $oldpid); This method removes the existing locks on the device. If the pid of the owner of the lock is provided, then it check if the locks are assigned to that process, avoiding to remove locks assigned to other existing processes. =head1 RETURN VALUES All the methods in LockDev library return ZERO on successfull completion of the function (LockDev::dev_testlock returns zero if there is no lock on the device), otherways, if the device is currently locked by an existing process, they return the pid of the process owner of the lock. They return a negative number when some kind of error happens. Actually they all return only (-1). =head1 AUTHOR (c) 1997 by Fabrizio Polacco . The LockDev extension library and the liblockdev 'C' library are licensed under the FSF's LGPL. =head1 SEE ALSO perl(1), lockdev(3). =cut lockdev-1.0.3/LockDev/Changes0000644000175000017500000000017006437043734015002 0ustar covencovenRevision history for Perl extension LockDev. 0.01 Wed Nov 26 18:01:32 1997 - original version; created by h2xs 1.18 lockdev-1.0.3/ChangeLog0000644000175000017500000000370010421760364013725 0ustar covencoven2006-04-20 Paweł Więcek * Version 1.0.3. * src/lockdev.c: Updated _dl_filename_1 to distinguish between character and block devices. Lock file name changes thus from LCK.012.345 to LCK.C.012.345. 2005-10-03 Roger Leigh * Version 1.0.2. * LockDev/Makefile.PL: Merge shobs support from the Debian diff. * Makefile Merge shobs support from the Debian diff. (tarball): Remove --exclude option which was broken with current versions of GNU tar. * src/sample.c (main): Use liblockdev_incr_debug when the "-d" option is used, to fix broken debugging support. * src/ttylock.h: Convert K&R C into ISO C89 C. * src/lockdev.h: Convert K&R C into ISO C89 C. * src/lockdev.c: (General) Replace the use of __linux__ with __GNU_LIBRARY__, and use the GNU libc gnu_dev_major() and gnu_dev_minor() functions rather than kernel macros. (General) Convert K&R C into ISO C89 C. (_dl_filename_1): Remove special casing for CUA devices on Linux systems; these devices have long been deprecated and are no longer available in current kernels. (_dl_filename_2): If a device name has '/' separators in its name, replace them with ':'s. This is to support devices in subdirectories. (_dl_check_devname): If a device pathname starts with DEV_PATH, e.g. "/dev/", strip off only "/dev/", rather than the entire path. This is to support devices in subdirectories under /dev, e.g. DevFS, udev, devpts and LVM. 2001-05-27 Gergely Nagy * Rules.mk: extracted from debian/policy * debian/rules: updated to new Debian Perl policy; move shared library from /lib to /usr/lib; properly strip binaries; include Section and Priority in the deb package * debian/policy: bumped standards-version, added min_perl_policy * debian/control: added build-depends, bumped standards-version, and a few cosmetic fixes * Makefile (perl-lib): Updated to new Debian Perl policy (tarball): do not include debian/ lockdev-1.0.3/AUTHORS0000644000175000017500000000132607304205012013213 0ustar covencovenliblockdev is (c) 1997, 1999 by Fabrizio Polacco Barak Pearlmutter - code revision - suggestion for the use of the semaphore. Juan Cespedes - code revision Daniel Quinlan - suggestion to support the cua devices. - suggestions for naming of functions. Raphael Hertzog - NMU for new perl Adam P. Harris - changes in debian postinst. Martin Schulze - changes in perl makefile - suggestions for changes in assembler stage for debug. Hamish Moffatt, James Troup - dependencies check. Yann Dirson - suggestions for a debugging shared library. Gergely Nagy - upstream maintainer since 1.0.1