#include #include #include #include #include #include #include #include #include int main( int argc, char * argv[] ) { int fd; const size_t buf_size = 40; char buf[ buf_size ]; unsigned int n; ssize_t bytes; int rc; int exit_status = 0; off_t offset; size_t out_bytes; if ( argc != 2 ) { fprintf( stderr, "usage: %s COUNT_FILE\n", argv[0] ); exit_status = 1; goto done; } fd = open( argv[1], O_RDWR | O_CREAT, 0666 ); if ( fd < 0 ) { fprintf( stderr, "%s: open: %s\n", argv[1], strerror( errno ) ); exit_status = 2; goto done; } rc = flock( fd, LOCK_EX ); if ( rc != 0 ) { fprintf( stderr, "%s: locking: %s\n", argv[1], strerror( errno ) ); exit_status = 3; goto close_fd; } bytes = read( fd, buf, buf_size ); if ( bytes < 0 ) { fprintf( stderr, "%s: read: %s\n", argv[1], strerror( errno ) ); exit_status = 4; goto unlock_fd; } else if ( bytes == 0 ) { /* new file */ n = 0; } else { if ( bytes >= buf_size ) bytes = buf_size - 1; buf[bytes] = '\0'; rc = sscanf( buf, "%u", &n ); if ( rc != 1 ) { fprintf( stderr, "%s: scanning '%s' for unsigned int\n", argv[1], buf ); exit_status = 5; goto unlock_fd; } offset = lseek( fd, 0, SEEK_SET ); if ( offset != 0 ) { fprintf( stderr, "%s: lseek: %s\n", argv[1], strerror( errno ) ); exit_status = 6; goto unlock_fd; } } rc = snprintf( buf, buf_size, "%u\n", ++n ); if ( rc < 1 ) { fprintf( stderr, "%s: snprintf: rc=%d\n", argv[1], rc ); exit_status = 7; goto unlock_fd; } else if ( rc > buf_size ) { fprintf( stderr, "%s: number too large for output buffer (%zu chars max)\n", argv[1], buf_size ); exit_status = 8; goto unlock_fd; } out_bytes = rc; rc = ftruncate( fd, 0 ); if ( rc != 0 ) { fprintf( stderr, "%s: truncate: %s\n", argv[1], strerror( errno ) ); exit_status = 9; goto unlock_fd; } bytes = write( fd, buf, out_bytes ); if ( bytes < 0 ) { fprintf( stderr, "%s: write: %s\n", argv[1], strerror( errno ) ); exit_status = 10; goto unlock_fd; } else if ( bytes != out_bytes ) { fprintf( stderr, "%s: write: tried to write %zu bytes, wrote %d\n", argv[1], out_bytes, (int)bytes ); exit_status = 11; goto unlock_fd; } printf( "%u\n", n ); unlock_fd: flock( fd, LOCK_UN ); close_fd: close( fd ); done: return exit_status; }