\r
// Author: Andy Rushton\r
// Copyright: (c) Southampton University 1999-2004\r
-// (c) Andy Rushton 2004-2009\r
+// (c) Andy Rushton 2004 onwards\r
// License: BSD License, see ../docs/license.html\r
\r
// This is a portable interface to the file system.\r
#include <direct.h>\r
#include <fcntl.h>\r
#include <io.h>\r
-#include <sys/stat.h>\r
#include <sys/types.h>\r
+#include <sys/stat.h>\r
#else\r
#include <dirent.h>\r
#include <fcntl.h>\r
#include <sys/param.h>\r
#include <unistd.h>\r
-#include <sys/stat.h>\r
#include <sys/types.h>\r
+#include <sys/stat.h>\r
#endif\r
\r
////////////////////////////////////////////////////////////////////////////////\r
////////////////////////////////////////////////////////////////////////////////\r
// classifying functions\r
\r
+// Under both Windows and Unix, the stat function is used for classification\r
+\r
+// Under Linux, the following classifications are defined\r
+// source: Linux man page for stat(2) http://linux.die.net/man/2/stat\r
+// S_IFMT 0170000 bitmask for the file type bitfields\r
+// S_IFSOCK 0140000 socket (Note this overlaps with S_IFDIR)\r
+// S_IFLNK 0120000 symbolic link\r
+// S_IFREG 0100000 regular file\r
+// S_IFBLK 0060000 block device\r
+// S_IFDIR 0040000 directory\r
+// S_IFCHR 0020000 character device\r
+// S_IFIFO 0010000 FIFO\r
+// There are also some Posix-standard macros:\r
+// S_ISREG(m) is it a regular file? \r
+// S_ISDIR(m) directory? \r
+// S_ISCHR(m) character device? \r
+// S_ISBLK(m) block device? \r
+// S_ISFIFO(m) FIFO (named pipe)? \r
+// S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) \r
+// S_ISSOCK(m) socket? (Not in POSIX.1-1996.)\r
+// Under Windows, the following are defined:\r
+// source: Header file sys/stat.h distributed with Visual Studio 10\r
+// _S_IFMT (S_IFMT) 0xF000 file type mask\r
+// _S_IFREG (S_IFREG) 0x8000 regular\r
+// _S_IFDIR (S_IFDIR) 0x4000 directory\r
+// _S_IFCHR (S_IFCHR) 0x2000 character special\r
+// _S_IFIFO 0x1000 pipe\r
+\r
#ifdef MSWINDOWS\r
// file type tests are not defined for some reason on Windows despite them providing the stat() function!\r
#define R_OK 4\r
#define W_OK 2\r
+// Posix-style macros for Windows\r
+#ifndef S_ISREG\r
+#define S_ISREG(mode) ((mode & _S_IFMT) == _S_IFREG)\r
+#endif\r
+#ifndef S_ISDIR\r
+#define S_ISDIR(mode) ((mode & _S_IFMT) == _S_IFDIR)\r
+#endif\r
+#ifndef S_ISCHR\r
+#define S_ISCHR(mode) ((mode & _S_IFMT) == _S_IFCHR)\r
+#endif\r
+#ifndef S_ISBLK\r
+#define S_ISBLK(mode) (false)\r
+#endif\r
+#ifndef S_ISFIFO\r
+#define S_ISFIFO(mode) ((mode & _S_IFMT) == _S_IFIFO)\r
+#endif\r
+#ifndef S_ISLNK\r
+#define S_ISLNK(mode) (false)\r
+#endif\r
+#ifndef S_ISSOCK\r
+#define S_ISSOCK(mode) (false)\r
+#endif\r
#endif\r
\r
bool is_present (const std::string& thing)\r
path.erase(path.size()-1,1);\r
// now test if this thing exists using the built-in stat function and if so, is it a folder\r
struct stat buf;\r
- if (!(stat(path.c_str(), &buf) == 0)) {return false;}\r
- return (buf.st_mode & S_IFDIR) != 0;\r
+ if (!(stat(path.c_str(), &buf) == 0))\r
+ return false;\r
+ // If the object is present, see if it is a directory\r
+ // this is the Posix-approved way of testing\r
+ return S_ISDIR(buf.st_mode);\r
}\r
\r
bool is_file (const std::string& thing)\r
path.erase(path.size()-1,1);\r
// now test if this thing exists using the built-in stat function and if so, is it a file\r
struct stat buf;\r
- if (!(stat(path.c_str(), &buf) == 0)) {return false;}\r
- return (buf.st_mode & S_IFREG) != 0;\r
+ if (!(stat(path.c_str(), &buf) == 0))\r
+ return false;\r
+ // If the object is present, see if it is a file or file-like object\r
+ // Note that devices are neither folders nor files\r
+ // this is the Posix-approved way of testing\r
+ return S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode) || S_ISSOCK(buf.st_mode) || S_ISFIFO(buf.st_mode);\r
}\r
\r
////////////////////////////////////////////////////////////////////////////////\r
\r
bool file_writable (const std::string& filespec)\r
{\r
- // a file is writable if it exists as a file and is writable or if it doesn't exist but could be created and would be writable\r
+ // a file is writable if it exists as a file and is writable or if\r
+ // it doesn't exist but could be created and would be writable\r
if (is_present(filespec))\r
{\r
if (!is_file(filespec)) return false;\r
return std::string(_fullpath(abspath, ".", MAX_PATH+1));\r
#else\r
char pathname [MAXPATHLEN+1];\r
- getcwd(pathname,MAXPATHLEN+1);\r
- return std::string(pathname);\r
+ char* result = getcwd(pathname,MAXPATHLEN+1);\r
+ if (!result)\r
+ {\r
+ // should really report the error from errno\r
+ return std::string();\r
+ }\r
+ return std::string(result);\r
#endif\r
}\r
\r