diff options
author | Peter Ammon <corydoras@ridiculousfish.com> | 2012-03-02 00:27:40 -0800 |
---|---|---|
committer | Peter Ammon <corydoras@ridiculousfish.com> | 2012-03-02 00:27:40 -0800 |
commit | 8b26d0104c1d85c271e5ce6e08bfe64a779beba7 (patch) | |
tree | 995568526f190084fd12d74bc6dcd0e828b1018a /common.cpp | |
parent | 36622c35781c3212c2102c45781a496f3e1b3659 (diff) |
Some initial changes to use CLO_EXEC, with an eye towards some day using it correctly.
Diffstat (limited to 'common.cpp')
-rw-r--r-- | common.cpp | 238 |
1 files changed, 1 insertions, 237 deletions
@@ -49,14 +49,6 @@ parts of fish. #include <execinfo.h> #endif -#ifndef HOST_NAME_MAX -/** - Maximum length of hostname return. It is ok if this is too short, - getting the actual hostname is not critical, so long as the string - is unique in the filesystem namespace. -*/ -#define HOST_NAME_MAX 255 -#endif #if HAVE_NCURSES_H #include <ncurses.h> @@ -88,11 +80,7 @@ parts of fish. #include "util.cpp" #include "fallback.cpp" -/** - The number of milliseconds to wait between polls when attempting to acquire - a lockfile -*/ -#define LOCKPOLLINTERVAL 10 + struct termios shell_modes; @@ -1693,231 +1681,7 @@ bool unescape_string(wcstring &str, int escape_special) return success; } -/** - Writes a pid_t in decimal representation to str. - str must contain sufficient space. - The conservatively approximate maximum number of characters a pid_t will - represent is given by: (int)(0.31 * sizeof(pid_t) + CHAR_BIT + 1) - Returns the length of the string -*/ -static int sprint_pid_t( pid_t pid, char *str ) -{ - int len, i = 0; - int dig; - - /* Store digits in reverse order into string */ - while( pid != 0 ) - { - dig = pid % 10; - str[i] = '0' + dig; - pid = ( pid - dig ) / 10; - i++; - } - len = i; - /* Reverse digits */ - i /= 2; - while( i ) - { - i--; - dig = str[i]; - str[i] = str[len - 1 - i]; - str[len - 1 - i] = dig; - } - return len; -} - -/** - Writes a pseudo-random number (between one and maxlen) of pseudo-random - digits into str. - str must point to an allocated buffer of size of at least maxlen chars. - Returns the number of digits written. - Since the randomness in part depends on machine time it has _some_ extra - strength but still not enough for use in concurrent locking schemes on a - single machine because gettimeofday may not return a different value on - consecutive calls when: - a) the OS does not support fine enough resolution - b) the OS is running on an SMP machine. - Additionally, gettimeofday errors are ignored. - Excludes chars other than digits since ANSI C only guarantees that digits - are consecutive. -*/ -static int sprint_rand_digits( char *str, int maxlen ) -{ - int i, max; - struct timeval tv; - - /* - Seed the pseudo-random generator based on time - this assumes - that consecutive calls to gettimeofday will return different values - and ignores errors returned by gettimeofday. - Cast to unsigned so that wrapping occurs on overflow as per ANSI C. - */ - (void)gettimeofday( &tv, NULL ); - srand( (unsigned int)tv.tv_sec + (unsigned int)tv.tv_usec * 1000000UL ); - max = 1 + (maxlen - 1) * (rand() / (RAND_MAX + 1.0)); - for( i = 0; i < max; i++ ) - { - str[i] = '0' + 10 * (rand() / (RAND_MAX + 1.0)); - } - return i; -} -/** - Generate a filename unique in an NFS namespace by creating a copy of str and - appending .{hostname}.{pid} to it. If gethostname() fails then a pseudo- - random string is substituted for {hostname} - the randomness of the string - should be strong enough across different machines. The main assumption - though is that gethostname will not fail and this is just a "safe enough" - fallback. - The memory returned should be freed using free(). -*/ -static char *gen_unique_nfs_filename( const char *filename ) -{ - int pidlen, hnlen, orglen = strlen( filename ); - char hostname[HOST_NAME_MAX + 1]; - char *newname; - - if ( gethostname( hostname, HOST_NAME_MAX + 1 ) == 0 ) - { - hnlen = strlen( hostname ); - } - else - { - hnlen = sprint_rand_digits( hostname, HOST_NAME_MAX ); - hostname[hnlen] = '\0'; - } - newname = (char *)malloc( orglen + 1 /* period */ + hnlen + 1 /* period */ + - /* max possible pid size: 0.31 ~= log(10)2 */ - (int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) - + 1 /* '\0' */ ); - - if ( newname == NULL ) - { - debug( 1, L"gen_unique_nfs_filename: %s", strerror( errno ) ); - return newname; - } - memcpy( newname, filename, orglen ); - newname[orglen] = '.'; - memcpy( newname + orglen + 1, hostname, hnlen ); - newname[orglen + 1 + hnlen] = '.'; - pidlen = sprint_pid_t( getpid(), newname + orglen + 1 + hnlen + 1 ); - newname[orglen + 1 + hnlen + 1 + pidlen] = '\0'; -/* debug( 1, L"gen_unique_nfs_filename returning with: newname = \"%s\"; " - L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; " - L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d", - newname, (int)HOST_NAME_MAX, hnlen, orglen, - (int)sizeof(pid_t), - (int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1), - (int)(orglen + 1 + hnlen + 1 + - (int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */ - return newname; -} - -int acquire_lock_file( const char *lockfile, const int timeout, int force ) -{ - int fd, timed_out = 0; - int ret = 0; /* early exit returns failure */ - struct timespec pollint; - struct timeval start, end; - double elapsed; - struct stat statbuf; - - /* - (Re)create a unique file and check that it has one only link. - */ - char *linkfile = gen_unique_nfs_filename( lockfile ); - if( linkfile == NULL ) - { - goto done; - } - (void)unlink( linkfile ); - if( ( fd = open( linkfile, O_CREAT|O_RDONLY, 0600 ) ) == -1 ) - { - debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) ); - goto done; - } - /* - Don't need to check exit status of close on read-only file descriptors - */ - close( fd ); - if( stat( linkfile, &statbuf ) != 0 ) - { - debug( 1, L"acquire_lock_file: stat: %s", strerror( errno ) ); - goto done; - } - if ( statbuf.st_nlink != 1 ) - { - debug( 1, L"acquire_lock_file: number of hardlinks on unique " - L"tmpfile is %d instead of 1.", (int)statbuf.st_nlink ); - goto done; - } - if( gettimeofday( &start, NULL ) != 0 ) - { - debug( 1, L"acquire_lock_file: gettimeofday: %s", strerror( errno ) ); - goto done; - } - end = start; - pollint.tv_sec = 0; - pollint.tv_nsec = LOCKPOLLINTERVAL * 1000000; - do - { - /* - Try to create a hard link to the unique file from the - lockfile. This will only succeed if the lockfile does not - already exist. It is guaranteed to provide race-free - semantics over NFS which the alternative of calling - open(O_EXCL|O_CREAT) on the lockfile is not. The lock - succeeds if the call to link returns 0 or the link count on - the unique file increases to 2. - */ - if( link( linkfile, lockfile ) == 0 || - ( stat( linkfile, &statbuf ) == 0 && - statbuf.st_nlink == 2 ) ) - { - /* Successful lock */ - ret = 1; - break; - } - elapsed = end.tv_sec + end.tv_usec/1000000.0 - - ( start.tv_sec + start.tv_usec/1000000.0 ); - /* - The check for elapsed < 0 is to deal with the unlikely event - that after the loop is entered the system time is set forward - past the loop's end time. This would otherwise result in a - (practically) infinite loop. - */ - if( timed_out || elapsed >= timeout || elapsed < 0 ) - { - if ( timed_out == 0 && force ) - { - /* - Timed out and force was specified - attempt to - remove stale lock and try a final time - */ - (void)unlink( lockfile ); - timed_out = 1; - continue; - } - else - { - /* - Timed out and final try was unsuccessful or - force was not specified - */ - debug( 1, L"acquire_lock_file: timed out " - L"trying to obtain lockfile %s using " - L"linkfile %s", lockfile, linkfile ); - break; - } - } - nanosleep( &pollint, NULL ); - } while( gettimeofday( &end, NULL ) == 0 ); - done: - /* The linkfile is not needed once the lockfile has been created */ - (void)unlink( linkfile ); - free( linkfile ); - return ret; -} void common_handle_winch( int signal ) { |