[sane-devel] Scanning Lineart/Halftone with MICROTEK Scanmak

Henning Meier-Geinitz henning@meier-geinitz.de
Sun, 26 May 2002 20:00:14 +0200


Hi,

On Sun, May 26, 2002 at 07:06:53PM +0200, mh wrote:
> When you "scan" a lineart image with the pnm backend, sane_read will allways 
> return the number of bytes requested by the frontend (or the number of bytes 
> left in the input file). This is normally more than one scanline, because 
> xsane probably request 32 kB or something.
> With the tevion backend (and probably other backends too), sane_read can 
> return a number of bytes smaller or equal to the size of one scanline.
> You can now modify the pnm backend in a way, that it returns one byte per 
> call to sane_read, and voila, suddenly the bug also occurrs with the pnm 
> backend :-)

I have added an entry in my TODO list for the test backend to allow
lineart mode with pixels_per_line % 8 != 0.

> This also reveals a small bug in the pnm backend, which will cause the 
> frontend to hang in some rare cases.
> See pnm.c around line 1162:
> 
> /* Suck in as much of the file as possible, since it's already in the
>    correct format. */
>   len = fread (data, 1, max_length, infile);
> 
> If fread returns 0, then *length is set to 0 and SANE_STATUS_GOOD is returned.

You did see the test for len == 0 and feof/ferror in the next lines of
the code (CVS)? Shouldn't those tests be enough?

  if (len == 0)
    {
      if (feof (infile))
	{
	  DBG (2, "sane_read: EOF reached\n");
	  return SANE_STATUS_EOF;
	}
      else
	{
	  DBG (1, "sane_read: error while reading file (%s)\n",
	       strerror (errno));
	  return SANE_STATUS_IO_ERROR;
	}
    }
    
> The frontend therefore expects more data, and calls sane_read again... -> 
> infinite loop

This should only happen if there is no eof or error. This can happen
e.g. if the file is on an NFS server and the connection was
interrupted. In this case the loop is ok IMHO.

> We should replace this with
> 
> {
>   /* Suck in as much of the file as possible, since it's already in the
>      correct format. */
>   len = fread (data, 1, max_length, infile);
>   if(len <= 0)
>     return SANE_STATUS_EOF;
> }

If I understand the man page correctly, len can't be < 0.

Bye,
  Henning