Mercurial > projects > ddmd
view dmd/File.d @ 189:a4c9de8e39b3
Now compileable with dmd2.053
author | Abscissa |
---|---|
date | Wed, 08 Jun 2011 02:21:32 -0400 |
parents | 190ba98276b3 |
children |
line wrap: on
line source
module dmd.File; import dmd.common; import dmd.FileName; import dmd.Array; import dmd.Util; import core.stdc.stdlib; version (Windows) { import core.sys.windows.windows; } version (POSIX) { import core.sys.posix.fcntl; import core.stdc.errno; import core.sys.posix.unistd; import core.sys.posix.utime; import core.stdc.stdio; } import std.string : toStringz; import std.stdio; import std.conv; import core.memory; import dmd.TObject; class File : TObject { int ref_; // != 0 if this is a reference to someone else's buffer ubyte* buffer; // data for our file uint len; // amount of data in buffer[] void* touchtime; // system time to use for file FileName name; // name of our file this(string n) { register(); name = new FileName(n); } this(FileName n) { register(); name = n; } ~this() { if (buffer !is null) { if (ref_ == 0) { ///free(buffer); } else { version (Windows) { if (ref_ == 2) { UnmapViewOfFile(buffer); } } } } if (touchtime !is null) { ///free(touchtime); } } void mark() { ///mem.mark(buffer); ///mem.mark(touchtime); ///mem.mark(name); } string toChars() { return name.toChars(); } /* Read file, return !=0 if error */ int read() { version (Posix) { int result = 0; string name = this.name.toChars(); //writefln("File::read('%s')\n",name); int fd = open(toStringz(name), O_RDONLY); if (fd == -1) { result = errno; printf("file: %s\n", toStringz(name)); printf("\topen error, errno = %d\n", errno); goto err1; } if (ref_ == 0) { ///free(buffer); } ref_ = 0; // we own the buffer now //printf("\tfile opened\n"); stat_t buf; if (fstat(fd, &buf)) { printf("\tfstat error, errno = %d\n", errno); goto err2; } size_t size = cast(size_t) buf.st_size; buffer = cast(ubyte*)GC.malloc(size + 2); if (buffer is null) { printf("\tmalloc error, errno = %d\n", errno); goto err2; } ssize_t numread = .read(fd, buffer, size); if (numread != size) { printf("\tread error, errno = %d\n",errno); goto err2; } if (touchtime !is null) { memcpy(touchtime, &buf, buf.sizeof); } 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 0; err2: close(fd); err: ///free(buffer); buffer = null; len = 0; err1: result = 1; return result; } else version (Windows) { DWORD size; DWORD numread; HANDLE h; int result = 0; string name = this.name.toChars(); //writeln("Open file ", name); h = CreateFileA(toStringz(name), GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init); if (h == INVALID_HANDLE_VALUE) { goto err1; } if (!ref_) { ///free(buffer); } ref_ = 0; size = GetFileSize(h, null); buffer = cast(ubyte*) GC.malloc(size + 2); if (!buffer) goto err2; if (ReadFile(h, buffer, size, &numread, null) != TRUE) goto err2; if (numread != size) goto err2; if (touchtime) { if (!GetFileTime(h, null, null, &(cast(WIN32_FIND_DATA*)touchtime).ftLastWriteTime)) 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: result = 1; return result; } else { static assert(0); } } /* Write file, either succeed or fail * with error message & exit. */ void readv() { if (read()) error("Error reading file '%s'\n",name.toChars()); } /* Read file, return !=0 if error */ int mmread() { assert(false); } /* Write file, either succeed or fail * with error message & exit. */ void mmreadv() { assert(false); } /* Write file, return !=0 if error */ /********************************************* * Write a file. * Returns: * 0 success */ int write() { version (POSIX) { //assert(false); int fd; ssize_t numwritten; const(char)* name = toStringz(this.name.toChars()); fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, std.conv.octal!644); if (fd == -1) goto err; numwritten = core.sys.posix.unistd.write(fd, buffer, len); if (len != numwritten) goto err2; if (close(fd) == -1) goto err; if (touchtime) { utimbuf ubuf; ubuf.actime = (cast(stat_t *)touchtime).st_atime; ubuf.modtime = (cast(stat_t *)touchtime).st_mtime; if (utime(name, &ubuf)) goto err; } return 0; err2: close(fd); .remove(name); err: return 1; } else version (Windows) { HANDLE h; DWORD numwritten; const(char)* name = toStringz(this.name.toChars()); 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 (touchtime) { SetFileTime(h, null, null, &(cast(WIN32_FIND_DATA*)touchtime).ftLastWriteTime); } if (!CloseHandle(h)) goto err; return 0; err2: CloseHandle(h); DeleteFileA(name); err: return 1; } else { static assert(false); } } /* Write file, either succeed or fail * with error message & exit. */ void writev() { if (write()) { error("Error writing file '%s'\n", name.toChars()); } } /* Return !=0 if file exists. * 0: file doesn't exist * 1: normal file * 2: directory */ /* Append to file, return !=0 if error */ int append() { assert(false); } /* Append to file, either succeed or fail * with error message & exit. */ void appendv() { assert(false); } /* Return !=0 if file exists. * 0: file doesn't exist * 1: normal file * 2: directory */ int exists() { assert(false); } /* Given wildcard filespec, return an array of * matching File's. */ static Array match(char*) { assert(false); } static Array match(FileName *) { assert(false); } // Compare file times. // Return <0 this < f // =0 this == f // >0 this > f int compareTime(File f) { assert(false); } // Read system file statistics void stat() { assert(false); } /* Set buffer */ void setbuffer(void* buffer, uint len) { this.buffer = cast(ubyte*)buffer; this.len = len; } void checkoffset(size_t offset, size_t nbytes) { assert(false); } void remove() // delete file { version (POSIX) { .remove(toStringz(this.name.toChars())); } else version (_WIN32) { DeleteFileA(toStringz(this.name.toChars())); } else { assert(0); } } }