digitalmars.D - std.file.exists()
- Ameer Armaly (22/22) Jul 02 2005 Hi all.
- Ben Hinkle (4/28) Jul 02 2005 Why easier? It's common in D to return int since it is (reportedly) fast...
- Ameer Armaly (11/37) Jul 03 2005 Ah yes. I see it calls stat() to verify the existance of the file.
- Walter (3/11) Jul 04 2005 If you want to code and test a patch, that would be great!
- Ameer Armaly (1915/1915) Jul 04 2005 Alright here it is. I successfully compiled and tested phobos with the...
- Walter (29/1944) Jul 04 2005 Is the linux function exists() the only thing changed here?
- Ameer Armaly (2/1947) Jul 04 2005
- James Dunne (4/1955) Jul 07 2005 Regards,
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (6/7) Jul 07 2005 Seriously, do make sure that the line endings match on both files...
Hi all.
I was looking at the code for std.file.exists(), and I observed a few
things.
1. Std.file.exists() returns an int, but wouldn't the job be made easier
with a bit?
2. It calls a function called GetFileAttributesA or GetFileAttributesW.
These sound like win32 specific functions, and if so should be in a version
block.
3. There seems to be no linux equivelant for these functions, thus I
propose the following.
A. Std.c.linux.linux should have in it the prototype for the function
access, which takes a string as the file name, and a number representing the
octal permition value we want checked, or 0 for just existance.
B. std.file.exists() should use access(toStringz(name), 0) to check for
the existance of the file.
Any comments would be appreciated, especially if I've got this all wrong :).
Ameer
--
---
Life is either tragedy or comedy.
Usually it's your choice. You can whine or you can laugh.
--Animorphs
Jul 02 2005
"Ameer Armaly" <ameer_armaly hotmail.com> wrote in message news:da6amc$q38$1 digitaldaemon.com...Hi all. I was looking at the code for std.file.exists(), and I observed a few things. 1. Std.file.exists() returns an int, but wouldn't the job be made easier with a bit?Why easier? It's common in D to return int since it is (reportedly) faster.2. It calls a function called GetFileAttributesA or GetFileAttributesW. These sound like win32 specific functions, and if so should be in a version block.It is. Scroll down for the linux version.3. There seems to be no linux equivelant for these functions, thus I propose the following. A. Std.c.linux.linux should have in it the prototype for the function access, which takes a string as the file name, and a number representing the octal permition value we want checked, or 0 for just existance. B. std.file.exists() should use access(toStringz(name), 0) to check for the existance of the file. Any comments would be appreciated, especially if I've got this all wrong :). Ameer -- --- Life is either tragedy or comedy. Usually it's your choice. You can whine or you can laugh. --Animorphs
Jul 02 2005
On Sat, 2 Jul 2005, Ben Hinkle wrote:"Ameer Armaly" <ameer_armaly hotmail.com> wrote in message news:da6amc$q38$1 digitaldaemon.com...Ah yes. I see it calls stat() to verify the existance of the file. However, what if we called access instead;for one, it's somewhat simpler since it is designed to do just checks, and more importantly, I've heard a few times on linux-c-programming that stat was pretty slow. This was in a discussion relating to checking for the existance of a directory, and several people said that stat was pretty slow, especially for something as simple as a check. What do you think? >> 3. There seems to be no linux equivelant for these functions, thus I >> propose the following.Hi all. I was looking at the code for std.file.exists(), and I observed a few things. 1. Std.file.exists() returns an int, but wouldn't the job be made easier with a bit?Why easier? It's common in D to return int since it is (reportedly) faster.2. It calls a function called GetFileAttributesA or GetFileAttributesW. These sound like win32 specific functions, and if so should be in a version block.It is. Scroll down for the linux version.A. Std.c.linux.linux should have in it the prototype for the function access, which takes a string as the file name, and a number representing the octal permition value we want checked, or 0 for just existance. B. std.file.exists() should use access(toStringz(name), 0) to check for the existance of the file. Any comments would be appreciated, especially if I've got this all wrong :). Ameer -- --- Life is either tragedy or comedy. Usually it's your choice. You can whine or you can laugh. --Animorphs
Jul 03 2005
"Ameer Armaly" <ameer bellsouth.net> wrote in message news:Pine.LNX.4.61.0507032218380.612 debian...Ah yes. I see it calls stat() to verify the existance of the file. However, what if we called access instead;for one, it's somewhat simpler since it is designed to do just checks, and more importantly, I've heard a few times on linux-c-programming that stat was pretty slow. This was in a discussion relating to checking for the existance of a directory, and several people said that stat was pretty slow, especially for something as simple as a check. What do you think?If you want to code and test a patch, that would be great!
Jul 04 2005
Alright here it is. I successfully compiled and tested phobos with these
modifications.
--- file.d 2005-06-30 16:04:29.000000000 -0400
+++ newfile.d 2005-07-04 12:55:21.000000000 -0400
-1,958 +1,952
-
-/*
- * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com
- * Written by Walter Bright, Christopher E. Miller, Andre Fornacon
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * o The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * o Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- * o This notice may not be removed or altered from any source
- * distribution.
- */
-
-module std.file;
-
-private import std.c.stdio;
-private import std.c.stdlib;
-private import std.path;
-private import std.string;
-
-/* =========================== Win32 ======================= */
-
-version (Win32)
-{
-
-private import std.c.windows.windows;
-private import std.utf;
-private import std.windows.syserror;
-
-int useWfuncs = 1;
-
-static this()
-{
- // Win 95, 98, ME do not implement the W functions
- useWfuncs = (GetVersion() < 0x80000000);
-}
-
-/***********************************
- */
-
-class FileException : Exception
-{
-
- uint errno; // operating system error code
-
- this(char[] name)
- {
- this(name, "file I/O");
- }
-
- this(char[] name, char[] message)
- {
- super(name ~ ": " ~ message);
- }
-
- this(char[] name, uint errno)
- {
- this(name, sysErrorString(errno));
- this.errno = errno;
- }
-}
-
-/***********************************
- * Basic File operations.
- */
-
-/********************************************
- * Read a file.
- * Returns:
- * array of bytes read
- */
-
-void[] read(char[] name)
-{
- DWORD size;
- DWORD numread;
- HANDLE h;
- byte[] buf;
-
- if (useWfuncs)
- {
- wchar* namez = std.utf.toUTF16z(name);
- h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
- }
- else
- {
- char* namez = toMBSz(name);
- h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
- }
-
- if (h == INVALID_HANDLE_VALUE)
- goto err1;
-
- size = GetFileSize(h, null);
- if (size == INVALID_FILE_SIZE)
- goto err2;
-
- buf = new byte[size];
-
- if (ReadFile(h,buf,size,&numread,null) != 1)
- goto err2;
-
- if (numread != size)
- goto err2;
-
- if (!CloseHandle(h))
- goto err;
-
- return buf;
-
-err2:
- CloseHandle(h);
-err:
- delete buf;
-err1:
- throw new FileException(name, GetLastError());
-}
-
-/*********************************************
- * Write a file.
- * Returns:
- * 0 success
- */
-
-void write(char[] name, void[] buffer)
-{
- HANDLE h;
- DWORD numwritten;
-
- if (useWfuncs)
- {
- wchar* namez = std.utf.toUTF16z(name);
- h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
- }
- else
- {
- char* namez = toMBSz(name);
- h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
- }
- if (h == INVALID_HANDLE_VALUE)
- goto err;
-
- if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1)
- goto err2;
-
- if (buffer.length != numwritten)
- goto err2;
-
- if (!CloseHandle(h))
- goto err;
- return;
-
-err2:
- CloseHandle(h);
-err:
- throw new FileException(name, GetLastError());
-}
-
-
-/*********************************************
- * Append to a file.
- */
-
-void append(char[] name, void[] buffer)
-{
- HANDLE h;
- DWORD numwritten;
-
- if (useWfuncs)
- {
- wchar* namez = std.utf.toUTF16z(name);
- h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
- }
- else
- {
- char* namez = toMBSz(name);
- h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
- }
- if (h == INVALID_HANDLE_VALUE)
- goto err;
-
- SetFilePointer(h, 0, null, FILE_END);
-
- if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1)
- goto err2;
-
- if (buffer.length != numwritten)
- goto err2;
-
- if (!CloseHandle(h))
- goto err;
- return;
-
-err2:
- CloseHandle(h);
-err:
- throw new FileException(name, GetLastError());
-}
-
-
-/***************************************************
- * Rename a file.
- */
-
-void rename(char[] from, char[] to)
-{
- BOOL result;
-
- if (useWfuncs)
- result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to));
- else
- result = MoveFileA(toMBSz(from), toMBSz(to));
- if (!result)
- throw new FileException(to, GetLastError());
-}
-
-
-/***************************************************
- * Delete a file.
- */
-
-void remove(char[] name)
-{
- BOOL result;
-
- if (useWfuncs)
- result = DeleteFileW(std.utf.toUTF16z(name));
- else
- result = DeleteFileA(toMBSz(name));
- if (!result)
- throw new FileException(name, GetLastError());
-}
-
-
-/***************************************************
- * Get file size.
- */
-
-ulong getSize(char[] name)
-{
- HANDLE findhndl;
- uint resulth;
- uint resultl;
-
- if (useWfuncs)
- {
- WIN32_FIND_DATAW filefindbuf;
-
- findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf);
- resulth = filefindbuf.nFileSizeHigh;
- resultl = filefindbuf.nFileSizeLow;
- }
- else
- {
- WIN32_FIND_DATA filefindbuf;
-
- findhndl = FindFirstFileA(toMBSz(name), &filefindbuf);
- resulth = filefindbuf.nFileSizeHigh;
- resultl = filefindbuf.nFileSizeLow;
- }
-
- if (findhndl == cast(HANDLE)-1)
- {
- throw new FileException(name, GetLastError());
- }
- FindClose(findhndl);
- return (cast(ulong)resulth << 32) + resultl;
-}
-
-/***************************************************
- * Does file (or directory) exist?
- */
-
-int exists(char[] name)
-{
- uint result;
-
- if (useWfuncs)
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp
- result = GetFileAttributesW(std.utf.toUTF16z(name));
- else
- result = GetFileAttributesA(toMBSz(name));
-
- return (result == 0xFFFFFFFF) ? 0 : 1;
-}
-
-/***************************************************
- * Get file attributes.
- */
-
-uint getAttributes(char[] name)
-{
- uint result;
-
- if (useWfuncs)
- result = GetFileAttributesW(std.utf.toUTF16z(name));
- else
- result = GetFileAttributesA(toMBSz(name));
- if (result == 0xFFFFFFFF)
- {
- throw new FileException(name, GetLastError());
- }
- return result;
-}
-
-/****************************************************
- * Is name a file?
- */
-
-int isfile(char[] name)
-{
- return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0;
-}
-
-/****************************************************
- * Is name a directory?
- */
-
-int isdir(char[] name)
-{
- return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0;
-}
-
-/****************************************************
- * Change directory.
- */
-
-void chdir(char[] pathname)
-{ BOOL result;
-
- if (useWfuncs)
- result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname));
- else
- result = SetCurrentDirectoryA(toMBSz(pathname));
-
- if (!result)
- {
- throw new FileException(pathname, GetLastError());
- }
-}
-
-/****************************************************
- * Make directory.
- */
-
-void mkdir(char[] pathname)
-{ BOOL result;
-
- if (useWfuncs)
- result = CreateDirectoryW(std.utf.toUTF16z(pathname), null);
- else
- result = CreateDirectoryA(toMBSz(pathname), null);
-
- if (!result)
- {
- throw new FileException(pathname, GetLastError());
- }
-}
-
-/****************************************************
- * Remove directory.
- */
-
-void rmdir(char[] pathname)
-{ BOOL result;
-
- if (useWfuncs)
- result = RemoveDirectoryW(std.utf.toUTF16z(pathname));
- else
- result = RemoveDirectoryA(toMBSz(pathname));
-
- if (!result)
- {
- throw new FileException(pathname, GetLastError());
- }
-}
-
-/****************************************************
- * Get current directory.
- */
-
-char[] getcwd()
-{
- if (useWfuncs)
- {
- wchar[] dir;
- int len;
- wchar c;
-
- len = GetCurrentDirectoryW(0, &c);
- if (!len)
- goto Lerr;
- dir = new wchar[len];
- len = GetCurrentDirectoryW(len, dir);
- if (!len)
- goto Lerr;
- return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0
- }
- else
- {
- char[] dir;
- int len;
- char c;
-
- len = GetCurrentDirectoryA(0, &c);
- if (!len)
- goto Lerr;
- dir = new char[len];
- len = GetCurrentDirectoryA(len, dir);
- if (!len)
- goto Lerr;
- return dir[0 .. len]; // leave off terminating 0
- }
-
-Lerr:
- throw new FileException("getcwd", GetLastError());
-}
-
-/***************************************************
- * Return contents of directory.
- */
-
-char[][] listdir(char[] pathname)
-{
- char[][] result;
-
- bool listing(char[] filename)
- {
- result ~= filename;
- return true; // continue
- }
-
- listdir(pathname, &listing);
- return result;
-}
-
-void listdir(char[] pathname, bool delegate(char[] filename) callback)
-{
- char[] c;
- HANDLE h;
-
- c = std.path.join(pathname, "*.*");
- if (useWfuncs)
- {
- WIN32_FIND_DATAW fileinfo;
-
- h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo);
- if (h != INVALID_HANDLE_VALUE)
- {
- do
- { int clength;
-
- // Skip "." and ".."
- if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 ||
- std.string.wcscmp(fileinfo.cFileName, "..") == 0)
- continue;
-
- clength = std.string.wcslen(fileinfo.cFileName);
- // toUTF8() returns a new buffer
- if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength])))
- break;
- } while (FindNextFileW(h,&fileinfo) != FALSE);
- FindClose(h);
- }
- }
- else
- {
- WIN32_FIND_DATA fileinfo;
-
- h = FindFirstFileA(toMBSz(c), &fileinfo);
- if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid?
- {
- do
- { int clength;
- wchar[] wbuf;
- int n;
-
- // Skip "." and ".."
- if (std.string.strcmp(fileinfo.cFileName, ".") == 0 ||
- std.string.strcmp(fileinfo.cFileName, "..") == 0)
- continue;
-
- clength = std.string.strlen(fileinfo.cFileName);
-
- // Convert cFileName[] to unicode
- wbuf.length = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);
- n = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.length);
- assert(n == wbuf.length);
- // toUTF8() returns a new buffer
- if (!callback(std.utf.toUTF8(wbuf)))
- break;
- } while (FindNextFileA(h,&fileinfo) != FALSE);
- FindClose(h);
- }
- }
-}
-
-/******************************************
- * Since Win 9x does not support the "W" API's, first convert
- * to wchar, then convert to multibyte using the current code
- * page.
- * (Thanks to yaneurao for this)
- */
-
-char* toMBSz(char[] s)
-{
- // Only need to do this if any chars have the high bit set
- foreach (char c; s)
- {
- if (c >= 0x80)
- { char[] result;
- int i;
- wchar* ws = std.utf.toUTF16z(s);
- result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null, null);
- i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null, null);
- assert(i == result.length);
- return result;
- }
- }
- return std.string.toStringz(s);
-}
-
-
-/***************************************************
- * Copy a file.
- */
-
-void copy(char[] from, char[] to)
-{
- BOOL result;
-
- if (useWfuncs)
- result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false);
- else
- result = CopyFileA(toMBSz(from), toMBSz(to), false);
- if (!result)
- throw new FileException(to, GetLastError());
-}
-
-
-}
-
-/* =========================== linux ======================= */
-
-version (linux)
-{
-
-private import std.c.linux.linux;
-
-extern (C) char* strerror(int);
-
-/***********************************
- */
-
-class FileException : Exception
-{
-
- uint errno; // operating system error code
-
- this(char[] name)
- {
- this(name, "file I/O");
- }
-
- this(char[] name, char[] message)
- {
- super(name ~ ": " ~ message);
- }
-
- this(char[] name, uint errno)
- { char* s = strerror(errno);
- this(name, std.string.toString(s).dup);
- this.errno = errno;
- }
-}
-
-/********************************************
- * Read a file.
- * Returns:
- * array of bytes read
- */
-
-void[] read(char[] name)
-{
- uint size;
- uint numread;
- int fd;
- struct_stat statbuf;
- byte[] buf;
- char *namez;
-
- namez = toStringz(name);
- //printf("file.read('%s')\n",namez);
- fd = std.c.linux.linux.open(namez, O_RDONLY);
- if (fd == -1)
- {
- //printf("\topen error, errno = %d\n",getErrno());
- goto err1;
- }
-
- //printf("\tfile opened\n");
- if (std.c.linux.linux.fstat(fd, &statbuf))
- {
- //printf("\tfstat error, errno = %d\n",getErrno());
- goto err2;
- }
- size = statbuf.st_size;
- buf = new byte[size];
-
- numread = std.c.linux.linux.read(fd, cast(char*)buf, size);
- if (numread != size)
- {
- //printf("\tread error, errno = %d\n",getErrno());
- goto err2;
- }
-
- if (std.c.linux.linux.close(fd) == -1)
- {
- //printf("\tclose error, errno = %d\n",getErrno());
- goto err;
- }
-
- return buf;
-
-err2:
- std.c.linux.linux.close(fd);
-err:
- delete buf;
-
-err1:
- throw new FileException(name, getErrno());
-}
-
-/*********************************************
- * Write a file.
- * Returns:
- * 0 success
- */
-
-void write(char[] name, void[] buffer)
-{
- int fd;
- int numwritten;
- char *namez;
-
- namez = toStringz(name);
- fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660);
- if (fd == -1)
- goto err;
-
- numwritten = std.c.linux.linux.write(fd, buffer, buffer.length);
- if (buffer.length != numwritten)
- goto err2;
-
- if (std.c.linux.linux.close(fd) == -1)
- goto err;
-
- return;
-
-err2:
- std.c.linux.linux.close(fd);
-err:
- throw new FileException(name, getErrno());
-}
-
-
-/*********************************************
- * Append to a file.
- */
-
-void append(char[] name, void[] buffer)
-{
- int fd;
- int numwritten;
- char *namez;
-
- namez = toStringz(name);
- fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660);
- if (fd == -1)
- goto err;
-
- numwritten = std.c.linux.linux.write(fd, buffer, buffer.length);
- if (buffer.length != numwritten)
- goto err2;
-
- if (std.c.linux.linux.close(fd) == -1)
- goto err;
-
- return;
-
-err2:
- std.c.linux.linux.close(fd);
-err:
- throw new FileException(name, getErrno());
-}
-
-
-/***************************************************
- * Rename a file.
- */
-
-void rename(char[] from, char[] to)
-{
- char *fromz = toStringz(from);
- char *toz = toStringz(to);
-
- if (std.c.stdio.rename(fromz, toz) == -1)
- throw new FileException(to, getErrno());
-}
-
-
-/***************************************************
- * Delete a file.
- */
-
-void remove(char[] name)
-{
- if (std.c.stdio.remove(toStringz(name)) == -1)
- throw new FileException(name, getErrno());
-}
-
-
-/***************************************************
- * Get file size.
- */
-
-ulong getSize(char[] name)
-{
- uint size;
- int fd;
- struct_stat statbuf;
- char *namez;
-
- namez = toStringz(name);
- //printf("file.getSize('%s')\n",namez);
- fd = std.c.linux.linux.open(namez, O_RDONLY);
- if (fd == -1)
- {
- //printf("\topen error, errno = %d\n",getErrno());
- goto err1;
- }
-
- //printf("\tfile opened\n");
- if (std.c.linux.linux.fstat(fd, &statbuf))
- {
- //printf("\tfstat error, errno = %d\n",getErrno());
- goto err2;
- }
- size = statbuf.st_size;
-
- if (std.c.linux.linux.close(fd) == -1)
- {
- //printf("\tclose error, errno = %d\n",getErrno());
- goto err;
- }
-
- return size;
-
-err2:
- std.c.linux.linux.close(fd);
-err:
-err1:
- throw new FileException(name, getErrno());
-}
-
-
-/***************************************************
- * Get file attributes.
- */
-
-uint getAttributes(char[] name)
-{
- struct_stat statbuf;
- char *namez;
-
- namez = toStringz(name);
- if (std.c.linux.linux.stat(namez, &statbuf))
- {
- throw new FileException(name, getErrno());
- }
-
- return statbuf.st_mode;
-}
-
-/****************************************************
- * Does file/directory exist?
- */
-
-int exists(char[] name)
-{
- struct_stat statbuf;
- char *namez;
-
- namez = toStringz(name);
- if (std.c.linux.linux.stat(namez, &statbuf))
- {
- return 0;
- }
-
- return 1;
-}
-
-/****************************************************
- * Is name a file?
- */
-
-int isfile(char[] name)
-{
- return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file
-}
-
-/****************************************************
- * Is name a directory?
- */
-
-int isdir(char[] name)
-{
- return (getAttributes(name) & S_IFMT) == S_IFDIR;
-}
-
-/****************************************************
- * Change directory.
- */
-
-void chdir(char[] pathname)
-{
- if (std.c.linux.linux.chdir(toStringz(pathname)))
- {
- throw new FileException(pathname, getErrno());
- }
-}
-
-/****************************************************
- * Make directory.
- */
-
-void mkdir(char[] pathname)
-{
- if (std.c.linux.linux.mkdir(toStringz(pathname), 0777))
- {
- throw new FileException(pathname, getErrno());
- }
-}
-
-/****************************************************
- * Remove directory.
- */
-
-void rmdir(char[] pathname)
-{
- if (std.c.linux.linux.rmdir(toStringz(pathname)))
- {
- throw new FileException(pathname, getErrno());
- }
-}
-
-/****************************************************
- * Get current directory.
- */
-
-char[] getcwd()
-{ char* p;
-
- p = std.c.linux.linux.getcwd(null, 0);
- if (!p)
- {
- throw new FileException("cannot get cwd", getErrno());
- }
-
- size_t len = std.string.strlen(p);
- char[] buf = new char[len];
- buf[] = p[0 .. len];
- std.c.stdlib.free(p);
- return buf;
-}
-
-/***************************************************
- * Return contents of directory.
- */
-
-char[][] listdir(char[] pathname)
-{
- char[][] result;
-
- bool listing(char[] filename)
- {
- result ~= filename;
- return true; // continue
- }
-
- listdir(pathname, &listing);
- return result;
-}
-
-void listdir(char[] pathname, bool delegate(char[] filename) callback)
-{
- DIR* h;
- dirent* fdata;
-
- h = opendir(toStringz(pathname));
- if (h)
- {
- while((fdata = readdir(h)) != null)
- {
- // Skip "." and ".."
- if (!std.string.strcmp(fdata.d_name, ".") ||
- !std.string.strcmp(fdata.d_name, ".."))
- continue;
-
- int len = std.string.strlen(fdata.d_name);
- if (!callback(fdata.d_name[0 .. len].dup))
- break;
- }
- closedir(h);
- }
- else
- {
- throw new FileException(pathname, getErrno());
- }
-}
-
-/***************************************************
- * Copy a file.
- */
-
-void copy(char[] from, char[] to)
-{
- void[] buffer;
-
- /* If the file is very large, this won't work, but
- * it's a good start.
- * BUG: it should maintain the file timestamps
- */
- buffer = read(from);
- write(to, buffer);
- delete buffer;
-}
-
-
-
-}
-
+
+/*
+ * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com
+ * Written by Walter Bright, Christopher E. Miller, Andre Fornacon
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * o The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * o Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ * o This notice may not be removed or altered from any source
+ * distribution.
+ */
+
+module std.file;
+
+private import std.c.stdio;
+private import std.c.stdlib;
+private import std.path;
+private import std.string;
+
+/* =========================== Win32 ======================= */
+
+version (Win32)
+{
+
+private import std.c.windows.windows;
+private import std.utf;
+private import std.windows.syserror;
+
+int useWfuncs = 1;
+
+static this()
+{
+ // Win 95, 98, ME do not implement the W functions
+ useWfuncs = (GetVersion() < 0x80000000);
+}
+
+/***********************************
+ */
+
+class FileException : Exception
+{
+
+ uint errno; // operating system error code
+
+ this(char[] name)
+ {
+ this(name, "file I/O");
+ }
+
+ this(char[] name, char[] message)
+ {
+ super(name ~ ": " ~ message);
+ }
+
+ this(char[] name, uint errno)
+ {
+ this(name, sysErrorString(errno));
+ this.errno = errno;
+ }
+}
+
+/***********************************
+ * Basic File operations.
+ */
+
+/********************************************
+ * Read a file.
+ * Returns:
+ * array of bytes read
+ */
+
+void[] read(char[] name)
+{
+ DWORD size;
+ DWORD numread;
+ HANDLE h;
+ byte[] buf;
+
+ if (useWfuncs)
+ {
+ wchar* namez = std.utf.toUTF16z(name);
+ h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
+ }
+ else
+ {
+ char* namez = toMBSz(name);
+ h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
+ }
+
+ if (h == INVALID_HANDLE_VALUE)
+ goto err1;
+
+ size = GetFileSize(h, null);
+ if (size == INVALID_FILE_SIZE)
+ goto err2;
+
+ buf = new byte[size];
+
+ if (ReadFile(h,buf,size,&numread,null) != 1)
+ goto err2;
+
+ if (numread != size)
+ goto err2;
+
+ if (!CloseHandle(h))
+ goto err;
+
+ return buf;
+
+err2:
+ CloseHandle(h);
+err:
+ delete buf;
+err1:
+ throw new FileException(name, GetLastError());
+}
+
+/*********************************************
+ * Write a file.
+ * Returns:
+ * 0 success
+ */
+
+void write(char[] name, void[] buffer)
+{
+ HANDLE h;
+ DWORD numwritten;
+
+ if (useWfuncs)
+ {
+ wchar* namez = std.utf.toUTF16z(name);
+ h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
+ }
+ else
+ {
+ char* namez = toMBSz(name);
+ h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
+ }
+ if (h == INVALID_HANDLE_VALUE)
+ goto err;
+
+ if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1)
+ goto err2;
+
+ if (buffer.length != numwritten)
+ goto err2;
+
+ if (!CloseHandle(h))
+ goto err;
+ return;
+
+err2:
+ CloseHandle(h);
+err:
+ throw new FileException(name, GetLastError());
+}
+
+
+/*********************************************
+ * Append to a file.
+ */
+
+void append(char[] name, void[] buffer)
+{
+ HANDLE h;
+ DWORD numwritten;
+
+ if (useWfuncs)
+ {
+ wchar* namez = std.utf.toUTF16z(name);
+ h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
+ }
+ else
+ {
+ char* namez = toMBSz(name);
+ h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
+ }
+ if (h == INVALID_HANDLE_VALUE)
+ goto err;
+
+ SetFilePointer(h, 0, null, FILE_END);
+
+ if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1)
+ goto err2;
+
+ if (buffer.length != numwritten)
+ goto err2;
+
+ if (!CloseHandle(h))
+ goto err;
+ return;
+
+err2:
+ CloseHandle(h);
+err:
+ throw new FileException(name, GetLastError());
+}
+
+
+/***************************************************
+ * Rename a file.
+ */
+
+void rename(char[] from, char[] to)
+{
+ BOOL result;
+
+ if (useWfuncs)
+ result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to));
+ else
+ result = MoveFileA(toMBSz(from), toMBSz(to));
+ if (!result)
+ throw new FileException(to, GetLastError());
+}
+
+
+/***************************************************
+ * Delete a file.
+ */
+
+void remove(char[] name)
+{
+ BOOL result;
+
+ if (useWfuncs)
+ result = DeleteFileW(std.utf.toUTF16z(name));
+ else
+ result = DeleteFileA(toMBSz(name));
+ if (!result)
+ throw new FileException(name, GetLastError());
+}
+
+
+/***************************************************
+ * Get file size.
+ */
+
+ulong getSize(char[] name)
+{
+ HANDLE findhndl;
+ uint resulth;
+ uint resultl;
+
+ if (useWfuncs)
+ {
+ WIN32_FIND_DATAW filefindbuf;
+
+ findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf);
+ resulth = filefindbuf.nFileSizeHigh;
+ resultl = filefindbuf.nFileSizeLow;
+ }
+ else
+ {
+ WIN32_FIND_DATA filefindbuf;
+
+ findhndl = FindFirstFileA(toMBSz(name), &filefindbuf);
+ resulth = filefindbuf.nFileSizeHigh;
+ resultl = filefindbuf.nFileSizeLow;
+ }
+
+ if (findhndl == cast(HANDLE)-1)
+ {
+ throw new FileException(name, GetLastError());
+ }
+ FindClose(findhndl);
+ return (cast(ulong)resulth << 32) + resultl;
+}
+
+/***************************************************
+ * Does file (or directory) exist?
+ */
+
+int exists(char[] name)
+{
+ uint result;
+
+ if (useWfuncs)
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp
+ result = GetFileAttributesW(std.utf.toUTF16z(name));
+ else
+ result = GetFileAttributesA(toMBSz(name));
+
+ return (result == 0xFFFFFFFF) ? 0 : 1;
+}
+
+/***************************************************
+ * Get file attributes.
+ */
+
+uint getAttributes(char[] name)
+{
+ uint result;
+
+ if (useWfuncs)
+ result = GetFileAttributesW(std.utf.toUTF16z(name));
+ else
+ result = GetFileAttributesA(toMBSz(name));
+ if (result == 0xFFFFFFFF)
+ {
+ throw new FileException(name, GetLastError());
+ }
+ return result;
+}
+
+/****************************************************
+ * Is name a file?
+ */
+
+int isfile(char[] name)
+{
+ return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+/****************************************************
+ * Is name a directory?
+ */
+
+int isdir(char[] name)
+{
+ return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0;
+}
+
+/****************************************************
+ * Change directory.
+ */
+
+void chdir(char[] pathname)
+{ BOOL result;
+
+ if (useWfuncs)
+ result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname));
+ else
+ result = SetCurrentDirectoryA(toMBSz(pathname));
+
+ if (!result)
+ {
+ throw new FileException(pathname, GetLastError());
+ }
+}
+
+/****************************************************
+ * Make directory.
+ */
+
+void mkdir(char[] pathname)
+{ BOOL result;
+
+ if (useWfuncs)
+ result = CreateDirectoryW(std.utf.toUTF16z(pathname), null);
+ else
+ result = CreateDirectoryA(toMBSz(pathname), null);
+
+ if (!result)
+ {
+ throw new FileException(pathname, GetLastError());
+ }
+}
+
+/****************************************************
+ * Remove directory.
+ */
+
+void rmdir(char[] pathname)
+{ BOOL result;
+
+ if (useWfuncs)
+ result = RemoveDirectoryW(std.utf.toUTF16z(pathname));
+ else
+ result = RemoveDirectoryA(toMBSz(pathname));
+
+ if (!result)
+ {
+ throw new FileException(pathname, GetLastError());
+ }
+}
+
+/****************************************************
+ * Get current directory.
+ */
+
+char[] getcwd()
+{
+ if (useWfuncs)
+ {
+ wchar[] dir;
+ int len;
+ wchar c;
+
+ len = GetCurrentDirectoryW(0, &c);
+ if (!len)
+ goto Lerr;
+ dir = new wchar[len];
+ len = GetCurrentDirectoryW(len, dir);
+ if (!len)
+ goto Lerr;
+ return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0
+ }
+ else
+ {
+ char[] dir;
+ int len;
+ char c;
+
+ len = GetCurrentDirectoryA(0, &c);
+ if (!len)
+ goto Lerr;
+ dir = new char[len];
+ len = GetCurrentDirectoryA(len, dir);
+ if (!len)
+ goto Lerr;
+ return dir[0 .. len]; // leave off terminating 0
+ }
+
+Lerr:
+ throw new FileException("getcwd", GetLastError());
+}
+
+/***************************************************
+ * Return contents of directory.
+ */
+
+char[][] listdir(char[] pathname)
+{
+ char[][] result;
+
+ bool listing(char[] filename)
+ {
+ result ~= filename;
+ return true; // continue
+ }
+
+ listdir(pathname, &listing);
+ return result;
+}
+
+void listdir(char[] pathname, bool delegate(char[] filename) callback)
+{
+ char[] c;
+ HANDLE h;
+
+ c = std.path.join(pathname, "*.*");
+ if (useWfuncs)
+ {
+ WIN32_FIND_DATAW fileinfo;
+
+ h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ { int clength;
+
+ // Skip "." and ".."
+ if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 ||
+ std.string.wcscmp(fileinfo.cFileName, "..") == 0)
+ continue;
+
+ clength = std.string.wcslen(fileinfo.cFileName);
+ // toUTF8() returns a new buffer
+ if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength])))
+ break;
+ } while (FindNextFileW(h,&fileinfo) != FALSE);
+ FindClose(h);
+ }
+ }
+ else
+ {
+ WIN32_FIND_DATA fileinfo;
+
+ h = FindFirstFileA(toMBSz(c), &fileinfo);
+ if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid?
+ {
+ do
+ { int clength;
+ wchar[] wbuf;
+ int n;
+
+ // Skip "." and ".."
+ if (std.string.strcmp(fileinfo.cFileName, ".") == 0 ||
+ std.string.strcmp(fileinfo.cFileName, "..") == 0)
+ continue;
+
+ clength = std.string.strlen(fileinfo.cFileName);
+
+ // Convert cFileName[] to unicode
+ wbuf.length = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);
+ n = MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.length);
+ assert(n == wbuf.length);
+ // toUTF8() returns a new buffer
+ if (!callback(std.utf.toUTF8(wbuf)))
+ break;
+ } while (FindNextFileA(h,&fileinfo) != FALSE);
+ FindClose(h);
+ }
+ }
+}
+
+/******************************************
+ * Since Win 9x does not support the "W" API's, first convert
+ * to wchar, then convert to multibyte using the current code
+ * page.
+ * (Thanks to yaneurao for this)
+ */
+
+char* toMBSz(char[] s)
+{
+ // Only need to do this if any chars have the high bit set
+ foreach (char c; s)
+ {
+ if (c >= 0x80)
+ { char[] result;
+ int i;
+ wchar* ws = std.utf.toUTF16z(s);
+ result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null, null);
+ i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null, null);
+ assert(i == result.length);
+ return result;
+ }
+ }
+ return std.string.toStringz(s);
+}
+
+
+/***************************************************
+ * Copy a file.
+ */
+
+void copy(char[] from, char[] to)
+{
+ BOOL result;
+
+ if (useWfuncs)
+ result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false);
+ else
+ result = CopyFileA(toMBSz(from), toMBSz(to), false);
+ if (!result)
+ throw new FileException(to, GetLastError());
+}
+
+
+}
+
+/* =========================== linux ======================= */
+
+version (linux)
+{
+
+private import std.c.linux.linux;
+
+extern (C) char* strerror(int);
+extern(C) int access(char *, int);
+/***********************************
+ */
+
+class FileException : Exception
+{
+
+ uint errno; // operating system error code
+
+ this(char[] name)
+ {
+ this(name, "file I/O");
+ }
+
+ this(char[] name, char[] message)
+ {
+ super(name ~ ": " ~ message);
+ }
+
+ this(char[] name, uint errno)
+ { char* s = strerror(errno);
+ this(name, std.string.toString(s).dup);
+ this.errno = errno;
+ }
+}
+
+/********************************************
+ * Read a file.
+ * Returns:
+ * array of bytes read
+ */
+
+void[] read(char[] name)
+{
+ uint size;
+ uint numread;
+ int fd;
+ struct_stat statbuf;
+ byte[] buf;
+ char *namez;
+
+ namez = toStringz(name);
+ //printf("file.read('%s')\n",namez);
+ fd = std.c.linux.linux.open(namez, O_RDONLY);
+ if (fd == -1)
+ {
+ //printf("\topen error, errno = %d\n",getErrno());
+ goto err1;
+ }
+
+ //printf("\tfile opened\n");
+ if (std.c.linux.linux.fstat(fd, &statbuf))
+ {
+ //printf("\tfstat error, errno = %d\n",getErrno());
+ goto err2;
+ }
+ size = statbuf.st_size;
+ buf = new byte[size];
+
+ numread = std.c.linux.linux.read(fd, cast(char*)buf, size);
+ if (numread != size)
+ {
+ //printf("\tread error, errno = %d\n",getErrno());
+ goto err2;
+ }
+
+ if (std.c.linux.linux.close(fd) == -1)
+ {
+ //printf("\tclose error, errno = %d\n",getErrno());
+ goto err;
+ }
+
+ return buf;
+
+err2:
+ std.c.linux.linux.close(fd);
+err:
+ delete buf;
+
+err1:
+ throw new FileException(name, getErrno());
+}
+
+/*********************************************
+ * Write a file.
+ * Returns:
+ * 0 success
+ */
+
+void write(char[] name, void[] buffer)
+{
+ int fd;
+ int numwritten;
+ char *namez;
+
+ namez = toStringz(name);
+ fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660);
+ if (fd == -1)
+ goto err;
+
+ numwritten = std.c.linux.linux.write(fd, buffer, buffer.length);
+ if (buffer.length != numwritten)
+ goto err2;
+
+ if (std.c.linux.linux.close(fd) == -1)
+ goto err;
+
+ return;
+
+err2:
+ std.c.linux.linux.close(fd);
+err:
+ throw new FileException(name, getErrno());
+}
+
+
+/*********************************************
+ * Append to a file.
+ */
+
+void append(char[] name, void[] buffer)
+{
+ int fd;
+ int numwritten;
+ char *namez;
+
+ namez = toStringz(name);
+ fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660);
+ if (fd == -1)
+ goto err;
+
+ numwritten = std.c.linux.linux.write(fd, buffer, buffer.length);
+ if (buffer.length != numwritten)
+ goto err2;
+
+ if (std.c.linux.linux.close(fd) == -1)
+ goto err;
+
+ return;
+
+err2:
+ std.c.linux.linux.close(fd);
+err:
+ throw new FileException(name, getErrno());
+}
+
+
+/***************************************************
+ * Rename a file.
+ */
+
+void rename(char[] from, char[] to)
+{
+ char *fromz = toStringz(from);
+ char *toz = toStringz(to);
+
+ if (std.c.stdio.rename(fromz, toz) == -1)
+ throw new FileException(to, getErrno());
+}
+
+
+/***************************************************
+ * Delete a file.
+ */
+
+void remove(char[] name)
+{
+ if (std.c.stdio.remove(toStringz(name)) == -1)
+ throw new FileException(name, getErrno());
+}
+
+
+/***************************************************
+ * Get file size.
+ */
+
+ulong getSize(char[] name)
+{
+ uint size;
+ int fd;
+ struct_stat statbuf;
+ char *namez;
+
+ namez = toStringz(name);
+ //printf("file.getSize('%s')\n",namez);
+ fd = std.c.linux.linux.open(namez, O_RDONLY);
+ if (fd == -1)
+ {
+ //printf("\topen error, errno = %d\n",getErrno());
+ goto err1;
+ }
+
+ //printf("\tfile opened\n");
+ if (std.c.linux.linux.fstat(fd, &statbuf))
+ {
+ //printf("\tfstat error, errno = %d\n",getErrno());
+ goto err2;
+ }
+ size = statbuf.st_size;
+
+ if (std.c.linux.linux.close(fd) == -1)
+ {
+ //printf("\tclose error, errno = %d\n",getErrno());
+ goto err;
+ }
+
+ return size;
+
+err2:
+ std.c.linux.linux.close(fd);
+err:
+err1:
+ throw new FileException(name, getErrno());
+}
+
+
+/***************************************************
+ * Get file attributes.
+ */
+
+uint getAttributes(char[] name)
+{
+ struct_stat statbuf;
+ char *namez;
+
+ namez = toStringz(name);
+ if (std.c.linux.linux.stat(namez, &statbuf))
+ {
+ throw new FileException(name, getErrno());
+ }
+
+ return statbuf.st_mode;
+}
+
+/****************************************************
+ * Does file/directory exist?
+ */
+
+int exists(char[] name)
+{
+ if(access(toStringz(name),0))
+ return 0;
+ else
+ return 1;
+}
+
+/****************************************************
+ * Is name a file?
+ */
+
+int isfile(char[] name)
+{
+ return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file
+}
+
+/****************************************************
+ * Is name a directory?
+ */
+
+int isdir(char[] name)
+{
+ return (getAttributes(name) & S_IFMT) == S_IFDIR;
+}
+
+/****************************************************
+ * Change directory.
+ */
+
+void chdir(char[] pathname)
+{
+ if (std.c.linux.linux.chdir(toStringz(pathname)))
+ {
+ throw new FileException(pathname, getErrno());
+ }
+}
+
+/****************************************************
+ * Make directory.
+ */
+
+void mkdir(char[] pathname)
+{
+ if (std.c.linux.linux.mkdir(toStringz(pathname), 0777))
+ {
+ throw new FileException(pathname, getErrno());
+ }
+}
+
+/****************************************************
+ * Remove directory.
+ */
+
+void rmdir(char[] pathname)
+{
+ if (std.c.linux.linux.rmdir(toStringz(pathname)))
+ {
+ throw new FileException(pathname, getErrno());
+ }
+}
+
+/****************************************************
+ * Get current directory.
+ */
+
+char[] getcwd()
+{ char* p;
+
+ p = std.c.linux.linux.getcwd(null, 0);
+ if (!p)
+ {
+ throw new FileException("cannot get cwd", getErrno());
+ }
+
+ size_t len = std.string.strlen(p);
+ char[] buf = new char[len];
+ buf[] = p[0 .. len];
+ std.c.stdlib.free(p);
+ return buf;
+}
+
+/***************************************************
+ * Return contents of directory.
+ */
+
+char[][] listdir(char[] pathname)
+{
+ char[][] result;
+
+ bool listing(char[] filename)
+ {
+ result ~= filename;
+ return true; // continue
+ }
+
+ listdir(pathname, &listing);
+ return result;
+}
+
+void listdir(char[] pathname, bool delegate(char[] filename) callback)
+{
+ DIR* h;
+ dirent* fdata;
+
+ h = opendir(toStringz(pathname));
+ if (h)
+ {
+ while((fdata = readdir(h)) != null)
+ {
+ // Skip "." and ".."
+ if (!std.string.strcmp(fdata.d_name, ".") ||
+ !std.string.strcmp(fdata.d_name, ".."))
+ continue;
+
+ int len = std.string.strlen(fdata.d_name);
+ if (!callback(fdata.d_name[0 .. len].dup))
+ break;
+ }
+ closedir(h);
+ }
+ else
+ {
+ throw new FileException(pathname, getErrno());
+ }
+}
+
+/***************************************************
+ * Copy a file.
+ */
+
+void copy(char[] from, char[] to)
+{
+ void[] buffer;
+
+ /* If the file is very large, this won't work, but
+ * it's a good start.
+ * BUG: it should maintain the file timestamps
+ */
+ buffer = read(from);
+ write(to, buffer);
+ delete buffer;
+}
+
+
+
+}
+
Jul 04 2005
Is the linux function exists() the only thing changed here? "Ameer Armaly" <ameer bellsouth.net> wrote in message news:Pine.LNX.4.61.0507041302450.1150 debian...Alright here it is. I successfully compiled and tested phobos with these modifications. --- file.d 2005-06-30 16:04:29.000000000 -0400 +++ newfile.d 2005-07-04 12:55:21.000000000 -0400 -1,958 +1,952 - -/* - * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com - * Written by Walter Bright, Christopher E. Miller, Andre Fornacon - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistributeit- * freely, subject to the following restrictions: - * - * o The origin of this software must not be misrepresented; you mustnot- * claim that you wrote the original software. If you use thissoftware- * in a product, an acknowledgment in the product documentation wouldbe- * appreciated but is not required. - * o Altered source versions must be plainly marked as such, and mustnot- * be misrepresented as being the original software. - * o This notice may not be removed or altered from any source - * distribution. - */ - -module std.file; - -private import std.c.stdio; -private import std.c.stdlib; -private import std.path; -private import std.string; - -/* =========================== Win32 ======================= */ - -version (Win32) -{ - -private import std.c.windows.windows; -private import std.utf; -private import std.windows.syserror; - -int useWfuncs = 1; - -static this() -{ - // Win 95, 98, ME do not implement the W functions - useWfuncs = (GetVersion() < 0x80000000); -} - -/*********************************** - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { - this(name, sysErrorString(errno)); - this.errno = errno; - } -} - -/*********************************** - * Basic File operations. - */ - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - DWORD size; - DWORD numread; - HANDLE h; - byte[] buf; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - - if (h == INVALID_HANDLE_VALUE) - goto err1; - - size = GetFileSize(h, null); - if (size == INVALID_FILE_SIZE) - goto err2; - - buf = new byte[size]; - - if (ReadFile(h,buf,size,&numread,null) != 1) - goto err2; - - if (numread != size) - goto err2; - - if (!CloseHandle(h)) - goto err; - - return buf; - -err2: - CloseHandle(h); -err: - delete buf; -err1: - throw new FileException(name, GetLastError()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - SetFilePointer(h, 0, null, FILE_END); - - if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); - else - result = MoveFileA(toMBSz(from), toMBSz(to)); - if (!result) - throw new FileException(to, GetLastError()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - BOOL result; - - if (useWfuncs) - result = DeleteFileW(std.utf.toUTF16z(name)); - else - result = DeleteFileA(toMBSz(name)); - if (!result) - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - HANDLE findhndl; - uint resulth; - uint resultl; - - if (useWfuncs) - { - WIN32_FIND_DATAW filefindbuf; - - findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - else - { - WIN32_FIND_DATA filefindbuf; - - findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - - if (findhndl == cast(HANDLE)-1) - { - throw new FileException(name, GetLastError()); - } - FindClose(findhndl); - return (cast(ulong)resulth << 32) + resultl; -} - -/*************************************************** - * Does file (or directory) exist? - */ - -int exists(char[] name) -{ - uint result; - - if (useWfuncs) - //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp- result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - - return (result == 0xFFFFFFFF) ? 0 : 1; -} - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - uint result; - - if (useWfuncs) - result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - if (result == 0xFFFFFFFF) - { - throw new FileException(name, GetLastError()); - } - return result; -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); - else - result = SetCurrentDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); - else - result = CreateDirectoryA(toMBSz(pathname), null); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); - else - result = RemoveDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ - if (useWfuncs) - { - wchar[] dir; - int len; - wchar c; - - len = GetCurrentDirectoryW(0, &c); - if (!len) - goto Lerr; - dir = new wchar[len]; - len = GetCurrentDirectoryW(len, dir); - if (!len) - goto Lerr; - return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 - } - else - { - char[] dir; - int len; - char c; - - len = GetCurrentDirectoryA(0, &c); - if (!len) - goto Lerr; - dir = new char[len]; - len = GetCurrentDirectoryA(len, dir); - if (!len) - goto Lerr; - return dir[0 .. len]; // leave off terminating 0 - } - -Lerr: - throw new FileException("getcwd", GetLastError()); -} - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - char[] c; - HANDLE h; - - c = std.path.join(pathname, "*.*"); - if (useWfuncs) - { - WIN32_FIND_DATAW fileinfo; - - h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) - { - do - { int clength; - - // Skip "." and ".." - if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 || - std.string.wcscmp(fileinfo.cFileName, "..") == 0) - continue; - - clength = std.string.wcslen(fileinfo.cFileName); - // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength]))) - break; - } while (FindNextFileW(h,&fileinfo) != FALSE); - FindClose(h); - } - } - else - { - WIN32_FIND_DATA fileinfo; - - h = FindFirstFileA(toMBSz(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? - { - do - { int clength; - wchar[] wbuf; - int n; - - // Skip "." and ".." - if (std.string.strcmp(fileinfo.cFileName, ".") == 0 || - std.string.strcmp(fileinfo.cFileName, "..") == 0) - continue; - - clength = std.string.strlen(fileinfo.cFileName); - - // Convert cFileName[] to unicode - wbuf.length =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);- n =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.len gth);- assert(n == wbuf.length); - // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(wbuf))) - break; - } while (FindNextFileA(h,&fileinfo) != FALSE); - FindClose(h); - } - } -} - -/****************************************** - * Since Win 9x does not support the "W" API's, first convert - * to wchar, then convert to multibyte using the current code - * page. - * (Thanks to yaneurao for this) - */ - -char* toMBSz(char[] s) -{ - // Only need to do this if any chars have the high bit set - foreach (char c; s) - { - if (c >= 0x80) - { char[] result; - int i; - wchar* ws = std.utf.toUTF16z(s); - result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null,null);- i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null,null);- assert(i == result.length); - return result; - } - } - return std.string.toStringz(s); -} - - -/*************************************************** - * Copy a file. - */ - -void copy(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); - else - result = CopyFileA(toMBSz(from), toMBSz(to), false); - if (!result) - throw new FileException(to, GetLastError()); -} - - -} - -/* =========================== linux ======================= */ - -version (linux) -{ - -private import std.c.linux.linux; - -extern (C) char* strerror(int); - -/*********************************** - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { char* s = strerror(errno); - this(name, std.string.toString(s).dup); - this.errno = errno; - } -} - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - uint size; - uint numread; - int fd; - struct_stat statbuf; - byte[] buf; - char *namez; - - namez = toStringz(name); - //printf("file.read('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - buf = new byte[size]; - - numread = std.c.linux.linux.read(fd, cast(char*)buf, size); - if (numread != size) - { - //printf("\tread error, errno = %d\n",getErrno()); - goto err2; - } - - if (std.c.linux.linux.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return buf; - -err2: - std.c.linux.linux.close(fd); -err: - delete buf; - -err1: - throw new FileException(name, getErrno()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - int fd; - int numwritten; - char *namez; - - namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC,0660);- if (fd == -1) - goto err; - - numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (std.c.linux.linux.close(fd) == -1) - goto err; - - return; - -err2: - std.c.linux.linux.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - int fd; - int numwritten; - char *namez; - - namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT,0660);- if (fd == -1) - goto err; - - numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (std.c.linux.linux.close(fd) == -1) - goto err; - - return; - -err2: - std.c.linux.linux.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - char *fromz = toStringz(from); - char *toz = toStringz(to); - - if (std.c.stdio.rename(fromz, toz) == -1) - throw new FileException(to, getErrno()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - if (std.c.stdio.remove(toStringz(name)) == -1) - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - uint size; - int fd; - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - //printf("file.getSize('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - - if (std.c.linux.linux.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return size; - -err2: - std.c.linux.linux.close(fd); -err: -err1: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) - { - throw new FileException(name, getErrno()); - } - - return statbuf.st_mode; -} - -/**************************************************** - * Does file/directory exist? - */ - -int exists(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) - { - return 0; - } - - return 1; -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFDIR; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ - if (std.c.linux.linux.chdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ - if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ - if (std.c.linux.linux.rmdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ char* p; - - p = std.c.linux.linux.getcwd(null, 0); - if (!p) - { - throw new FileException("cannot get cwd", getErrno()); - } - - size_t len = std.string.strlen(p); - char[] buf = new char[len]; - buf[] = p[0 .. len]; - std.c.stdlib.free(p); - return buf; -} - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - DIR* h; - dirent* fdata; - - h = opendir(toStringz(pathname)); - if (h) - { - while((fdata = readdir(h)) != null) - { - // Skip "." and ".." - if (!std.string.strcmp(fdata.d_name, ".") || - !std.string.strcmp(fdata.d_name, "..")) - continue; - - int len = std.string.strlen(fdata.d_name); - if (!callback(fdata.d_name[0 .. len].dup)) - break; - } - closedir(h); - } - else - { - throw new FileException(pathname, getErrno()); - } -} - -/*************************************************** - * Copy a file. - */ - -void copy(char[] from, char[] to) -{ - void[] buffer; - - /* If the file is very large, this won't work, but - * it's a good start. - * BUG: it should maintain the file timestamps - */ - buffer = read(from); - write(to, buffer); - delete buffer; -} - - - -} - + +/* + * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright, Christopher E. Miller, Andre Fornacon + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistributeit+ * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you mustnot+ * claim that you wrote the original software. If you use thissoftware+ * in a product, an acknowledgment in the product documentation wouldbe+ * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and mustnot+ * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +module std.file; + +private import std.c.stdio; +private import std.c.stdlib; +private import std.path; +private import std.string; + +/* =========================== Win32 ======================= */ + +version (Win32) +{ + +private import std.c.windows.windows; +private import std.utf; +private import std.windows.syserror; + +int useWfuncs = 1; + +static this() +{ + // Win 95, 98, ME do not implement the W functions + useWfuncs = (GetVersion() < 0x80000000); +} + +/*********************************** + */ + +class FileException : Exception +{ + + uint errno; // operating system error code + + this(char[] name) + { + this(name, "file I/O"); + } + + this(char[] name, char[] message) + { + super(name ~ ": " ~ message); + } + + this(char[] name, uint errno) + { + this(name, sysErrorString(errno)); + this.errno = errno; + } +} + +/*********************************** + * Basic File operations. + */ + +/******************************************** + * Read a file. + * Returns: + * array of bytes read + */ + +void[] read(char[] name) +{ + DWORD size; + DWORD numread; + HANDLE h; + byte[] buf; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + + if (h == INVALID_HANDLE_VALUE) + goto err1; + + size = GetFileSize(h, null); + if (size == INVALID_FILE_SIZE) + goto err2; + + buf = new byte[size]; + + if (ReadFile(h,buf,size,&numread,null) != 1) + goto err2; + + if (numread != size) + goto err2; + + if (!CloseHandle(h)) + goto err; + + return buf; + +err2: + CloseHandle(h); +err: + delete buf; +err1: + throw new FileException(name, GetLastError()); +} + +/********************************************* + * Write a file. + * Returns: + * 0 success + */ + +void write(char[] name, void[] buffer) +{ + HANDLE h; + DWORD numwritten; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + if (h == INVALID_HANDLE_VALUE) + goto err; + + if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) + goto err2; + + if (buffer.length != numwritten) + goto err2; + + if (!CloseHandle(h)) + goto err; + return; + +err2: + CloseHandle(h); +err: + throw new FileException(name, GetLastError()); +} + + +/********************************************* + * Append to a file. + */ + +void append(char[] name, void[] buffer) +{ + HANDLE h; + DWORD numwritten; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + if (h == INVALID_HANDLE_VALUE) + goto err; + + SetFilePointer(h, 0, null, FILE_END); + + if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) + goto err2; + + if (buffer.length != numwritten) + goto err2; + + if (!CloseHandle(h)) + goto err; + return; + +err2: + CloseHandle(h); +err: + throw new FileException(name, GetLastError()); +} + + +/*************************************************** + * Rename a file. + */ + +void rename(char[] from, char[] to) +{ + BOOL result; + + if (useWfuncs) + result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); + else + result = MoveFileA(toMBSz(from), toMBSz(to)); + if (!result) + throw new FileException(to, GetLastError()); +} + + +/*************************************************** + * Delete a file. + */ + +void remove(char[] name) +{ + BOOL result; + + if (useWfuncs) + result = DeleteFileW(std.utf.toUTF16z(name)); + else + result = DeleteFileA(toMBSz(name)); + if (!result) + throw new FileException(name, GetLastError()); +} + + +/*************************************************** + * Get file size. + */ + +ulong getSize(char[] name) +{ + HANDLE findhndl; + uint resulth; + uint resultl; + + if (useWfuncs) + { + WIN32_FIND_DATAW filefindbuf; + + findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); + resulth = filefindbuf.nFileSizeHigh; + resultl = filefindbuf.nFileSizeLow; + } + else + { + WIN32_FIND_DATA filefindbuf; + + findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); + resulth = filefindbuf.nFileSizeHigh; + resultl = filefindbuf.nFileSizeLow; + } + + if (findhndl == cast(HANDLE)-1) + { + throw new FileException(name, GetLastError()); + } + FindClose(findhndl); + return (cast(ulong)resulth << 32) + resultl; +} + +/*************************************************** + * Does file (or directory) exist? + */ + +int exists(char[] name) +{ + uint result; + + if (useWfuncs) + //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp+ result = GetFileAttributesW(std.utf.toUTF16z(name)); + else + result = GetFileAttributesA(toMBSz(name)); + + return (result == 0xFFFFFFFF) ? 0 : 1; +} + +/*************************************************** + * Get file attributes. + */ + +uint getAttributes(char[] name) +{ + uint result; + + if (useWfuncs) + result = GetFileAttributesW(std.utf.toUTF16z(name)); + else + result = GetFileAttributesA(toMBSz(name)); + if (result == 0xFFFFFFFF) + { + throw new FileException(name, GetLastError()); + } + return result; +} + +/**************************************************** + * Is name a file? + */ + +int isfile(char[] name) +{ + return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + +/**************************************************** + * Is name a directory? + */ + +int isdir(char[] name) +{ + return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +/**************************************************** + * Change directory. + */ + +void chdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); + else + result = SetCurrentDirectoryA(toMBSz(pathname)); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Make directory. + */ + +void mkdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); + else + result = CreateDirectoryA(toMBSz(pathname), null); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Remove directory. + */ + +void rmdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); + else + result = RemoveDirectoryA(toMBSz(pathname)); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Get current directory. + */ + +char[] getcwd() +{ + if (useWfuncs) + { + wchar[] dir; + int len; + wchar c; + + len = GetCurrentDirectoryW(0, &c); + if (!len) + goto Lerr; + dir = new wchar[len]; + len = GetCurrentDirectoryW(len, dir); + if (!len) + goto Lerr; + return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 + } + else + { + char[] dir; + int len; + char c; + + len = GetCurrentDirectoryA(0, &c); + if (!len) + goto Lerr; + dir = new char[len]; + len = GetCurrentDirectoryA(len, dir); + if (!len) + goto Lerr; + return dir[0 .. len]; // leave off terminating 0 + } + +Lerr: + throw new FileException("getcwd", GetLastError()); +} + +/*************************************************** + * Return contents of directory. + */ + +char[][] listdir(char[] pathname) +{ + char[][] result; + + bool listing(char[] filename) + { + result ~= filename; + return true; // continue + } + + listdir(pathname, &listing); + return result; +} + +void listdir(char[] pathname, bool delegate(char[] filename) callback) +{ + char[] c; + HANDLE h; + + c = std.path.join(pathname, "*.*"); + if (useWfuncs) + { + WIN32_FIND_DATAW fileinfo; + + h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); + if (h != INVALID_HANDLE_VALUE) + { + do + { int clength; + + // Skip "." and ".." + if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 || + std.string.wcscmp(fileinfo.cFileName, "..") == 0) + continue; + + clength = std.string.wcslen(fileinfo.cFileName); + // toUTF8() returns a new buffer + if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength]))) + break; + } while (FindNextFileW(h,&fileinfo) != FALSE); + FindClose(h); + } + } + else + { + WIN32_FIND_DATA fileinfo; + + h = FindFirstFileA(toMBSz(c), &fileinfo); + if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? + { + do + { int clength; + wchar[] wbuf; + int n; + + // Skip "." and ".." + if (std.string.strcmp(fileinfo.cFileName, ".") == 0 || + std.string.strcmp(fileinfo.cFileName, "..") == 0) + continue; + + clength = std.string.strlen(fileinfo.cFileName); + + // Convert cFileName[] to unicode + wbuf.length =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);+ n =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.len gth);+ assert(n == wbuf.length); + // toUTF8() returns a new buffer + if (!callback(std.utf.toUTF8(wbuf))) + break; + } while (FindNextFileA(h,&fileinfo) != FALSE); + FindClose(h); + } + } +} + +/****************************************** + * Since Win 9x does not support the "W" API's, first convert + * to wchar, then convert to multibyte using the current code + * page. + * (Thanks to yaneurao for this) + */ + +char* toMBSz(char[] s) +{ + // Only need to do this if any chars have the high bit set + foreach (char c; s) + { + if (c >= 0x80) + { char[] result; + int i; + wchar* ws = std.utf.toUTF16z(s); + result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null,null);+ i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null,null);+ assert(i == result.length); + return result; + } + } + return std.string.toStringz(s); +} + + +/*************************************************** + * Copy a file. + */ + +void copy(char[] from, char[] to) +{ + BOOL result; + + if (useWfuncs) + result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); + else + result = CopyFileA(toMBSz(from), toMBSz(to), false); + if (!result) + throw new FileException(to, GetLastError()); +} + + +} + +/* =========================== linux ======================= */ + +version (linux) +{ + +private import std.c.linux.linux; + +extern (C) char* strerror(int); +extern(C) int access(char *, int); +/*********************************** + */ + +class FileException : Exception +{ + + uint errno; // operating system error code + + this(char[] name) + { + this(name, "file I/O"); + } + + this(char[] name, char[] message) + { + super(name ~ ": " ~ message); + } + + this(char[] name, uint errno) + { char* s = strerror(errno); + this(name, std.string.toString(s).dup); + this.errno = errno; + } +} + +/******************************************** + * Read a file. + * Returns: + * array of bytes read + */ + +void[] read(char[] name) +{ + uint size; + uint numread; + int fd; + struct_stat statbuf; + byte[] buf; + char *namez; + + namez = toStringz(name); + //printf("file.read('%s')\n",namez); + fd = std.c.linux.linux.open(namez, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + size = statbuf.st_size; + buf = new byte[size]; + + numread = std.c.linux.linux.read(fd, cast(char*)buf, size); + if (numread != size) + { + //printf("\tread error, errno = %d\n",getErrno()); + goto err2; + } + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err; + } + + return buf; + +err2: + std.c.linux.linux.close(fd); +err: + delete buf; + +err1: + throw new FileException(name, getErrno()); +} + +/********************************************* + * Write a file. + * Returns: + * 0 success + */ + +void write(char[] name, void[] buffer) +{ + int fd; + int numwritten; + char *namez; + + namez = toStringz(name); + fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC,0660);+ if (fd == -1) + goto err; + + numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); + if (buffer.length != numwritten) + goto err2; + + if (std.c.linux.linux.close(fd) == -1) + goto err; + + return; + +err2: + std.c.linux.linux.close(fd); +err: + throw new FileException(name, getErrno()); +} + + +/********************************************* + * Append to a file. + */ + +void append(char[] name, void[] buffer) +{ + int fd; + int numwritten; + char *namez; + + namez = toStringz(name); + fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT,0660);+ if (fd == -1) + goto err; + + numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); + if (buffer.length != numwritten) + goto err2; + + if (std.c.linux.linux.close(fd) == -1) + goto err; + + return; + +err2: + std.c.linux.linux.close(fd); +err: + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Rename a file. + */ + +void rename(char[] from, char[] to) +{ + char *fromz = toStringz(from); + char *toz = toStringz(to); + + if (std.c.stdio.rename(fromz, toz) == -1) + throw new FileException(to, getErrno()); +} + + +/*************************************************** + * Delete a file. + */ + +void remove(char[] name) +{ + if (std.c.stdio.remove(toStringz(name)) == -1) + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Get file size. + */ + +ulong getSize(char[] name) +{ + uint size; + int fd; + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + //printf("file.getSize('%s')\n",namez); + fd = std.c.linux.linux.open(namez, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + size = statbuf.st_size; + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err; + } + + return size; + +err2: + std.c.linux.linux.close(fd); +err: +err1: + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Get file attributes. + */ + +uint getAttributes(char[] name) +{ + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + if (std.c.linux.linux.stat(namez, &statbuf)) + { + throw new FileException(name, getErrno()); + } + + return statbuf.st_mode; +} + +/**************************************************** + * Does file/directory exist? + */ + +int exists(char[] name) +{ + if(access(toStringz(name),0)) + return 0; + else + return 1; +} + +/**************************************************** + * Is name a file? + */ + +int isfile(char[] name) +{ + return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file +} + +/**************************************************** + * Is name a directory? + */ + +int isdir(char[] name) +{ + return (getAttributes(name) & S_IFMT) == S_IFDIR; +} + +/**************************************************** + * Change directory. + */ + +void chdir(char[] pathname) +{ + if (std.c.linux.linux.chdir(toStringz(pathname))) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Make directory. + */ + +void mkdir(char[] pathname) +{ + if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Remove directory. + */ + +void rmdir(char[] pathname) +{ + if (std.c.linux.linux.rmdir(toStringz(pathname))) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Get current directory. + */ + +char[] getcwd() +{ char* p; + + p = std.c.linux.linux.getcwd(null, 0); + if (!p) + { + throw new FileException("cannot get cwd", getErrno()); + } + + size_t len = std.string.strlen(p); + char[] buf = new char[len]; + buf[] = p[0 .. len]; + std.c.stdlib.free(p); + return buf; +} + +/*************************************************** + * Return contents of directory. + */ + +char[][] listdir(char[] pathname) +{ + char[][] result; + + bool listing(char[] filename) + { + result ~= filename; + return true; // continue + } + + listdir(pathname, &listing); + return result; +} + +void listdir(char[] pathname, bool delegate(char[] filename) callback) +{ + DIR* h; + dirent* fdata; + + h = opendir(toStringz(pathname)); + if (h) + { + while((fdata = readdir(h)) != null) + { + // Skip "." and ".." + if (!std.string.strcmp(fdata.d_name, ".") || + !std.string.strcmp(fdata.d_name, "..")) + continue; + + int len = std.string.strlen(fdata.d_name); + if (!callback(fdata.d_name[0 .. len].dup)) + break; + } + closedir(h); + } + else + { + throw new FileException(pathname, getErrno()); + } +} + +/*************************************************** + * Copy a file. + */ + +void copy(char[] from, char[] to) +{ + void[] buffer; + + /* If the file is very large, this won't work, but + * it's a good start. + * BUG: it should maintain the file timestamps + */ + buffer = read(from); + write(to, buffer); + delete buffer; +} + + + +} +
Jul 04 2005
On Mon, 4 Jul 2005, Walter wrote:Is the linux function exists() the only thing changed here?Yes."Ameer Armaly" <ameer bellsouth.net> wrote in message news:Pine.LNX.4.61.0507041302450.1150 debian...Alright here it is. I successfully compiled and tested phobos with these modifications. --- file.d 2005-06-30 16:04:29.000000000 -0400 +++ newfile.d 2005-07-04 12:55:21.000000000 -0400 -1,958 +1,952 - -/* - * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com - * Written by Walter Bright, Christopher E. Miller, Andre Fornacon - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistributeit- * freely, subject to the following restrictions: - * - * o The origin of this software must not be misrepresented; you mustnot- * claim that you wrote the original software. If you use thissoftware- * in a product, an acknowledgment in the product documentation wouldbe- * appreciated but is not required. - * o Altered source versions must be plainly marked as such, and mustnot- * be misrepresented as being the original software. - * o This notice may not be removed or altered from any source - * distribution. - */ - -module std.file; - -private import std.c.stdio; -private import std.c.stdlib; -private import std.path; -private import std.string; - -/* =========================== Win32 ======================= */ - -version (Win32) -{ - -private import std.c.windows.windows; -private import std.utf; -private import std.windows.syserror; - -int useWfuncs = 1; - -static this() -{ - // Win 95, 98, ME do not implement the W functions - useWfuncs = (GetVersion() < 0x80000000); -} - -/*********************************** - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { - this(name, sysErrorString(errno)); - this.errno = errno; - } -} - -/*********************************** - * Basic File operations. - */ - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - DWORD size; - DWORD numread; - HANDLE h; - byte[] buf; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - - if (h == INVALID_HANDLE_VALUE) - goto err1; - - size = GetFileSize(h, null); - if (size == INVALID_FILE_SIZE) - goto err2; - - buf = new byte[size]; - - if (ReadFile(h,buf,size,&numread,null) != 1) - goto err2; - - if (numread != size) - goto err2; - - if (!CloseHandle(h)) - goto err; - - return buf; - -err2: - CloseHandle(h); -err: - delete buf; -err1: - throw new FileException(name, GetLastError()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - SetFilePointer(h, 0, null, FILE_END); - - if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); - else - result = MoveFileA(toMBSz(from), toMBSz(to)); - if (!result) - throw new FileException(to, GetLastError()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - BOOL result; - - if (useWfuncs) - result = DeleteFileW(std.utf.toUTF16z(name)); - else - result = DeleteFileA(toMBSz(name)); - if (!result) - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - HANDLE findhndl; - uint resulth; - uint resultl; - - if (useWfuncs) - { - WIN32_FIND_DATAW filefindbuf; - - findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - else - { - WIN32_FIND_DATA filefindbuf; - - findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - - if (findhndl == cast(HANDLE)-1) - { - throw new FileException(name, GetLastError()); - } - FindClose(findhndl); - return (cast(ulong)resulth << 32) + resultl; -} - -/*************************************************** - * Does file (or directory) exist? - */ - -int exists(char[] name) -{ - uint result; - - if (useWfuncs) - //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp- result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - - return (result == 0xFFFFFFFF) ? 0 : 1; -} - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - uint result; - - if (useWfuncs) - result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - if (result == 0xFFFFFFFF) - { - throw new FileException(name, GetLastError()); - } - return result; -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); - else - result = SetCurrentDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); - else - result = CreateDirectoryA(toMBSz(pathname), null); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); - else - result = RemoveDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ - if (useWfuncs) - { - wchar[] dir; - int len; - wchar c; - - len = GetCurrentDirectoryW(0, &c); - if (!len) - goto Lerr; - dir = new wchar[len]; - len = GetCurrentDirectoryW(len, dir); - if (!len) - goto Lerr; - return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 - } - else - { - char[] dir; - int len; - char c; - - len = GetCurrentDirectoryA(0, &c); - if (!len) - goto Lerr; - dir = new char[len]; - len = GetCurrentDirectoryA(len, dir); - if (!len) - goto Lerr; - return dir[0 .. len]; // leave off terminating 0 - } - -Lerr: - throw new FileException("getcwd", GetLastError()); -} - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - char[] c; - HANDLE h; - - c = std.path.join(pathname, "*.*"); - if (useWfuncs) - { - WIN32_FIND_DATAW fileinfo; - - h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) - { - do - { int clength; - - // Skip "." and ".." - if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 || - std.string.wcscmp(fileinfo.cFileName, "..") == 0) - continue; - - clength = std.string.wcslen(fileinfo.cFileName); - // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength]))) - break; - } while (FindNextFileW(h,&fileinfo) != FALSE); - FindClose(h); - } - } - else - { - WIN32_FIND_DATA fileinfo; - - h = FindFirstFileA(toMBSz(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? - { - do - { int clength; - wchar[] wbuf; - int n; - - // Skip "." and ".." - if (std.string.strcmp(fileinfo.cFileName, ".") == 0 || - std.string.strcmp(fileinfo.cFileName, "..") == 0) - continue; - - clength = std.string.strlen(fileinfo.cFileName); - - // Convert cFileName[] to unicode - wbuf.length =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);- n =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.len gth);- assert(n == wbuf.length); - // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(wbuf))) - break; - } while (FindNextFileA(h,&fileinfo) != FALSE); - FindClose(h); - } - } -} - -/****************************************** - * Since Win 9x does not support the "W" API's, first convert - * to wchar, then convert to multibyte using the current code - * page. - * (Thanks to yaneurao for this) - */ - -char* toMBSz(char[] s) -{ - // Only need to do this if any chars have the high bit set - foreach (char c; s) - { - if (c >= 0x80) - { char[] result; - int i; - wchar* ws = std.utf.toUTF16z(s); - result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null,null);- i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null,null);- assert(i == result.length); - return result; - } - } - return std.string.toStringz(s); -} - - -/*************************************************** - * Copy a file. - */ - -void copy(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); - else - result = CopyFileA(toMBSz(from), toMBSz(to), false); - if (!result) - throw new FileException(to, GetLastError()); -} - - -} - -/* =========================== linux ======================= */ - -version (linux) -{ - -private import std.c.linux.linux; - -extern (C) char* strerror(int); - -/*********************************** - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { char* s = strerror(errno); - this(name, std.string.toString(s).dup); - this.errno = errno; - } -} - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - uint size; - uint numread; - int fd; - struct_stat statbuf; - byte[] buf; - char *namez; - - namez = toStringz(name); - //printf("file.read('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - buf = new byte[size]; - - numread = std.c.linux.linux.read(fd, cast(char*)buf, size); - if (numread != size) - { - //printf("\tread error, errno = %d\n",getErrno()); - goto err2; - } - - if (std.c.linux.linux.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return buf; - -err2: - std.c.linux.linux.close(fd); -err: - delete buf; - -err1: - throw new FileException(name, getErrno()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - int fd; - int numwritten; - char *namez; - - namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC,0660);- if (fd == -1) - goto err; - - numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (std.c.linux.linux.close(fd) == -1) - goto err; - - return; - -err2: - std.c.linux.linux.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - int fd; - int numwritten; - char *namez; - - namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT,0660);- if (fd == -1) - goto err; - - numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (std.c.linux.linux.close(fd) == -1) - goto err; - - return; - -err2: - std.c.linux.linux.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - char *fromz = toStringz(from); - char *toz = toStringz(to); - - if (std.c.stdio.rename(fromz, toz) == -1) - throw new FileException(to, getErrno()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - if (std.c.stdio.remove(toStringz(name)) == -1) - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - uint size; - int fd; - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - //printf("file.getSize('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - - if (std.c.linux.linux.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return size; - -err2: - std.c.linux.linux.close(fd); -err: -err1: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) - { - throw new FileException(name, getErrno()); - } - - return statbuf.st_mode; -} - -/**************************************************** - * Does file/directory exist? - */ - -int exists(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) - { - return 0; - } - - return 1; -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFDIR; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ - if (std.c.linux.linux.chdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ - if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ - if (std.c.linux.linux.rmdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ char* p; - - p = std.c.linux.linux.getcwd(null, 0); - if (!p) - { - throw new FileException("cannot get cwd", getErrno()); - } - - size_t len = std.string.strlen(p); - char[] buf = new char[len]; - buf[] = p[0 .. len]; - std.c.stdlib.free(p); - return buf; -} - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - DIR* h; - dirent* fdata; - - h = opendir(toStringz(pathname)); - if (h) - { - while((fdata = readdir(h)) != null) - { - // Skip "." and ".." - if (!std.string.strcmp(fdata.d_name, ".") || - !std.string.strcmp(fdata.d_name, "..")) - continue; - - int len = std.string.strlen(fdata.d_name); - if (!callback(fdata.d_name[0 .. len].dup)) - break; - } - closedir(h); - } - else - { - throw new FileException(pathname, getErrno()); - } -} - -/*************************************************** - * Copy a file. - */ - -void copy(char[] from, char[] to) -{ - void[] buffer; - - /* If the file is very large, this won't work, but - * it's a good start. - * BUG: it should maintain the file timestamps - */ - buffer = read(from); - write(to, buffer); - delete buffer; -} - - - -} - + +/* + * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright, Christopher E. Miller, Andre Fornacon + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistributeit+ * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you mustnot+ * claim that you wrote the original software. If you use thissoftware+ * in a product, an acknowledgment in the product documentation wouldbe+ * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and mustnot+ * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +module std.file; + +private import std.c.stdio; +private import std.c.stdlib; +private import std.path; +private import std.string; + +/* =========================== Win32 ======================= */ + +version (Win32) +{ + +private import std.c.windows.windows; +private import std.utf; +private import std.windows.syserror; + +int useWfuncs = 1; + +static this() +{ + // Win 95, 98, ME do not implement the W functions + useWfuncs = (GetVersion() < 0x80000000); +} + +/*********************************** + */ + +class FileException : Exception +{ + + uint errno; // operating system error code + + this(char[] name) + { + this(name, "file I/O"); + } + + this(char[] name, char[] message) + { + super(name ~ ": " ~ message); + } + + this(char[] name, uint errno) + { + this(name, sysErrorString(errno)); + this.errno = errno; + } +} + +/*********************************** + * Basic File operations. + */ + +/******************************************** + * Read a file. + * Returns: + * array of bytes read + */ + +void[] read(char[] name) +{ + DWORD size; + DWORD numread; + HANDLE h; + byte[] buf; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + + if (h == INVALID_HANDLE_VALUE) + goto err1; + + size = GetFileSize(h, null); + if (size == INVALID_FILE_SIZE) + goto err2; + + buf = new byte[size]; + + if (ReadFile(h,buf,size,&numread,null) != 1) + goto err2; + + if (numread != size) + goto err2; + + if (!CloseHandle(h)) + goto err; + + return buf; + +err2: + CloseHandle(h); +err: + delete buf; +err1: + throw new FileException(name, GetLastError()); +} + +/********************************************* + * Write a file. + * Returns: + * 0 success + */ + +void write(char[] name, void[] buffer) +{ + HANDLE h; + DWORD numwritten; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + if (h == INVALID_HANDLE_VALUE) + goto err; + + if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) + goto err2; + + if (buffer.length != numwritten) + goto err2; + + if (!CloseHandle(h)) + goto err; + return; + +err2: + CloseHandle(h); +err: + throw new FileException(name, GetLastError()); +} + + +/********************************************* + * Append to a file. + */ + +void append(char[] name, void[] buffer) +{ + HANDLE h; + DWORD numwritten; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + if (h == INVALID_HANDLE_VALUE) + goto err; + + SetFilePointer(h, 0, null, FILE_END); + + if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) + goto err2; + + if (buffer.length != numwritten) + goto err2; + + if (!CloseHandle(h)) + goto err; + return; + +err2: + CloseHandle(h); +err: + throw new FileException(name, GetLastError()); +} + + +/*************************************************** + * Rename a file. + */ + +void rename(char[] from, char[] to) +{ + BOOL result; + + if (useWfuncs) + result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); + else + result = MoveFileA(toMBSz(from), toMBSz(to)); + if (!result) + throw new FileException(to, GetLastError()); +} + + +/*************************************************** + * Delete a file. + */ + +void remove(char[] name) +{ + BOOL result; + + if (useWfuncs) + result = DeleteFileW(std.utf.toUTF16z(name)); + else + result = DeleteFileA(toMBSz(name)); + if (!result) + throw new FileException(name, GetLastError()); +} + + +/*************************************************** + * Get file size. + */ + +ulong getSize(char[] name) +{ + HANDLE findhndl; + uint resulth; + uint resultl; + + if (useWfuncs) + { + WIN32_FIND_DATAW filefindbuf; + + findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); + resulth = filefindbuf.nFileSizeHigh; + resultl = filefindbuf.nFileSizeLow; + } + else + { + WIN32_FIND_DATA filefindbuf; + + findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); + resulth = filefindbuf.nFileSizeHigh; + resultl = filefindbuf.nFileSizeLow; + } + + if (findhndl == cast(HANDLE)-1) + { + throw new FileException(name, GetLastError()); + } + FindClose(findhndl); + return (cast(ulong)resulth << 32) + resultl; +} + +/*************************************************** + * Does file (or directory) exist? + */ + +int exists(char[] name) +{ + uint result; + + if (useWfuncs) + //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp+ result = GetFileAttributesW(std.utf.toUTF16z(name)); + else + result = GetFileAttributesA(toMBSz(name)); + + return (result == 0xFFFFFFFF) ? 0 : 1; +} + +/*************************************************** + * Get file attributes. + */ + +uint getAttributes(char[] name) +{ + uint result; + + if (useWfuncs) + result = GetFileAttributesW(std.utf.toUTF16z(name)); + else + result = GetFileAttributesA(toMBSz(name)); + if (result == 0xFFFFFFFF) + { + throw new FileException(name, GetLastError()); + } + return result; +} + +/**************************************************** + * Is name a file? + */ + +int isfile(char[] name) +{ + return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + +/**************************************************** + * Is name a directory? + */ + +int isdir(char[] name) +{ + return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +/**************************************************** + * Change directory. + */ + +void chdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); + else + result = SetCurrentDirectoryA(toMBSz(pathname)); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Make directory. + */ + +void mkdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); + else + result = CreateDirectoryA(toMBSz(pathname), null); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Remove directory. + */ + +void rmdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); + else + result = RemoveDirectoryA(toMBSz(pathname)); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Get current directory. + */ + +char[] getcwd() +{ + if (useWfuncs) + { + wchar[] dir; + int len; + wchar c; + + len = GetCurrentDirectoryW(0, &c); + if (!len) + goto Lerr; + dir = new wchar[len]; + len = GetCurrentDirectoryW(len, dir); + if (!len) + goto Lerr; + return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 + } + else + { + char[] dir; + int len; + char c; + + len = GetCurrentDirectoryA(0, &c); + if (!len) + goto Lerr; + dir = new char[len]; + len = GetCurrentDirectoryA(len, dir); + if (!len) + goto Lerr; + return dir[0 .. len]; // leave off terminating 0 + } + +Lerr: + throw new FileException("getcwd", GetLastError()); +} + +/*************************************************** + * Return contents of directory. + */ + +char[][] listdir(char[] pathname) +{ + char[][] result; + + bool listing(char[] filename) + { + result ~= filename; + return true; // continue + } + + listdir(pathname, &listing); + return result; +} + +void listdir(char[] pathname, bool delegate(char[] filename) callback) +{ + char[] c; + HANDLE h; + + c = std.path.join(pathname, "*.*"); + if (useWfuncs) + { + WIN32_FIND_DATAW fileinfo; + + h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); + if (h != INVALID_HANDLE_VALUE) + { + do + { int clength; + + // Skip "." and ".." + if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 || + std.string.wcscmp(fileinfo.cFileName, "..") == 0) + continue; + + clength = std.string.wcslen(fileinfo.cFileName); + // toUTF8() returns a new buffer + if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength]))) + break; + } while (FindNextFileW(h,&fileinfo) != FALSE); + FindClose(h); + } + } + else + { + WIN32_FIND_DATA fileinfo; + + h = FindFirstFileA(toMBSz(c), &fileinfo); + if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? + { + do + { int clength; + wchar[] wbuf; + int n; + + // Skip "." and ".." + if (std.string.strcmp(fileinfo.cFileName, ".") == 0 || + std.string.strcmp(fileinfo.cFileName, "..") == 0) + continue; + + clength = std.string.strlen(fileinfo.cFileName); + + // Convert cFileName[] to unicode + wbuf.length =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);+ n =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.len gth);+ assert(n == wbuf.length); + // toUTF8() returns a new buffer + if (!callback(std.utf.toUTF8(wbuf))) + break; + } while (FindNextFileA(h,&fileinfo) != FALSE); + FindClose(h); + } + } +} + +/****************************************** + * Since Win 9x does not support the "W" API's, first convert + * to wchar, then convert to multibyte using the current code + * page. + * (Thanks to yaneurao for this) + */ + +char* toMBSz(char[] s) +{ + // Only need to do this if any chars have the high bit set + foreach (char c; s) + { + if (c >= 0x80) + { char[] result; + int i; + wchar* ws = std.utf.toUTF16z(s); + result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null,null);+ i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null,null);+ assert(i == result.length); + return result; + } + } + return std.string.toStringz(s); +} + + +/*************************************************** + * Copy a file. + */ + +void copy(char[] from, char[] to) +{ + BOOL result; + + if (useWfuncs) + result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); + else + result = CopyFileA(toMBSz(from), toMBSz(to), false); + if (!result) + throw new FileException(to, GetLastError()); +} + + +} + +/* =========================== linux ======================= */ + +version (linux) +{ + +private import std.c.linux.linux; + +extern (C) char* strerror(int); +extern(C) int access(char *, int); +/*********************************** + */ + +class FileException : Exception +{ + + uint errno; // operating system error code + + this(char[] name) + { + this(name, "file I/O"); + } + + this(char[] name, char[] message) + { + super(name ~ ": " ~ message); + } + + this(char[] name, uint errno) + { char* s = strerror(errno); + this(name, std.string.toString(s).dup); + this.errno = errno; + } +} + +/******************************************** + * Read a file. + * Returns: + * array of bytes read + */ + +void[] read(char[] name) +{ + uint size; + uint numread; + int fd; + struct_stat statbuf; + byte[] buf; + char *namez; + + namez = toStringz(name); + //printf("file.read('%s')\n",namez); + fd = std.c.linux.linux.open(namez, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + size = statbuf.st_size; + buf = new byte[size]; + + numread = std.c.linux.linux.read(fd, cast(char*)buf, size); + if (numread != size) + { + //printf("\tread error, errno = %d\n",getErrno()); + goto err2; + } + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err; + } + + return buf; + +err2: + std.c.linux.linux.close(fd); +err: + delete buf; + +err1: + throw new FileException(name, getErrno()); +} + +/********************************************* + * Write a file. + * Returns: + * 0 success + */ + +void write(char[] name, void[] buffer) +{ + int fd; + int numwritten; + char *namez; + + namez = toStringz(name); + fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC,0660);+ if (fd == -1) + goto err; + + numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); + if (buffer.length != numwritten) + goto err2; + + if (std.c.linux.linux.close(fd) == -1) + goto err; + + return; + +err2: + std.c.linux.linux.close(fd); +err: + throw new FileException(name, getErrno()); +} + + +/********************************************* + * Append to a file. + */ + +void append(char[] name, void[] buffer) +{ + int fd; + int numwritten; + char *namez; + + namez = toStringz(name); + fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT,0660);+ if (fd == -1) + goto err; + + numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); + if (buffer.length != numwritten) + goto err2; + + if (std.c.linux.linux.close(fd) == -1) + goto err; + + return; + +err2: + std.c.linux.linux.close(fd); +err: + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Rename a file. + */ + +void rename(char[] from, char[] to) +{ + char *fromz = toStringz(from); + char *toz = toStringz(to); + + if (std.c.stdio.rename(fromz, toz) == -1) + throw new FileException(to, getErrno()); +} + + +/*************************************************** + * Delete a file. + */ + +void remove(char[] name) +{ + if (std.c.stdio.remove(toStringz(name)) == -1) + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Get file size. + */ + +ulong getSize(char[] name) +{ + uint size; + int fd; + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + //printf("file.getSize('%s')\n",namez); + fd = std.c.linux.linux.open(namez, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + size = statbuf.st_size; + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err; + } + + return size; + +err2: + std.c.linux.linux.close(fd); +err: +err1: + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Get file attributes. + */ + +uint getAttributes(char[] name) +{ + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + if (std.c.linux.linux.stat(namez, &statbuf)) + { + throw new FileException(name, getErrno()); + } + + return statbuf.st_mode; +} + +/**************************************************** + * Does file/directory exist? + */ + +int exists(char[] name) +{ + if(access(toStringz(name),0)) + return 0; + else + return 1; +} + +/**************************************************** + * Is name a file? + */ + +int isfile(char[] name) +{ + return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file +} + +/**************************************************** + * Is name a directory? + */ + +int isdir(char[] name) +{ + return (getAttributes(name) & S_IFMT) == S_IFDIR; +} + +/**************************************************** + * Change directory. + */ + +void chdir(char[] pathname) +{ + if (std.c.linux.linux.chdir(toStringz(pathname))) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Make directory. + */ + +void mkdir(char[] pathname) +{ + if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Remove directory. + */ + +void rmdir(char[] pathname) +{ + if (std.c.linux.linux.rmdir(toStringz(pathname))) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Get current directory. + */ + +char[] getcwd() +{ char* p; + + p = std.c.linux.linux.getcwd(null, 0); + if (!p) + { + throw new FileException("cannot get cwd", getErrno()); + } + + size_t len = std.string.strlen(p); + char[] buf = new char[len]; + buf[] = p[0 .. len]; + std.c.stdlib.free(p); + return buf; +} + +/*************************************************** + * Return contents of directory. + */ + +char[][] listdir(char[] pathname) +{ + char[][] result; + + bool listing(char[] filename) + { + result ~= filename; + return true; // continue + } + + listdir(pathname, &listing); + return result; +} + +void listdir(char[] pathname, bool delegate(char[] filename) callback) +{ + DIR* h; + dirent* fdata; + + h = opendir(toStringz(pathname)); + if (h) + { + while((fdata = readdir(h)) != null) + { + // Skip "." and ".." + if (!std.string.strcmp(fdata.d_name, ".") || + !std.string.strcmp(fdata.d_name, "..")) + continue; + + int len = std.string.strlen(fdata.d_name); + if (!callback(fdata.d_name[0 .. len].dup)) + break; + } + closedir(h); + } + else + { + throw new FileException(pathname, getErrno()); + } +} + +/*************************************************** + * Copy a file. + */ + +void copy(char[] from, char[] to) +{ + void[] buffer; + + /* If the file is very large, this won't work, but + * it's a good start. + * BUG: it should maintain the file timestamps + */ + buffer = read(from); + write(to, buffer); + delete buffer; +} + + + +} +
Jul 04 2005
Congratulations, you've defeated the purpose of the patch/diff utility :). In article <Pine.LNX.4.61.0507041524470.1082 debian>, Ameer Armaly says...On Mon, 4 Jul 2005, Walter wrote:Regards, James DunneIs the linux function exists() the only thing changed here?Yes."Ameer Armaly" <ameer bellsouth.net> wrote in message news:Pine.LNX.4.61.0507041302450.1150 debian...Alright here it is. I successfully compiled and tested phobos with these modifications. --- file.d 2005-06-30 16:04:29.000000000 -0400 +++ newfile.d 2005-07-04 12:55:21.000000000 -0400 -1,958 +1,952 - -/* - * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com - * Written by Walter Bright, Christopher E. Miller, Andre Fornacon - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistributeit- * freely, subject to the following restrictions: - * - * o The origin of this software must not be misrepresented; you mustnot- * claim that you wrote the original software. If you use thissoftware- * in a product, an acknowledgment in the product documentation wouldbe- * appreciated but is not required. - * o Altered source versions must be plainly marked as such, and mustnot- * be misrepresented as being the original software. - * o This notice may not be removed or altered from any source - * distribution. - */ - -module std.file; - -private import std.c.stdio; -private import std.c.stdlib; -private import std.path; -private import std.string; - -/* =========================== Win32 ======================= */ - -version (Win32) -{ - -private import std.c.windows.windows; -private import std.utf; -private import std.windows.syserror; - -int useWfuncs = 1; - -static this() -{ - // Win 95, 98, ME do not implement the W functions - useWfuncs = (GetVersion() < 0x80000000); -} - -/*********************************** - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { - this(name, sysErrorString(errno)); - this.errno = errno; - } -} - -/*********************************** - * Basic File operations. - */ - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - DWORD size; - DWORD numread; - HANDLE h; - byte[] buf; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - - if (h == INVALID_HANDLE_VALUE) - goto err1; - - size = GetFileSize(h, null); - if (size == INVALID_FILE_SIZE) - goto err2; - - buf = new byte[size]; - - if (ReadFile(h,buf,size,&numread,null) != 1) - goto err2; - - if (numread != size) - goto err2; - - if (!CloseHandle(h)) - goto err; - - return buf; - -err2: - CloseHandle(h); -err: - delete buf; -err1: - throw new FileException(name, GetLastError()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - SetFilePointer(h, 0, null, FILE_END); - - if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); - else - result = MoveFileA(toMBSz(from), toMBSz(to)); - if (!result) - throw new FileException(to, GetLastError()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - BOOL result; - - if (useWfuncs) - result = DeleteFileW(std.utf.toUTF16z(name)); - else - result = DeleteFileA(toMBSz(name)); - if (!result) - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - HANDLE findhndl; - uint resulth; - uint resultl; - - if (useWfuncs) - { - WIN32_FIND_DATAW filefindbuf; - - findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - else - { - WIN32_FIND_DATA filefindbuf; - - findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - - if (findhndl == cast(HANDLE)-1) - { - throw new FileException(name, GetLastError()); - } - FindClose(findhndl); - return (cast(ulong)resulth << 32) + resultl; -} - -/*************************************************** - * Does file (or directory) exist? - */ - -int exists(char[] name) -{ - uint result; - - if (useWfuncs) - //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp- result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - - return (result == 0xFFFFFFFF) ? 0 : 1; -} - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - uint result; - - if (useWfuncs) - result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - if (result == 0xFFFFFFFF) - { - throw new FileException(name, GetLastError()); - } - return result; -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); - else - result = SetCurrentDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); - else - result = CreateDirectoryA(toMBSz(pathname), null); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); - else - result = RemoveDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ - if (useWfuncs) - { - wchar[] dir; - int len; - wchar c; - - len = GetCurrentDirectoryW(0, &c); - if (!len) - goto Lerr; - dir = new wchar[len]; - len = GetCurrentDirectoryW(len, dir); - if (!len) - goto Lerr; - return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 - } - else - { - char[] dir; - int len; - char c; - - len = GetCurrentDirectoryA(0, &c); - if (!len) - goto Lerr; - dir = new char[len]; - len = GetCurrentDirectoryA(len, dir); - if (!len) - goto Lerr; - return dir[0 .. len]; // leave off terminating 0 - } - -Lerr: - throw new FileException("getcwd", GetLastError()); -} - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - char[] c; - HANDLE h; - - c = std.path.join(pathname, "*.*"); - if (useWfuncs) - { - WIN32_FIND_DATAW fileinfo; - - h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) - { - do - { int clength; - - // Skip "." and ".." - if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 || - std.string.wcscmp(fileinfo.cFileName, "..") == 0) - continue; - - clength = std.string.wcslen(fileinfo.cFileName); - // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength]))) - break; - } while (FindNextFileW(h,&fileinfo) != FALSE); - FindClose(h); - } - } - else - { - WIN32_FIND_DATA fileinfo; - - h = FindFirstFileA(toMBSz(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? - { - do - { int clength; - wchar[] wbuf; - int n; - - // Skip "." and ".." - if (std.string.strcmp(fileinfo.cFileName, ".") == 0 || - std.string.strcmp(fileinfo.cFileName, "..") == 0) - continue; - - clength = std.string.strlen(fileinfo.cFileName); - - // Convert cFileName[] to unicode - wbuf.length =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);- n =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.len gth);- assert(n == wbuf.length); - // toUTF8() returns a new buffer - if (!callback(std.utf.toUTF8(wbuf))) - break; - } while (FindNextFileA(h,&fileinfo) != FALSE); - FindClose(h); - } - } -} - -/****************************************** - * Since Win 9x does not support the "W" API's, first convert - * to wchar, then convert to multibyte using the current code - * page. - * (Thanks to yaneurao for this) - */ - -char* toMBSz(char[] s) -{ - // Only need to do this if any chars have the high bit set - foreach (char c; s) - { - if (c >= 0x80) - { char[] result; - int i; - wchar* ws = std.utf.toUTF16z(s); - result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null,null);- i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null,null);- assert(i == result.length); - return result; - } - } - return std.string.toStringz(s); -} - - -/*************************************************** - * Copy a file. - */ - -void copy(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); - else - result = CopyFileA(toMBSz(from), toMBSz(to), false); - if (!result) - throw new FileException(to, GetLastError()); -} - - -} - -/* =========================== linux ======================= */ - -version (linux) -{ - -private import std.c.linux.linux; - -extern (C) char* strerror(int); - -/*********************************** - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { char* s = strerror(errno); - this(name, std.string.toString(s).dup); - this.errno = errno; - } -} - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - uint size; - uint numread; - int fd; - struct_stat statbuf; - byte[] buf; - char *namez; - - namez = toStringz(name); - //printf("file.read('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - buf = new byte[size]; - - numread = std.c.linux.linux.read(fd, cast(char*)buf, size); - if (numread != size) - { - //printf("\tread error, errno = %d\n",getErrno()); - goto err2; - } - - if (std.c.linux.linux.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return buf; - -err2: - std.c.linux.linux.close(fd); -err: - delete buf; - -err1: - throw new FileException(name, getErrno()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - int fd; - int numwritten; - char *namez; - - namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC,0660);- if (fd == -1) - goto err; - - numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (std.c.linux.linux.close(fd) == -1) - goto err; - - return; - -err2: - std.c.linux.linux.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - int fd; - int numwritten; - char *namez; - - namez = toStringz(name); - fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT,0660);- if (fd == -1) - goto err; - - numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (std.c.linux.linux.close(fd) == -1) - goto err; - - return; - -err2: - std.c.linux.linux.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - char *fromz = toStringz(from); - char *toz = toStringz(to); - - if (std.c.stdio.rename(fromz, toz) == -1) - throw new FileException(to, getErrno()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - if (std.c.stdio.remove(toStringz(name)) == -1) - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - uint size; - int fd; - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - //printf("file.getSize('%s')\n",namez); - fd = std.c.linux.linux.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (std.c.linux.linux.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - - if (std.c.linux.linux.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return size; - -err2: - std.c.linux.linux.close(fd); -err: -err1: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) - { - throw new FileException(name, getErrno()); - } - - return statbuf.st_mode; -} - -/**************************************************** - * Does file/directory exist? - */ - -int exists(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (std.c.linux.linux.stat(namez, &statbuf)) - { - return 0; - } - - return 1; -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFDIR; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ - if (std.c.linux.linux.chdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ - if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ - if (std.c.linux.linux.rmdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ char* p; - - p = std.c.linux.linux.getcwd(null, 0); - if (!p) - { - throw new FileException("cannot get cwd", getErrno()); - } - - size_t len = std.string.strlen(p); - char[] buf = new char[len]; - buf[] = p[0 .. len]; - std.c.stdlib.free(p); - return buf; -} - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - DIR* h; - dirent* fdata; - - h = opendir(toStringz(pathname)); - if (h) - { - while((fdata = readdir(h)) != null) - { - // Skip "." and ".." - if (!std.string.strcmp(fdata.d_name, ".") || - !std.string.strcmp(fdata.d_name, "..")) - continue; - - int len = std.string.strlen(fdata.d_name); - if (!callback(fdata.d_name[0 .. len].dup)) - break; - } - closedir(h); - } - else - { - throw new FileException(pathname, getErrno()); - } -} - -/*************************************************** - * Copy a file. - */ - -void copy(char[] from, char[] to) -{ - void[] buffer; - - /* If the file is very large, this won't work, but - * it's a good start. - * BUG: it should maintain the file timestamps - */ - buffer = read(from); - write(to, buffer); - delete buffer; -} - - - -} - + +/* + * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright, Christopher E. Miller, Andre Fornacon + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistributeit+ * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you mustnot+ * claim that you wrote the original software. If you use thissoftware+ * in a product, an acknowledgment in the product documentation wouldbe+ * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and mustnot+ * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +module std.file; + +private import std.c.stdio; +private import std.c.stdlib; +private import std.path; +private import std.string; + +/* =========================== Win32 ======================= */ + +version (Win32) +{ + +private import std.c.windows.windows; +private import std.utf; +private import std.windows.syserror; + +int useWfuncs = 1; + +static this() +{ + // Win 95, 98, ME do not implement the W functions + useWfuncs = (GetVersion() < 0x80000000); +} + +/*********************************** + */ + +class FileException : Exception +{ + + uint errno; // operating system error code + + this(char[] name) + { + this(name, "file I/O"); + } + + this(char[] name, char[] message) + { + super(name ~ ": " ~ message); + } + + this(char[] name, uint errno) + { + this(name, sysErrorString(errno)); + this.errno = errno; + } +} + +/*********************************** + * Basic File operations. + */ + +/******************************************** + * Read a file. + * Returns: + * array of bytes read + */ + +void[] read(char[] name) +{ + DWORD size; + DWORD numread; + HANDLE h; + byte[] buf; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + + if (h == INVALID_HANDLE_VALUE) + goto err1; + + size = GetFileSize(h, null); + if (size == INVALID_FILE_SIZE) + goto err2; + + buf = new byte[size]; + + if (ReadFile(h,buf,size,&numread,null) != 1) + goto err2; + + if (numread != size) + goto err2; + + if (!CloseHandle(h)) + goto err; + + return buf; + +err2: + CloseHandle(h); +err: + delete buf; +err1: + throw new FileException(name, GetLastError()); +} + +/********************************************* + * Write a file. + * Returns: + * 0 success + */ + +void write(char[] name, void[] buffer) +{ + HANDLE h; + DWORD numwritten; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + if (h == INVALID_HANDLE_VALUE) + goto err; + + if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) + goto err2; + + if (buffer.length != numwritten) + goto err2; + + if (!CloseHandle(h)) + goto err; + return; + +err2: + CloseHandle(h); +err: + throw new FileException(name, GetLastError()); +} + + +/********************************************* + * Append to a file. + */ + +void append(char[] name, void[] buffer) +{ + HANDLE h; + DWORD numwritten; + + if (useWfuncs) + { + wchar* namez = std.utf.toUTF16z(name); + h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + else + { + char* namez = toMBSz(name); + h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); + } + if (h == INVALID_HANDLE_VALUE) + goto err; + + SetFilePointer(h, 0, null, FILE_END); + + if (WriteFile(h,buffer,buffer.length,&numwritten,null) != 1) + goto err2; + + if (buffer.length != numwritten) + goto err2; + + if (!CloseHandle(h)) + goto err; + return; + +err2: + CloseHandle(h); +err: + throw new FileException(name, GetLastError()); +} + + +/*************************************************** + * Rename a file. + */ + +void rename(char[] from, char[] to) +{ + BOOL result; + + if (useWfuncs) + result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); + else + result = MoveFileA(toMBSz(from), toMBSz(to)); + if (!result) + throw new FileException(to, GetLastError()); +} + + +/*************************************************** + * Delete a file. + */ + +void remove(char[] name) +{ + BOOL result; + + if (useWfuncs) + result = DeleteFileW(std.utf.toUTF16z(name)); + else + result = DeleteFileA(toMBSz(name)); + if (!result) + throw new FileException(name, GetLastError()); +} + + +/*************************************************** + * Get file size. + */ + +ulong getSize(char[] name) +{ + HANDLE findhndl; + uint resulth; + uint resultl; + + if (useWfuncs) + { + WIN32_FIND_DATAW filefindbuf; + + findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); + resulth = filefindbuf.nFileSizeHigh; + resultl = filefindbuf.nFileSizeLow; + } + else + { + WIN32_FIND_DATA filefindbuf; + + findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); + resulth = filefindbuf.nFileSizeHigh; + resultl = filefindbuf.nFileSizeLow; + } + + if (findhndl == cast(HANDLE)-1) + { + throw new FileException(name, GetLastError()); + } + FindClose(findhndl); + return (cast(ulong)resulth << 32) + resultl; +} + +/*************************************************** + * Does file (or directory) exist? + */ + +int exists(char[] name) +{ + uint result; + + if (useWfuncs) + //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp+ result = GetFileAttributesW(std.utf.toUTF16z(name)); + else + result = GetFileAttributesA(toMBSz(name)); + + return (result == 0xFFFFFFFF) ? 0 : 1; +} + +/*************************************************** + * Get file attributes. + */ + +uint getAttributes(char[] name) +{ + uint result; + + if (useWfuncs) + result = GetFileAttributesW(std.utf.toUTF16z(name)); + else + result = GetFileAttributesA(toMBSz(name)); + if (result == 0xFFFFFFFF) + { + throw new FileException(name, GetLastError()); + } + return result; +} + +/**************************************************** + * Is name a file? + */ + +int isfile(char[] name) +{ + return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + +/**************************************************** + * Is name a directory? + */ + +int isdir(char[] name) +{ + return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +/**************************************************** + * Change directory. + */ + +void chdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); + else + result = SetCurrentDirectoryA(toMBSz(pathname)); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Make directory. + */ + +void mkdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); + else + result = CreateDirectoryA(toMBSz(pathname), null); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Remove directory. + */ + +void rmdir(char[] pathname) +{ BOOL result; + + if (useWfuncs) + result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); + else + result = RemoveDirectoryA(toMBSz(pathname)); + + if (!result) + { + throw new FileException(pathname, GetLastError()); + } +} + +/**************************************************** + * Get current directory. + */ + +char[] getcwd() +{ + if (useWfuncs) + { + wchar[] dir; + int len; + wchar c; + + len = GetCurrentDirectoryW(0, &c); + if (!len) + goto Lerr; + dir = new wchar[len]; + len = GetCurrentDirectoryW(len, dir); + if (!len) + goto Lerr; + return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 + } + else + { + char[] dir; + int len; + char c; + + len = GetCurrentDirectoryA(0, &c); + if (!len) + goto Lerr; + dir = new char[len]; + len = GetCurrentDirectoryA(len, dir); + if (!len) + goto Lerr; + return dir[0 .. len]; // leave off terminating 0 + } + +Lerr: + throw new FileException("getcwd", GetLastError()); +} + +/*************************************************** + * Return contents of directory. + */ + +char[][] listdir(char[] pathname) +{ + char[][] result; + + bool listing(char[] filename) + { + result ~= filename; + return true; // continue + } + + listdir(pathname, &listing); + return result; +} + +void listdir(char[] pathname, bool delegate(char[] filename) callback) +{ + char[] c; + HANDLE h; + + c = std.path.join(pathname, "*.*"); + if (useWfuncs) + { + WIN32_FIND_DATAW fileinfo; + + h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); + if (h != INVALID_HANDLE_VALUE) + { + do + { int clength; + + // Skip "." and ".." + if (std.string.wcscmp(fileinfo.cFileName, ".") == 0 || + std.string.wcscmp(fileinfo.cFileName, "..") == 0) + continue; + + clength = std.string.wcslen(fileinfo.cFileName); + // toUTF8() returns a new buffer + if (!callback(std.utf.toUTF8(fileinfo.cFileName[0 .. clength]))) + break; + } while (FindNextFileW(h,&fileinfo) != FALSE); + FindClose(h); + } + } + else + { + WIN32_FIND_DATA fileinfo; + + h = FindFirstFileA(toMBSz(c), &fileinfo); + if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? + { + do + { int clength; + wchar[] wbuf; + int n; + + // Skip "." and ".." + if (std.string.strcmp(fileinfo.cFileName, ".") == 0 || + std.string.strcmp(fileinfo.cFileName, "..") == 0) + continue; + + clength = std.string.strlen(fileinfo.cFileName); + + // Convert cFileName[] to unicode + wbuf.length =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,null,0);+ n =MultiByteToWideChar(0,0,fileinfo.cFileName,clength,cast(wchar*)wbuf,wbuf.len gth);+ assert(n == wbuf.length); + // toUTF8() returns a new buffer + if (!callback(std.utf.toUTF8(wbuf))) + break; + } while (FindNextFileA(h,&fileinfo) != FALSE); + FindClose(h); + } + } +} + +/****************************************** + * Since Win 9x does not support the "W" API's, first convert + * to wchar, then convert to multibyte using the current code + * page. + * (Thanks to yaneurao for this) + */ + +char* toMBSz(char[] s) +{ + // Only need to do this if any chars have the high bit set + foreach (char c; s) + { + if (c >= 0x80) + { char[] result; + int i; + wchar* ws = std.utf.toUTF16z(s); + result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null,null);+ i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null,null);+ assert(i == result.length); + return result; + } + } + return std.string.toStringz(s); +} + + +/*************************************************** + * Copy a file. + */ + +void copy(char[] from, char[] to) +{ + BOOL result; + + if (useWfuncs) + result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); + else + result = CopyFileA(toMBSz(from), toMBSz(to), false); + if (!result) + throw new FileException(to, GetLastError()); +} + + +} + +/* =========================== linux ======================= */ + +version (linux) +{ + +private import std.c.linux.linux; + +extern (C) char* strerror(int); +extern(C) int access(char *, int); +/*********************************** + */ + +class FileException : Exception +{ + + uint errno; // operating system error code + + this(char[] name) + { + this(name, "file I/O"); + } + + this(char[] name, char[] message) + { + super(name ~ ": " ~ message); + } + + this(char[] name, uint errno) + { char* s = strerror(errno); + this(name, std.string.toString(s).dup); + this.errno = errno; + } +} + +/******************************************** + * Read a file. + * Returns: + * array of bytes read + */ + +void[] read(char[] name) +{ + uint size; + uint numread; + int fd; + struct_stat statbuf; + byte[] buf; + char *namez; + + namez = toStringz(name); + //printf("file.read('%s')\n",namez); + fd = std.c.linux.linux.open(namez, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + size = statbuf.st_size; + buf = new byte[size]; + + numread = std.c.linux.linux.read(fd, cast(char*)buf, size); + if (numread != size) + { + //printf("\tread error, errno = %d\n",getErrno()); + goto err2; + } + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err; + } + + return buf; + +err2: + std.c.linux.linux.close(fd); +err: + delete buf; + +err1: + throw new FileException(name, getErrno()); +} + +/********************************************* + * Write a file. + * Returns: + * 0 success + */ + +void write(char[] name, void[] buffer) +{ + int fd; + int numwritten; + char *namez; + + namez = toStringz(name); + fd = std.c.linux.linux.open(namez, O_CREAT | O_WRONLY | O_TRUNC,0660);+ if (fd == -1) + goto err; + + numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); + if (buffer.length != numwritten) + goto err2; + + if (std.c.linux.linux.close(fd) == -1) + goto err; + + return; + +err2: + std.c.linux.linux.close(fd); +err: + throw new FileException(name, getErrno()); +} + + +/********************************************* + * Append to a file. + */ + +void append(char[] name, void[] buffer) +{ + int fd; + int numwritten; + char *namez; + + namez = toStringz(name); + fd = std.c.linux.linux.open(namez, O_APPEND | O_WRONLY | O_CREAT,0660);+ if (fd == -1) + goto err; + + numwritten = std.c.linux.linux.write(fd, buffer, buffer.length); + if (buffer.length != numwritten) + goto err2; + + if (std.c.linux.linux.close(fd) == -1) + goto err; + + return; + +err2: + std.c.linux.linux.close(fd); +err: + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Rename a file. + */ + +void rename(char[] from, char[] to) +{ + char *fromz = toStringz(from); + char *toz = toStringz(to); + + if (std.c.stdio.rename(fromz, toz) == -1) + throw new FileException(to, getErrno()); +} + + +/*************************************************** + * Delete a file. + */ + +void remove(char[] name) +{ + if (std.c.stdio.remove(toStringz(name)) == -1) + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Get file size. + */ + +ulong getSize(char[] name) +{ + uint size; + int fd; + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + //printf("file.getSize('%s')\n",namez); + fd = std.c.linux.linux.open(namez, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + size = statbuf.st_size; + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err; + } + + return size; + +err2: + std.c.linux.linux.close(fd); +err: +err1: + throw new FileException(name, getErrno()); +} + + +/*************************************************** + * Get file attributes. + */ + +uint getAttributes(char[] name) +{ + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + if (std.c.linux.linux.stat(namez, &statbuf)) + { + throw new FileException(name, getErrno()); + } + + return statbuf.st_mode; +} + +/**************************************************** + * Does file/directory exist? + */ + +int exists(char[] name) +{ + if(access(toStringz(name),0)) + return 0; + else + return 1; +} + +/**************************************************** + * Is name a file? + */ + +int isfile(char[] name) +{ + return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file +} + +/**************************************************** + * Is name a directory? + */ + +int isdir(char[] name) +{ + return (getAttributes(name) & S_IFMT) == S_IFDIR; +} + +/**************************************************** + * Change directory. + */ + +void chdir(char[] pathname) +{ + if (std.c.linux.linux.chdir(toStringz(pathname))) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Make directory. + */ + +void mkdir(char[] pathname) +{ + if (std.c.linux.linux.mkdir(toStringz(pathname), 0777)) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Remove directory. + */ + +void rmdir(char[] pathname) +{ + if (std.c.linux.linux.rmdir(toStringz(pathname))) + { + throw new FileException(pathname, getErrno()); + } +} + +/**************************************************** + * Get current directory. + */ + +char[] getcwd() +{ char* p; + + p = std.c.linux.linux.getcwd(null, 0); + if (!p) + { + throw new FileException("cannot get cwd", getErrno()); + } + + size_t len = std.string.strlen(p); + char[] buf = new char[len]; + buf[] = p[0 .. len]; + std.c.stdlib.free(p); + return buf; +} + +/*************************************************** + * Return contents of directory. + */ + +char[][] listdir(char[] pathname) +{ + char[][] result; + + bool listing(char[] filename) + { + result ~= filename; + return true; // continue + } + + listdir(pathname, &listing); + return result; +} + +void listdir(char[] pathname, bool delegate(char[] filename) callback) +{ + DIR* h; + dirent* fdata; + + h = opendir(toStringz(pathname)); + if (h) + { + while((fdata = readdir(h)) != null) + { + // Skip "." and ".." + if (!std.string.strcmp(fdata.d_name, ".") || + !std.string.strcmp(fdata.d_name, "..")) + continue; + + int len = std.string.strlen(fdata.d_name); + if (!callback(fdata.d_name[0 .. len].dup)) + break; + } + closedir(h); + } + else + { + throw new FileException(pathname, getErrno()); + } +} + +/*************************************************** + * Copy a file. + */ + +void copy(char[] from, char[] to) +{ + void[] buffer; + + /* If the file is very large, this won't work, but + * it's a good start. + * BUG: it should maintain the file timestamps + */ + buffer = read(from); + write(to, buffer); + delete buffer; +} + + + +} +
Jul 07 2005
James Dunne wrote:Congratulations, you've defeated the purpose of the patch/diff utility :).Seriously, do make sure that the line endings match on both files... Most of the DMD files come with DOS line endings (i.e. \r\n) so they need to be converted first - before doing diff/patch. Maybe this is a good time to renew the request for a .tar.gz ? ;-) --anders
Jul 07 2005








=?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se>