1 2/* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved 3 * http://www.digitalmars.com 4 * Distributed under the Boost Software License, Version 1.0. 5 * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) 6 * https://github.com/D-Programming-Language/dmd/blob/master/src/root/file.c 7 */ 8 9#include "dsystem.h" 10#include "file.h" 11 12#if _WIN32 13#include <windows.h> 14#endif 15 16#if POSIX 17#include <utime.h> 18#endif 19 20#include "filename.h" 21#include "array.h" 22#include "rmem.h" 23 24/****************************** File ********************************/ 25 26File::File(const FileName *n) 27{ 28 ref = 0; 29 buffer = NULL; 30 len = 0; 31 name = const_cast<FileName *>(n); 32} 33 34File *File::create(const char *n) 35{ 36 return new File(n); 37} 38 39File::File(const char *n) 40{ 41 ref = 0; 42 buffer = NULL; 43 len = 0; 44 name = new FileName(n); 45} 46 47File::~File() 48{ 49 if (buffer) 50 { 51 if (ref == 0) 52 mem.xfree(buffer); 53#if _WIN32 54 if (ref == 2) 55 UnmapViewOfFile(buffer); 56#endif 57 } 58} 59 60/************************************* 61 */ 62 63bool File::read() 64{ 65 if (len) 66 return false; // already read the file 67#if POSIX 68 size_t size; 69 struct stat buf; 70 ssize_t numread; 71 72 const char *name = this->name->toChars(); 73 //printf("File::read('%s')\n",name); 74 int fd = open(name, O_RDONLY); 75 if (fd == -1) 76 { 77 //printf("\topen error, errno = %d\n",errno); 78 goto err1; 79 } 80 81 if (!ref) 82 ::free(buffer); 83 ref = 0; // we own the buffer now 84 85 //printf("\tfile opened\n"); 86 if (fstat(fd, &buf)) 87 { 88 printf("\tfstat error, errno = %d\n",errno); 89 goto err2; 90 } 91 size = (size_t)buf.st_size; 92#ifdef IN_GCC 93 buffer = (unsigned char *) ::xmalloc(size + 2); 94#else 95 buffer = (unsigned char *) ::malloc(size + 2); 96#endif 97 if (!buffer) 98 { 99 printf("\tmalloc error, errno = %d\n",errno); 100 goto err2; 101 } 102 103 numread = ::read(fd, buffer, size); 104 if (numread != (ssize_t)size) 105 { 106 printf("\tread error, errno = %d\n",errno); 107 goto err2; 108 } 109 110 if (close(fd) == -1) 111 { 112 printf("\tclose error, errno = %d\n",errno); 113 goto err; 114 } 115 116 len = size; 117 118 // Always store a wchar ^Z past end of buffer so scanner has a sentinel 119 buffer[size] = 0; // ^Z is obsolete, use 0 120 buffer[size + 1] = 0; 121 return false; 122 123err2: 124 close(fd); 125err: 126 ::free(buffer); 127 buffer = NULL; 128 len = 0; 129 130err1: 131 return true; 132#elif _WIN32 133 DWORD size; 134 DWORD numread; 135 136 const char *name = this->name->toChars(); 137 HANDLE h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, 138 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); 139 if (h == INVALID_HANDLE_VALUE) 140 goto err1; 141 142 if (!ref) 143 ::free(buffer); 144 ref = 0; 145 146 size = GetFileSize(h,NULL); 147#ifdef IN_GCC 148 buffer = (unsigned char *) ::xmalloc(size + 2); 149#else 150 buffer = (unsigned char *) ::malloc(size + 2); 151#endif 152 if (!buffer) 153 goto err2; 154 155 if (ReadFile(h,buffer,size,&numread,NULL) != TRUE) 156 goto err2; 157 158 if (numread != size) 159 goto err2; 160 161 if (!CloseHandle(h)) 162 goto err; 163 164 len = size; 165 166 // Always store a wchar ^Z past end of buffer so scanner has a sentinel 167 buffer[size] = 0; // ^Z is obsolete, use 0 168 buffer[size + 1] = 0; 169 return 0; 170 171err2: 172 CloseHandle(h); 173err: 174 ::free(buffer); 175 buffer = NULL; 176 len = 0; 177 178err1: 179 return true; 180#else 181 assert(0); 182#endif 183} 184 185/********************************************* 186 * Write a file. 187 * Returns: 188 * false success 189 */ 190 191bool File::write() 192{ 193#if POSIX 194 ssize_t numwritten; 195 196 const char *name = this->name->toChars(); 197 int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4); 198 if (fd == -1) 199 goto err; 200 201 numwritten = ::write(fd, buffer, len); 202 if ((ssize_t)len != numwritten) 203 goto err2; 204 205 if (close(fd) == -1) 206 goto err; 207 208 return false; 209 210err2: 211 close(fd); 212 ::remove(name); 213err: 214 return true; 215#elif _WIN32 216 DWORD numwritten; 217 218 const char *name = this->name->toChars(); 219 HANDLE h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, 220 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); 221 if (h == INVALID_HANDLE_VALUE) 222 goto err; 223 224 if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) 225 goto err2; 226 227 if (len != numwritten) 228 goto err2; 229 230 if (!CloseHandle(h)) 231 goto err; 232 return false; 233 234err2: 235 CloseHandle(h); 236 DeleteFileA(name); 237err: 238 return true; 239#else 240 assert(0); 241#endif 242} 243 244void File::remove() 245{ 246#if POSIX 247 ::remove(this->name->toChars()); 248#elif _WIN32 249 DeleteFileA(this->name->toChars()); 250#else 251 assert(0); 252#endif 253} 254 255const char *File::toChars() 256{ 257 return name->toChars(); 258} 259