int my_fstat(int fd, Stat_t *sbufptr) { /* This fixes a bug in fstat() on Windows 9x. fstat() uses the * GetFileType() win32 syscall, which will fail on Windows 9x. * So if we recognize a socket on Windows 9x, we return the * same results as on Windows NT/2000. * XXX this should be extended further to set S_IFSOCK on * sbufptr->st_mode. */ int osf; if (!wsock_started || IsWinNT()) { #if defined(WIN64) || defined(USE_LARGE_FILES) #if defined(__BORLANDC__) /* buk */ return win32_fstat(fd, sbufptr ); #else return _fstati64(fd, sbufptr); #endif #else return fstat(fd, sbufptr); #endif } osf = TO_SOCKET(fd); if (osf != -1) { char sockbuf[256]; int optlen = sizeof(sockbuf); int retval; retval = getsockopt((SOCKET)osf, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); if (retval != SOCKET_ERROR || WSAGetLastError() != WSAENOTSOCK) { #if defined(__BORLANDC__)&&(__BORLANDC__<=0x520) sbufptr->st_mode = S_IFIFO; #else sbufptr->st_mode = _S_IFIFO; #endif sbufptr->st_rdev = sbufptr->st_dev = (dev_t)fd; sbufptr->st_nlink = 1; sbufptr->st_uid = sbufptr->st_gid = sbufptr->st_ino = 0; sbufptr->st_atime = sbufptr->st_mtime = sbufptr->st_ctime = 0; sbufptr->st_size = (Off_t)0; return 0; } } #if defined(WIN64) || defined(USE_LARGE_FILES) #if defined(__BORLANDC__) /* buk */ return win32_fstat(fd, sbufptr ); #else return _fstati64(fd, sbufptr); #endif #else return fstat(fd, sbufptr); #endif }
/* Win32 */ sf_count_t psf_get_filelen (SF_PRIVATE *psf) { #if 0 /* ** Windoze is SOOOOO F****D!!!!!!! ** This code should work but doesn't. Why? ** Code below does work. */ struct _stati64 statbuf ; if (_fstati64 (psf->filedes, &statbuf)) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; return statbuf.st_size ; #else sf_count_t current, len ; current = psf_fseek (psf, 0, SEEK_CUR) ; len = psf_fseek (psf, 0, SEEK_END) ; psf_fseek (psf, current, SEEK_SET) ; return len ; #endif } /* psf_get_filelen */
/* 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 ); }
/* Quick and dirty my_fstat() implementation for Windows. Use CRT fstat on temporarily allocated file descriptor. Patch file size, because size that fstat returns is not reliable (may be outdated) */ int my_win_fstat(File fd, struct _stati64 *buf) { int crt_fd; int retval; HANDLE hFile, hDup; DBUG_ENTER("my_win_fstat"); hFile= my_get_osfhandle(fd); if(!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(), &hDup ,0,FALSE,DUPLICATE_SAME_ACCESS)) { my_osmaperr(GetLastError()); DBUG_RETURN(-1); } if ((crt_fd= _open_osfhandle((intptr_t)hDup,0)) < 0) DBUG_RETURN(-1); retval= _fstati64(crt_fd, buf); if(retval == 0) { /* File size returned by stat is not accurate (may be outdated), fix it*/ GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(buf->st_size))); } _close(crt_fd); DBUG_RETURN(retval); }
int sim_fseeko (FILE *st, t_offset offset, int whence) { fpos_t fileaddr; struct _stati64 statb; switch (whence) { case SEEK_SET: fileaddr = (fpos_t)offset; break; case SEEK_END: if (_fstati64 (_fileno (st), &statb)) return (-1); fileaddr = statb.st_size + offset; break; case SEEK_CUR: if (fgetpos (st, &fileaddr)) return (-1); fileaddr = fileaddr + offset; break; default: errno = EINVAL; return (-1); } return fsetpos (st, &fileaddr); }
int mingw_fstat(int fd, struct stat *buf) { HANDLE fh = (HANDLE)_get_osfhandle(fd); BY_HANDLE_FILE_INFORMATION fdata; if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; } /* direct non-file handles to MS's fstat() */ if (GetFileType(fh) != FILE_TYPE_DISK) return _fstati64(fd, buf); if (GetFileInformationByHandle(fh, &fdata)) { buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_nlink = 1; buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); buf->st_size = fdata.nFileSizeLow | (((off_t)fdata.nFileSizeHigh)<<32); buf->st_dev = buf->st_rdev = 0; /* not used by Git */ buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); return 0; } errno = EBADF; return -1; }
CAMLprim value unix_fstat_64(value handle) { int ret; struct _stati64 buf; ret = _fstati64(win_CRT_fd_of_filedescr(handle), &buf); if (ret == -1) uerror("fstat", Nothing); return stat_aux(1, &buf); }
/* 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 ); }
/* Win32 */ sf_count_t psf_get_filelen (int fd) { struct _stati64 statbuf ; if (_fstati64 (fd, &statbuf)) { perror ("fstat") ; return -1 ; } ; return statbuf.st_size ; } /* psf_fclose */
void fs__fstat(uv_fs_t* req, uv_file file) { int result; result = _fstati64(file, &req->stat); if (result == -1) { req->ptr = NULL; } else { req->ptr = &req->stat; } SET_REQ_RESULT(req, result); }
CAMLprim value unix_fstat(value handle) { int ret; struct _stati64 buf; ret = _fstati64(win_CRT_fd_of_filedescr(handle), &buf); if (ret == -1) uerror("fstat", Nothing); if (buf.st_size > Max_long) { win32_maperr(ERROR_ARITHMETIC_OVERFLOW); uerror("fstat", Nothing); } return stat_aux(0, &buf); }
int _fstat64i32( int fd, struct _stat64i32 *buffer ) { struct _stat64 s; int retval = _fstati64( fd, &s ); if(!retval ) { buffer->st_atime = s.st_atime; buffer->st_ctime = s.st_ctime; buffer->st_dev = s.st_dev; buffer->st_gid = s.st_gid; buffer->st_ino = s.st_ino; buffer->st_mode = s.st_mode; buffer->st_mtime = s.st_mtime; buffer->st_nlink = s.st_nlink; buffer->st_rdev = s.st_rdev; buffer->st_size = (_off_t)s.st_size; buffer->st_uid = s.st_uid; } return retval; }
//============================== // FileSize static size_t FileSize( FILE * f ) { if ( f == NULL ) { return 0; } #if defined( WIN32 ) struct _stat64 stats; __int64 r = _fstati64( f->_file, &stats ); #else struct stat stats; int r = fstat( f->_file, &stats ); #endif if ( r < 0 ) { return 0; } return static_cast< size_t >( stats.st_size ); // why st_size is signed I have no idea... negative file lengths? }
/** * Internal implementation of _wstati64(). * MSVCRT's _wstati64() fails if the filename contains '?' or '*', * which breaks long filename support, e.g. \\?\. * @param pathname Pathname. * @param buf Stat buffer. * @return 0 on success; -1 on error. */ static int W32U_wstati64(const wchar_t *pathname, struct _stati64 *buffer) { int fd, ret; if (!pathname || !buffer) { errno = EINVAL; return -1; } // _fstati64() can obtain all the information. // We just need to open the file first. // FIXME: Use FindFirstFileW() instead to avoid having to open the file? fd = _wopen(pathname, _O_RDONLY, 0); if (fd < 0) { // Error opening the file. return fd; } ret = _fstati64(fd, buffer); _close(fd); return ret; }
// must not be called in the ctor, can throw exceptions void MemoryDataSource::_loadFile() { if (this->data == NULL) { VideoClip::Format format; FILE* file = openSupportedFormatFile(filename, format, this->fullFilename); if (file == NULL) { std::string message = "Can't open or find video file: " + filename; log(message); throw TheoraplayerException(message); } this->formatName = format.name; #ifdef _WIN32 struct _stat64 s; _fstati64(_fileno(file), &s); #else struct stat s; fstat(fileno(file), &s); #endif this->size = (int64_t)s.st_size; if (this->size > 0xFFFFFFFF) { fclose(file); throw TheoraplayerException("MemoryDataSource doesn't support files larger than 4GB!"); } if (this->size < UINT_MAX) { this->data = new unsigned char[(unsigned int)this->size]; fread(this->data, 1, (size_t)this->size, file); } else { fclose(file); throw TheoraplayerException("Unable to preload file to memory, file is too large."); } fclose(file); } }
/** Retrieves a file's size * @param[in] _pstFile Concerned file * @return Returns the length of the file, <= 0 if invalid */ orxS64 orxFASTCALL orxFile_GetSize(const orxFILE *_pstFile) { orxS64 s64Result; /* Checks */ orxASSERT((sstFile.u32Flags & orxFILE_KU32_STATIC_FLAG_READY) == orxFILE_KU32_STATIC_FLAG_READY); /* Valid? */ if(_pstFile != orxNULL) { #if defined(__orxWINDOWS__) && (_MSC_VER < 1900) struct _stati64 stStat; /* Gets file stats */ _fstati64(((FILE *)_pstFile)->_file, &stStat); #else /* __orxWINDOWS__ && _MSC_VER < 1900 */ struct stat stStat; /* Gets file stats */ fstat(fileno((FILE *)_pstFile), &stStat); #endif /* __orxWINDOWS__ && _MSC_VER < 1900 */ /* Updates result */ s64Result = (orxS64)stStat.st_size; } else { /* Updates result */ s64Result = 0; } /* Done! */ return s64Result; }
void FileDataSource::_openFile() { if (this->filePtr == NULL) { VideoClip::Format format; this->filePtr = openSupportedFormatFile(this->filename, format, this->fullFilename); if (this->filePtr == NULL) { std::string message = "Can't open or find video file: " + filename; log(message); throw TheoraplayerException(message); } this->formatName = format.name; #ifdef _WIN32 struct _stat64 s; _fstati64(_fileno(this->filePtr), &s); #else struct stat s; fstat(fileno(this->filePtr), &s); #endif this->length = (int64_t)s.st_size; } }
int sim_fseeko (FILE *st, t_offset offset, int whence) { fpos_t fileaddr; #ifdef _WIN32_WCE struct stat statb; #else struct _stati64 statb; #endif switch (whence) { case SEEK_SET: fileaddr = (fpos_t)offset; break; case SEEK_END: #ifdef _WIN32_WCE if(fstat(fileno(st), &statb) < 0) #else if (_fstati64(_fileno (st), &statb) < 0) #endif return (-1); fileaddr = statb.st_size + offset; break; case SEEK_CUR: if (fgetpos (st, &fileaddr)) return (-1); fileaddr = fileaddr + offset; break; default: errno = EINVAL; return (-1); } return fsetpos (st, &fileaddr); }
__private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pathURL, Boolean *exists, SInt32 *posixMode, int64_t *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents) { Boolean fileExists; Boolean isDirectory = false; #if DEPLOYMENT_TARGET_WINDOWS struct _stati64 statBuf; int fd = -1; #else struct stat64 statBuf; #endif char path[CFMaxPathSize]; if ((exists == NULL) && (posixMode == NULL) && (size == NULL) && (modTime == NULL) && (ownerID == NULL) && (dirContents == NULL)) { // Nothing to do. return 0; } if (!CFURLGetFileSystemRepresentation(pathURL, true, (uint8_t *)path, CFMaxPathLength)) { return -1; } #if DEPLOYMENT_TARGET_WINDOWS HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (INVALID_HANDLE_VALUE == hFile) return -1; fd = _open_osfhandle((intptr_t)hFile, _O_RDONLY|CF_OPENFLGS); if (fd < 0) { if (thread_errno() == ENOENT) { fileExists = false; } else { CloseHandle (hFile); return thread_errno(); } } else { if (_fstati64(fd, &statBuf) != 0) { close(fd); CloseHandle (hFile); // stat failed, but why? if (thread_errno() == ENOENT) { fileExists = false; } else { return thread_errno(); } } else { close(fd); CloseHandle (hFile); fileExists = true; isDirectory = ((statBuf.st_mode & S_IFMT) == S_IFDIR); } } #else if (stat64(path, &statBuf) != 0) { // stat failed, but why? if (thread_errno() == ENOENT) { fileExists = false; } else { return thread_errno(); } } else { fileExists = true; isDirectory = ((statBuf.st_mode & S_IFMT) == S_IFDIR); } #endif if (exists != NULL) { *exists = fileExists; } if (posixMode != NULL) { if (fileExists) { *posixMode = statBuf.st_mode; } else { *posixMode = 0; } } if (size != NULL) { if (fileExists) { *size = statBuf.st_size; } else { *size = 0; } } if (modTime != NULL) { if (fileExists) { #if DEPLOYMENT_TARGET_WINDOWS CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtime; #elif DEPLOYMENT_TARGET_LINUX #if defined _BSD_SOURCE || defined _SVID_SOURCE CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtim.tv_sec - kCFAbsoluteTimeIntervalSince1970; theTime += (CFAbsoluteTime)statBuf.st_mtim.tv_nsec / 1000000000.0; #else CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtime - kCFAbsoluteTimeIntervalSince1970; theTime += (CFAbsoluteTime)statBuf.st_mtimensec / 1000000000.0; #endif /* defined _BSD_SOURCE || defined _SVID_SOURCE */ #else CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtimespec.tv_sec - kCFAbsoluteTimeIntervalSince1970; theTime += (CFAbsoluteTime)statBuf.st_mtimespec.tv_nsec / 1000000000.0; #endif *modTime = CFDateCreate(alloc, theTime); } else { *modTime = NULL; } } if (ownerID != NULL) { if (fileExists) { *ownerID = statBuf.st_uid; } else { *ownerID = -1; } } if (dirContents != NULL) { if (fileExists && isDirectory) { CFMutableArrayRef contents = _CFContentsOfDirectory(alloc, path, NULL, pathURL, NULL); if (contents) { *dirContents = contents; } else { *dirContents = NULL; } } else { *dirContents = NULL; } } return 0; }
__private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pathURL, Boolean *exists, SInt32 *posixMode, int64_t *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents) { Boolean fileExists; Boolean isDirectory = false; #if DEPLOYMENT_TARGET_WINDOWS struct _stati64 statBuf; int fd = -1; #else struct stat64 statBuf; #endif char path[CFMaxPathSize]; if ((exists == NULL) && (posixMode == NULL) && (size == NULL) && (modTime == NULL) && (ownerID == NULL) && (dirContents == NULL)) { // Nothing to do. return 0; } if (!CFURLGetFileSystemRepresentation(pathURL, true, (uint8_t *)path, CFMaxPathLength)) { return -1; } #if DEPLOYMENT_TARGET_WINDOWS SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (INVALID_HANDLE_VALUE == hFile) { DWORD error = GetLastError (); return -1; } fd = _open_osfhandle((intptr_t)hFile, _O_RDONLY|CF_OPENFLGS); if (fd < 0) { if (thread_errno() == ENOENT) { fileExists = false; } else { CloseHandle (hFile); return thread_errno(); } } else { if (_fstati64(fd, &statBuf) != 0) { close(fd); // stat failed, but why? if (thread_errno() == ENOENT) { fileExists = false; } else { return thread_errno(); } } else { fileExists = true; // Hack to work around Windows strange stat behavior: DWORD attributes = GetFileAttributesA (path); close(fd); if (attributes & FILE_ATTRIBUTE_DIRECTORY) { statBuf.st_mode &= ~S_IFREG; // Don't claim it's a regular file. statBuf.st_mode |= S_IFDIR; // Properly mark it as a directory } isDirectory = ((statBuf.st_mode & S_IFMT) == S_IFDIR); } } #else if (stat64(path, &statBuf) != 0) { // stat failed, but why? if (thread_errno() == ENOENT) { fileExists = false; } else { return thread_errno(); } } else { fileExists = true; isDirectory = ((statBuf.st_mode & S_IFMT) == S_IFDIR); } #endif if (exists != NULL) { *exists = fileExists; } if (posixMode != NULL) { if (fileExists) { *posixMode = statBuf.st_mode; } else { *posixMode = 0; } } if (size != NULL) { if (fileExists) { *size = statBuf.st_size; } else { *size = 0; } } if (modTime != NULL) { if (fileExists) { #if DEPLOYMENT_TARGET_WINDOWS CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtime; #elif DEPLOYMENT_TARGET_LINUX #if defined _BSD_SOURCE || defined _SVID_SOURCE CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtim.tv_sec - kCFAbsoluteTimeIntervalSince1970; theTime += (CFAbsoluteTime)statBuf.st_mtim.tv_nsec / 1000000000.0; #else CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtime - kCFAbsoluteTimeIntervalSince1970; theTime += (CFAbsoluteTime)statBuf.st_mtimensec / 1000000000.0; #endif /* defined _BSD_SOURCE || defined _SVID_SOURCE */ #else CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtimespec.tv_sec - kCFAbsoluteTimeIntervalSince1970; theTime += (CFAbsoluteTime)statBuf.st_mtimespec.tv_nsec / 1000000000.0; #endif *modTime = CFDateCreate(alloc, theTime); } else { *modTime = NULL; } } if (ownerID != NULL) { if (fileExists) { *ownerID = statBuf.st_uid; } else { *ownerID = -1; } } if (dirContents != NULL) { if (fileExists && isDirectory) { CFMutableArrayRef contents = _CFContentsOfDirectory(alloc, path, NULL, pathURL, NULL); if (contents) { *dirContents = contents; } else { *dirContents = NULL; } } else { *dirContents = NULL; } } return 0; }
static int handle_overwrite_open (const char *filename, const char *etag, gboolean create_backup, char **temp_filename, GCancellable *cancellable, GError **error) { int fd = -1; GLocalFileStat original_stat; char *current_etag; gboolean is_symlink; int open_flags; int res; /* We only need read access to the original file if we are creating a backup. * We also add O_CREATE to avoid a race if the file was just removed */ if (create_backup) open_flags = O_RDWR | O_CREAT | O_BINARY; else open_flags = O_WRONLY | O_CREAT | O_BINARY; /* Some systems have O_NOFOLLOW, which lets us avoid some races * when finding out if the file we opened was a symlink */ #ifdef O_NOFOLLOW is_symlink = FALSE; fd = g_open (filename, open_flags | O_NOFOLLOW, 0666); if (fd == -1 && errno == ELOOP) { /* Could be a symlink, or it could be a regular ELOOP error, * but then the next open will fail too. */ is_symlink = TRUE; fd = g_open (filename, open_flags, 0666); } #else fd = g_open (filename, open_flags, 0666); /* This is racy, but we do it as soon as possible to minimize the race */ is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK); #endif if (fd == -1) { int errsv = errno; char *display_name = g_filename_display_name (filename); g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error opening file '%s': %s"), display_name, g_strerror (errsv)); g_free (display_name); return -1; } #ifdef G_OS_WIN32 res = _fstati64 (fd, &original_stat); #else res = fstat (fd, &original_stat); #endif if (res != 0) { int errsv = errno; char *display_name = g_filename_display_name (filename); g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error stating file '%s': %s"), display_name, g_strerror (errsv)); g_free (display_name); goto err_out; } /* not a regular file */ if (!S_ISREG (original_stat.st_mode)) { if (S_ISDIR (original_stat.st_mode)) g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, _("Target file is a directory")); else g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_REGULAR_FILE, _("Target file is not a regular file")); goto err_out; } if (etag != NULL) { current_etag = _g_local_file_info_create_etag (&original_stat); if (strcmp (etag, current_etag) != 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG, _("The file was externally modified")); g_free (current_etag); goto err_out; } g_free (current_etag); } /* We use two backup strategies. * The first one (which is faster) consist in saving to a * tmp file then rename the original file to the backup and the * tmp file to the original name. This is fast but doesn't work * when the file is a link (hard or symbolic) or when we can't * write to the current dir or can't set the permissions on the * new file. * The second strategy consist simply in copying the old file * to a backup file and rewrite the contents of the file. */ if (!(original_stat.st_nlink > 1) && !is_symlink) { char *dirname, *tmp_filename; int tmpfd; dirname = g_path_get_dirname (filename); tmp_filename = g_build_filename (dirname, ".goutputstream-XXXXXX", NULL); g_free (dirname); tmpfd = g_mkstemp (tmp_filename); if (tmpfd == -1) { g_free (tmp_filename); goto fallback_strategy; } /* try to keep permissions */ if ( #ifdef HAVE_FCHOWN fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 || #endif #ifdef HAVE_FCHMOD fchmod (tmpfd, original_stat.st_mode) == -1 || #endif 0 ) { struct stat tmp_statbuf; /* Check that we really needed to change something */ if (fstat (tmpfd, &tmp_statbuf) != 0 || original_stat.st_uid != tmp_statbuf.st_uid || original_stat.st_gid != tmp_statbuf.st_gid || original_stat.st_mode != tmp_statbuf.st_mode) { close (tmpfd); g_unlink (tmp_filename); g_free (tmp_filename); goto fallback_strategy; } } close (fd); *temp_filename = tmp_filename; return tmpfd; } fallback_strategy: if (create_backup) { #if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD) struct stat tmp_statbuf; #endif char *backup_filename; int bfd; backup_filename = create_backup_filename (filename); if (g_unlink (backup_filename) == -1 && errno != ENOENT) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_free (backup_filename); goto err_out; } bfd = g_open (backup_filename, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, original_stat.st_mode & 0777); if (bfd == -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_free (backup_filename); goto err_out; } /* If needed, Try to set the group of the backup same as the * original file. If this fails, set the protection * bits for the group same as the protection bits for * others. */ #if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD) if (fstat (bfd, &tmp_statbuf) != 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_unlink (backup_filename); g_free (backup_filename); goto err_out; } if ((original_stat.st_gid != tmp_statbuf.st_gid) && fchown (bfd, (uid_t) -1, original_stat.st_gid) != 0) { if (fchmod (bfd, (original_stat.st_mode & 0707) | ((original_stat.st_mode & 07) << 3)) != 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_unlink (backup_filename); close (bfd); g_free (backup_filename); goto err_out; } } #endif if (!copy_file_data (fd, bfd, NULL)) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_unlink (backup_filename); close (bfd); g_free (backup_filename); goto err_out; } close (bfd); g_free (backup_filename); /* Seek back to the start of the file after the backup copy */ if (lseek (fd, 0, SEEK_SET) == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error seeking in file: %s"), g_strerror (errsv)); goto err_out; } } /* Truncate the file at the start */ #ifdef G_OS_WIN32 if (g_win32_ftruncate (fd, 0) == -1) #else if (ftruncate (fd, 0) == -1) #endif { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error truncating file: %s"), g_strerror (errsv)); goto err_out; } return fd; err_out: close (fd); return -1; }
static gboolean g_local_file_output_stream_close (GOutputStream *stream, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; GLocalFileStat final_stat; int res; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); #ifdef G_OS_WIN32 /* Must close before renaming on Windows, so just do the close first * in all cases for now. */ if (_fstati64 (file->priv->fd, &final_stat) == 0) file->priv->etag = _g_local_file_info_create_etag (&final_stat); res = close (file->priv->fd); if (res == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error closing file: %s"), g_strerror (errsv)); return FALSE; } #endif if (file->priv->tmp_filename) { /* We need to move the temp file to its final place, * and possibly create the backup file */ if (file->priv->backup_filename) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; #ifdef HAVE_LINK /* create original -> backup link, the original is then renamed over */ if (g_unlink (file->priv->backup_filename) != 0 && errno != ENOENT) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error removing old backup link: %s"), g_strerror (errsv)); goto err_out; } if (link (file->priv->original_filename, file->priv->backup_filename) != 0) { /* link failed or is not supported, try rename */ if (g_rename (file->priv->original_filename, file->priv->backup_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error creating backup copy: %s"), g_strerror (errsv)); goto err_out; } } #else /* If link not supported, just rename... */ if (g_rename (file->priv->original_filename, file->priv->backup_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error creating backup copy: %s"), g_strerror (errsv)); goto err_out; } #endif } if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; /* tmp -> original */ if (g_rename (file->priv->tmp_filename, file->priv->original_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), _("Error renaming temporary file: %s"), g_strerror (errsv)); goto err_out; } } if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; #ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */ if (fstat (file->priv->fd, &final_stat) == 0) file->priv->etag = _g_local_file_info_create_etag (&final_stat); while (1) { res = close (file->priv->fd); if (res == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error closing file: %s"), g_strerror (errsv)); } break; } return res != -1; #else return TRUE; #endif err_out: #ifndef G_OS_WIN32 /* A simple try to close the fd in case we fail before the actual close */ close (file->priv->fd); #endif return FALSE; }
/* 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 ); }
/* Retrieves the size of the file * This function uses the POSIX fstat function or equivalent * Returns 1 if successful or -1 on error */ int libcfile_stream_get_size( libcfile_stream_t *stream, size64_t *size, libcerror_error_t **error ) { #if defined( _MSC_VER ) struct __stat64 file_statistics; #elif defined( __BORLANDC__ ) struct stati64 file_statistics; #else struct stat file_statistics; #endif libcfile_internal_stream_t *internal_stream = NULL; static char *function = "libcfile_stream_get_size"; size_t file_statistics_size = 0; int file_descriptor = 0; #if defined( S_ISBLK ) && defined( S_ISCHR ) off64_t current_offset = 0; off64_t offset = 0; #endif if( stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid stream.", function ); return( -1 ); } internal_stream = (libcfile_internal_stream_t *) stream; if( internal_stream->stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid stream - missing stream.", function ); return( -1 ); } if( size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid size.", function ); return( -1 ); } #if defined( _MSC_VER ) file_statistics_size = sizeof( struct __stat64 ); #elif defined( __BORLANDC__ ) file_statistics_size = sizeof( struct stati64 ); #else file_statistics_size = sizeof( struct stat ); #endif if( memory_set( &file_statistics, 0, file_statistics_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file statistics.", function ); return( -1 ); } #if defined( WINAPI ) file_descriptor = _fileno( internal_stream->stream ); #else file_descriptor = fileno( internal_stream->stream ); #endif if( file_descriptor == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file descriptor of stream.", function ); return( -1 ); } #if defined( _MSC_VER ) if( _fstat64( file_descriptor, &file_statistics ) != 0 ) #elif defined( __BORLANDC__ ) if( _fstati64( file_descriptor, &file_statistics ) != 0 ) #else if( fstat( file_descriptor, &file_statistics ) != 0 ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file statistics.", function ); return( -1 ); } /* TODO implement device support ? */ /* TODO does not work on Mac OS X or WINAPI */ #if defined( S_ISBLK ) && defined( S_ISCHR ) if( S_ISBLK( file_statistics.st_mode ) || S_ISCHR( file_statistics.st_mode ) ) { if( libcfile_stream_get_offset( stream, ¤t_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve current offset.", function ); return( -1 ); } /* If the file is a device try to seek the end of the file */ offset = libcfile_stream_seek_offset( stream, 0, SEEK_END, error ); if( offset == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek end of file.", function ); return( -1 ); } *size = (size64_t) offset; offset = libcfile_stream_seek_offset( stream, current_offset, SEEK_SET, error ); if( offset == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset: %" PRIi64 ".", function, current_offset ); return( -1 ); } } else #endif { *size = (size64_t) file_statistics.st_size; } return( 1 ); }
gboolean _g_local_file_output_stream_really_close (GLocalFileOutputStream *file, GCancellable *cancellable, GError **error) { GLocalFileStat final_stat; #ifdef HAVE_FSYNC if (file->priv->sync_on_close && fsync (file->priv->fd) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to file: %s"), g_strerror (errsv)); goto err_out; } #endif #ifdef G_OS_WIN32 /* Must close before renaming on Windows, so just do the close first * in all cases for now. */ if (_fstati64 (file->priv->fd, &final_stat) == 0) file->priv->etag = _g_local_file_info_create_etag (&final_stat); if (!g_close (file->priv->fd, NULL)) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error closing file: %s"), g_strerror (errsv)); return FALSE; } #endif if (file->priv->tmp_filename) { /* We need to move the temp file to its final place, * and possibly create the backup file */ if (file->priv->backup_filename) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; #ifdef G_OS_UNIX /* create original -> backup link, the original is then renamed over */ if (g_unlink (file->priv->backup_filename) != 0 && errno != ENOENT) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error removing old backup link: %s"), g_strerror (errsv)); goto err_out; } if (link (file->priv->original_filename, file->priv->backup_filename) != 0) { /* link failed or is not supported, try rename */ if (g_rename (file->priv->original_filename, file->priv->backup_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error creating backup copy: %s"), g_strerror (errsv)); goto err_out; } } #else /* If link not supported, just rename... */ if (g_rename (file->priv->original_filename, file->priv->backup_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error creating backup copy: %s"), g_strerror (errsv)); goto err_out; } #endif } if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; /* tmp -> original */ if (g_rename (file->priv->tmp_filename, file->priv->original_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error renaming temporary file: %s"), g_strerror (errsv)); goto err_out; } g_clear_pointer (&file->priv->tmp_filename, g_free); } if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; #ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */ if (fstat (file->priv->fd, &final_stat) == 0) file->priv->etag = _g_local_file_info_create_etag (&final_stat); if (!g_close (file->priv->fd, NULL)) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error closing file: %s"), g_strerror (errsv)); goto err_out; } #endif return TRUE; err_out: #ifndef G_OS_WIN32 /* A simple try to close the fd in case we fail before the actual close */ g_close (file->priv->fd, NULL); #endif if (file->priv->tmp_filename) g_unlink (file->priv->tmp_filename); return FALSE; }