/* -*-C-*- */

/*  replay.c  */


/*
 * Author: Nikita Danilov <NikitaDanilov@yahoo.COM>
 * Keywords: faked io, logging, io profiling
 *
 * Copyright (C) 2000 Namesys (Hans Reiser)
 *
 * This file is part of fakeio.
 *
 * Fakeio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This software 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 */

#include <sys/types.h>
#include <errno.h>
#include <stdarg.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <stdio.h>
#include <unistd.h>

static char *chomp( char *str )
{
  if( ( str != NULL ) && 
	  ( str[ 0 ] != '\0' ) && 
	  ( str[ strlen( str ) - 1 ] == '\n' ) )
	{
	  str[ strlen( str ) - 1 ] = '\0';
	}
  return str;
}

int main( int argc, char **argv )
{
  pid_t pid;
  char  cmd;
  double timeStamp;
  int   callResult;
  int   callErrno;
  char  path[ 1024 ];
  char  line[ 2048 ];
  int   count;
  int   fd;
  __off64_t offset;
  int   shift;
  int   baseShift;
  
  while( 1 )
	{
	  if( fgets( line, sizeof line, stdin ) == NULL )
		{
		  break;
		}
	  chomp( line );

	  sscanf( line, "%lf %i %c%n", &timeStamp, &pid, &cmd, &baseShift );
	  switch( cmd )
		{
		case 'O': /* open */
		  {
			int flags;
			int mode;

			sscanf( line + baseShift, "%i %i %o %i%n",
					&callResult, &flags, &mode, &callErrno, &shift );
			path[ 0 ] = '\0';
			sscanf( line + baseShift + shift, " %s", path );
			fprintf( stderr, "Open: %s %i %3.3o\n", path, flags, mode );
			break;
		  }
		case 'R': /* read */
		  {
			sscanf( line + baseShift, "%i %lli %i %i %i%n",
					&fd, &offset, &count, &callResult, &callErrno, &shift );
			path[ 0 ] = '\0';
			sscanf( line + baseShift + shift, " %s", path );
			fprintf( stderr, "Read: `%s': %i %lli %i\n", path, fd, offset, count );
			break;
		  }
		case 'W': /* write */
		  {
			sscanf( line + baseShift, "%i %lli %i %i %i%n",
					&fd, &offset, &count, &callResult, &callErrno, &shift );
			path[ 0 ] = '\0';
			sscanf( line + baseShift + shift, " %s", path );
			fprintf( stderr, "Write: `%s':%i %lli %i\n", path, fd, offset, count );
			break;
		  }
		case 'S': /* lseek */
		  {
			int whence;

			sscanf( line + baseShift, "%i %lli %i %i %i%n",
					&fd, &offset, &whence, &callResult, &callErrno, &shift );
			path[ 0 ] = '\0';
			sscanf( line + baseShift + shift, " %s", path );
			fprintf( stderr, "Seek: %s %s %lli\n", path, 
					 ( whence == SEEK_SET ) ? "SEEK_SET" :
					 ( whence == SEEK_CUR ) ? "SEEK_CUR" : 
					 ( whence == SEEK_END ) ? "SEEK_END" :
					 "unknown seek whence", offset );
 			break;
		  }
		case 'C': /* close */
		  {
			sscanf( line + baseShift, "%i %i %i%n",
					&fd, &callResult, &callErrno, &shift );
			path[ 0 ] = '\0';
			sscanf( line + baseShift + shift, " %s", path );
			fprintf( stderr, "Close: %s\n", path );
			break;
		  }
		case 'I': /* info */
		  {
			char message[ 1024 ];

			message[ 0 ] = '\0';
			sscanf( line + baseShift, " %s", message );
			fprintf( stderr, "Info: %s\n", message );
			break;
		  }
		default:
		  {
			fprintf( stderr, "Unknown cmd: %c pid: %i\n", cmd, pid );
			break;
		  }
		}
	}
  return 1;
}

