mirror of git://gcc.gnu.org/git/gcc.git
259 lines
4.8 KiB
C
259 lines
4.8 KiB
C
|
|
/* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
|
|
* http://www.digitalmars.com
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
* https://github.com/D-Programming-Language/dmd/blob/master/src/root/file.c
|
|
*/
|
|
|
|
#include "dsystem.h"
|
|
#include "file.h"
|
|
|
|
#if _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#if POSIX
|
|
#include <utime.h>
|
|
#endif
|
|
|
|
#include "filename.h"
|
|
#include "array.h"
|
|
#include "rmem.h"
|
|
|
|
/****************************** File ********************************/
|
|
|
|
File::File(const FileName *n)
|
|
{
|
|
ref = 0;
|
|
buffer = NULL;
|
|
len = 0;
|
|
name = const_cast<FileName *>(n);
|
|
}
|
|
|
|
File *File::create(const char *n)
|
|
{
|
|
return new File(n);
|
|
}
|
|
|
|
File::File(const char *n)
|
|
{
|
|
ref = 0;
|
|
buffer = NULL;
|
|
len = 0;
|
|
name = new FileName(n);
|
|
}
|
|
|
|
File::~File()
|
|
{
|
|
if (buffer)
|
|
{
|
|
if (ref == 0)
|
|
mem.xfree(buffer);
|
|
#if _WIN32
|
|
if (ref == 2)
|
|
UnmapViewOfFile(buffer);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*************************************
|
|
*/
|
|
|
|
bool File::read()
|
|
{
|
|
if (len)
|
|
return false; // already read the file
|
|
#if POSIX
|
|
size_t size;
|
|
struct stat buf;
|
|
ssize_t numread;
|
|
|
|
const char *name = this->name->toChars();
|
|
//printf("File::read('%s')\n",name);
|
|
int fd = open(name, O_RDONLY);
|
|
if (fd == -1)
|
|
{
|
|
//printf("\topen error, errno = %d\n",errno);
|
|
goto err1;
|
|
}
|
|
|
|
if (!ref)
|
|
::free(buffer);
|
|
ref = 0; // we own the buffer now
|
|
|
|
//printf("\tfile opened\n");
|
|
if (fstat(fd, &buf))
|
|
{
|
|
printf("\tfstat error, errno = %d\n",errno);
|
|
goto err2;
|
|
}
|
|
size = (size_t)buf.st_size;
|
|
#ifdef IN_GCC
|
|
buffer = (unsigned char *) ::xmalloc(size + 2);
|
|
#else
|
|
buffer = (unsigned char *) ::malloc(size + 2);
|
|
#endif
|
|
if (!buffer)
|
|
{
|
|
printf("\tmalloc error, errno = %d\n",errno);
|
|
goto err2;
|
|
}
|
|
|
|
numread = ::read(fd, buffer, size);
|
|
if (numread != (ssize_t)size)
|
|
{
|
|
printf("\tread error, errno = %d\n",errno);
|
|
goto err2;
|
|
}
|
|
|
|
if (close(fd) == -1)
|
|
{
|
|
printf("\tclose error, errno = %d\n",errno);
|
|
goto err;
|
|
}
|
|
|
|
len = size;
|
|
|
|
// Always store a wchar ^Z past end of buffer so scanner has a sentinel
|
|
buffer[size] = 0; // ^Z is obsolete, use 0
|
|
buffer[size + 1] = 0;
|
|
return false;
|
|
|
|
err2:
|
|
close(fd);
|
|
err:
|
|
::free(buffer);
|
|
buffer = NULL;
|
|
len = 0;
|
|
|
|
err1:
|
|
return true;
|
|
#elif _WIN32
|
|
DWORD size;
|
|
DWORD numread;
|
|
|
|
const char *name = this->name->toChars();
|
|
HANDLE h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
goto err1;
|
|
|
|
if (!ref)
|
|
::free(buffer);
|
|
ref = 0;
|
|
|
|
size = GetFileSize(h,NULL);
|
|
#ifdef IN_GCC
|
|
buffer = (unsigned char *) ::xmalloc(size + 2);
|
|
#else
|
|
buffer = (unsigned char *) ::malloc(size + 2);
|
|
#endif
|
|
if (!buffer)
|
|
goto err2;
|
|
|
|
if (ReadFile(h,buffer,size,&numread,NULL) != TRUE)
|
|
goto err2;
|
|
|
|
if (numread != size)
|
|
goto err2;
|
|
|
|
if (!CloseHandle(h))
|
|
goto err;
|
|
|
|
len = size;
|
|
|
|
// Always store a wchar ^Z past end of buffer so scanner has a sentinel
|
|
buffer[size] = 0; // ^Z is obsolete, use 0
|
|
buffer[size + 1] = 0;
|
|
return 0;
|
|
|
|
err2:
|
|
CloseHandle(h);
|
|
err:
|
|
::free(buffer);
|
|
buffer = NULL;
|
|
len = 0;
|
|
|
|
err1:
|
|
return true;
|
|
#else
|
|
assert(0);
|
|
#endif
|
|
}
|
|
|
|
/*********************************************
|
|
* Write a file.
|
|
* Returns:
|
|
* false success
|
|
*/
|
|
|
|
bool File::write()
|
|
{
|
|
#if POSIX
|
|
ssize_t numwritten;
|
|
|
|
const char *name = this->name->toChars();
|
|
int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4);
|
|
if (fd == -1)
|
|
goto err;
|
|
|
|
numwritten = ::write(fd, buffer, len);
|
|
if ((ssize_t)len != numwritten)
|
|
goto err2;
|
|
|
|
if (close(fd) == -1)
|
|
goto err;
|
|
|
|
return false;
|
|
|
|
err2:
|
|
close(fd);
|
|
::remove(name);
|
|
err:
|
|
return true;
|
|
#elif _WIN32
|
|
DWORD numwritten;
|
|
|
|
const char *name = this->name->toChars();
|
|
HANDLE h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
goto err;
|
|
|
|
if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
|
|
goto err2;
|
|
|
|
if (len != numwritten)
|
|
goto err2;
|
|
|
|
if (!CloseHandle(h))
|
|
goto err;
|
|
return false;
|
|
|
|
err2:
|
|
CloseHandle(h);
|
|
DeleteFileA(name);
|
|
err:
|
|
return true;
|
|
#else
|
|
assert(0);
|
|
#endif
|
|
}
|
|
|
|
void File::remove()
|
|
{
|
|
#if POSIX
|
|
::remove(this->name->toChars());
|
|
#elif _WIN32
|
|
DeleteFileA(this->name->toChars());
|
|
#else
|
|
assert(0);
|
|
#endif
|
|
}
|
|
|
|
const char *File::toChars()
|
|
{
|
|
return name->toChars();
|
|
}
|