locking (3740B)
1 #!/usr/bin/env zsh 2 # 3 # Jaro Mail, your humble and faithful electronic postman 4 # 5 # a tool to easily and privately handle your e-mail communication 6 # 7 # Copyleft (C) 2010-2015 Denis Roio <jaromil@dyne.org> 8 # 9 # This source code is free software; you can redistribute it and/or 10 # modify it under the terms of the GNU Public License as published by 11 # the Free Software Foundation; either version 3 of the License, or 12 # (at your option) any later version. 13 # 14 # This source code is distributed in the hope that it will be useful, 15 # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 # Please refer to the GNU Public License for more details. 18 # 19 # You should have received a copy of the GNU Public License along with 20 # this source code; if not, write to: 21 # Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23 24 lock() { 25 fn "lock $*" 26 _file=$1 27 # can't use ckreq as that returns error on file empty 28 [[ -r "$_file" ]] || { 29 error "cannot unlock, file not existing: $_file" 30 return 1 } 31 32 if helper.isfound dotlock; then 33 dotlock=`command -v dotlock` 34 else 35 dotlock="${WORKDIR}/bin/dotlock" 36 fi 37 38 ${dotlock} "$_file" 39 res=$? 40 case $res in 41 1) error "Cannot lock non existing file: $_file" 42 return 1 ;; 43 3) error "Locked file in use: $_file" 44 45 pidcheck "$1" 46 return 3 ;; 47 48 5) error "Lock is impossible on: $_file" 49 return 5 ;; 50 # success 51 0) print "$$" > "$_file.pid" 52 return 0 ;; 53 54 *) error "Unknown error locking: $res" 55 return 1 ;; 56 esac 57 } 58 59 newlock() { # lock file, create if not existing 60 fn "newlock $*" 61 _file="$1" 62 63 touch "$_file" 64 chmod 600 "$_file" 65 lock "$_file" 66 } 67 68 pidcheck() { # check if lock belongs to us 69 fn "pidcheck $@" 70 _pid="$1" 71 req=(_pid) 72 ckreq || return 1 73 74 if [ -r "${_pid}.pid" ]; then 75 76 lockpid="`cat ${_pid}.pid`" 77 func "pidcheck: $lockpid" 78 if [[ "$$" = "$lockpid" ]]; then 79 func "${_pid} lock belongs to us" 80 else 81 82 error "Unlock attempt by multiple processes on `basename $_pid`" 83 [[ "$FORCE" = "1" ]] || { 84 _prun=1 85 while [ "$_prun" = "1" ]; do 86 [[ $global_quit = 1 ]] && { break } 87 for p in `ps ax | awk '{ print $_pid }'`; do 88 { test "$p" = "$lockpid" } && { break } 89 done 90 if [ "$p" = "$lockpid" ]; then 91 act "Owner (${lockpid}) still running, waiting release..." 92 sleep 1; 93 continue 94 else 95 act "Owner (${lockpid}) not running, taking over the lock" 96 rm -f "${_pid}.pid"; print "$$" > "${_pid}.pid" 97 _prun=0 98 fi 99 done 100 } 101 act "left behind by $lockpid - we ($$) will take over" 102 103 fi 104 105 else # pid file doesn't exists 106 func "no pid file found for: $_pid" 107 func "we will take it over" 108 print "$$" > "${_pid}.pid" 109 fi 110 return 0 111 } 112 113 unlock() { 114 fn "unlock $*" 115 _file="$1" 116 # can't use ckreq as that returns error on file empty 117 [[ -r "$_file" ]] || { 118 error "cannot unlock, file not existing: $_file" 119 return 1 } 120 121 pidcheck "$_file" 122 [[ $? = 0 ]] || { return 1 } 123 124 ${WORKDIR}/bin/dotlock -u "$_file" 125 [[ $? = 0 ]] || { 126 rm -f "${_file}.lock" 127 [[ $? = 0 ]] || { error "Unable to unlock: $_file"; return 1 } 128 } 129 [[ -r "${_file}.pid" ]] && { rm -f "${_file}.pid" } 130 return 0 131 } 132 133 unlink() { # delete a file that we are locking 134 fn "unlink $*" 135 _file="$1" 136 # can't use ckreq as that returns error on file empty 137 [[ -r "$_file" ]] || { 138 error "cannot unlock, file not existing: $_file" 139 return 1 } 140 141 unlock "$_file" 142 ${=rm} "$_file" 143 func "$_file removed" 144 }