2015-01-14 19:11:12 +03:00
/*
2003-08-13 05:53:07 +04:00
Unix SMB / CIFS implementation .
pidfile handling
Copyright ( C ) Andrew Tridgell 1998
2017-07-31 08:11:33 +03:00
Copyright ( C ) Amitay Isaccs 2016
2015-01-14 19:11:12 +03:00
2003-08-13 05:53:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
2015-01-14 19:11:12 +03:00
2003-08-13 05:53:07 +04:00
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 .
2015-01-14 19:11:12 +03:00
2003-08-13 05:53:07 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
2017-07-31 07:47:01 +03:00
# include "replace.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2017-07-31 07:47:01 +03:00
# include "lib/util/blocking.h"
# include "lib/util/debug.h"
# include "lib/util/samba_util.h" /* For process_exists_by_pid() */
2012-07-20 02:41:52 +04:00
# include "lib/util/pidfile.h"
2003-08-13 05:53:07 +04:00
2006-02-28 16:12:39 +03:00
/**
* @ file
* @ brief Pid file handling
*/
2017-07-31 08:11:33 +03:00
int pidfile_path_create ( const char * path , int * outfd )
{
struct flock lck ;
char tmp [ 64 ] = { 0 } ;
pid_t pid ;
int fd , ret = 0 ;
int len ;
ssize_t nwritten ;
pid = getpid ( ) ;
fd = open ( path , O_CREAT | O_WRONLY | O_NONBLOCK , 0644 ) ;
if ( fd = = - 1 ) {
return errno ;
}
if ( ! set_close_on_exec ( fd ) ) {
close ( fd ) ;
return EIO ;
}
lck = ( struct flock ) {
. l_type = F_WRLCK ,
. l_whence = SEEK_SET ,
} ;
do {
ret = fcntl ( fd , F_SETLK , & lck ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ret ! = 0 ) {
ret = errno ;
close ( fd ) ;
return ret ;
}
/*
* PID file is locked by us so from here on we should unlink
* on failure
*/
do {
ret = ftruncate ( fd , 0 ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ret = = - 1 ) {
ret = EIO ;
goto fail_unlink ;
}
len = snprintf ( tmp , sizeof ( tmp ) , " %u \n " , pid ) ;
if ( len < 0 ) {
ret = errno ;
goto fail_unlink ;
}
if ( len > = sizeof ( tmp ) ) {
ret = ENOSPC ;
goto fail_unlink ;
}
do {
nwritten = write ( fd , tmp , len ) ;
} while ( ( nwritten = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ( nwritten = = - 1 ) | | ( nwritten ! = len ) ) {
ret = EIO ;
goto fail_unlink ;
}
if ( outfd ! = NULL ) {
* outfd = fd ;
}
return 0 ;
fail_unlink :
unlink ( path ) ;
close ( fd ) ;
return ret ;
}
void pidfile_fd_close ( int fd )
{
struct flock lck = {
. l_type = F_UNLCK ,
. l_whence = SEEK_SET ,
} ;
int ret ;
do {
ret = fcntl ( fd , F_SETLK , & lck ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
do {
ret = close ( fd ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
}
2006-02-28 16:12:39 +03:00
/**
* return the pid in a pidfile . return 0 if the process ( or pidfile )
2015-01-14 19:11:12 +03:00
* does not exist
2006-02-28 16:12:39 +03:00
*/
2007-12-03 00:32:11 +03:00
pid_t pidfile_pid ( const char * piddir , const char * name )
2003-08-13 05:53:07 +04:00
{
2015-01-19 12:52:11 +03:00
size_t len = strlen ( piddir ) + strlen ( name ) + 6 ;
char pidFile [ len ] ;
2003-08-13 05:53:07 +04:00
int fd ;
char pidstr [ 20 ] ;
2012-12-06 19:02:57 +04:00
pid_t ret = - 1 ;
2003-08-13 05:53:07 +04:00
2015-01-19 12:52:11 +03:00
snprintf ( pidFile , sizeof ( pidFile ) , " %s/%s.pid " , piddir , name ) ;
2003-08-13 05:53:07 +04:00
2004-11-01 23:21:54 +03:00
fd = open ( pidFile , O_NONBLOCK | O_RDONLY , 0644 ) ;
2005-09-26 20:57:08 +04:00
2003-08-13 05:53:07 +04:00
if ( fd = = - 1 ) {
return 0 ;
}
2005-02-10 10:39:14 +03:00
ZERO_STRUCT ( pidstr ) ;
2003-08-13 05:53:07 +04:00
if ( read ( fd , pidstr , sizeof ( pidstr ) - 1 ) < = 0 ) {
goto noproc ;
}
2006-04-24 13:36:09 +04:00
ret = ( pid_t ) atoi ( pidstr ) ;
2012-06-28 05:34:25 +04:00
if ( ret < = 0 ) {
2012-07-20 03:08:16 +04:00
DEBUG ( 1 , ( " Could not parse contents of pidfile %s \n " ,
pidFile ) ) ;
2012-06-28 05:34:25 +04:00
goto noproc ;
}
2015-01-14 19:11:12 +03:00
2008-10-17 14:48:19 +04:00
if ( ! process_exists_by_pid ( ret ) ) {
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d does not exist. \n " , ( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
goto noproc ;
}
2004-11-01 23:21:54 +03:00
if ( fcntl_lock ( fd , F_SETLK , 0 , 1 , F_RDLCK ) ) {
2003-08-13 05:53:07 +04:00
/* we could get the lock - it can't be a Samba process */
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d is not a Samba process. \n " ,
( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
goto noproc ;
}
close ( fd ) ;
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d is running. \n " , ( int ) ret ) ) ;
2006-04-24 13:36:09 +04:00
return ret ;
2003-08-13 05:53:07 +04:00
noproc :
close ( fd ) ;
return 0 ;
}
2006-02-28 16:12:39 +03:00
/**
2015-01-14 19:11:12 +03:00
* create a pid file in the pid directory . open it and leave it locked
2006-02-28 16:12:39 +03:00
*/
2007-12-03 00:32:11 +03:00
void pidfile_create ( const char * piddir , const char * name )
2003-08-13 05:53:07 +04:00
{
2015-01-19 12:52:11 +03:00
size_t len = strlen ( piddir ) + strlen ( name ) + 6 ;
char pidFile [ len ] ;
2003-08-13 05:53:07 +04:00
pid_t pid ;
2017-07-31 08:20:19 +03:00
int ret ;
2003-08-13 05:53:07 +04:00
2015-01-19 12:52:11 +03:00
snprintf ( pidFile , sizeof ( pidFile ) , " %s/%s.pid " , piddir , name ) ;
2003-08-13 05:53:07 +04:00
2007-12-03 00:32:11 +03:00
pid = pidfile_pid ( piddir , name ) ;
2003-08-13 05:53:07 +04:00
if ( pid ! = 0 ) {
2015-01-14 19:11:12 +03:00
DEBUG ( 0 , ( " ERROR: %s is already running. File %s exists and process id %d is running. \n " ,
2003-08-13 05:53:07 +04:00
name , pidFile , ( int ) pid ) ) ;
exit ( 1 ) ;
}
2017-07-31 08:20:19 +03:00
ret = pidfile_path_create ( pidFile , NULL ) ;
if ( ret ! = 0 ) {
DBG_ERR ( " ERROR: Failed to create PID file %s (%s) \n " ,
pidFile , strerror ( ret ) ) ;
2003-08-13 05:53:07 +04:00
exit ( 1 ) ;
}
2005-09-26 20:57:08 +04:00
2003-08-13 05:53:07 +04:00
/* Leave pid file open & locked for the duration... */
}
2012-07-20 03:08:16 +04:00
void pidfile_unlink ( const char * piddir , const char * name )
{
int ret ;
char * pidFile = NULL ;
if ( asprintf ( & pidFile , " %s/%s.pid " , piddir , name ) < 0 ) {
DEBUG ( 0 , ( " ERROR: Out of memory \n " ) ) ;
exit ( 1 ) ;
}
ret = unlink ( pidFile ) ;
if ( ret = = - 1 ) {
DEBUG ( 0 , ( " Failed to delete pidfile %s. Error was %s \n " ,
pidFile , strerror ( errno ) ) ) ;
}
}