1775 lines
55 KiB
C
1775 lines
55 KiB
C
/*
|
|
* COMPONENT_NAME: BLDPROCESS
|
|
*
|
|
* FUNCTIONS: add_hold_entries
|
|
* add_to_hold_file1001
|
|
* append_to_hold_file
|
|
* check_file
|
|
* check_lock
|
|
* cleanup_hold
|
|
* copy_admin
|
|
* copy_hold
|
|
* copy_log
|
|
* delete_from_hold_file1595
|
|
* filecp
|
|
* filename
|
|
* files_are_held
|
|
* hold_cleanup
|
|
* lock_for_edit
|
|
* set_lock
|
|
* set_lock2
|
|
* sort_defunct
|
|
* sort_snap
|
|
* unset_lock
|
|
* unset_lock2
|
|
* update_all_logs
|
|
* update_defunct
|
|
* update_logs
|
|
* update_snapshot
|
|
* update_submit_log1550
|
|
*
|
|
* ORIGINS: 27,71
|
|
*
|
|
* This module contains IBM CONFIDENTIAL code. -- (IBM
|
|
* Confidential Restricted when combined with the aggregated
|
|
* modules for this product)
|
|
* SOURCE MATERIALS
|
|
*
|
|
* (C) COPYRIGHT International Business Machines Corp. 1994
|
|
* All Rights Reserved
|
|
* US Government Users Restricted Rights - Use, duplication or
|
|
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
|
*/
|
|
/*
|
|
* @OSF_FREE_COPYRIGHT@
|
|
* COPYRIGHT NOTICE
|
|
* Copyright (c) 1992, 1991, 1990
|
|
* Open Software Foundation, Inc.
|
|
*
|
|
* Permission is hereby granted to use, copy, modify and freely distribute
|
|
* the software in this file and its documentation for any purpose without
|
|
* fee, provided that the above copyright notice appears in all copies and
|
|
* that both the copyright notice and this permission notice appear in
|
|
* supporting documentation. Further, provided that the name of Open
|
|
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
|
* publicity pertaining to distribution of the software without prior
|
|
* written permission from OSF. OSF makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*/
|
|
/*
|
|
* HISTORY
|
|
* $Log: lockcmds.c,v $
|
|
* Revision 1.11.12.8 1993/11/18 17:14:23 damon
|
|
* CR 745. Fixed unlocking code
|
|
* [1993/11/18 17:14:07 damon]
|
|
*
|
|
* Revision 1.11.12.7 1993/11/10 23:03:28 damon
|
|
* CR 463. changed done=TRUE to done=FALSE
|
|
* [1993/11/10 23:03:19 damon]
|
|
*
|
|
* Revision 1.11.12.6 1993/11/10 18:44:39 root
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/10 18:43:11 root]
|
|
*
|
|
* Revision 1.11.12.5 1993/11/09 16:53:44 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/09 16:52:42 damon]
|
|
*
|
|
* Revision 1.11.12.4 1993/11/08 17:58:45 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/08 16:08:33 damon]
|
|
*
|
|
* Revision 1.11.12.3 1993/11/05 18:50:42 damon
|
|
* CR 745. Fixed bad comment
|
|
* [1993/11/05 18:49:46 damon]
|
|
*
|
|
* Revision 1.11.12.2 1993/11/05 16:42:01 robert
|
|
* Merged with changes from 1.11.12.1
|
|
* [1993/11/05 16:41:50 robert]
|
|
*
|
|
* clean up again
|
|
* [1993/11/04 22:19:59 robert]
|
|
*
|
|
* clean up
|
|
* [1993/11/04 22:09:02 robert]
|
|
*
|
|
* add call to unset_lock() for case where "if (submit)" false
|
|
* in add_to_hold_file()
|
|
* [1993/11/04 16:51:18 robert]
|
|
*
|
|
* In both add_to_hold_file() and rename(), the order of calls
|
|
* to rename() and unset_lock() were changexids so that if a
|
|
* rename() occurs successfully, the call to unset_lock()
|
|
* is not made. This is because rename(), in manipulating
|
|
* the bsubmit.hold and bsubmit.log file, breaks the write
|
|
* lock on the file, and a subsequent call to unset_lock()
|
|
* can generate an error.
|
|
*
|
|
* Added a check to unset_lock() so that in debug mode a
|
|
* warning is printed out if thet target file to unlock
|
|
* is already unlocked. This should help diagnose problems
|
|
* like the above. This is apparently still happening with
|
|
* bsubmit, though I'm not sure why.
|
|
* [1993/10/28 20:38:42 robert]
|
|
*
|
|
* Revision 1.11.12.1 1993/11/03 20:40:33 damon
|
|
* CR 463. More pedantic
|
|
* [1993/11/03 20:38:09 damon]
|
|
*
|
|
* Revision 1.11.3.6 1993/06/11 14:35:20 damon
|
|
* CR 588. Changed a HOLD_FILE to HOLD_FILE_23
|
|
* [1993/06/11 14:35:04 damon]
|
|
*
|
|
* Revision 1.11.3.5 1993/06/07 20:22:16 damon
|
|
* CR 573. Added set_lock2 & unset_lock2 as meta-rcs locks
|
|
* [1993/06/07 20:21:57 damon]
|
|
*
|
|
* Revision 1.11.3.4 1993/05/25 15:09:04 damon
|
|
* CR 395. Added HOLD_FILE_23
|
|
* [1993/05/25 15:07:19 damon]
|
|
*
|
|
* Revision 1.11.3.3 1993/05/21 18:07:17 damon
|
|
* CR 395. Added lock_for_edit()
|
|
* [1993/05/21 18:06:04 damon]
|
|
*
|
|
* Revision 1.11.3.2 1993/05/11 21:27:42 damon
|
|
* Submitting to correct problem with this file being outdated
|
|
* [1993/05/11 21:27:26 damon]
|
|
*
|
|
* Revision 1.11.6.26 1993/05/07 14:36:11 damon
|
|
* CR 504. Check for EACCES after fnctl() too
|
|
* [1993/05/07 14:36:01 damon]
|
|
*
|
|
* Revision 1.11.6.25 1993/05/06 22:57:04 damon
|
|
* CR 504. Set file writeable before fcntl()
|
|
* [1993/05/06 22:52:02 damon]
|
|
*
|
|
* Revision 1.11.6.24 1993/05/06 17:46:12 marty
|
|
* Fix fcntl() bugs.
|
|
* [1993/05/06 17:45:54 marty]
|
|
*
|
|
* Revision 1.11.6.23 1993/05/06 15:59:26 marty
|
|
* Correct argument call to fcntl().
|
|
* [1993/05/06 15:59:09 marty]
|
|
*
|
|
* Revision 1.11.6.22 1993/05/05 20:00:07 marty
|
|
* Use fcntl instead of flock().
|
|
* [1993/05/05 19:59:36 marty]
|
|
*
|
|
* Revision 1.11.6.21 1993/05/05 18:40:22 damon
|
|
* CR 473. files_are_held needed set passed in
|
|
* [1993/05/05 18:40:15 damon]
|
|
*
|
|
* Revision 1.11.6.20 1993/05/04 16:47:10 damon
|
|
* CR 473. Fixed files_are_held
|
|
* [1993/05/04 16:47:00 damon]
|
|
*
|
|
* Revision 1.11.6.19 1993/05/03 21:30:08 damon
|
|
* CR 473. Removed unneeded functions
|
|
* [1993/05/03 21:29:59 damon]
|
|
*
|
|
* Revision 1.11.6.18 1993/05/03 20:17:08 damon
|
|
* CR 473. Simplified outdated functions
|
|
* [1993/05/03 20:17:01 damon]
|
|
*
|
|
* Revision 1.11.6.17 1993/04/29 21:20:00 marty
|
|
* Remove STATIC from add_to_hold_file(), cleanup_hold(), and
|
|
* check_file().
|
|
* [1993/04/29 21:19:45 marty]
|
|
*
|
|
* Revision 1.11.6.16 1993/04/29 20:51:29 marty
|
|
* update_all_logs() is no longer STATIC.
|
|
* [1993/04/29 20:51:12 marty]
|
|
*
|
|
* Revision 1.11.6.15 1993/04/29 14:23:48 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/04/29 14:23:39 damon]
|
|
*
|
|
* Revision 1.11.6.14 1993/04/14 19:17:48 damon
|
|
* CR 193. Put strict locking code into serer side
|
|
* [1993/04/14 19:17:33 damon]
|
|
*
|
|
* Revision 1.11.6.13 1993/04/14 14:43:24 damon
|
|
* CR 457. Keep flock on an open file desc.
|
|
* [1993/04/14 14:43:12 damon]
|
|
*
|
|
* Revision 1.11.6.12 1993/04/09 17:15:53 damon
|
|
* CR 446. Remove warnings with added includes
|
|
* [1993/04/09 17:15:06 damon]
|
|
*
|
|
* Revision 1.11.6.11 1993/04/08 18:42:55 damon
|
|
* CR 446. Clean up include files
|
|
* [1993/04/08 18:41:51 damon]
|
|
*
|
|
* Revision 1.11.6.10 1993/04/05 17:42:16 damon
|
|
* CR 457. Removed refs to cleanup()
|
|
* [1993/04/05 17:42:07 damon]
|
|
*
|
|
* Revision 1.11.6.9 1993/04/05 17:26:29 damon
|
|
* CR 457. Replaced lock dirs with flock calls
|
|
* [1993/04/05 17:04:22 damon]
|
|
*
|
|
* Revision 1.11.6.8 1993/03/17 16:13:06 damon
|
|
* CR 436. Added code from logsubmit.c
|
|
* [1993/03/17 16:02:46 damon]
|
|
*
|
|
* Revision 1.11.6.7 1993/02/19 18:56:05 damon
|
|
* CR 193. Added strict locking to lockcmds.c
|
|
* [1993/02/19 18:55:18 damon]
|
|
*
|
|
* Revision 1.11.6.6 1993/02/16 18:22:45 damon
|
|
* CR 397. Generalized functions
|
|
* [1993/02/16 18:21:42 damon]
|
|
*
|
|
* Revision 1.11.6.5 1993/02/12 23:11:58 damon
|
|
* CR 136. Hold file checking now done by logsubmit
|
|
* [1993/02/12 23:08:28 damon]
|
|
*
|
|
* Revision 1.11.6.4 1993/02/12 16:35:49 damon
|
|
* CR 417. Move bsubmit.hold to rcs tree.
|
|
* CR 193. Prepare for doing strict locking using bsubmit.hold
|
|
* [1993/02/12 16:33:03 damon]
|
|
*
|
|
* Revision 1.11.6.3 1993/01/14 16:30:45 damon
|
|
* CR 397. Removed set_environ
|
|
* [1993/01/14 16:30:30 damon]
|
|
*
|
|
* Revision 1.11.6.2 1993/01/13 20:31:34 damon
|
|
* CR 392. Moved lockcmds to lib/libode
|
|
* [1993/01/13 20:31:03 damon]
|
|
*
|
|
* Revision 1.11.2.5 1992/12/03 19:04:17 damon
|
|
* ODE 2.2 CR 346. Expanded copyright
|
|
* [1992/12/03 18:34:14 damon]
|
|
*
|
|
* Revision 1.11.2.4 1992/10/27 20:10:12 damon
|
|
* CR 290. Fixed defuncting problem.
|
|
* [1992/10/27 20:09:50 damon]
|
|
*
|
|
* Revision 1.11.2.3 1992/09/21 20:00:42 damon
|
|
* CR 240. Converted to odexm
|
|
* [1992/09/21 20:00:21 damon]
|
|
*
|
|
* Converted to sci_rcs
|
|
* [1992/09/09 20:22:12 damon]
|
|
*
|
|
* Revision 1.11.2.2 1992/01/27 19:19:33 damon
|
|
* Fixes bsubmit facet of bug 136.
|
|
* [1992/01/27 18:47:07 damon]
|
|
*
|
|
* Revision 1.11 1991/12/17 20:58:53 devrcs
|
|
* Ported to hp300_hpux
|
|
* [1991/12/17 14:30:38 damon]
|
|
*
|
|
* Revision 1.10 1991/12/05 20:40:49 devrcs
|
|
* Changed COPYHOLD to COPYFILE
|
|
* [1991/10/30 21:48:48 damon]
|
|
*
|
|
* Info switch now works better
|
|
* [91/10/30 09:17:09 damon]
|
|
*
|
|
* Since the 'files held' message was a level VWARN message,
|
|
* if the user used -quiet, he would only see that bsubmit
|
|
* exitted. He would not know why. The message has been changed
|
|
* to level VALWAYS.
|
|
* [91/10/29 15:02:41 damon]
|
|
*
|
|
* lock_hold_file() and unlock_hold_file() are now boolean functions
|
|
* [91/09/18 10:56:59 ezf]
|
|
*
|
|
* don't attempt to unlink track file unless it exists
|
|
* [91/09/13 15:19:57 ezf]
|
|
*
|
|
* Now uses COPYHOLD function to read hold file.
|
|
* [91/09/09 15:09:59 damon]
|
|
*
|
|
* Changed to use new COPYHOLD command of logsubmit.
|
|
* [91/09/05 15:46:03 damon]
|
|
*
|
|
* now uses more descriptive error messages
|
|
* [91/08/29 15:46:54 ezf]
|
|
*
|
|
* Cleaned up append_to_hold_file.
|
|
* Changed check_for_holds to be files_are_held.
|
|
* Changed return value for files_are_held. FALSE->TRUE TRUE->FALSE.
|
|
* [91/08/10 18:15:35 damon]
|
|
*
|
|
* Putting all bsubmit code in synch
|
|
* [91/08/05 17:07:26 damon]
|
|
*
|
|
* Added more defuncting code. Changed to use SCI_ELEM/SCI_LIST
|
|
* [91/08/02 16:56:42 damon]
|
|
*
|
|
* First version using library version of SCAPI
|
|
* [91/07/31 20:10:30 damon]
|
|
*
|
|
* Changed check_for_holds and append_to_hold file to use new SCAPI
|
|
* [91/07/15 14:49:44 damon]
|
|
*
|
|
* Upgrade to Tools II and new user interface
|
|
* [91/01/03 16:48:59 randyb]
|
|
*
|
|
* Added ability to determine backing tree by using the rc variable
|
|
* build_list
|
|
* [90/12/07 13:53:18 randyb]
|
|
*
|
|
* Put in changes to create and use file-by-file tracking log
|
|
* [90/12/05 15:26:16 randyb]
|
|
*
|
|
* This is essentially a new file though many of the routines have the
|
|
* same names as the old ones. The reason for the complete re-write is
|
|
* to make all the log processing steps happen over the network. The
|
|
* same functionality is done but through a different method.
|
|
* [90/11/29 15:01:37 randyb]
|
|
*
|
|
* Style updates; saber c lint
|
|
* [90/11/08 09:17:17 randyb]
|
|
*
|
|
* Revision 1.8 90/10/07 21:50:21 devrcs
|
|
* pre OSF1.0 changes
|
|
*
|
|
* $EndLog$
|
|
*/
|
|
/******************************************************************************
|
|
** Open Software Foundation **
|
|
** Cambridge, MA **
|
|
** Randy Barbano **
|
|
** June 1990 **
|
|
*******************************************************************************
|
|
**
|
|
** Description:
|
|
** These routines provide the commands to lock and unlock the
|
|
** various files used in submitting.
|
|
**
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char sccsid[] = "@(#)89 1.1 src/bldenv/sbtools/libode/lockcmds.c, bldprocess, bos412, GOLDA411a 1/19/94 17:41:20";
|
|
#endif /* not lint */
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <ode/errno.h>
|
|
#include <ode/interface.h>
|
|
#include <ode/lockcmds.h>
|
|
#include <ode/odedefs.h>
|
|
#include <ode/sci.h>
|
|
#include <ode/public/odexm_client.h>
|
|
#include <ode/util.h>
|
|
#include <stdlib.h>
|
|
#include <sys/param.h>
|
|
#include <sys/stat.h>
|
|
|
|
|
|
extern int errno; /* records error type */
|
|
|
|
# define WAITING 1 /* return value for legal waiting */
|
|
# define NO_OPT 2 /* return value for doing no operation */
|
|
# define HELD 3 /* return value indicating that files are held */
|
|
# define MAX_ARGS 1
|
|
# define ONEWRITE 0600 /* mode for lock directories */
|
|
|
|
# define LOCAL_SNAP "LOCAL_SNAP" /* name of temp, local snapshot */
|
|
# define LOCAL_DEF "LOCAL_DEF" /* name of temp, local defunct file */
|
|
# define LOCAL_HOLD "LOCAL_HOLD" /* name of temp, local hold file */
|
|
# define LOCAL_LOG "LOCAL_LOG" /* name of temp, local log file */
|
|
|
|
/*
|
|
* Prototypes
|
|
*/
|
|
int
|
|
add_to_hold_file ( char *, SCI_LIST, BOOLEAN );
|
|
int
|
|
cleanup_hold ( const char * , SCI_LIST, const char *, BOOLEAN );
|
|
STATIC char *
|
|
filename ( const char * string );
|
|
STATIC int
|
|
filecp ( const char * from, const char * to, const char * mode );
|
|
int
|
|
update_snapshot ( const char *, const char *, const char *, const char *,
|
|
BOOLEAN );
|
|
int
|
|
update_defunct ( const char *, const char *, const char * );
|
|
int
|
|
delete_from_hold_file ( const char * start, SCI_LIST, const char *, BOOLEAN );
|
|
int
|
|
update_submit_log ( const char *, const char *, const char * );
|
|
int
|
|
sort_snap ( FILE *, FILE *, FILE * ptr_df, FILE * ptr_tmp );
|
|
int
|
|
sort_defunct ( FILE *, FILE * ptr_up, FILE * ptr_tmp );
|
|
|
|
ERR_LOG
|
|
add_hold_entries ( const char * holdline, const char * hold_file,
|
|
const char * mode, SCI_LIST file_set, BOOLEAN submit )
|
|
|
|
/* This procedure creates the user's hold file which contains
|
|
the list of files being submitted. It then sends that
|
|
file to server and calls the routine to have the server
|
|
append the file to the build's hold file. */
|
|
|
|
{
|
|
|
|
FILE * ptr_uhold; /* misc file pointer */
|
|
SCI_ELEM sci_ptr;
|
|
|
|
ui_print ( VDEBUG, "Entering append_to_hold_file\n" );
|
|
|
|
if (( ptr_uhold = fopen ( hold_file, mode )) == NULL ) {
|
|
ui_print ( VFATAL, "Could not open user hold file: %s.\n",
|
|
hold_file );
|
|
return ( err_log ( OE_OPEN ) );
|
|
} /* if */
|
|
if ( submit ) {
|
|
ui_print ( VDEBUG, "holdline :%s:\n", holdline );
|
|
fprintf ( ptr_uhold, "%s\n", holdline );
|
|
} /* if */
|
|
for ( sci_ptr = sci_first ( file_set ); sci_ptr != NULL;
|
|
sci_ptr = sci_next ( sci_ptr) ) {
|
|
if ( submit )
|
|
fprintf ( ptr_uhold, "%s\n", sci_ptr -> name );
|
|
/* Don't add co locks to already co'd files */
|
|
else if ( sci_ptr -> ver_user == NULL ) {
|
|
fprintf ( ptr_uhold, "%s %s\n", holdline, sci_ptr -> name );
|
|
} /* if */
|
|
} /* for */
|
|
fclose ( ptr_uhold );
|
|
return ( OE_OK );
|
|
}
|
|
|
|
BOOLEAN
|
|
append_to_hold_file ( char * holdline, SCI_LIST file_set,
|
|
BOOLEAN submit, ERR_LOG * log )
|
|
|
|
/* This procedure calls the routine to append the user's hold
|
|
file to the submission's hold file. It does this by sending
|
|
the request to the server through runcmd. */
|
|
|
|
|
|
{
|
|
int status; /* error report */
|
|
BOOLEAN first = TRUE;
|
|
BOOLEAN done=FALSE;
|
|
BOOLEAN result=FALSE;
|
|
|
|
if ( file_set == NULL ) {
|
|
ui_print ( VFATAL, "list of files to lock is NULL.\n" );
|
|
return ( FALSE );
|
|
} /* end if */
|
|
|
|
*log = OE_OK;
|
|
while ( ! done ) {
|
|
status = add_to_hold_file ( holdline, file_set, submit );
|
|
switch ( status ) {
|
|
case ERROR:
|
|
ui_print ( VFATAL, "Could not append to hold file.\n" );
|
|
done = TRUE;
|
|
result = FALSE;
|
|
break;
|
|
case OK:
|
|
done = TRUE;
|
|
result = TRUE;
|
|
break;
|
|
case HELD:
|
|
done = TRUE;
|
|
result = FALSE;
|
|
break;
|
|
case WAITING:
|
|
if ( first ) {
|
|
ui_print ( VNORMAL, "Lock file is temporarily unavailable. Waiting" );
|
|
first = FALSE;
|
|
} /* if */
|
|
ui_print ( VNORMAL, "." );
|
|
fflush ( stdout );
|
|
sleep ( LOCKWAIT );
|
|
break;
|
|
case NO_OPT:
|
|
default:
|
|
ui_print ( VFATAL, "logsubmit exit status=%d while appending to hold file.\n%s\n",
|
|
status, NOTIFY );
|
|
done = TRUE;
|
|
result = FALSE;
|
|
break;
|
|
} /* switch */
|
|
} /* while */
|
|
return ( result );
|
|
} /* unlock log files */
|
|
|
|
|
|
BOOLEAN
|
|
update_all_logs (
|
|
BOOLEAN defunct, /* are any files defunct? */
|
|
char * usr_snap,
|
|
char * usr_defunct,
|
|
char * usr_log )
|
|
|
|
/* This function calls the server routine which updates all
|
|
the update logs: SNAPSHOT, DEFUNCT, and bsubmit.log. This
|
|
routine also passes the user's log file to the server. It
|
|
returns TRUE if all went well, FALSE otherwise. */
|
|
|
|
|
|
{
|
|
int status; /* error report */
|
|
OXM_CNXTN build_monitor;
|
|
int i;
|
|
ERR_LOG log;
|
|
const char *av [16];
|
|
BOOLEAN locked = FALSE, /* misc boolean */
|
|
first = TRUE; /* misc boolean */
|
|
|
|
ui_print ( VDETAIL, "updating SNAPSHOT, DEFUNCT, and submit logs.\n" );
|
|
|
|
oxm_open ( &build_monitor, 2 );
|
|
i = 0;
|
|
av [i++] = "-t1";
|
|
av [i++] = "1";
|
|
av [i++] = COPYLOG;
|
|
av [i++] = usr_snap;
|
|
av [i++] = ui_ver_switch ();
|
|
log = oxm_runcmd ( build_monitor, i, av, NULL );
|
|
log = oxm_endcmd ( build_monitor, &status );
|
|
if ( defunct ) {
|
|
i = 0;
|
|
av [i++] = "-t1";
|
|
av [i++] = "1";
|
|
av [i++] = COPYLOG;
|
|
av [i++] = usr_defunct;
|
|
av [i++] = ui_ver_switch ();
|
|
log = oxm_runcmd ( build_monitor, i, av, NULL );
|
|
log = oxm_endcmd ( build_monitor, &status );
|
|
} /* if */
|
|
log = oxm_close ( build_monitor );
|
|
|
|
if ( status == OK ) {
|
|
while ( ! locked ) {
|
|
oxm_open ( &build_monitor, 2 );
|
|
i = 0;
|
|
av [i++] = "-t1";
|
|
av [i++] = "1";
|
|
av [i++] = UPDATELOGS;
|
|
av [i++] = usr_log;
|
|
av [i++] = ui_ver_switch ();
|
|
log = oxm_runcmd ( build_monitor, i, av, NULL );
|
|
log = oxm_endcmd ( build_monitor, &status );
|
|
log = oxm_close ( build_monitor );
|
|
|
|
switch ( status ) {
|
|
case ERROR:
|
|
return ( FALSE );
|
|
|
|
case OK:
|
|
locked = TRUE;
|
|
break;
|
|
|
|
case WAITING:
|
|
if ( first == TRUE ) {
|
|
ui_print ( VNORMAL,
|
|
"Lock file is temporarily unavailable. Waiting" );
|
|
first = FALSE;
|
|
} /* if */
|
|
|
|
ui_print ( VNORMAL, "." );
|
|
fflush ( stdout );
|
|
sleep ( LOCKWAIT );
|
|
break;
|
|
|
|
case NO_OPT:
|
|
default:
|
|
ui_print ( VFATAL, "logsubmit exit status=%d while updating log files.\n%s\n",
|
|
status, NOTIFY );
|
|
return ( FALSE );
|
|
} /* switch */
|
|
}
|
|
} else
|
|
return ( FALSE );
|
|
/* if */
|
|
return ( TRUE );
|
|
} /* update all logs */
|
|
|
|
int
|
|
hold_cleanup ( const char * holdline, SCI_LIST file_set,
|
|
const char * submit_set, BOOLEAN submit )
|
|
|
|
/* This procedure cleans up the hold file by calling the
|
|
server to remove the files held. */
|
|
|
|
{
|
|
int status; /* error report */
|
|
BOOLEAN first = TRUE;
|
|
BOOLEAN done = FALSE;
|
|
|
|
ui_print ( VDETAIL, "cleaning up hold file; removing entries.\n" );
|
|
while ( !done ) {
|
|
status = cleanup_hold ( holdline, file_set, submit_set, submit );
|
|
switch ( status ) {
|
|
case ERROR:
|
|
ui_print ( VFATAL, "submitted files may still be held.\n%s\n", NOTIFY );
|
|
return ( ERROR );
|
|
|
|
case OK:
|
|
done = TRUE;
|
|
break;
|
|
|
|
case WAITING:
|
|
if ( first == TRUE ) {
|
|
ui_print ( VNORMAL,
|
|
"Lock file is temporarily unavailable. Waiting" );
|
|
first = FALSE;
|
|
} /* if */
|
|
|
|
ui_print ( VNORMAL, "." );
|
|
fflush ( stdout );
|
|
sleep ( LOCKWAIT );
|
|
break;
|
|
|
|
case NO_OPT:
|
|
default:
|
|
ui_print ( VFATAL, "logsubmit exit status=%d while cleaning up hold file.\n%s\n",
|
|
status, NOTIFY );
|
|
ui_print ( VWARN, "submitted files are still held.\n" );
|
|
return ( ERROR );
|
|
} /* switch */
|
|
} /* while */
|
|
return ( OK );
|
|
} /* hold cleanup */
|
|
|
|
/* logsubmit */
|
|
int
|
|
check_file ( void )
|
|
|
|
/* This procedure makes sure the file to append to is there. */
|
|
|
|
{
|
|
if ( ui_entry_cnt ( ARGS_OP ) != 1 ) {
|
|
ui_print ( VFATAL, "file to use is required argument.\n" );
|
|
return ( NO_OPT );
|
|
} /* if */
|
|
|
|
if ( access ( ui_entry_value ( ARGS_OP, 1 ), R_OK ) != OK ) {
|
|
ui_print ( VFATAL, "File to use, %s, not accessible.\n",
|
|
ui_entry_value ( ARGS_OP, 1 ));
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
return ( OK );
|
|
} /* check file */
|
|
|
|
|
|
|
|
int check_lock ( const char * lockdir )
|
|
|
|
/* This procedure sets up the lock type then tries to lock
|
|
the file. If it succeeds, it returns OK, else ERROR. */
|
|
|
|
{
|
|
/*
|
|
* FIXME: this is bogus, no waiting is done. What is really needed is
|
|
a counting lock.
|
|
*/
|
|
int rval = WAITING; /* return value */
|
|
|
|
if ( access ( lockdir, R_OK ) == ERROR ) {
|
|
rval = OK;
|
|
} /* if */
|
|
|
|
return ( rval );
|
|
} /* set lock */
|
|
|
|
int
|
|
lock_for_edit ( const char * file )
|
|
{
|
|
int fd;
|
|
char buf[MAXPATHLEN];
|
|
int status;
|
|
|
|
if ( ( status = set_lock ( file, &fd ) ) != OK ) {
|
|
ui_print ( VALWAYS, "locked\n" );
|
|
fflush ( stdout );
|
|
return ( status );
|
|
} /* if */
|
|
ui_print ( VALWAYS, "locking\n" );
|
|
fflush ( stdout );
|
|
/*
|
|
* Wait for input (any input is fine) from calling process
|
|
* before removing lock.
|
|
*/
|
|
read ( 0, buf, sizeof(buf) );
|
|
|
|
unset_lock ( file, fd );
|
|
return ( OK );
|
|
} /* end lock_for_edit */
|
|
|
|
int
|
|
set_lock ( const char * file, int * fd )
|
|
|
|
/* This procedure sets up the lock type then tries to lock
|
|
the file. If it succeeds, it returns OK, else ERROR. */
|
|
|
|
{
|
|
int rval = OK; /* return value */
|
|
struct flock flk_desc;
|
|
struct flock *flk_ptr;
|
|
|
|
flk_desc.l_type = F_WRLCK;
|
|
flk_desc.l_whence = 0;
|
|
flk_desc.l_start = 0;
|
|
flk_desc.l_len = 0;
|
|
flk_ptr = &flk_desc;
|
|
chmod ( file, S_IWUSR | S_IRUSR );
|
|
/*
|
|
* After the chmod, it is possible for another process to have already
|
|
* gained the lock and performed an operation setting the file read only.
|
|
* This will result in a O_WRONLY open to fail.
|
|
*/
|
|
*fd = open ( file, O_WRONLY );
|
|
if ( *fd == -1 && errno == EACCES )
|
|
return ( WAITING );
|
|
/* if */
|
|
if ( fcntl ( *fd, F_SETLK, flk_ptr ) == -1 ) {
|
|
if ( errno == EWOULDBLOCK ) { /* okay to err on existing lock */
|
|
ui_print ( VDEBUG, "\tfile, %s, already locked.\n", file );
|
|
rval = WAITING;
|
|
} else if ( errno == EACCES )
|
|
return ( WAITING );
|
|
else {
|
|
ui_print ( VFATAL, "could not lock: %s; error: %d.\n", file, errno );
|
|
rval = ERROR;
|
|
} /* else */
|
|
} /* if */
|
|
return ( rval );
|
|
} /* set lock */
|
|
|
|
int
|
|
set_lock2 ( const char * file, int * fd )
|
|
{
|
|
char f [MAXPATHLEN];
|
|
char d [MAXPATHLEN];
|
|
char dbl_comma_file [MAXPATHLEN];
|
|
|
|
path ( file, d, f );
|
|
concat ( dbl_comma_file, sizeof(dbl_comma_file), d, "/,,", f, NULL );
|
|
*fd = open ( dbl_comma_file, O_CREAT | O_EXCL, 0600 );
|
|
if ( *fd == -1 ) {
|
|
return ( WAITING );
|
|
} else {
|
|
return ( OK );
|
|
} /* if */
|
|
} /* end set_lock2 */
|
|
|
|
int
|
|
unset_lock ( const char * file, int fd )
|
|
|
|
/* This procedure sets the lock type then tries to unlock
|
|
the directory. If it succeeds, it returns OK, else ERROR. */
|
|
|
|
{
|
|
struct flock flk_desc;
|
|
struct flock *flk_ptr;
|
|
|
|
flk_desc.l_type = F_UNLCK;
|
|
flk_desc.l_whence = 0;
|
|
flk_desc.l_start = 0;
|
|
flk_desc.l_len = 0;
|
|
flk_ptr = &flk_desc;
|
|
|
|
/*
|
|
* The code in the following ifdef does not properly check the state
|
|
* of the file and thus the unlock operation may never occur.
|
|
*/
|
|
#ifdef notdef
|
|
/* add more debug information about state of the target file */
|
|
|
|
if (fcntl( fd, F_GETLK, flk_ptr) < 0) {
|
|
ui_print (VDEBUG, "could not check lock status on %s", file);
|
|
return(ERROR);
|
|
}
|
|
|
|
if (flk_desc.l_type == F_WRLCK) {
|
|
ui_print (VDEBUG, " ok to unlock - %s already locked\n", file);
|
|
}
|
|
|
|
/* if somehow the lock on the file was broken by some file operation, */
|
|
/* print a warning, but allow OK return. For now assume this is OK */
|
|
/* and allow an OK return until the locking scheme is improved (this */
|
|
/* should really never happen */
|
|
|
|
if (flk_desc.l_type == F_UNLCK) {
|
|
ui_print (VDEBUG, " WARNING - %s was unlocked previous to unset_lock \n", file);
|
|
return ( OK );
|
|
}
|
|
#endif
|
|
if ( fcntl ( fd, F_SETLK, flk_ptr ) == -1 ) {
|
|
ui_print ( VFATAL, "could not unlock: %s, error: %d.\n", file, errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
close (fd);
|
|
return ( OK );
|
|
} /* unset lock */
|
|
|
|
int
|
|
unset_lock2 ( const char * file, int fd )
|
|
|
|
/* This procedure sets the lock type then tries to unlock
|
|
the directory. If it succeeds, it returns OK, else ERROR. */
|
|
|
|
{
|
|
char f [MAXPATHLEN];
|
|
char d [MAXPATHLEN];
|
|
char dbl_comma_file [MAXPATHLEN];
|
|
|
|
path ( file, d, f );
|
|
concat ( dbl_comma_file, sizeof(dbl_comma_file), d, "/,,", f, NULL );
|
|
close ( fd );
|
|
if ( unlink ( dbl_comma_file ) == -1 ) {
|
|
ui_print ( VFATAL, "could not unlock: %s, error: %d.\n", file, errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
return ( OK );
|
|
} /* unset lock */
|
|
|
|
|
|
int
|
|
copy_log ( const char * copyfile )
|
|
|
|
/* This function copys the file designated by the first argument
|
|
in the args list to the second argument. It returns OK if
|
|
all went well, ERROR otherwise. */
|
|
|
|
{
|
|
char * chptr; /* points to end name */
|
|
|
|
if (( chptr = filename ( copyfile )) == NULL )
|
|
return ( ERROR );
|
|
|
|
if ( streq ( chptr, TMP_DEFUNCT ) || streq ( chptr, TMP_SNAP ))
|
|
return ( filecp ( copyfile, chptr, WRITE ));
|
|
|
|
else {
|
|
ui_print ( VFATAL, "ERROR: file to copy, %s, is not a legal name.\n",
|
|
copyfile );
|
|
return ( ERROR );
|
|
} /* else */
|
|
} /* copy log */
|
|
|
|
int
|
|
copy_hold ( const char * holdfile, const char * copyfile )
|
|
/* This function copys the file designated by the first argument
|
|
in the args list to the second argument. It returns OK if
|
|
all went well, ERROR otherwise. */
|
|
|
|
{
|
|
ui_print ( VDEBUG, "copy_hold: %s --> %s\n", holdfile, copyfile );
|
|
|
|
if (( filename ( copyfile )) == NULL )
|
|
return ( ERROR );
|
|
|
|
return ( filecp ( holdfile, copyfile, WRITE ));
|
|
} /* copy hold */
|
|
|
|
STATIC char *
|
|
filename ( const char * string )
|
|
|
|
/* This function returns the name of the file which is at the end
|
|
of string. It accounts for the date stamp in front of the
|
|
name. It returns NULL if anything goes wrong. */
|
|
|
|
{
|
|
|
|
char * ptr; /* points to name in string */
|
|
|
|
if (( ptr = strrchr ( string, SLASH )) == NULL ) {
|
|
#ifdef notdef
|
|
ui_print ( VFATAL, "ERROR: file to copy, %s, is not in legal directory.\n",
|
|
string );
|
|
return (( char *) NULL );
|
|
#endif
|
|
ptr = (char *)string;
|
|
} /* if */
|
|
if ( *(ptr + 3) == COLON )
|
|
ptr += 7; /* advance beyond hh.mm. prefix */
|
|
else
|
|
ptr += 6; /* advance beyond h.mm. prefix */
|
|
|
|
ui_print ( VDEBUG, "filename is: %s.\n", ptr );
|
|
return ( ptr );
|
|
} /* filename */
|
|
|
|
|
|
|
|
STATIC int
|
|
filecp ( const char * from, const char * to, const char * mode )
|
|
|
|
/* This function appends the from file information to the to
|
|
file. It returns OK if all went well, ERROR otherwise. */
|
|
|
|
{
|
|
FILE * ptr_to, /* file to append to */
|
|
* ptr_from; /* file to append */
|
|
|
|
if (( ptr_to = fopen ( to, mode )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not open file: %s, to copy to.\n", to );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( ptr_from = fopen ( from, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not open user file: %s.\n", from );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ffilecopy ( ptr_from, ptr_to ) != OK ) {
|
|
ui_print ( VFATAL, "file copy, mode %s failed: %s to %s.\n",
|
|
mode, from, to );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
fclose ( ptr_to );
|
|
fclose ( ptr_from );
|
|
return ( OK );
|
|
} /* filecp */
|
|
|
|
|
|
|
|
int copy_admin ( const char * fromfile )
|
|
|
|
/* This function copies the file designated by the first argument
|
|
in the args list to the second argument. It returns OK if
|
|
all went well, ERROR otherwise. */
|
|
|
|
{
|
|
char * chptr; /* points to end name */
|
|
|
|
if (( chptr = strrchr ( fromfile, SLASH )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: file to copy, %s, is not in legal directory.\n",
|
|
fromfile );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
chptr++;
|
|
ui_print ( VDEBUG, "filename is: %s.\n", chptr );
|
|
#ifdef notdef
|
|
if ( streq ( chptr, DEFUNCT ) || streq ( chptr, SNAPSHOT ) ||
|
|
streq ( chptr, SUBLOG ) || streq ( chptr, HOLD_FILE ))
|
|
#endif
|
|
if ( strcmp ( chptr, HOLD_FILE ) == 0 ) {
|
|
return ( filecp ( fromfile, HOLD_FILE_23, WRITE ));
|
|
} else {
|
|
return ( filecp ( fromfile, chptr, WRITE ));
|
|
} /* if */
|
|
#ifdef notdef
|
|
else {
|
|
ui_print ( VFATAL, "ERROR: file to copy, %s, is not a legal name.\n",
|
|
fromfile );
|
|
return ( ERROR );
|
|
} /* else */
|
|
#endif
|
|
} /* copy admin */
|
|
|
|
STATIC BOOLEAN
|
|
files_are_held ( SCI_LIST file_set, int * status, BOOLEAN submit,
|
|
const char * set )
|
|
|
|
/* This function compares the list of held files with the usrhold
|
|
file to see if any of the files are already held */
|
|
|
|
{
|
|
FILE * real_hold; /* pointer to hold file */
|
|
char line [ PATH_LEN ]; /* misc string */
|
|
char * line_ptr;
|
|
BOOLEAN files_held = FALSE;
|
|
char hold_holder [ STRING_LEN ]; /* name and date of holder */
|
|
char * token;
|
|
char * user;
|
|
char * locked_set;
|
|
SCI_ELEM sci_ptr;
|
|
|
|
*status = OK;
|
|
|
|
if (( real_hold = fopen ( HOLD_FILE_23, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read from hold file: %s.\n",
|
|
HOLD_FILE_23 );
|
|
fclose ( real_hold );
|
|
*status = ERROR;
|
|
return ( TRUE );
|
|
} /* if */
|
|
|
|
while ( fgets ( line, PATH_LEN, real_hold ) != NULL ) {
|
|
line[strlen(line) - 1] = NUL;
|
|
if ( line[0] == ':' ) {
|
|
if ( line[1] != ':' ) {
|
|
strcpy ( hold_holder, line );
|
|
continue;
|
|
|
|
/* If a '::' line is encountered, then it is a co lock. If */
|
|
/* hold_skip == 0, then this is a submission and co locks don't */
|
|
/* need to be checked since this stage can't be reached if */
|
|
/* the files aren't already checked-out. */
|
|
} else if ( line[1] == ':' && !submit ) {
|
|
line_ptr = line;
|
|
token = nxtarg ( &line_ptr, WHITESPACE );
|
|
locked_set = nxtarg ( &line_ptr, WHITESPACE );
|
|
|
|
/* Is the lock for the same set? If not, don't check this lock. */
|
|
if ( strcmp ( set, locked_set ) == 0 ) {
|
|
user = nxtarg ( &line_ptr, WHITESPACE );
|
|
token = nxtarg ( &line_ptr, WHITESPACE );
|
|
for ( sci_ptr = sci_first ( file_set ); sci_ptr != NULL;
|
|
sci_ptr = sci_next ( sci_ptr ) ) {
|
|
if ( strcmp ( sci_ptr -> name, token ) == 0) {
|
|
fprintf ( stderr, "File: %s\nis held by %s\n", token, user );
|
|
files_held = TRUE;
|
|
continue;
|
|
} /* if */
|
|
} /* for */
|
|
} /* if */
|
|
} /* if */
|
|
} else
|
|
for ( sci_ptr = sci_first ( file_set ); sci_ptr != NULL;
|
|
sci_ptr = sci_next ( sci_ptr ) ) {
|
|
if ( gmatch ( sci_ptr -> name, line ) ) {
|
|
fprintf ( stderr, "File: %s\nis held by %s\n", line, hold_holder );
|
|
files_held = TRUE;
|
|
continue;
|
|
} /* if */
|
|
} /* for */
|
|
/* if */
|
|
} /* while */
|
|
|
|
fclose ( real_hold );
|
|
|
|
return ( files_held );
|
|
} /* files_are_held */
|
|
|
|
int
|
|
add_to_hold_file ( char * holdline, SCI_LIST file_set, BOOLEAN submit )
|
|
|
|
/* This function appends the new hold file information to the
|
|
existing hold file. It also unsets the lock on the hold
|
|
file. It returns OK if all went well, ERROR otherwise. */
|
|
|
|
|
|
{
|
|
int status;
|
|
int lock_fd;
|
|
ERR_LOG log;
|
|
char * set_ptr;
|
|
char * set_tmp;
|
|
char * set;
|
|
|
|
if ( (status = set_lock ( HOLD_FILE_23, &lock_fd ) ) != OK ) return ( status );
|
|
set_tmp = strdup ( holdline );
|
|
set_ptr = set_tmp;
|
|
set = nxtarg ( &set_ptr, WHITESPACE ); /* skip first token */
|
|
set = nxtarg ( &set_ptr, WHITESPACE );
|
|
if ( !files_are_held (file_set, &status, submit, set )
|
|
&& status != ERROR ) {
|
|
|
|
free ( set_tmp );
|
|
|
|
/* co locks go at the end of the file, submit locks */
|
|
/* go at the beginning of the file */
|
|
|
|
if ( submit ) {
|
|
|
|
log = add_hold_entries ( holdline, LOCAL_HOLD, WRITE, file_set, submit );
|
|
status = filecp ( HOLD_FILE_23, LOCAL_HOLD, APPEND );
|
|
if ( status == ERROR ) {
|
|
status = unset_lock ( HOLD_FILE_23, lock_fd );
|
|
return (status);
|
|
} /* if */
|
|
status = rename ( LOCAL_HOLD, HOLD_FILE_23 ); /* breaking the lock */
|
|
if ( status == ERROR ) {
|
|
ui_print ( VFATAL, "ERROR: could not mv %s to %s.\n", LOCAL_HOLD, HOLD_FILE_23 );
|
|
} /* if */
|
|
return(status);
|
|
|
|
} else {
|
|
|
|
log = add_hold_entries ( holdline, HOLD_FILE_23, APPEND, file_set, submit );
|
|
status = unset_lock ( HOLD_FILE_23, lock_fd );
|
|
return (status);
|
|
|
|
} /* if */
|
|
|
|
} else {
|
|
|
|
free ( set_tmp );
|
|
unset_lock ( HOLD_FILE_23, lock_fd );
|
|
return ( HELD );
|
|
|
|
} /* if */
|
|
} /* add to hold file */
|
|
|
|
|
|
int update_logs ( const char * usrlog )
|
|
|
|
/* This function updates the submissions logs. There are three
|
|
logs which can be updated; the submission log and SNAPSHOT
|
|
file, both of which are always updated, and the DEFUNCT file
|
|
which is updated if is_defunct is TRUE. If the logs are
|
|
updated successfully, this routine returns OK, else ERROR. */
|
|
|
|
{
|
|
char * name; /* points to end name */
|
|
BOOLEAN isdefunct; /* misc boolean */
|
|
int status;
|
|
int lock_fd;
|
|
|
|
isdefunct = ( access ( TMP_DEFUNCT, R_OK ) == OK );
|
|
|
|
if (( name = filename ( usrlog )) == NULL )
|
|
return ( ERROR );
|
|
|
|
ui_print ( VDEBUG, "opened tmp defunct file\n" );
|
|
if ( ! streq ( name, TMP_LOG )) {
|
|
ui_print ( VFATAL, "ERROR: user log file, %s, is not a legal name.\n",
|
|
usrlog );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ( status = set_lock ( SUBLOG, &lock_fd ) ) != OK)
|
|
return ( status );
|
|
/* if */
|
|
ui_print ( VDEBUG, "about to update snapshot file\n" );
|
|
if ( update_snapshot ( SNAPSHOT, TMP_SNAP, LOCAL_SNAP, TMP_DEFUNCT, isdefunct)
|
|
== ERROR ) {
|
|
unset_lock ( SUBLOG, lock_fd );
|
|
return ( ERROR );
|
|
} /* if */
|
|
ui_print ( VDEBUG, "about to update defunct file\n" );
|
|
if ( isdefunct ) {
|
|
if ( update_defunct ( DEFUNCT, TMP_DEFUNCT, LOCAL_DEF ) == ERROR ) {
|
|
unset_lock ( SUBLOG, lock_fd );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* if */
|
|
|
|
ui_print ( VDEBUG, "about to update submit log\n" );
|
|
if ( update_submit_log ( SUBLOG, usrlog, LOCAL_LOG ) == ERROR ) {
|
|
unset_lock ( SUBLOG, lock_fd );
|
|
return ( ERROR );
|
|
}
|
|
ui_print ( VDEBUG, "about to replace snapshot file\n" );
|
|
if ( rename ( LOCAL_SNAP, SNAPSHOT ) == ERROR ) {
|
|
ui_print ( VFATAL, "ERROR: could not mv %s to %s.\n", LOCAL_SNAP, SNAPSHOT);
|
|
unset_lock ( SUBLOG, lock_fd );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
ui_print ( VDEBUG, "about to replace defunct file\n" );
|
|
if ( isdefunct ) {
|
|
if ( rename ( LOCAL_DEF, DEFUNCT ) == ERROR ) {
|
|
ui_print ( VFATAL, "ERROR: could not mv %s to %s.\n", LOCAL_DEF, DEFUNCT);
|
|
unset_lock ( SUBLOG, lock_fd );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* if */
|
|
|
|
ui_print ( VDEBUG, "about to remove tmp defunct file\n" );
|
|
if ( access ( TMP_DEFUNCT, F_OK ) == OK ) {
|
|
if ( unlink ( TMP_DEFUNCT ) == ERROR )
|
|
ui_print ( VFATAL, "could not remove tmp log: %s.\n",
|
|
TMP_DEFUNCT );
|
|
} /* if */
|
|
|
|
ui_print ( VDEBUG, "about to remove tmp snapshot file\n" );
|
|
if ( access ( TMP_SNAP, F_OK ) == OK ) {
|
|
if ( unlink ( TMP_SNAP ) == ERROR )
|
|
ui_print ( VFATAL, "could not remove tmp log: %s.\n", TMP_SNAP );
|
|
} /* if */
|
|
|
|
ui_print ( VDEBUG, "about to replace submit log file\n" );
|
|
status = rename ( LOCAL_LOG, SUBLOG );
|
|
if (status == ERROR ) {
|
|
ui_print ( VFATAL, "ERROR: could not mv %s to %s.\n", LOCAL_LOG, SUBLOG );
|
|
unset_lock ( SUBLOG, lock_fd );
|
|
return ( ERROR );
|
|
} /* if */
|
|
/* and the rename() call has broken the lock */
|
|
|
|
ui_print ( VDEBUG, "done updating logs, unlocking\n" );
|
|
return (status);
|
|
} /* update logs */
|
|
|
|
|
|
|
|
int
|
|
update_snapshot ( const char * snapshot_f, const char * update_f,
|
|
const char * tmp_f, const char * defunct_f,
|
|
BOOLEAN defunct )
|
|
|
|
/* This function attempts to update the SNAPSHOT file.
|
|
It returns OK if the update and snapshot files were
|
|
merged and moved to SNAPSHOT, ERROR if not. */
|
|
|
|
{
|
|
FILE * ptr_ss, /* pointer to snapshot file */
|
|
* ptr_df = NULL, /* pointer to defunct file */
|
|
* ptr_up, /* pointer to update file */
|
|
* ptr_tmp; /* pointer to tmp file */
|
|
int rvalue; /* return value */
|
|
|
|
if (( ptr_ss = fopen ( snapshot_f, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read SNAPSHOT file: %s.\n",
|
|
snapshot_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( ptr_up = fopen ( update_f, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read user snapshot file: %s.\n",
|
|
update_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( ptr_tmp = fopen ( tmp_f, WRITE )) == NULL ) {
|
|
ui_print ( VFATAL,
|
|
"ERROR: could not write to temporary snapshot file: %s.\n", tmp_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( defunct ) {
|
|
if (( ptr_df = fopen ( defunct_f, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read defunct file: %s.\n",
|
|
defunct_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
rvalue = sort_snap ( ptr_ss, ptr_up, ptr_df, ptr_tmp );
|
|
} /* if */
|
|
|
|
else
|
|
rvalue = sort_snap ( ptr_ss, ptr_up, (FILE *) NULL, ptr_tmp );
|
|
|
|
fclose ( ptr_ss );
|
|
if ( defunct ) {
|
|
fclose ( ptr_df );
|
|
}
|
|
fclose ( ptr_up );
|
|
fclose ( ptr_tmp );
|
|
return ( rvalue );
|
|
} /* update snapshot */
|
|
|
|
|
|
|
|
int
|
|
sort_snap (
|
|
FILE * ptr_ss, /* pointer to snapshot file */
|
|
FILE * ptr_up, /* pointer to update file */
|
|
FILE * ptr_df, /* pointer to defunct file */
|
|
FILE * ptr_tmp ) /* pointer to tmp file */
|
|
|
|
|
|
/* This function merges the SNAPSHOT file with the new
|
|
changes. It does it by assuming each file is an ascii
|
|
sorted list. It is all in one long procedure to save
|
|
time; SNAPSHOT is a long file. If everything works,
|
|
it returns OK, ERROR otherwise. */
|
|
|
|
{
|
|
char lnss [ STRING_LEN ], /* misc string */
|
|
lnup [ STRING_LEN ], /* misc string */
|
|
lndf [ STRING_LEN ], /* misc string */
|
|
* chss, /* points to each ch */
|
|
* chnew; /* points to each ch */
|
|
BOOLEAN endmerge, /* misc boolean */
|
|
next_line, /* -1 if line from defunct, 1 if from update */
|
|
endss = FALSE, /* misc boolean */
|
|
endup = FALSE, /* misc boolean */
|
|
enddf = FALSE; /* misc boolean */
|
|
|
|
ui_print ( VDEBUG, "sorting snapshot file\n" );
|
|
if ( fgets ( lnss, STRING_LEN, ptr_ss ) == NULL ) {
|
|
ui_print ( VFATAL, "SNAPSHOT file is empty.\n" );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( fgets ( lnup, STRING_LEN, ptr_up ) == NULL )
|
|
endup = TRUE;
|
|
|
|
if ( ptr_df == NULL || fgets ( lndf, STRING_LEN, ptr_df ) == NULL )
|
|
enddf = TRUE;
|
|
|
|
if ( endup && enddf ) {
|
|
ui_print ( VFATAL, "ERROR: user update and defunct files are empty.\n" );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ! endup ) { /* more lines in update */
|
|
if (( enddf ) || ( strcmp ( lnup, lndf ) < 0 ))
|
|
next_line = 1;
|
|
else
|
|
next_line = -1;
|
|
} /* if */
|
|
|
|
else if ( enddf ) /* no more lines in either */
|
|
next_line = 0;
|
|
else /* lines left in defunct */
|
|
next_line = -1;
|
|
|
|
endmerge = ( endss ) || ( next_line == 0 );
|
|
|
|
while ( ! endmerge ) {
|
|
chss = lnss;
|
|
|
|
if ( next_line == 1 )
|
|
chnew = lnup;
|
|
else
|
|
chnew = lndf;
|
|
|
|
while (( *chss == *chnew ) && /* check char by char */
|
|
(( *chss != TAB ) && ( *chss != SPACE ))) {
|
|
chss++;
|
|
chnew++;
|
|
} /* while */
|
|
|
|
if ( *chss == *chnew ) { /* first fields match */
|
|
if ( next_line == 1 ) { /* put in update line and get two more */
|
|
if ( fputs ( lnup, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating SNAPSHOT(1).\n",
|
|
errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* if */
|
|
/* the else here would be to put in lndf but defunct lines are skipped */
|
|
|
|
if ( fgets ( lnss, STRING_LEN, ptr_ss ) == NULL )
|
|
endss = TRUE;
|
|
|
|
if ( next_line == 1 ) {
|
|
if ( fgets ( lnup, STRING_LEN, ptr_up ) == NULL )
|
|
endup = TRUE;
|
|
} /* if */
|
|
|
|
else if ( next_line == -1 ) {
|
|
if ( fgets ( lndf, STRING_LEN, ptr_df ) == NULL )
|
|
enddf = TRUE;
|
|
} /* else */
|
|
|
|
else {
|
|
ui_print ( VFATAL, "ERROR: reached impossible point(1).\n" );
|
|
return ( ERROR );
|
|
} /* else */
|
|
} /* if */
|
|
|
|
else if ( *chss < *chnew ) { /* line not in update files */
|
|
if ( fputs ( lnss, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating SNAPSHOT(2).\n",
|
|
errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( fgets ( lnss, STRING_LEN, ptr_ss ) == NULL )
|
|
endss = TRUE;
|
|
} /* if */
|
|
|
|
else if ( next_line == 1 ) { /* update line not in snapshot file */
|
|
if ( fputs ( lnup, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating SNAPSHOT(3).\n",
|
|
errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( fgets ( lnup, STRING_LEN, ptr_up ) == NULL )
|
|
endup = TRUE;
|
|
} /* else */
|
|
|
|
else if ( next_line == -1 ) { /* defunct line not in snapshot file */
|
|
if ( fgets ( lndf, STRING_LEN, ptr_df ) == NULL )
|
|
enddf = TRUE;
|
|
} /* else if */
|
|
|
|
else {
|
|
ui_print ( VFATAL, "ERROR: reached impossible point(2).\n" );
|
|
return ( ERROR );
|
|
} /* else */
|
|
|
|
if ( ! endup ) { /* more lines in update */
|
|
if (( enddf ) || ( strcmp ( lnup, lndf ) < 0 ))
|
|
next_line = 1;
|
|
else
|
|
next_line = -1;
|
|
} /* if */
|
|
|
|
else if ( enddf ) /* no more lines in either */
|
|
next_line = 0;
|
|
else /* lines left in defunct */
|
|
next_line = -1;
|
|
|
|
endmerge = ( endss ) || ( next_line == 0 );
|
|
} /* while */
|
|
|
|
if ( endup && ! endss ) { /* finish putting one of the files in */
|
|
if ( fputs ( lnss, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating SNAPSHOT(4).\n", errno);
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ffilecopy ( ptr_ss, ptr_tmp ) != OK ) {
|
|
ui_print ( VFATAL, "ERROR: file copy error: %s to %s.\n", ptr_ss,
|
|
ptr_tmp );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* if */
|
|
|
|
else if ( ! endup ) {
|
|
if ( fputs ( lnup, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating SNAPSHOT(5).\n", errno);
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ffilecopy ( ptr_up, ptr_tmp ) != OK ) {
|
|
ui_print ( VFATAL, "ERROR: file copy error: %s to %s.\n", ptr_up,
|
|
ptr_tmp );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* else if */
|
|
|
|
return ( OK );
|
|
} /* sort snap */
|
|
|
|
|
|
|
|
int update_defunct (
|
|
const char * defunct_f, /* defunct file name */
|
|
const char * update_f, /* update file name */
|
|
const char * tmp_f ) /* temporary file name */
|
|
|
|
|
|
/* This function attempts to update the DEFUNCT file.
|
|
It returns OK if the update and defunct files were
|
|
merged and moved to DEFUNCT, ERROR otherwise. */
|
|
|
|
{
|
|
FILE * ptr_df, /* pointer to defunct file */
|
|
* ptr_up, /* pointer to update file */
|
|
* ptr_tmp; /* pointer to tmp file */
|
|
int rvalue; /* return value */
|
|
|
|
if (( ptr_df = fopen ( defunct_f, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read defunct file: %s.\n", defunct_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( ptr_up = fopen ( update_f, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read file user defunct file: %s.\n",
|
|
update_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( ptr_tmp = fopen ( tmp_f, WRITE )) == NULL ) {
|
|
ui_print ( VFATAL,
|
|
"ERROR: could not write to temporary defunct file: %s.\n", tmp_f );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
rvalue = sort_defunct ( ptr_df, ptr_up, ptr_tmp );
|
|
fclose ( ptr_df );
|
|
fclose ( ptr_up );
|
|
fclose ( ptr_tmp );
|
|
return ( rvalue );
|
|
} /* update defunct */
|
|
|
|
|
|
|
|
int
|
|
sort_defunct (
|
|
FILE * ptr_df, /* pointer to defunct file */
|
|
FILE * ptr_up, /* pointer to update file */
|
|
FILE * ptr_tmp ) /* pointer to tmp file */
|
|
|
|
|
|
/* This function merges the DEFUNCT file with the new changes.
|
|
It does it by assuming each file is an ascii sorted list.
|
|
It is all in one long procedure to save time; DEFUNCT is a
|
|
long file. If the merge works, it returns OK, else ERROR. */
|
|
|
|
{
|
|
char lndf [ STRING_LEN ], /* misc string */
|
|
lnup [ STRING_LEN ], /* misc string */
|
|
* chdf, /* points to each ch */
|
|
* chup; /* points to each ch */
|
|
BOOLEAN more = TRUE, /* misc boolean */
|
|
enddf = FALSE, /* misc boolean */
|
|
endup = FALSE; /* misc boolean */
|
|
|
|
if ( fgets ( lndf, STRING_LEN, ptr_df ) == NULL ) {
|
|
enddf = TRUE;
|
|
more = FALSE;
|
|
} /* if */
|
|
|
|
if ( fgets ( lnup, STRING_LEN, ptr_up ) == NULL ) {
|
|
endup = TRUE;
|
|
more = FALSE;
|
|
} /* if */
|
|
|
|
while ( more ) {
|
|
chdf = lndf;
|
|
chup = lnup;
|
|
|
|
while (( *chdf == *chup ) && /* check char by char */
|
|
(( *chdf != TAB ) && ( *chdf != SPACE ))) {
|
|
chdf++;
|
|
chup++;
|
|
} /* while */
|
|
|
|
if ( *chdf == *chup ) { /* first fields match */
|
|
if ( fputs ( lnup, ptr_tmp ) == EOF ) {
|
|
/* put in update line and get two more */
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating DEFUNCT(1).\n",
|
|
errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( fgets ( lndf, STRING_LEN, ptr_df ) == NULL ) {
|
|
more = FALSE;
|
|
enddf = TRUE;
|
|
} /* if */
|
|
|
|
if ( fgets ( lnup, STRING_LEN, ptr_up ) == NULL ) {
|
|
more = FALSE;
|
|
endup = TRUE;
|
|
} /* if */
|
|
|
|
} /* if */
|
|
|
|
else if ( *chdf < *chup ) {
|
|
if ( fputs ( lndf, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating DEFUNCT(2).\n",
|
|
errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( fgets ( lndf, STRING_LEN, ptr_df ) == NULL ) {
|
|
more = FALSE;
|
|
enddf = TRUE;
|
|
} /* if */
|
|
} /* else if */
|
|
|
|
else {
|
|
if ( fputs ( lnup, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating DEFUNCT(3).\n",
|
|
errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( fgets ( lnup, STRING_LEN, ptr_up ) == NULL ) {
|
|
more = FALSE;
|
|
endup = TRUE;
|
|
} /* if */
|
|
} /* else */
|
|
} /* while */
|
|
|
|
if ( endup && ! enddf ) { /* finish putting one of the files in */
|
|
if ( fputs ( lndf, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating DEFUNCT(4).\n", errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ffilecopy ( ptr_df, ptr_tmp ) != OK ) {
|
|
ui_print ( VFATAL, "ERROR: file copy error: %s to %s.\n", ptr_df,
|
|
ptr_tmp );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* if */
|
|
|
|
else if ( ! endup ) {
|
|
if ( fputs ( lnup, ptr_tmp ) == EOF ) {
|
|
ui_print ( VFATAL, "ERROR: fputs: %d, in updating DEFUNCT(5).\n", errno );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( ffilecopy ( ptr_up, ptr_tmp ) != OK ) {
|
|
ui_print ( VFATAL, "ERROR: file copy error: %s to %s.\n", ptr_up,
|
|
ptr_tmp );
|
|
return ( ERROR );
|
|
} /* if */
|
|
} /* else if */
|
|
|
|
return ( OK );
|
|
} /* sort defunct */
|
|
|
|
|
|
|
|
int update_submit_log (
|
|
const char * submitlog, /* original submission log */
|
|
const char * usrlog, /* user's added submission log */
|
|
const char * tmplog ) /* new log to create */
|
|
|
|
|
|
/* This function appends the user's log to the bsubmit log.
|
|
It returns OK if that operation was successful, ERROR if not. */
|
|
|
|
{
|
|
if ( filecp ( submitlog, tmplog, WRITE ) == OK )
|
|
return ( filecp ( usrlog, tmplog, APPEND ));
|
|
else
|
|
return ( ERROR );
|
|
} /* update submit log */
|
|
|
|
|
|
|
|
int
|
|
cleanup_hold (
|
|
const char * string, /* string with info to pass on */
|
|
SCI_LIST file_set, const char * submit_set, BOOLEAN submit )
|
|
|
|
/* This function locks the hold file, removes entries from
|
|
it, then unlocks it. It does no real work itself. It
|
|
returns OK or ERROR. */
|
|
|
|
{
|
|
int rvalue; /* return value */
|
|
int lock_fd;
|
|
|
|
if (( rvalue = set_lock ( HOLD_FILE_23, &lock_fd )) == OK ) {
|
|
if (( rvalue = delete_from_hold_file ( string, file_set, submit_set,
|
|
submit )) == OK )
|
|
rvalue = unset_lock ( HOLD_FILE_23, lock_fd );
|
|
else /* don't change rvalue if delete_from_hold_file() failed */
|
|
(void) unset_lock ( HOLD_FILE_23, lock_fd );
|
|
} /* if */
|
|
|
|
return ( rvalue );
|
|
} /* cleanup hold */
|
|
|
|
|
|
|
|
int
|
|
delete_from_hold_file ( const char * start, SCI_LIST file_set,
|
|
const char * submit_set, BOOLEAN submit )
|
|
|
|
/* This function removes the list of held files from the
|
|
hold file. It returns OK or ERROR depending on the
|
|
results. */
|
|
|
|
{
|
|
FILE * real_hold, /* pointer to hold file */
|
|
* tmp_hold; /* pointer to tmp file */
|
|
char line [ PATH_LEN ]; /* misc string */
|
|
char line_tmp [ PATH_LEN ]; /* misc string */
|
|
BOOLEAN found_start = FALSE; /* misc boolean */
|
|
char * token;
|
|
char * line_ptr;
|
|
char * locked_set;
|
|
char * user;
|
|
BOOLEAN match = FALSE;
|
|
char * res;
|
|
SCI_ELEM sci_ptr;
|
|
|
|
if (( tmp_hold = fopen ( LOCAL_HOLD, WRITE )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not write to temporary hold file: %s.\n",
|
|
LOCAL_HOLD );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( real_hold = fopen ( HOLD_FILE_23, READ )) == NULL ) {
|
|
ui_print ( VFATAL, "ERROR: could not read from hold file: %s.\n",
|
|
HOLD_FILE );
|
|
fclose ( tmp_hold );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
while (( ! found_start ) &&
|
|
(( fgets ( line, PATH_LEN, real_hold )) != NULL )) {
|
|
if ( *line == COLON ) {
|
|
line[strlen ( line ) - 1] = NUL;
|
|
|
|
if ( line[1] != ':' ) {
|
|
if ( streq ( line, start ))
|
|
found_start = TRUE;
|
|
else
|
|
fprintf ( tmp_hold, "%s\n", line );
|
|
/* if */
|
|
} else if ( line[1] == ':' ) {
|
|
strcpy ( line_tmp, line );
|
|
line_ptr = line_tmp;
|
|
token = nxtarg ( &line_ptr, WHITESPACE );
|
|
locked_set = nxtarg ( &line_ptr, WHITESPACE );
|
|
|
|
/* Is the lock for the same set? If not, don't check this lock. */
|
|
if ( strcmp ( submit_set, locked_set ) == 0 ) {
|
|
user = nxtarg ( &line_ptr, WHITESPACE );
|
|
token = nxtarg ( &line_ptr, WHITESPACE );
|
|
match = FALSE;
|
|
for ( sci_ptr = sci_first ( file_set ); sci_ptr != NULL;
|
|
sci_ptr = sci_next ( sci_ptr ) ) {
|
|
if ( strcmp ( sci_ptr -> name, token ) == 0 ) {
|
|
match = TRUE;
|
|
} /* if */
|
|
} /* for */
|
|
} /* if */
|
|
if ( ! match )
|
|
fprintf ( tmp_hold, "%s\n", line );
|
|
/* if */
|
|
} else
|
|
fprintf ( tmp_hold, "%s\n", line );
|
|
/* if */
|
|
} /* if */
|
|
|
|
else
|
|
fputs ( line, tmp_hold );
|
|
} /* while */
|
|
|
|
if ( submit && !found_start ) {
|
|
ui_print ( VWARN, "No startline, %s, in hold file: %s.\n",
|
|
start, HOLD_FILE_23 );
|
|
fclose ( real_hold );
|
|
fclose ( tmp_hold );
|
|
( void ) unlink ( LOCAL_HOLD );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
while ( (res = fgets ( line, PATH_LEN, real_hold )) != NULL &&
|
|
*line != COLON ); /* skip until next user */
|
|
|
|
while ( res != NULL ) {
|
|
if ( *line == COLON ) {
|
|
line[strlen ( line ) - 1] = NUL;
|
|
|
|
if ( line[1] != ':' ) {
|
|
fprintf ( tmp_hold, "%s\n", line );
|
|
} else if ( line[1] == ':' ) {
|
|
strcpy ( line_tmp, line );
|
|
line_ptr = line_tmp;
|
|
token = nxtarg ( &line_ptr, WHITESPACE );
|
|
locked_set = nxtarg ( &line_ptr, WHITESPACE );
|
|
|
|
/* Is the lock for the same set? If not, don't check this lock. */
|
|
if ( strcmp ( submit_set, locked_set ) == 0 ) {
|
|
user = nxtarg ( &line_ptr, WHITESPACE );
|
|
token = nxtarg ( &line_ptr, WHITESPACE );
|
|
match = FALSE;
|
|
for ( sci_ptr = sci_first ( file_set ); sci_ptr != NULL;
|
|
sci_ptr = sci_next ( sci_ptr ) ) {
|
|
if ( strcmp ( sci_ptr -> name, token ) == 0 ) {
|
|
match = TRUE;
|
|
} /* if */
|
|
} /* for */
|
|
} /* if */
|
|
if ( ! match )
|
|
fprintf ( tmp_hold, "%s\n", line );
|
|
/* if */
|
|
} else
|
|
fprintf ( tmp_hold, "%s\n", line );
|
|
/* if */
|
|
} else
|
|
fputs ( line, tmp_hold );
|
|
/* if */
|
|
res = fgets ( line, PATH_LEN, real_hold );
|
|
} /* while */
|
|
|
|
fclose ( real_hold );
|
|
fclose ( tmp_hold );
|
|
|
|
if ( rename ( LOCAL_HOLD, HOLD_FILE_23 ) == ERROR ) {
|
|
ui_print ( VFATAL, "ERROR: could not mv %s to %s.\n", LOCAL_HOLD,
|
|
HOLD_FILE_23 );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
return ( OK );
|
|
} /* delete from hold file */
|