// File: /workspace/github_c_makefile_star2_O2/sTeeLM[P]dwipe/pass.c
// Function: dwipe_static_pass
int dwipe_static_pass( DWIPE_METHOD_SIGNATURE, dwipe_pattern_t* pattern )
{
/**
 * Writes a static pattern to the device.
 *
 */

	/* The result holder. */
	int r;

	/* The IO size. */
	size_t blocksize;

	/* The result buffer for calls to lseek. */
	loff_t offset;

	/* The output buffer. */
	char* b;

	/* A pointer into the output buffer. */
	char* p;

	/* The output buffer window offset. */
	int w = 0;

	/* The number of bytes remaining in the pass. */
	u64 z = c->device_size;

	if( pattern == NULL )
	{
		/* Caught insanity. */	
		dwipe_log( DWIPE_LOG_SANITY, "__FUNCTION__: Null pattern pointer." );
		return -1;
	}

	if( pattern->length <= 0 )
	{
		/* Caught insanity. */	
		dwipe_log( DWIPE_LOG_SANITY, "__FUNCTION__: The pattern length member is %i.", pattern->length );
		return -1;
	}

	/* Create the output buffer. */
	b = malloc( c->device_stat.st_blksize * 1024 + pattern->length * 2 );

	/* Check the memory allocation. */
	if( ! b )
	{
		dwipe_perror( errno, __FUNCTION__, "malloc" );
		dwipe_log( DWIPE_LOG_FATAL, "Unable to allocate memory for the pattern buffer." );
		return -1;
	}

	for( p = b ; p < b + c->device_stat.st_blksize * 1024 + pattern->length ; p += pattern->length )
	{
		/* Fill the output buffer with the pattern. */
		memcpy( p, pattern->s, pattern->length ); 
	}


	/* Reset the file pointer. */
	offset = lseek( c->device_fd, 0, SEEK_SET );

	if( offset == (loff_t)-1 )
	{
		dwipe_perror( errno, __FUNCTION__, "lseek" );
		dwipe_log( DWIPE_LOG_FATAL, "Unable to reset the '%s' file offset.", c->device_name );
		return -1;
	}

	if( offset != 0 )
	{
		/* This is system insanity. */
		dwipe_log( DWIPE_LOG_SANITY, "__FUNCTION__: lseek() returned a bogus offset on '%s'.", c->device_name );
		return -1;
	}


	while( z > 0 )
	{
		if( c->device_stat.st_blksize * 1024 < z )
		{
			blocksize = c->device_stat.st_blksize * 1024;
		}
		else
		{
			/* This is a seatbelt for buggy drivers and programming errors because */
			/* the device size should always be an even multiple of its blocksize. */
			blocksize = z;
			dwipe_log( DWIPE_LOG_WARNING,
			  "%s: The size of '%s' is not a multiple of its block size %i.",
			  __FUNCTION__, c->device_name, c->device_stat.st_blksize );
		}

		/* Fill the output buffer with the random pattern. */
		/* Write the next block out to the device. */
		r = write( c->device_fd, &b[w], blocksize );

		/* Check the result for a fatal error. */
		if( r < 0 )
		{
			dwipe_perror( errno, __FUNCTION__, "write" );
			dwipe_log( DWIPE_LOG_FATAL, "Unable to write to '%s'.", c->device_name );
			return -1;
		}

		/* Check for a partial write. */
		if( r != blocksize )
		{
			/* TODO: Handle a partial write. */

			/* The number of bytes that were not written. */
			int s = blocksize - r;
			
			/* Increment the error count. */
			c->pass_errors += s;

			dwipe_log( DWIPE_LOG_WARNING, "Partial write on '%s', %i bytes short.", c->device_name, s );

			/* Bump the file pointer to the next block. */
			offset = lseek( c->device_fd, s, SEEK_CUR );

			if( offset == (loff_t)-1 )
			{
				dwipe_perror( errno, __FUNCTION__, "lseek" );
				dwipe_log( DWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial write.", c->device_name );
				return -1;
			}

		} /* partial write */


		/* Adjust the window. */
		w = ( c->device_stat.st_blksize * 1024 + w ) % pattern->length;

		/* Intuition check: 
		 *
		 *   If the pattern length evenly divides the block size
		 *   then ( w == 0 ) always.
		 */

		/* Decrement the bytes remaining in this pass. */
		z -= r;

		/* Increment the total progress counterr. */
		c->round_done += r;
		c->pass_done += r;

	} /* remaining bytes */

	/* Tell our parent that we are syncing the device. */
	c->sync_status = 1;

	/* Sync the device. */
	r = fdatasync( c->device_fd );

	/* Tell our parent that we have finished syncing the device. */
	c->sync_status = 0;

	if( r != 0 )
	{
		/* FIXME: Is there a better way to handle this? */
		dwipe_perror( errno, __FUNCTION__, "fdatasync" );
		dwipe_log( DWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name );
	}

	/* Release the output buffer. */
	free( b );
	
	/* We're done. */
	return 0;	

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
testq %rsi, %rsi
je 0x9533
movq %rsi, %r15
movl (%rsi), %r12d
testl %r12d, %r12d
jle 0x963a
movq %rdi, %rbx
movq 0x230(%rdi), %rbp
movq 0x270(%rdi), %r14
shlq $0xa, %r14
leaq (%r14,%r12,2), %rdi
callq 0x3300
testq %rax, %rax
je 0x9653
addq %rax, %r14
addq %r12, %r14
movq %rax, (%rsp)
movq %rax, %r13
cmpq %r14, %r13
jae 0x9541
movq 0x8(%r15), %rsi
movq %r13, %rdi
movq %r12, %rdx
callq 0x32a0
addq %r12, %r13
jmp 0x951a
leaq 0x3d28(%rip), %rsi      # 0xd262
pushq $0x7
jmp 0x9676
movl 0x8(%rbx), %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x3420
cmpq $-0x1, %rax
je 0x9683
testq %rax, %rax
jne 0x96b0
xorl %r12d, %r12d
testq %rbp, %rbp
je 0x96c5
movq 0x270(%rbx), %r8
movq %r8, %r13
shlq $0xa, %r13
cmpq %rbp, %r13
jb 0x95a1
movq 0x228(%rbx), %rcx
pushq $0x4
popq %rdi
leaq 0x3a0a(%rip), %rsi      # 0xcf9a
leaq 0x3d1e(%rip), %rdx      # 0xd2b5
xorl %eax, %eax
callq 0x73a8
movq %rbp, %r13
movl 0x8(%rbx), %edi
movq (%rsp), %rax
leaq (%rax,%r12), %rsi
movq %r13, %rdx
callq 0x3110
testl %eax, %eax
js 0x9721
movl %eax, %r14d
andl $0x7fffffff, %r14d      # imm = 0x7FFFFFFF
cmpq %r13, %r14
je 0x960b
subq %rax, %r13
movslq %r13d, %r13
addq %r13, 0x2f8(%rbx)
movq 0x228(%rbx), %rdx
pushq $0x4
popq %rdi
leaq 0x3b3e(%rip), %rsi      # 0xd127
movl %r13d, %ecx
xorl %eax, %eax
callq 0x73a8
movl 0x8(%rbx), %edi
movq %r13, %rsi
pushq $0x1
popq %rdx
callq 0x3420
cmpq $-0x1, %rax
je 0x9765
movq 0x270(%rbx), %rax
shlq $0xa, %rax
addq %r12, %rax
movslq (%r15), %rcx
cqto
idivq %rcx
subq %r14, %rbp
addq %r14, 0x340(%rbx)
addq %r14, 0x2f0(%rbx)
movq %rdx, %r12
jmp 0x9563
leaq 0x3c45(%rip), %rsi      # 0xd286
pushq $0x7
popq %rdi
movl %r12d, %edx
xorl %eax, %eax
callq 0x73a8
jmp 0x9753
callq 0x3070
movl (%rax), %edi
leaq 0x3c54(%rip), %rsi      # 0xd2b5
leaq 0x1548(%rip), %rdx      # 0xabb0
callq 0x7600
leaq 0x38cc(%rip), %rsi      # 0xcf40
pushq $0x6
popq %rdi
xorl %eax, %eax
callq 0x73a8
jmp 0x9753
callq 0x3070
movl (%rax), %edi
leaq 0x3c24(%rip), %rsi      # 0xd2b5
leaq 0x1701(%rip), %rdx      # 0xad99
callq 0x7600
movq 0x228(%rbx), %rdx
leaq 0x171a(%rip), %rsi      # 0xadc5
jmp 0x9749
movq 0x228(%rbx), %rdx
leaq 0x3a2c(%rip), %rsi      # 0xd0ea
pushq $0x7
jmp 0x974b
movw $0x1, 0x57c(%rbx)
movl 0x8(%rbx), %edi
callq 0x3080
andw $0x0, 0x57c(%rbx)
testl %eax, %eax
je 0x9714
callq 0x3070
movl (%rax), %edi
leaq 0x3bc5(%rip), %rsi      # 0xd2b5
leaq 0x387b(%rip), %rdx      # 0xcf72
callq 0x7600
movq 0x228(%rbx), %rdx
leaq 0x3872(%rip), %rsi      # 0xcf7c
pushq $0x4
popq %rdi
xorl %eax, %eax
callq 0x73a8
movq (%rsp), %rdi
callq 0x3060
xorl %eax, %eax
jmp 0x9756
callq 0x3070
movl (%rax), %edi
leaq 0x3b86(%rip), %rsi      # 0xd2b5
leaq 0x39eb(%rip), %rdx      # 0xd121
callq 0x7600
movq 0x228(%rbx), %rdx
leaq 0x3b7e(%rip), %rsi      # 0xd2c7
pushq $0x6
popq %rdi
xorl %eax, %eax
callq 0x73a8
pushq $-0x1
popq %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x3070
movl (%rax), %edi
leaq 0x3b42(%rip), %rsi      # 0xd2b5
leaq 0x161f(%rip), %rdx      # 0xad99
callq 0x7600
movq 0x228(%rbx), %rdx
leaq 0x39c1(%rip), %rsi      # 0xd14e
pushq $0x5
jmp 0x974b
nopl (%rax)