#ifndef _STAT_VER
#define _STAT_VER 0
#endif

static int STAT(z)(int ver, __const char *name, char *newname, STATTYPE *buf)
{


  int fd,st,ft;
  unsigned char size_buffer[4];

  ft = zlib_getfiletype(name,-1);

  if( (ft & PM_READ_MASK) == PM_LEAVE_COMPR ){
    errno = ENOENT ;
    return -1;
  }

  if ((ft & PM_SIZE_COMPR_MASK) == PM_SIZE_COMPR) {
      STAT(___zlibc_x)(ver,newname,buf);
  } else {
      fd=zlib_real_open(newname, O_RDONLY | O_NDELAY, 0);

      if ( fd < 0 ){
	  if ( errno == ENOENT )
	      return -1;
	  return 2;
      } else {  
	st = fSTAT;
	
	if(ver == _STAT_VER) {
	  /* If we do know the layout of stuct stat, do some smart things
	   * here, else don't bother */
	  if ( st < 0 ){
	    close(fd);
	    return st;
	  }	
	  if ( ! S_ISREG ( buf->st_mode )) {
	    /* not a regular file. Don't waste time determining its size */
	    return st;
	  }

	  lseek(fd, -4 , SEEK_END);
	  read(fd, size_buffer, 4 );

	  buf->st_size = size_buffer[0] + ( size_buffer[1] << 8 ) + 
	    (size_buffer[2] << 16 ) + (size_buffer[3] << 24 );
	}
	close(fd);
      }	  

  }

  if(ver == _STAT_VER) {
    /* If we happen to know the layout of stuct stat, do some smart
     * things here, else don't bother */


    if ((ft & PM_READ_MASK) == PM_SHOW_PIPE) {
      buf->st_mode ^= S_IFIFO | S_IFREG;
    }
    
    if (!(ft & (PM_CREATE_COMPR | PM_APPEND_COMPR | PM_UNCOMPR_BEFORE_WRITE)))
      buf->st_mode &= ~0222;
    
#ifdef NEGATE_INODES
    buf->st_ino= -buf->st_ino;
#endif
  }
  return 0;

}

static int STAT(zlibc_x)(int ver, __const char *file_name, STATTYPE *buf)
{

  int st, olderrno;

  olderrno = errno;
  errno = 0;

  st = STAT(___zlibc_x)(ver, file_name, buf );

  if ( st >= 0 || errno != ENOENT )
    return st;

  {
    char newname[MAXPATHLEN + MAXEXTLEN + 1];
    zlib_initialise();

    if ( zlib_mode & CM_DISAB ) {
      errno = ENOENT;
      return st;
    }

    if ( zlib_mode & CM_VERBOSE )
      fprintf(stderr,"stating %s\n", file_name);

    strncpy(newname,file_name,MAXPATHLEN);
    strcat(newname,zlib_ext);

    st = STAT(z)(ver, file_name,newname, buf);

    if ( zlib_mode & CM_VERBOSE )
      fprintf(stderr,"stated %s, rv=%d\n", file_name, st);

    if ( st == 2 ){
      st = STAT(___zlibc_x)(ver, newname, buf);
      if(ver == _STAT_VER)
	buf->st_size = 0;
    }

    if ( st < 0 ){
      errno = ENOENT;
      return st;
    }

  }

  errno = olderrno;
  return st;

}

static int STAT(zlibc_lx)(int ver, __const char *file_name, STATTYPE *buf)
{
  int st, olderrno;

  olderrno = errno;
  st = STAT(___zlibc_lx)(ver,file_name, buf);

  if ( st >= 0 || errno != ENOENT )
    return st;

  {
    char newname[MAXPATHLEN + MAXEXTLEN + 1];

    zlib_initialise();
    if ( zlib_mode & CM_DISAB ) {
      errno = ENOENT;
      return st;
    }
    if ( zlib_mode & CM_VERBOSE )
      fprintf(stderr,"lstating %s\n", file_name);

    strncpy(newname,file_name,MAXPATHLEN);
    strcat(newname,zlib_ext);

    st = STAT(___zlibc_lx)(ver,newname, buf);

    if ( st < 0 ){
      errno = ENOENT;
      return st;
    }

    if (ver == _STAT_VER && S_ISLNK(buf->st_mode) ){
      if ( (signed int) buf->st_size > zlib_extlen )
	buf->st_size -= zlib_extlen;
      errno = olderrno;
      return st;
    }
     
    st = STAT(z)(ver,file_name,newname,buf);
    if ( st == 2 )
      /* could not zstat it, keep first info */
      st=0;
  }

  errno = olderrno;
  return st;
}
