Exemple #1
0
/* Get file length ... 64-bitally. -1 for error.
 */
gint64
vips_file_length( int fd )
{
#ifdef OS_WIN32
	struct _stati64 st;

	if( _fstati64( fd, &st ) == -1 ) {
#else /*!OS_WIN32*/
	struct stat st;

	if( fstat( fd, &st ) == -1 ) {
#endif /*OS_WIN32*/
		vips_error_system( errno, "vips_file_length", 
			"%s", _( "unable to get file stats" ) );
		return( -1 );
	}

	return( st.st_size );
}

/* Wrap write() up
 */
int
vips__write( int fd, const void *buf, size_t count )
{
	do {
		size_t nwritten = write( fd, buf, count );

		if( nwritten == (size_t) -1 ) {
                        vips_error_system( errno, "vips__write", 
				"%s", _( "write failed" ) );
                        return( -1 ); 
		}

		buf = (void *) ((char *) buf + nwritten);
		count -= nwritten;
	} while( count > 0 );

	return( 0 );
}

#ifdef OS_WIN32
/* Set the create date on a file. On Windows, the create date may be copied 
 * over from an existing file of the same name, unless you reset it. 
 *
 * See https://blogs.msdn.microsoft.com/oldnewthing/20050715-14/?p=34923
 */
void
vips__set_create_time( int fd )
{
	HANDLE handle;
	SYSTEMTIME st;
	FILETIME ft;

	if( (handle = _get_osfhandle( fd )) == INVALID_HANDLE_VALUE )
		return;
	GetSystemTime( &st );
	SystemTimeToFileTime( &st, &ft );
	SetFileTime( handle, &ft, &ft, &ft );
}
Exemple #2
0
/* Need our own ftruncate(), since ftruncate() on win32 can't do long files.

	DANGER ... this moves the file pointer to the end of file on win32,
	but not on *nix; don't make any assumptions about the file pointer
	position after calling this

 */
int
vips__ftruncate( int fd, gint64 pos )
{
#ifdef OS_WIN32
{
	HANDLE hFile = (HANDLE) _get_osfhandle( fd );
	LARGE_INTEGER p;

	p.QuadPart = pos;
	if( vips__seek( fd, pos ) )
		return( -1 );
	if( !SetEndOfFile( hFile ) ) {
                vips_error_system( GetLastError(), "vips__ftruncate", 
			"%s", _( "unable to truncate" ) );
		return( -1 );
	}
}
#else /*!OS_WIN32*/
	if( ftruncate( fd, pos ) ) {
		vips_error_system( errno, "vips__ftruncate", 
			"%s", _( "unable to truncate" ) );
		return( -1 );
	}
#endif /*OS_WIN32*/

	return( 0 );
}
Exemple #3
0
/* Get file length ... 64-bitally. -1 for error.
 */
gint64
vips_file_length( int fd )
{
#ifdef OS_WIN32
	struct _stati64 st;

	if( _fstati64( fd, &st ) == -1 ) {
#else /*!OS_WIN32*/
	struct stat st;

	if( fstat( fd, &st ) == -1 ) {
#endif /*OS_WIN32*/
		vips_error_system( errno, "vips_file_length", 
			"%s", _( "unable to get file stats" ) );
		return( -1 );
	}

	return( st.st_size );
}

/* Wrap write() up
 */
int
vips__write( int fd, const void *buf, size_t count )
{
	do {
		size_t nwritten = write( fd, buf, count );

		if( nwritten == (size_t) -1 ) {
                        vips_error_system( errno, "vips__write", 
				"%s", _( "write failed" ) );
                        return( -1 ); 
		}

		buf = (void *) ((char *) buf + nwritten);
		count -= nwritten;
	} while( count > 0 );

	return( 0 );
}

/* Does a filename contain a directory separator?
 */
static gboolean 
filename_hasdir( const char *filename )
{
	char *dirname;
	gboolean hasdir;

	dirname = g_path_get_dirname( filename );
	hasdir = (strcmp( dirname, "." ) != 0);
	g_free( dirname );

	return( hasdir );
}
/* Init function for doublevec input.
 */
static int
input_doublevec_init( im_object *obj, char *str )
{
	im_doublevec_object *dv = *obj;
	char **strv;
	int nargs;
	int i;

	strv = g_strsplit( str, VEC_SEPS, -1 );
	nargs = g_strv_length( strv );

	if( !(dv->vec = VIPS_ARRAY( NULL, nargs, double )) ) {
		g_strfreev( strv );
		return( -1 );
	}
	dv->n = nargs;

	for( i = 0; i < nargs; i++ ) {
		dv->vec[i] = g_ascii_strtod( strv[i], NULL );
		if( errno ) {
			vips_error_system( errno, "input_doublevec_init", 
				_( "bad double \"%s\"" ), strv[i] );
			g_strfreev( strv );
			return( -1 );
		}
	}

	g_strfreev( strv );

	return( 0 );
}
Exemple #5
0
/* Open for write for image files. 
 */
int
vips__open_image_write( const char *filename, gboolean temp )
{
	int flags;
	int fd;

	flags = MODE_WRITE;

#ifdef _O_TEMPORARY
	/* On Windows, setting O_TEMP gets the file automatically
	 * deleted on process exit, even if the processes crashes. See
	 * vips_image_rewind() for what we do to help on *nix.
	 */
	if( temp )
		flags |= _O_TEMPORARY;
#endif /*_O_TEMPORARY*/

	if( (fd = vips_tracked_open( filename, flags, 0666 )) < 0 ) {
		vips_error_system( errno, "VipsImage", 
			_( "unable to write to \"%s\"" ), 
			filename );
		return( -1 );
	}

	return( fd );
}
Exemple #6
0
int
vips__munmap( const void *start, size_t length )
{
#ifdef OS_WIN32
	if( !UnmapViewOfFile( (void *) start ) ) {
		vips_error_system( GetLastError(), "vips_mapfile",
			"%s", _( "unable to UnmapViewOfFile" ) );
		return( -1 );
	}
#else /*!OS_WIN32*/
	if( munmap( (void *) start, length ) < 0 ) {
		vips_error_system( errno, "vips_mapfile", 
			"%s", _( "unable to munmap file" ) );
		return( -1 );
	}
#endif /*OS_WIN32*/

	return( 0 );
}
Exemple #7
0
/* Like fwrite(), but returns non-zero on error and sets error message.
 */
int
vips__file_write( void *data, size_t size, size_t nmemb, FILE *stream )
{
	size_t n;

	if( !data ) 
		return( 0 );

	if( (n = fwrite( data, size, nmemb, stream )) != nmemb ) {
		vips_error_system( errno, "vips__file_write", 
			_( "write error (%zd out of %zd blocks written)" ),
			n, nmemb );
		return( -1 );
	}

	return( 0 );
}
Exemple #8
0
/* Open for read for image files. 
 */
int
vips__open_image_read( const char *filename )
{
	int fd;

	/* Try to open read-write, so that calls to vips_image_inplace() will 
	 * work. When we later mmap this file, we set read-only, so there 
	 * is little danger of scrubbing over files we own.
	 */
	fd = vips_tracked_open( filename, MODE_READWRITE );
	if( fd == -1 ) 
		/* Open read-write failed. Fall back to open read-only.
		 */
		fd = vips_tracked_open( filename, MODE_READONLY );
	
	if( fd == -1 ) {
		vips_error_system( errno, "VipsImage", 
			_( "unable to open \"%s\"" ), filename );
		return( -1 );
	}

	return( fd );
}
/* Init function for intvec input.
 */
static int
input_intvec_init( im_object *obj, char *str )
{
	im_intvec_object *iv = *obj;
	char **strv;
	int nargs;
	int i;

	strv = g_strsplit( str, VEC_SEPS, -1 );
	nargs = g_strv_length( strv );

	if( !(iv->vec = VIPS_ARRAY( NULL, nargs, int )) ) {
		g_strfreev( strv );
		return( -1 );
	}
	iv->n = nargs;

	for( i = 0; i < nargs; i++ ) {
                long int val= strtol( strv[i], NULL, 10 );

		if( errno ) {
			vips_error_system( errno, "input_intvec_init", 
				_( "bad integer \"%s\"" ), strv[i] );
			g_strfreev( strv );
			return( -1 );
		}
                if( INT_MAX < val || INT_MIN > val ) {
                        vips_error( "input_intvec_init", 
                                "%ld overflows integer type", val );
                }
		iv->vec[i] = (int) val;
	}

	g_strfreev( strv );

	return( 0 );
}
Exemple #10
0
/* Need our own seek(), since lseek() on win32 can't do long files.
 */
int
vips__seek( int fd, gint64 pos )
{
#ifdef OS_WIN32
{
	HANDLE hFile = (HANDLE) _get_osfhandle( fd );
	LARGE_INTEGER p;

	p.QuadPart = pos;
	if( !SetFilePointerEx( hFile, p, NULL, FILE_BEGIN ) ) {
                vips_error_system( GetLastError(), "vips__seek", 
			"%s", _( "unable to seek" ) );
		return( -1 );
	}
}
#else /*!OS_WIN32*/
	if( lseek( fd, pos, SEEK_SET ) == (off_t) -1 ) {
		vips_error( "vips__seek", "%s", _( "unable to seek" ) );
		return( -1 );
	}
#endif /*OS_WIN32*/

	return( 0 );
}
Exemple #11
0
FILE *
vips__file_open_write( const char *filename, gboolean text_mode )
{
	char *mode;
	FILE *fp;

#ifdef BINARY_OPEN
	if( text_mode )
		mode = "w";
	else
		mode = "wb";
#else /*BINARY_OPEN*/
	mode = "w";
#endif /*BINARY_OPEN*/

        if( !(fp = vips__fopen( filename, mode )) ) {
		vips_error_system( errno, "vips__file_open_write", 
			_( "unable to open file \"%s\" for writing" ), 
			filename );
		return( NULL );
	}

	return( fp );
}
Exemple #12
0
/* Open a file. We take an optional fallback dir as well and will try opening
 * there if opening directly fails.
 *
 * This is used for things like finding ICC profiles. We try to open the file
 * directly first, and if that fails and the filename does not contain a
 * directory separator, we try looking in the fallback dir.
 */
FILE *
vips__file_open_read( const char *filename, const char *fallback_dir, 
	gboolean text_mode )
{
	char *mode;
	FILE *fp;

#ifdef BINARY_OPEN
	if( text_mode )
		mode = "r";
	else
		mode = "rb";
#else /*BINARY_OPEN*/
	mode = "r";
#endif /*BINARY_OPEN*/

	if( (fp = vips__fopen( filename, mode )) )
		return( fp );

	if( fallback_dir && 
		!filename_hasdir( filename ) ) {
		char *path;

		path = g_build_filename( fallback_dir, filename, NULL );
	        fp = vips__fopen( path, mode );
		g_free( path );

		if( fp )
			return( fp );
	}

	vips_error_system( errno, "vips__file_open_read", 
		_( "unable to open file \"%s\" for reading" ), filename );

	return( NULL );
}
Exemple #13
0
static int
read_csv( FILE *fp, VipsImage *out, 
	int skip, 
	int lines,
	const char *whitespace, const char *separator,
	gboolean read_image )
{
	int i;
	char whitemap[256];
	char sepmap[256];
	const char *p;
	fpos_t pos;
	int columns;
	int ch;
	double d;
	double *buf;
	int y;

	/* Make our char maps. 
	 */
	for( i = 0; i < 256; i++ ) {
		whitemap[i] = 0;
		sepmap[i] = 0;
	}
	for( p = whitespace; *p; p++ )
		whitemap[(int) *p] = 1;
	for( p = separator; *p; p++ )
		sepmap[(int) *p] = 1;

	/* Skip first few lines.
	 */
	for( i = 0; i < skip; i++ )
		if( !skip_line( fp ) ) {
			vips_error( "csv2vips", 
				"%s", _( "end of file while skipping start" ) );
			return( -1 );
		}

	/* Parse the first line to get number of columns. Only bother checking
	 * fgetpos() the first time we use it: assume it's working after this.
	 */
	if( fgetpos( fp, &pos ) ) {
		vips_error_system( errno, "csv2vips", 
			"%s", _( "unable to seek" ) );
		return( -1 );
	}
	for( columns = 0; 
		(ch = read_double( fp, whitemap, sepmap, 
			skip + 1, columns + 1, &d )) == 0; 
		columns++ )
		;
	fsetpos( fp, &pos );

	if( columns == 0 ) {
		vips_error( "csv2vips", "%s", _( "empty line" ) );
		return( -1 );
	}

	/* If lines is -1, we have to scan the whole file to get the
	 * number of lines out.
	 */
	if( lines == -1 ) {
		fgetpos( fp, &pos );
		for( lines = 0; skip_line( fp ); lines++ )
			;
		fsetpos( fp, &pos );
	}

	vips_image_init_fields( out,
		columns, lines, 1, 
		VIPS_FORMAT_DOUBLE, 
		VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 );
	vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );

	/* Just reading the header? We are done.
	 */
	if( !read_image )
		return( 0 );

	if( !(buf = VIPS_ARRAY( out, 
		VIPS_IMAGE_N_ELEMENTS( out ), double )) )
		return( -1 );

	for( y = 0; y < lines; y++ ) {
		int x;

		for( x = 0; x < columns; x++ ) {
			int lineno = y + skip + 1;
			int colno = x + 1;

			ch = read_double( fp, whitemap, sepmap,
				lineno, colno, &d );
			if( ch == EOF ) {
				vips_error( "csv2vips", 
					_( "unexpected EOF, line %d col %d" ), 
					lineno, colno );
				return( -1 );
			}
			else if( ch == '\n' ) {
				vips_error( "csv2vips", 
					_( "unexpected EOL, line %d col %d" ), 
					lineno, colno );
				return( -1 );
			}
			else if( ch )
				/* Parse error.
				 */
				return( -1 );

			buf[x] = d;
		}

		if( vips_image_write_line( out, y, (VipsPel *) buf ) )
			return( -1 );

		/* Skip over the '\n' to the next line.
		 */
		skip_line( fp );
	}

	return( 0 );
}
Exemple #14
0
void *
vips__mmap( int fd, int writeable, size_t length, gint64 offset )
{
	void *baseaddr;

#ifdef DEBUG
	printf( "vips__mmap: length = 0x%zx, offset = 0x%lx\n", 
		length, offset );
#endif /*DEBUG*/

#ifdef OS_WIN32
{
	HANDLE hFile = (HANDLE) _get_osfhandle( fd );

	DWORD flProtect;
	DWORD dwDesiredAccess;

        HANDLE hMMFile;

	ULARGE_INTEGER quad;
	DWORD dwFileOffsetHigh;
	DWORD dwFileOffsetLow;

	if( writeable ) {
		flProtect = PAGE_READWRITE;
		dwDesiredAccess = FILE_MAP_WRITE;
	}
	else {
		flProtect = PAGE_READONLY;
		dwDesiredAccess = FILE_MAP_READ;
	}

	quad.QuadPart = offset;
	dwFileOffsetLow = quad.LowPart;
	dwFileOffsetHigh = quad.HighPart;

        if( !(hMMFile = CreateFileMapping( hFile,
		NULL, flProtect, 0, 0, NULL )) ) {
                vips_error_system( GetLastError(), "vips_mapfile", 
			"%s", _( "unable to CreateFileMapping" ) );
		printf( "CreateFileMapping failed: %s\n", vips_error_buffer() );
                return( NULL );
        }

        if( !(baseaddr = (char *)MapViewOfFile( hMMFile, dwDesiredAccess, 
		dwFileOffsetHigh, dwFileOffsetLow, length )) ) {
                vips_error_system( GetLastError(), "vips_mapfile",
			"%s", _( "unable to MapViewOfFile" ) );
		printf( "MapViewOfFile failed: %s\n", vips_error_buffer() );
		CloseHandle( hMMFile );
                return( NULL );
        }

	/* Can close mapping now ... view stays until UnmapViewOfFile().

		FIXME ... is this a performance problem?

	 */
	CloseHandle( hMMFile );
}
#else /*!OS_WIN32*/
{
	int prot;
	int flags;

	if( writeable ) 
		prot = PROT_WRITE;
	else 
		prot = PROT_READ;

	flags = MAP_SHARED;

	/* OS X caches mmapped files very aggressively if this flags is not
	 * set. Scanning a large file without this flag will cause every other
	 * process to get swapped out and kill performance.
	 */
#ifdef MAP_NOCACHE
	flags |= MAP_NOCACHE;
#endif /*MAP_NOCACHE*/

	/* Casting gint64 to off_t should be safe, even on *nixes without
	 * LARGEFILE.
	 */

	baseaddr = mmap( 0, length, prot, flags, fd, (off_t) offset );
	if( baseaddr == MAP_FAILED ) { 
		vips_error_system( errno, "vips_mapfile", 
			"%s", _( "unable to mmap" ) );
		g_warning( _( "map failed (%s), "
			"running very low on system resources, "
			"expect a crash soon" ), strerror( errno ) );
		return( NULL ); 
	}
}
#endif /*OS_WIN32*/

	return( baseaddr );
}
Exemple #15
0
/* From im_rwcheck() ... image needs to be a completely mapped read-only file, 
 * we try to remap it read-write. 
 */
int
vips_remapfilerw( VipsImage *image )
{
	void *baseaddr;

#ifdef OS_WIN32
{
	HANDLE hFile = (HANDLE) _get_osfhandle( image->fd );
        HANDLE hMMFile;

        if( !(hMMFile = CreateFileMapping( hFile,
		NULL, PAGE_READWRITE, 0, 0, NULL )) ) {
                vips_error_system( GetLastError(), "vips_mapfile", 
			"%s", _( "unable to CreateFileMapping" ) );
                return( -1 );
        }

	if( !UnmapViewOfFile( image->baseaddr ) ) {
		vips_error_system( GetLastError(), "vips_mapfile", 
			"%s", _( "unable to UnmapViewOfFile" ) );
		return( -1 );
	}
        if( !(baseaddr = (char *)MapViewOfFileEx( hMMFile, FILE_MAP_WRITE, 
		0, 0, 0, image->baseaddr )) ) {
                vips_error_system( GetLastError(), "vips_mapfile",
			"%s", _( "unable to MapViewOfFile" ) );
		CloseHandle( hMMFile );
                return( -1 );
        }

	/* Can close mapping now ... view stays until UnmapViewOfFile().

		FIXME ... is this a performance problem?

	 */
	CloseHandle( hMMFile );
}
#else /*!OS_WIN32*/
{
	assert( image->dtype == VIPS_IMAGE_MMAPIN );

	baseaddr = mmap( image->baseaddr, image->length,
		PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, 
		image->fd, 0 );
	if( baseaddr == (void *)-1 ) { 
		vips_error( "vips_mapfile", _( "unable to mmap: \"%s\" - %s" ),
			image->filename, strerror( errno ) );
		return( -1 ); 
	}
}
#endif /*OS_WIN32*/

	image->dtype = VIPS_IMAGE_MMAPINRW;

	if( baseaddr != image->baseaddr ) {
		vips_error( "vips_mapfile", _( "unable to mmap \"%s\" to same "
			"address" ), image->filename );
		image->baseaddr = baseaddr;
		return( -1 ); 
	}

	return( 0 );
}
Exemple #16
0
/* Get file length ... 64-bitally. -1 for error.
 */
gint64
vips_file_length( int fd )
{
#ifdef OS_WIN32
	struct _stati64 st;

	if( _fstati64( fd, &st ) == -1 ) {
#else /*!OS_WIN32*/
	struct stat st;

	if( fstat( fd, &st ) == -1 ) {
#endif /*OS_WIN32*/
		vips_error_system( errno, "vips_file_length", 
			"%s", _( "unable to get file stats" ) );
		return( -1 );
	}

	return( st.st_size );
}

/* Wrap write() up
 */
int
vips__write( int fd, const void *buf, size_t count )
{
	do {
		size_t nwritten = write( fd, buf, count );

		if( nwritten == (size_t) -1 ) {
                        vips_error_system( errno, "vips__write", 
				"%s", _( "write failed" ) );
                        return( -1 ); 
		}

		buf = (void *) ((char *) buf + nwritten);
		count -= nwritten;
	} while( count > 0 );

	return( 0 );
}

/* open() with a utf8 filename, setting errno.
 */
int
vips__open( const char *filename, int flags, ... )
{
	int fd;
	mode_t mode;
	va_list ap;

	va_start( ap, flags );
	mode = va_arg( ap, int );
	va_end( ap );

#ifdef OS_WIN32
{
	wchar_t *path16;

	if( !(path16 = (wchar_t *) 
		g_utf8_to_utf16( filename, -1, NULL, NULL, NULL )) ) { 
		errno = EACCES;
		return( -1 );
	}

	fd = _wopen( path16, flags, mode );

	g_free( path16 );
}
#else /*!OS_WIN32*/
	fd = open( filename, flags, mode );
#endif

	return( fd );
}