From 71e9b7e35835613e95a5894ff4ad7949c0e716a8 Mon Sep 17 00:00:00 2001 From: AlistairGrant Date: Sun, 30 Sep 2018 07:34:59 +0200 Subject: [PATCH] FileAttributesPlugin: restructure platform support files Restructure FileAttributesPlugin to move platform specific functionality out to separate files. This is required as Windows requires the "wide" versions of posix functions to be used, e.g. access() vs. _waccess(), while other seem to require the Windows native functions, e.g. iterating over directories, and interleaving #ifdef _WIN32 was becoming unwieldy. --- .../plugins/FileAttributesPlugin/faCommon.c | 36 + .../plugins/FileAttributesPlugin/faPlugin.h | 10 + .../plugins/FileAttributesPlugin/faSupport.c | 514 +++++++++-- .../plugins/FileAttributesPlugin/faSupport.h | 65 +- .../plugins/FileAttributesPlugin/faSupport.c | 663 ++++++++++++-- .../plugins/FileAttributesPlugin/faSupport.h | 60 +- .../FileAttributesPlugin.c | 846 ++++-------------- 7 files changed, 1397 insertions(+), 797 deletions(-) create mode 100644 platforms/Cross/plugins/FileAttributesPlugin/faCommon.c create mode 100644 platforms/Cross/plugins/FileAttributesPlugin/faPlugin.h diff --git a/platforms/Cross/plugins/FileAttributesPlugin/faCommon.c b/platforms/Cross/plugins/FileAttributesPlugin/faCommon.c new file mode 100644 index 0000000000..48590073cc --- /dev/null +++ b/platforms/Cross/plugins/FileAttributesPlugin/faCommon.c @@ -0,0 +1,36 @@ +/* + * faCommon.c + * + * Provides a number of platform independent functions. + */ + +#include "sq.h" +#include "faSupport.h" + +extern struct VirtualMachine * interpreterProxy; + + +sqInt faSetStDirOop(fapath *aFaPath, sqInt pathNameOop) +{ +int len; +char *pathName; + + + len = interpreterProxy->stSizeOf(pathNameOop); + pathName = interpreterProxy->arrayValueOf(pathNameOop); + return faSetStDir(aFaPath, pathName, len); +} + + + +sqInt faSetStPathOop(fapath *aFaPath, sqInt pathNameOop) +{ +int len; +char *pathName; + + + len = interpreterProxy->stSizeOf(pathNameOop); + pathName = interpreterProxy->arrayValueOf(pathNameOop); + return faSetStPath(aFaPath, pathName, len); +} + diff --git a/platforms/Cross/plugins/FileAttributesPlugin/faPlugin.h b/platforms/Cross/plugins/FileAttributesPlugin/faPlugin.h new file mode 100644 index 0000000000..85144c76f2 --- /dev/null +++ b/platforms/Cross/plugins/FileAttributesPlugin/faPlugin.h @@ -0,0 +1,10 @@ +/* + * faPlugin.h + * + * Declarations of routines generated by the plugin and used by the platform + * support routines. + */ + + +sqInt byteArrayFromCStringto(const char *aCString, sqInt *byteArrayOop); + diff --git a/platforms/unix/plugins/FileAttributesPlugin/faSupport.c b/platforms/unix/plugins/FileAttributesPlugin/faSupport.c index 2b1d04237f..d10f01f862 100644 --- a/platforms/unix/plugins/FileAttributesPlugin/faSupport.c +++ b/platforms/unix/plugins/FileAttributesPlugin/faSupport.c @@ -3,11 +3,230 @@ * * Author: akgrant@gmail.com */ -#include #include +#include +#include +#include #include "sq.h" #include "faSupport.h" +#include "faPlugin.h" + +extern struct VirtualMachine * interpreterProxy; + + +sqInt faSetStDir(fapath *aFaPath, char *pathName, int len) +{ +sqInt status; + + /* Set the St encoded path and ensure trailing delimiter */ + if (len+1 >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + memcpy(aFaPath->path, pathName, len); + if (aFaPath->path[len-1] != PATH_SEPARATOR) + aFaPath->path[len++] = PATH_SEPARATOR; + aFaPath->path[len] = 0; + aFaPath->path_len = len; + aFaPath->path_file = aFaPath->path + len; + aFaPath->max_file_len = FA_PATH_MAX - len; + + /* Convert to platform specific form */ + status = sq2uxPath(aFaPath->path, len, aFaPath->uxpath, FA_PATH_MAX, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->uxpath_len = strlen(aFaPath->uxpath); + aFaPath->uxpath_file = aFaPath->uxpath + aFaPath->uxpath_len; + aFaPath->uxmax_file_len = FA_PATH_MAX - aFaPath->uxpath_len; + + return 0; +} + + + +sqInt faSetStPath(fapath *aFaPath, char *pathName, int len) +{ +sqInt status; + + /* Set the St encoded path */ + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + memcpy(aFaPath->path, pathName, len); + aFaPath->path[len] = 0; + aFaPath->path_len = len; + aFaPath->path_file = 0; + aFaPath->max_file_len = 0; + + /* Convert to platform specific form */ + status = sq2uxPath(aFaPath->path, len, aFaPath->uxpath, FA_PATH_MAX, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->uxpath_len = strlen(aFaPath->uxpath); + aFaPath->uxpath_file = 0; + aFaPath->uxmax_file_len = 0; + + return 0; +} + + + +sqInt faSetStFile(fapath *aFaPath, char *pathName) +{ +int len; +sqInt status; + + assert(aFaPath->path_file != 0); + /* Set the St encoded path */ + len = strlen(pathName); + if (len >= aFaPath->max_file_len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + strcpy(aFaPath->path_file, pathName); + + /* Convert to platform specific form */ + status = sq2uxPath(aFaPath->path_file, len, aFaPath->uxpath_file, aFaPath->uxmax_file_len, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + + return 0; +} + + + +sqInt faSetPlatPath(fapath *aFaPath, char *pathName) +{ +int len; +sqInt status; + + /* Set the platform encoded path */ + len = strlen(pathName); + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + strcpy(aFaPath->uxpath, pathName); + aFaPath->uxpath[len] = 0; + aFaPath->uxpath_len = len; + aFaPath->uxpath_file = 0; + aFaPath->uxmax_file_len = 0; + + /* Convert to St specific form */ + status = ux2sqPath(aFaPath->uxpath, len, aFaPath->path, FA_PATH_MAX, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->path_len = strlen(aFaPath->path); + aFaPath->path_file = 0; + aFaPath->max_file_len = 0; + + return 0; +} + + + +sqInt faSetPlatPathOop(fapath *aFaPath, sqInt pathNameOop) +{ +int len; +char *bytePtr; +sqInt status; + + len = interpreterProxy->stSizeOf(pathNameOop); + bytePtr = interpreterProxy->arrayValueOf(pathNameOop); + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + memcpy(aFaPath->uxpath, bytePtr, len); + aFaPath->uxpath[len] = 0; + aFaPath->uxpath_len = len; + aFaPath->uxpath_file = 0; + aFaPath->uxmax_file_len = 0; + + /* Convert to St specific form */ + status = ux2sqPath(aFaPath->uxpath, len, aFaPath->path, FA_PATH_MAX, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->path_len = strlen(aFaPath->path); + aFaPath->path_file = 0; + aFaPath->max_file_len = 0; + + return 0; +} + + + +sqInt faSetPlatFile(fapath *aFaPath, char *pathName) +{ +int len; +sqInt status; + + assert(aFaPath->uxpath_file != 0); + /* Set the platform encoded file name */ + len = strlen(pathName); + if (len >= aFaPath->uxmax_file_len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + strcpy(aFaPath->uxpath_file, pathName); + + /* Convert to St specific form */ + status = ux2sqPath(aFaPath->uxpath_file, len, aFaPath->path_file, aFaPath->max_file_len, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + + return 0; +} + + + + +/* + * Convert the supplied Unix (UTC) time to Squeak time. + * Squeak time has an epoch of 1901 and uses local time + * i.e. timezone + daylight savings + * + * Answer an sqLong which is guaranteed to be 64 bits on all platforms. + */ +sqLong faConvertUnixToLongSqueakTime(time_t unixTime) +{ +sqLong squeakTime; + + squeakTime = unixTime; +#if defined(HAVE_TM_GMTOFF) + squeakTime = squeakTime + localtime(&unixTime)->tm_gmtoff; +#elif defined(HAVE_TIMEZONE) + squeakTime = squeakTime + (daylight*60*60) - timezone; +#else + #error: cannot determine timezone correction +#endif + /* Squeak epoch is Jan 1, 1901. Unix epoch is Jan 1, 1970: 17 leap years + * and 52 non-leap years later than Squeak. */ + squeakTime = squeakTime + + (52*365UL + 17*366UL) * 24*60*60UL; + return squeakTime; +} + + + +/* + * pathNameToOop + * + * Convert the supplied platform encoded C string to a + * precomposed UTF8 ByteArray. + */ +sqInt pathNameToOop(char *pathName) +{ +sqInt pathOop; +int status; +int len; +char uxName[FA_PATH_MAX]; + + len = strlen(pathName); + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + status = ux2sqPath(pathName, len, uxName, FA_PATH_MAX, 1); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_INVALID_ARGUMENTS); + status = byteArrayFromCStringto(uxName, &pathOop); + if (status) + return interpreterProxy->primitiveFailForOSError(status); + return pathOop; +} @@ -23,22 +242,14 @@ * If there are no entries, close the directory and return FA_NO_MORE_DATA */ -sqInt faOpenDirectory(osdir *dirState) +sqInt faOpenDirectory(fapath *aFaPath) { -sqInt pathLength; -sqInt status; -DIR *dir; - - -/* Open the directory */ -dir = opendir(dirState->path); -if (dir == NULL) - return FA_CANT_OPEN_DIR; + /* Open the directory */ + aFaPath->platformDir = opendir(faGetPlatPath(aFaPath)); + if (aFaPath->platformDir == NULL) + return FA_CANT_OPEN_DIR; -dirState->platformDir = (void *)dir; -fprintf(stderr, "faOpenDirectory: osdir * %p, DIR * %p\n", dirState, dir); -fflush(stderr); -return faReadDirectory(dirState); + return faReadDirectory(aFaPath); } @@ -52,63 +263,256 @@ return faReadDirectory(dirState); * If there are no entries, return FA_NO_MORE_DATA */ -sqInt faReadDirectory(osdir *dirState) +sqInt faReadDirectory(fapath *aFaPath) { -sqInt haveEntry; +sqInt haveEntry; struct dirent *entry; -sqInt entry_length; -DIR *dirPtr; -sqInt status; - -dirPtr = (DIR *)dirState->platformDir; -fprintf(stderr, "faReadDirectory: osdir * %p, DIR * %p\n", dirState, dirPtr); -fflush(stderr); -haveEntry = 0; -errno = 0; -do { - entry = readdir(dirPtr); - if (entry == NULL) - if (errno == 0) - return FA_NO_MORE_DATA; - else - return FA_CANT_READ_DIR; - if ((!(entry->d_name[0] == '.' && entry->d_name[1] == 0)) && strcmp(entry->d_name, "..")) - haveEntry = 1; -} while (!haveEntry); - -entry_length = strlen(entry->d_name); -if (entry_length > dirState->max_file_len) - return FA_STRING_TOO_LONG; +sqInt status; -fprintf(stderr, "read: %s\n", entry->d_name); -fflush(stderr); + haveEntry = 0; + errno = 0; + do { + entry = readdir(aFaPath->platformDir); + if (entry == NULL) { + if (errno == 0) + return FA_NO_MORE_DATA; + else + return FA_CANT_READ_DIR; } + if ((!(entry->d_name[0] == '.' && entry->d_name[1] == 0)) && strcmp(entry->d_name, "..")) + haveEntry = 1; + } while (!haveEntry); -strncpy(dirState->path_file, entry->d_name, dirState->max_file_len); + status = faSetPlatFile(aFaPath, entry->d_name); + if (status) return status; -return FA_SUCCESS; + return FA_SUCCESS; } /* - * faCloseDirectory(void *dirStateId) + * faCloseDirectory * * Close the supplied directory. */ -sqInt faCloseDirectory(osdir *dirState) +sqInt faCloseDirectory(fapath *aFaPath) { -DIR *dirPtr; -sqInt status; + sqInt status; -dirPtr = (DIR *)dirState->platformDir; -fprintf(stderr, "faCloseDirectory: osdir * %p, DIR * %p\n", dirState, dirPtr); -fflush(stderr); -status = closedir(dirPtr); -if (status) return FA_UNABLE_TO_CLOSE_DIR; -dirState->platformDir = 0; + status = closedir(aFaPath->platformDir); + if (status) return FA_UNABLE_TO_CLOSE_DIR; + aFaPath->platformDir = 0; -return FA_SUCCESS; + return FA_SUCCESS; } + +/* + * faFileAttribute + * + * Answer a single attribute (OOP) for the supplied file name. + * + * Set the interpreterProxy primitiveFailure flag on error. + * + * The attributeNumber has previously been validated. + * + * See FileAttributesPlugin>>primitiveFileAttribute for the list of attribute + * numbers. + */ +sqInt faFileAttribute(fapath *aFaPath, sqInt attributeNumber) +{ +faStatStruct statBuf; +int status; +sqInt resultOop = 0; +int mode; + + + if (attributeNumber <= 12) { + /* Requested attribute comes from stat() entry */ + status = stat(faGetPlatPath(aFaPath), &statBuf); + if (status) + return interpreterProxy->primitiveFailForOSError(FA_CANT_STAT_PATH); + + switch (attributeNumber) { + + case 1: /* fileName, not supported for a single attribute */ + resultOop = interpreterProxy->nilObject(); + break; + + case 2: /* Mode */ + resultOop = interpreterProxy->positive32BitIntegerFor(statBuf.st_mode); + break; + + case 3: /* inode */ + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_ino); + break; + + case 4: /* device id */ + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_dev); + break; + + case 5: /* nlink */ + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_nlink); + break; + + case 6: /* uid */ + resultOop = interpreterProxy->positive32BitIntegerFor(statBuf.st_uid); + break; + + case 7: /* gid */ + resultOop = interpreterProxy->positive32BitIntegerFor(statBuf.st_gid); + break; + + case 8: /* size (if file) */ + if (S_ISDIR(statBuf.st_mode) == 0) + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_size); + else + resultOop = interpreterProxy->positive32BitIntegerFor(0); + break; + + case 9: /* access time */ + resultOop = interpreterProxy->signed64BitIntegerFor( + faConvertUnixToLongSqueakTime(statBuf.st_atime)); + break; + + case 10: /* modified time */ + resultOop = interpreterProxy->signed64BitIntegerFor( + faConvertUnixToLongSqueakTime(statBuf.st_mtime)); + break; + + case 11: /* change time */ + resultOop = interpreterProxy->signed64BitIntegerFor( + faConvertUnixToLongSqueakTime(statBuf.st_ctime)); + break; + + case 12: /* creation time */ + resultOop = interpreterProxy->nilObject(); + break; + } + } else if (attributeNumber < 16) { + switch (attributeNumber) { + case 13: + mode = R_OK; + break; + + case 14: + mode = W_OK; + break; + + case 15: + mode = X_OK; + break; + } + if (access(faGetPlatPath(aFaPath), mode) == 0) + resultOop = interpreterProxy->trueObject(); + else + resultOop = interpreterProxy->falseObject(); + } else if (attributeNumber == 16) { + /* isSymlink */ + status = lstat(faGetPlatPath(aFaPath), &statBuf); + if (status) + return interpreterProxy->primitiveFailForOSError(FA_CANT_STAT_PATH); + if (S_ISLNK(statBuf.st_mode)) + resultOop = interpreterProxy->trueObject(); + else + resultOop = interpreterProxy->falseObject(); + } + + return resultOop; +} + + + +/* + * faStat + * + * Populate the supplied stat buffer. + * + * fileNameOop only applies to symbolic links, answer nil. + */ +sqInt faStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop) +{ +int status; + + status = stat(faGetPlatPath(aFaPath), statBuf); + if (status) return FA_CANT_STAT_PATH; + fileNameOop[0] = interpreterProxy->nilObject(); + return 0; +} + + + +/* + * faLinkStat + * + * Populate the supplied stat buffer with symbolic link information + */ +sqInt faLinkStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop) +{ +int status; +char targetFile[FA_PATH_MAX]; + + status = lstat(faGetPlatPath(aFaPath), statBuf); + if (status) return FA_CANT_STAT_PATH; + if (S_ISLNK(statBuf->st_mode)) { + /* This is a symbolic link, provide the target filename */ + status = readlink(faGetPlatPath(aFaPath), targetFile, FA_PATH_MAX); + if (status < 0) return FA_CANT_READ_LINK; + *fileNameOop = pathNameToOop(targetFile); + if (interpreterProxy->failed()) + return interpreterProxy->primitiveFailureCode(); + } else { + fileNameOop[0] = interpreterProxy->nilObject(); + } + return 0; +} + + +/* + * faExists + * + * Answer a boolean indicating whether the supplied path name exists. + */ +sqInt faExists(fapath *aFaPath) +{ +int status; + + if (access(faGetPlatPath(aFaPath), F_OK)) + return interpreterProxy->falseObject(); + else + return interpreterProxy->trueObject(); +} + + + +/* + * faAccessAttributes + * + * Call access() for each access type (R, W, X) on the supplied path, + * storing the results in the st array attributeArray. + */ +sqInt faAccessAttributes(fapath *aFaPath, sqInt attributeArray, sqInt offset) +{ +sqInt index; +sqInt trueOop; +sqInt falseOop; +sqInt accessOop; + + + index = offset; + trueOop = interpreterProxy->trueObject(); + falseOop = interpreterProxy->falseObject(); + + accessOop = access(faGetPlatPath(aFaPath), R_OK) ? falseOop : trueOop; + interpreterProxy->storePointerofObjectwithValue(index++, attributeArray, accessOop); + + accessOop = access(faGetPlatPath(aFaPath), W_OK) ? falseOop : trueOop; + interpreterProxy->storePointerofObjectwithValue(index++, attributeArray, accessOop); + + accessOop = access(faGetPlatPath(aFaPath), X_OK) ? falseOop : trueOop; + interpreterProxy->storePointerofObjectwithValue(index++, attributeArray, accessOop); + + return 0; +} diff --git a/platforms/unix/plugins/FileAttributesPlugin/faSupport.h b/platforms/unix/plugins/FileAttributesPlugin/faSupport.h index a69224eaf1..678a4b64af 100644 --- a/platforms/unix/plugins/FileAttributesPlugin/faSupport.h +++ b/platforms/unix/plugins/FileAttributesPlugin/faSupport.h @@ -1,10 +1,21 @@ +#include +#include +# include "sqUnixCharConv.h" /* REQUIRED: c file must have included standard squeak definitions */ #include "faConstants.h" + +/* Maximum path length allowed on this platform */ +#define FA_PATH_MAX PATH_MAX +#define PATH_SEPARATOR '/' + +typedef struct stat faStatStruct; + + /* - * typedef osdir + * typedef fapath * * This holds the current state for retrieving all the children of a * directory. @@ -12,25 +23,55 @@ * The directory (path) being enumerated and the current file name are stored * in a single string (path) to simplify stat()ing the file. * - * platformDir - platform specific data for directory enumeration. * path_len - length of the name of the path being enumerated. - * path_file - points to the file name of the current entry. + * path - The directory name being enumerated, with precomposed UTF8 + * encoding. + * platformDir - platform specific data for directory enumeration. + * uxpath - The directory name being enumerated in platform specific encoding + * Linux: precomposed UTF8 + * OSX: HFS decomposed UTF8 + * uxpath_file - points to the file name of the current entry. * This is set to the byte after the directory name * and is used to stat() each file. * max_file_len - The space remaining after the path for the file name. - * path - The directory name being enumerated, with platform specific - * encoding. */ -typedef struct dirptrstruct { - void *platformDir; +typedef struct fapathstruct { + char path[FA_PATH_MAX]; sqInt path_len; char *path_file; sqInt max_file_len; - char path[PATH_MAX+4]; - } osdir; + char uxpath[FA_PATH_MAX]; + sqInt uxpath_len; + char *uxpath_file; + sqInt uxmax_file_len; + + DIR *platformDir; + } fapath; + +sqInt faSetStDir(fapath *aFaPath, char *pathName, int len); +sqInt faSetStDirOop(fapath *aFaPath, sqInt pathNameOop); +sqInt faSetStPath(fapath *aFaPath, char *pathName, int len); +sqInt faSetStPathOop(fapath *aFaPath, sqInt pathNameOop); +sqInt faSetStFile(fapath *aFaPath, char *pathName); +sqInt faSetPlatPath(fapath *aFaPath, char *pathName); +sqInt faSetPlatPathOop(fapath *aFaPath, sqInt pathNameOop); +sqInt faSetPlatFile(fapath *aFaPath, char *pathName); +#define faGetStPath(aFaPath) aFaPath->path +#define faGetStPathLen(aFaPath) aFaPath->path_len +#define faGetStFile(aFaPath) aFaPath->path_file +#define faGetPlatPath(aFaPath) aFaPath->uxpath +#define faGetPlatFile(aFaPath) aFaPath->uxpath_file +#define faGetPlatPathByteCount(aFaPath) (aFaPath->uxpath_len * sizeof(char)) + +sqLong faConvertUnixToLongSqueakTime(time_t unixTime); -sqInt faOpenDirectory(osdir *dirState); -sqInt faReadDirectory(osdir *dirState); -sqInt faCloseDirectory(osdir *dirState); +sqInt faOpenDirectory(fapath *aFaPath); +sqInt faReadDirectory(fapath *aFaPath); +sqInt faCloseDirectory(fapath *aFaPath); +sqInt faFileAttribute(fapath *aFaPath, sqInt attributeNumber); +sqInt faStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop); +sqInt faLinkStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop); +sqInt faExists(fapath *aFaPath); +sqInt faAccessAttributes(fapath *aFaPath, sqInt attributeArray, sqInt offset); diff --git a/platforms/win32/plugins/FileAttributesPlugin/faSupport.c b/platforms/win32/plugins/FileAttributesPlugin/faSupport.c index fe4d6b66f4..d2765a6139 100644 --- a/platforms/win32/plugins/FileAttributesPlugin/faSupport.c +++ b/platforms/win32/plugins/FileAttributesPlugin/faSupport.c @@ -3,49 +3,368 @@ * * Author: akgrant@gmail.com */ -#include +#include +#include +#include +#include #include "sq.h" #include "faSupport.h" +#include "faPlugin.h" +extern struct VirtualMachine * interpreterProxy; +sqInt faSetStDir(fapath *aFaPath, char *pathName, int len) +{ +sqInt status; + + /* Set the St encoded path and ensure trailing delimiter */ + if (len+1 >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + memcpy(aFaPath->path, pathName, len); + if (aFaPath->path[len-1] != PATH_SEPARATOR) + aFaPath->path[len++] = PATH_SEPARATOR; + aFaPath->path[len] = 0; + aFaPath->path_len = len; + aFaPath->path_file = aFaPath->path + len; + aFaPath->max_file_len = FA_PATH_MAX - len; + + /* Convert to platform specific form + Include the \\?\ prefix to allow long path names */ + aFaPath->winpath[0] = L'\\'; + aFaPath->winpath[1] = L'\\'; + aFaPath->winpath[2] = L'?'; + aFaPath->winpath[3] = L'\\'; + status = MultiByteToWideChar(CP_UTF8, 0, + aFaPath->path, -1, + aFaPath->winpath+4, FA_PATH_MAX); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->winpath2 = aFaPath->winpath+4; + aFaPath->winpath_len = wcslen(aFaPath->winpath); + aFaPath->winpath_file = aFaPath->winpath + aFaPath->winpath_len; + aFaPath->winmax_file_len = FA_PATH_MAX - aFaPath->winpath_len; + + return 0; +} + + + +sqInt faSetStPath(fapath *aFaPath, char *pathName, int len) +{ +sqInt status; + + /* Set the St encoded path */ + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + memcpy(aFaPath->path, pathName, len); + aFaPath->path[len] = 0; + aFaPath->path_len = len; + aFaPath->path_file = 0; + aFaPath->max_file_len = 0; + + /* Convert to platform specific form + Include the \\?\ prefix to allow long path names */ + aFaPath->winpath[0] = L'\\'; + aFaPath->winpath[1] = L'\\'; + aFaPath->winpath[2] = L'?'; + aFaPath->winpath[3] = L'\\'; + status = MultiByteToWideChar(CP_UTF8, 0, + aFaPath->path, -1, + aFaPath->winpath+4, FA_PATH_MAX); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->winpath2 = aFaPath->winpath+4; + aFaPath->winpath_len = wcslen(aFaPath->winpath); + aFaPath->winpath_file = 0; + aFaPath->winmax_file_len = 0; + + return 0; +} + + + +sqInt faSetStFile(fapath *aFaPath, char *pathName) +{ +int len; +sqInt status; + + assert(aFaPath->path_file != 0); + /* Set the St encoded path */ + len = strlen(pathName); + if (len >= aFaPath->max_file_len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + strcpy(aFaPath->path_file, pathName); + + /* Convert to platform specific form */ + status = MultiByteToWideChar(CP_UTF8, 0, + aFaPath->path_file, -1, + aFaPath->winpath_file, aFaPath->winmax_file_len); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + + return 0; +} + + + +sqInt faSetPlatPath(fapath *aFaPath, WCHAR *pathName) +{ +int len; + + /* Set the platform encoded path */ + len = wcslen(pathName); + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + wcscpy(aFaPath->winpath, pathName); + aFaPath->winpath[len] = 0; + aFaPath->winpath_len = len; + aFaPath->winpath_file = 0; + aFaPath->winmax_file_len = 0; + if (aFaPath->winpath[0] == L'\\' && + aFaPath->winpath[1] == L'\\' && + aFaPath->winpath[2] == L'?' && + aFaPath->winpath[3] == L'\\') + aFaPath->winpath2 = aFaPath->winpath + 4; + else + aFaPath->winpath2 = aFaPath->winpath; + + /* Convert to St specific form */ + len = WideCharToMultiByte(CP_UTF8, + 0, + pathName, + -1, + aFaPath->path, + FA_PATH_MAX, + NULL, + NULL); + if (!len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->path_len = strlen(aFaPath->path); + aFaPath->path_file = 0; + aFaPath->max_file_len = 0; + + return 0; +} + + + +sqInt faSetPlatPathOop(fapath *aFaPath, sqInt pathNameOop) +{ +int byteCount; +char *bytePtr; +int len; + + byteCount = interpreterProxy->stSizeOf(pathNameOop); + bytePtr = interpreterProxy->arrayValueOf(pathNameOop); + len = byteCount / sizeof(WCHAR); + if (len >= FA_PATH_MAX) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + memcpy(aFaPath->winpath, bytePtr, byteCount); + aFaPath->winpath[len] = 0; + aFaPath->winpath_len = len; + aFaPath->winpath_file = 0; + aFaPath->winmax_file_len = 0; + if (aFaPath->winpath[0] == L'\\' && + aFaPath->winpath[1] == L'\\' && + aFaPath->winpath[2] == L'?' && + aFaPath->winpath[3] == L'\\') + aFaPath->winpath2 = aFaPath->winpath + 4; + else + aFaPath->winpath2 = aFaPath->winpath; + + /* Convert to St specific form */ + len = WideCharToMultiByte(CP_UTF8, + 0, + aFaPath->winpath, + -1, + aFaPath->path, + FA_PATH_MAX, + NULL, + NULL); + if (!len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + /* Set aFaPath->uxpath_file and max_file_len to the buffer after the directory */ + aFaPath->path_len = strlen(aFaPath->path); + aFaPath->path_file = 0; + aFaPath->max_file_len = 0; + + return 0; +} -sqInt faCheckFindData(osdir *dirState, sqInt closeFind) + + +sqInt faSetPlatFile(fapath *aFaPath, WCHAR *pathName) +{ +int len; + + assert(aFaPath->winpath_file != 0); + /* Set the platform encoded file name */ + len = wcslen(pathName); + if (len >= aFaPath->winmax_file_len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + wcscpy(aFaPath->winpath_file, pathName); + + /* Convert to St specific form */ + len = WideCharToMultiByte(CP_UTF8, + 0, + pathName, + -1, + aFaPath->path_file, + aFaPath->winmax_file_len, + NULL, + NULL); + if (!len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + + return 0; +} + + +/* + * faDbgDump + * + * Print the contents of the supplied fapath + */ +void faDbgDump(fapath *aFaPath) +{ +int i; + + printf("StPath: %s\n", aFaPath->path); + printf("StPathLen: %d\n", aFaPath->path_len); + printf("Path: 0x%p, File: 0x%p\n", (void *)aFaPath->path, (void *)aFaPath->path_file); + printf("Max File Len: %d\n\n", aFaPath->max_file_len); + + printf("Plat code points: "); + for (i=0; iwinpath_len; i++) { + printf(" %d", aFaPath->winpath[i]); + } + printf("\n"); + printf("PlatPathLen: %d\n", aFaPath->winpath_len); + printf("Path: 0x%p, Path2: 0x%p, File: 0x%p\n", + (void *)aFaPath->winpath, (void *)aFaPath->winpath2, (void *)aFaPath->winpath_file); + printf("Max File Len: %d\n", aFaPath->winmax_file_len); + printf("\n\n\n"); + fflush(stdout); +} + + + + +/* + * faCheckFindData + * + * Check the current file in aFaPath and retrieve entries until a valid file + * is returned or the end of directory is reached. + * + * Invalid files are '.' and '..'. + */ +sqInt faCheckFindData(fapath *aFaPath, sqInt closeFind) +{ +sqInt sz; +sqInt status; +sqInt haveEntry; + +haveEntry = FALSE; +do { + if ((!(aFaPath->findData.cFileName[0] == L'.' && + aFaPath->findData.cFileName[1] == 0)) + && wcscmp(aFaPath->findData.cFileName, L"..")) + haveEntry = TRUE; + else { + status = FindNextFileW(aFaPath->directoryHandle, &aFaPath->findData); + if (status == 0) { + if (closeFind == 1) + FindClose(aFaPath->directoryHandle); + return FA_NO_MORE_DATA; + } + } +} while (!haveEntry); + + status = faSetPlatFile(aFaPath, aFaPath->findData.cFileName); + if (status) return status; + + return FA_SUCCESS; +} + + +/* + * faConvertWinToLongSqueakTime + * + * Convert the supplied Windows System time to a long Squeak time. + * Squeak time has an epoch of 1901 and uses local time + * i.e. timezone + daylight savings + * + * Answer an sqLong which is guaranteed to be 64 bits on all platforms. + */ +sqLong faConvertWinToLongSqueakTime(SYSTEMTIME st) { -while (1) { - /* check for '.' or '..' directories */ - if (dirState->findData.cFileName[0] == L'.') - if (dirState->findData.cFileName[1] == 0 || - (dirState->findData.cFileName[1] == L'.' && - dirState->findData.cFileName[2] == 0)) { - if (!FindNextFileW(dirState->directoryHandle, &dirState->findData)) { - if (closeFind) - FindClose(dirState->directoryHandle); - return NO_MORE_DATA; - } else - break; +sqLong dy; +sqLong secs; +static sqLong nDaysPerMonth[14] = { + /* SYSTEMTIME uses 1 based month number. + * Add a offset entry at the start instead of subtracting + * 1 from the index */ + 0, 0, 31, 59, 90, 120, 151, + 181, 212, 243, 273, 304, 334, 365 }; + + /* Squeak epoch is Jan 1, 1901 + * compute delta year */ + dy = st.wYear - 1901; + secs = (dy * 365 * 24 * 60 * 60) /* base seconds */ + + ((dy >> 2) * 24 * 60 * 60); /* seconds of leap years */ + /* check if month > 2 and current year is a leap year */ + if ((st.wMonth > 2) && ((dy & 0x3) == 0x3)) { + /* add one day */ + secs += 24 * 60 * 60; } + /* add the days from the beginning of the year */ + secs += (nDaysPerMonth[st.wMonth] + st.wDay - 1) * 24 * 60 * 60; + /* add the hours, minutes, and seconds */ + secs += st.wSecond + 60*(st.wMinute + 60*st.wHour); + return secs; } -/* convert to UTF-8 */ -sz = WideCharToMultiByte(CP_UTF8, - 0, - dirState->findData.cFileName, - -1, - dirState->path_file, - dirState->max_file_len, - NULL, - NULL); -if (!sz) - return FA_CANT_READ_DIR; -return FA_SUCCESS; + +/* + * pathNameToOop + * + * Convert the supplied platform encoded C string to a + * precomposed UTF8 ByteArray. + */ +sqInt pathNameToOop(WCHAR *pathName) +{ +sqInt pathOop; +int status; +int len; +char stName[FA_PATH_MAX]; + + len = WideCharToMultiByte(CP_UTF8, + 0, + pathName, + -1, + stName, + FA_PATH_MAX, + NULL, + NULL); + if (!len) + return interpreterProxy->primitiveFailForOSError(FA_STRING_TOO_LONG); + + status = byteArrayFromCStringto(stName, &pathOop); + if (status) + return interpreterProxy->primitiveFailForOSError(status); + return pathOop; } + /* - * faOpenDirectory(char *pathString) + * faOpenDirectory * * Open the supplied directory for iteration and return the first entry. * @@ -57,79 +376,283 @@ return FA_SUCCESS; * If there are no entries, close the directory and return FA_NO_MORE_DATA */ -sqInt faOpenDirectory(osdir *dirState) +sqInt faOpenDirectory(fapath *aFaPath) { -WCHAR *widePathString; -sqInt sz; -sqInt patternLength; -DWORD ffError; +int status; +DWORD ffError; -/* Ensure wildcard pattern in dirState->path (which must already end in a path separator). */ -if (dirState->path_len == 0) - return FA_INVALID_ARGUMENTS; -patternLength = dirState->path_len; -pattern[patternLength++] = '*'; -pattern[patternLength] = 0; + /* aFaPath already has the directory set, with trailing separator. + * Add the wildcard for the search */ + status = faSetStFile(aFaPath, "*"); + if (status) return status; -/* convert the path name into a wide null-terminated C string */ -ALLOC_WIN32_PATH(widePathString, dirState->path, patternLength); + aFaPath->directoryHandle = FindFirstFileW(faGetPlatPath(aFaPath), &aFaPath->findData); + if (aFaPath->directoryHandle == INVALID_HANDLE_VALUE) { + ffError = GetLastError(); + if (ffError == ERROR_NO_MORE_FILES) + return FA_NO_MORE_DATA; + return FA_CANT_OPEN_DIR; + } -/* remove the wildcard pattern from dirState->path (but leave the trailing - * delimeter */ -dirState->path[dirState->path_len] = 0; - -dirState->directoryHandle = FindFirstFileW(widePathString, &dirState->findData); -if (dirState->directoryHandle == INVALID_HANDLE_ERROR) { - ffError = GetLastError(); - if (ffError == ERROR_NO_MORE_FILES) - return FA_NO_MORE_DATA; - return FA_CANT_OPEN_DIR; -} - -return faCheckFindData(dirState, 1); + return faCheckFindData(aFaPath, 1); } /* - * faReadDirectory(osdir *dirState) + * faReadDirectory * * Return the next entry for the already opened directory identified by - * dirStateId. + * aFaPath. * * Return FA_NO_MORE_DATA after the last file. */ -sqInt faReadDirectory(osdir *dirState) +sqInt faReadDirectory(fapath *aFaPath) { -DWORD ffError; - - -if (!FindNextFileW(dirState->directoryHandle, &dirState->findData)) - return FA_NO_MORE_DATA; + if (!FindNextFileW(aFaPath->directoryHandle, &aFaPath->findData)) + return FA_NO_MORE_DATA; -return faCheckFindData(dirState, 0); + return faCheckFindData(aFaPath, 0); } /* - * faCloseDirectory(void *dirStateId) + * faCloseDirectory * * Close the supplied directory. */ -sqInt faCloseDirectory(osdir *dirState) +sqInt faCloseDirectory(fapath *aFaPath) { sqInt status; -status = FindClose(dirState->directoryHandle); -dirState->directoryHandle = 0; -if (status) - return FA_SUCCESS; -else - return FA_UNABLE_TO_CLOSE_DIR; + status = FindClose(aFaPath->directoryHandle); + aFaPath->directoryHandle = 0; + if (status) + return FA_SUCCESS; + else + return FA_UNABLE_TO_CLOSE_DIR; +} + + +/* + * faFileAttribute + * + * Answer a single attribute (OOP) for the supplied file name. + * + * Set the interpreterProxy primitiveFailure flag on error. + * + * The attributeNumber has previously been validated. + * + * See FileAttributesPlugin>>primitiveFileAttribute for the list of attribute + * numbers. + */ +sqInt faFileAttribute(fapath *aFaPath, sqInt attributeNumber) +{ +int status; +sqInt resultOop = 0; +int mode; +sqLong attributeDate; +FILETIME fileTime; +SYSTEMTIME sysTime; +faStatStruct statBuf; +WIN32_FILE_ATTRIBUTE_DATA winAttrs; + + if (attributeNumber <= 8) { + /* Requested attribute comes from stat() entry */ + status = _wstat(faGetPlatPath2(aFaPath), &statBuf); + if (status) + return interpreterProxy->primitiveFailForOSError(FA_CANT_STAT_PATH); + + switch (attributeNumber) { + + case 1: /* fileName, not supported for a single attribute */ + resultOop = interpreterProxy->nilObject(); + break; + + case 2: /* Mode */ + resultOop = interpreterProxy->positive32BitIntegerFor(statBuf.st_mode); + break; + + case 3: /* inode */ + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_ino); + break; + + case 4: /* device id */ + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_dev); + break; + + case 5: /* nlink */ + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_nlink); + break; + + case 6: /* uid */ + resultOop = interpreterProxy->positive32BitIntegerFor(statBuf.st_uid); + break; + + case 7: /* gid */ + resultOop = interpreterProxy->positive32BitIntegerFor(statBuf.st_gid); + break; + + case 8: /* size (if file) */ + if (S_ISDIR(statBuf.st_mode) == 0) + resultOop = interpreterProxy->positive64BitIntegerFor(statBuf.st_size); + else + resultOop = interpreterProxy->positive32BitIntegerFor(0); + break; + } + + } else if (attributeNumber <= 12) { + status = GetFileAttributesExW(faGetPlatPath2(aFaPath), + GetFileExInfoStandard, &winAttrs); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_CANT_STAT_PATH); + switch (attributeNumber) { + case 9: /* access time */ + if (!FileTimeToLocalFileTime(&winAttrs.ftLastAccessTime, &fileTime)) + return interpreterProxy->primitiveFailForOSError(FA_TIME_CONVERSION_FAILED); + if (!FileTimeToSystemTime(&fileTime, &sysTime)) + return interpreterProxy->primitiveFailForOSError(FA_TIME_CONVERSION_FAILED); + attributeDate = faConvertWinToLongSqueakTime(sysTime); + resultOop = interpreterProxy->signed64BitIntegerFor(attributeDate); + break; + + case 10: /* modified time */ + if (!FileTimeToLocalFileTime(&winAttrs.ftLastWriteTime, &fileTime)) + return interpreterProxy->primitiveFailForOSError(FA_TIME_CONVERSION_FAILED); + if (!FileTimeToSystemTime(&fileTime, &sysTime)) + return interpreterProxy->primitiveFailForOSError(FA_TIME_CONVERSION_FAILED); + attributeDate = faConvertWinToLongSqueakTime(sysTime); + resultOop = interpreterProxy->signed64BitIntegerFor(attributeDate); + break; + + case 11: /* change time */ + resultOop = interpreterProxy->nilObject(); + break; + + case 12: /* creation time */ + if (!FileTimeToLocalFileTime(&winAttrs.ftCreationTime, &fileTime)) + return interpreterProxy->primitiveFailForOSError(FA_TIME_CONVERSION_FAILED); + if (!FileTimeToSystemTime(&fileTime, &sysTime)) + return interpreterProxy->primitiveFailForOSError(FA_TIME_CONVERSION_FAILED); + attributeDate = faConvertWinToLongSqueakTime(sysTime); + resultOop = interpreterProxy->signed64BitIntegerFor(attributeDate); + break; + } + } else if (attributeNumber < 16) { + switch (attributeNumber) { + case 13: + mode = R_OK; + break; + + case 14: + mode = W_OK; + break; + + case 15: + mode = X_OK; + break; + } + if (_waccess(faGetPlatPath2(aFaPath), mode) == 0) + resultOop = interpreterProxy->trueObject(); + else + resultOop = interpreterProxy->falseObject(); + } else if (attributeNumber == 16) { + /* isSymlink */ + status = GetFileAttributesExW(faGetPlatPath2(aFaPath), + GetFileExInfoStandard, &winAttrs); + if (!status) + return interpreterProxy->primitiveFailForOSError(FA_CANT_STAT_PATH); + if (winAttrs.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + resultOop = interpreterProxy->trueObject(); + else + resultOop = interpreterProxy->falseObject(); + } + + return resultOop; } + +/* + * faStat + * + * Populate the supplied stat buffer. + * + * fileNameOop only applies to symbolic links, answer nil. + */ +sqInt faStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop) +{ +int status; + + status = _wstat(faGetPlatPath2(aFaPath), statBuf); + if (status) return FA_CANT_STAT_PATH; + fileNameOop[0] = interpreterProxy->nilObject(); + return 0; +} + + + +/* + * faLinkStat + * + * Populate the supplied stat buffer with symbolic link information. + * + * Not supported on Windows + */ +sqInt faLinkStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop) +{ + return FA_UNSUPPORTED_OPERATION; +} + + + +/* + * faExists + * + * Answer a boolean indicating whether the supplied path name exists. + */ +sqInt faExists(fapath *aFaPath) +{ +int status; + + if (_waccess(faGetPlatPath2(aFaPath), F_OK)) + return interpreterProxy->falseObject(); + else + return interpreterProxy->trueObject(); +} + + + +/* + * faAccessAttributes + * + * Call access() for each access type (R, W, X) on the supplied path, + * storing the results in the st array attributeArray. + */ +sqInt faAccessAttributes(fapath *aFaPath, sqInt attributeArray, sqInt offset) +{ +sqInt index; +sqInt trueOop; +sqInt falseOop; +sqInt accessOop; + + + index = offset; + trueOop = interpreterProxy->trueObject(); + falseOop = interpreterProxy->falseObject(); + + accessOop = _waccess(faGetPlatPath2(aFaPath), R_OK) ? falseOop : trueOop; + interpreterProxy->storePointerofObjectwithValue(index++, attributeArray, accessOop); + + accessOop = _waccess(faGetPlatPath2(aFaPath), W_OK) ? falseOop : trueOop; + interpreterProxy->storePointerofObjectwithValue(index++, attributeArray, accessOop); + + accessOop = _waccess(faGetPlatPath2(aFaPath), X_OK) ? falseOop : trueOop; + interpreterProxy->storePointerofObjectwithValue(index++, attributeArray, accessOop); + + return 0; +} diff --git a/platforms/win32/plugins/FileAttributesPlugin/faSupport.h b/platforms/win32/plugins/FileAttributesPlugin/faSupport.h index 6078456d63..d2553ad514 100644 --- a/platforms/win32/plugins/FileAttributesPlugin/faSupport.h +++ b/platforms/win32/plugins/FileAttributesPlugin/faSupport.h @@ -1,8 +1,16 @@ - +#include +#include /* REQUIRED: c file must have included standard squeak definitions */ #include "faConstants.h" +/* Maximum path length allowed on this platform */ +#define FA_PATH_MAX 4096 +#define PATH_SEPARATOR '\\' + +typedef struct _stat faStatStruct; + + /* * typedef osdir * @@ -20,18 +28,48 @@ * max_file_len - The space remaining after the path for the file name. * path - The directory name being enumerated, with UTF8 encoding. */ -typedef struct dirptrstruct { - sqInt path_len; - char *path_file; - sqInt max_file_len; - char path[PATH_MAX+4]; +typedef struct fapathstruct { + char path[FA_PATH_MAX]; + sqInt path_len; + char *path_file; + sqInt max_file_len; + + /* Add 4 bytes to winpath for the \\?\ prefix */ + WCHAR winpath[FA_PATH_MAX+4]; + sqInt winpath_len; /* Number of characters, including the prefix */ + WCHAR *winpath_file; + WCHAR *winpath2; + sqInt winpath2_len; /* Number of characters, not bytes */ + sqInt winmax_file_len; + HANDLE directoryHandle; WIN32_FIND_DATAW findData; - } osdir; + } fapath; -#define PATH_SEPARATOR '\\' +sqInt faSetStDir(fapath *aFaPath, char *pathName, int len); +sqInt faSetStPath(fapath *aFaPath, char *pathName, int len); +sqInt faSetStFile(fapath *aFaPath, char *pathName); +sqInt faSetPlatPath(fapath *aFaPath, WCHAR *pathName); +sqInt faSetPlatPathOop(fapath *aFaPath, sqInt pathNameOop); +sqInt faSetPlatFile(fapath *aFaPath, WCHAR *pathName); +#define faGetStPath(aFaPath) aFaPath->path +#define faGetStPathLen(aFaPath) aFaPath->path_len +#define faGetStFile(aFaPath) aFaPath->path_file +#define faGetPlatPath(aFaPath) aFaPath->winpath +#define faGetPlatPathByteCount(aFaPath) (aFaPath->winpath_len * sizeof(WCHAR)) +#define faGetPlatPath2(aFaPath) aFaPath->winpath2 +#define faGetPlatPath2ByteCount(aFaPath) (aFaPath->winpath2_len * sizeof(WCHAR)) +#define faGetPlatFile(aFaPath) aFaPath->winpath_file + +sqInt faSetStDirOop(fapath *aFaPath, sqInt pathNameOop); +sqInt faSetStPathOop(fapath *aFaPath, sqInt pathNameOop); -sqInt faOpenDirectory(osdir *dirState); -sqInt faReadDirectory(osdir *dirState); -sqInt faCloseDirectory(osdir *dirState); +sqInt faOpenDirectory(fapath *aFaPath); +sqInt faReadDirectory(fapath *aFaPath); +sqInt faCloseDirectory(fapath *aFaPath); +sqInt faFileAttribute(fapath *aFaPath, sqInt attributeNumber); +sqInt faStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop); +sqInt faLinkStat(fapath *aFaPath, faStatStruct *statBuf, sqInt *fileNameOop); +sqInt faExists(fapath *aFaPath); +sqInt faAccessAttributes(fapath *aFaPath, sqInt attributeArray, sqInt offset); diff --git a/src/plugins/FileAttributesPlugin/FileAttributesPlugin.c b/src/plugins/FileAttributesPlugin/FileAttributesPlugin.c index 5838f90c70..859d2d40fa 100644 --- a/src/plugins/FileAttributesPlugin/FileAttributesPlugin.c +++ b/src/plugins/FileAttributesPlugin/FileAttributesPlugin.c @@ -31,11 +31,6 @@ static char __buildInfo[] = "FileAttributesPlugin * FileAttributesPlugin.oscog-A #else #define HAVE_CHMOD 1 #define HAVE_CHOWN 1 -# include "sqUnixCharConv.h" -#endif -#include -#if !defined(HAVE_LSTAT) && !defined(_WIN32) && !defined(_WIN64) -# define HAVE_LSTAT 1 #endif #include /* AKG 2018 - FileAttributesPlugin.c translated from class FileAttributesPlugin */ @@ -57,6 +52,9 @@ static char __buildInfo[] = "FileAttributesPlugin * FileAttributesPlugin.oscog-A #endif #include "faSupport.h" +#if !defined(HAVE_LSTAT) && !defined(_WIN32) && !defined(_WIN64) +# define HAVE_LSTAT 1 +#endif #include "sqMemoryAccess.h" @@ -66,30 +64,17 @@ static char __buildInfo[] = "FileAttributesPlugin * FileAttributesPlugin.oscog-A /*** Function Prototypes ***/ -static sqInt accessAttributesForFilenameintostartingAt(char *cPathName, sqInt attributeArray, sqInt offset); static sqInt addressObjectFor(void *aMachineAddress); -static sqInt byteArrayFromCStringto(const char *aCString, sqInt *byteArrayOop); +EXPORT(sqInt) byteArrayFromCStringto(const char *aCString, sqInt *byteArrayOop); static sqInt canOpenDirectoryStreamForlength(char *aPathCString, sqInt length); static sqInt canStatFilePathlength(char *aPathCString, sqInt length); #if _WIN32 static sqLong convertWinToSqueakTime(SYSTEMTIME st); #endif /* _WIN32 */ -static sqLong faConvertUnixToLongSqueakTime(time_t unixTime); -#if _WIN32 -static sqInt fileCreationTimeForlengthto(char *pathString, sqInt pathLength, sqLong *creationDate); -#endif /* _WIN32 */ -#if _WIN32 -static sqInt fileLastAccessTimeForlengthto(char *pathString, sqInt pathLength, sqLong *creationDate); -#endif /* _WIN32 */ -#if _WIN32 -static sqInt fileLastWriteTimeForlengthto(char *pathString, sqInt pathLength, sqLong *creationDate); -#endif /* _WIN32 */ -static int fileToAttributeArraymaskarray(char *cPathName, sqInt attributeMask, sqInt *attributeArray); +static int fileToAttributeArraymaskarray(fapath *faPath, sqInt attributeMask, sqInt *attributeArray); EXPORT(const char*) getModuleName(void); EXPORT(sqInt) initialiseModule(void); -static sqInt isSymlinkboolean(char *cPathName, sqInt *resultOop); static int pathOoptoBuffermaxLen(sqInt pathNameOop, char *cPathName, sqInt maxLen); -static sqInt platformPathToOop(char *cPathString); static void * pointerFrom(sqInt directoryPointerBytes); static sqInt posixFileTimesFromto(struct stat *statBufPointer, sqInt attributeArray); EXPORT(sqInt) primitiveChangeMode(void); @@ -102,22 +87,21 @@ EXPORT(sqInt) primitiveFileMasks(void); EXPORT(sqInt) primitiveLogicalDrives(void); EXPORT(sqInt) primitiveOpendir(void); EXPORT(sqInt) primitivePathMax(void); +EXPORT(sqInt) primitivePlatToStPath(void); EXPORT(sqInt) primitiveReaddir(void); EXPORT(sqInt) primitiveRewinddir(void); +EXPORT(sqInt) primitiveStToPlatPath(void); EXPORT(sqInt) primitiveSymlinkChangeOwner(void); EXPORT(sqInt) primitiveVersionString(void); -static sqInt processDirectory(osdir *dirStream); +static sqInt processDirectory(fapath *faPath); static sqInt putLStatForintoBuffertargetName(char *cPathName, struct stat *statBufPointer, sqInt *fileNameOop); static sqInt putStatForintoBuffertargetName(char *cPathName, struct stat *statBufPointer, sqInt *fileNameOop); static sqInt readLinkintomaxLength(char *cPathName, char *cLinkPtr, size_t maxLength); EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter); static sqInt squeakPathtoPlatformmaxLen(sqInt pathOop, char *cPathString, sqInt maxLength); -static sqInt statArrayFortoArrayfromfileName(char *cPathName, sqInt attributeArray, struct stat *statBufPointer, sqInt fileNameOop); +static sqInt statArrayFortoArrayfromfileName(fapath *faPath, sqInt attributeArray, struct stat *statBufPointer, sqInt fileNameOop); static sqInt stringFromCString(const char *aCString); #if _WIN32 -static sqInt winFileAttributesForlengthto(char *pathString, sqInt pathLength, WIN32_FILE_ATTRIBUTE_DATA *winAttrs); -#endif /* _WIN32 */ -#if _WIN32 static sqInt winFileCreationTimeForto(WIN32_FILE_ATTRIBUTE_DATA *winAttrs, sqLong *creationDate); #endif /* _WIN32 */ #if _WIN32 @@ -127,7 +111,7 @@ static sqInt winFileLastAccessTimeForto(WIN32_FILE_ATTRIBUTE_DATA *winAttrs, sqL static sqInt winFileLastWriteTimeForto(WIN32_FILE_ATTRIBUTE_DATA *winAttrs, sqLong *writeDate); #endif /* _WIN32 */ #if _WIN32 -static sqInt winFileTimesForto(char *cPathName, sqInt attributeArray); +static sqInt winFileTimesForto(fapath *faPath, sqInt attributeArray); #endif /* _WIN32 */ @@ -140,7 +124,6 @@ static sqInt (*classArray)(void); static sqInt (*classByteArray)(void); static sqInt (*classString)(void); static sqInt (*failed)(void); -static sqInt (*falseObject)(void); static sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size); static sqInt (*integerObjectOf)(sqInt value); static void * (*ioLoadFunctionFrom)(char *functionName, char *moduleName); @@ -163,14 +146,12 @@ static sqInt (*stackIntegerValue)(sqInt offset); static sqInt (*stackObjectValue)(sqInt offset); static sqInt (*stackValue)(sqInt offset); static sqInt (*storePointerofObjectwithValue)(sqInt index, sqInt oop, sqInt valuePointer); -static sqInt (*trueObject)(void); #else /* !defined(SQUEAK_BUILTIN_PLUGIN) */ extern void * arrayValueOf(sqInt oop); extern sqInt classArray(void); extern sqInt classByteArray(void); extern sqInt classString(void); extern sqInt failed(void); -extern sqInt falseObject(void); extern sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size); extern sqInt integerObjectOf(sqInt value); extern void * ioLoadFunctionFrom(char *functionName, char *moduleName); @@ -193,7 +174,6 @@ extern sqInt stackIntegerValue(sqInt offset); extern sqInt stackObjectValue(sqInt offset); extern sqInt stackValue(sqInt offset); extern sqInt storePointerofObjectwithValue(sqInt index, sqInt oop, sqInt valuePointer); -extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; @@ -209,39 +189,6 @@ static void * sCOFfn; -/* Call access() for each access type (R, W, X) on the c string cPathName, - storing the results in the st array attributeArray. - */ - - /* FileAttributesPlugin>>#accessAttributesForFilename:into:startingAt: */ -static sqInt -accessAttributesForFilenameintostartingAt(char *cPathName, sqInt attributeArray, sqInt offset) -{ - sqInt boolean; - sqInt index; - - index = offset; - if ((access(cPathName, R_OK)) == 0) { - boolean = trueObject(); - } - else { - boolean = falseObject(); - } - storePointerofObjectwithValue(index, attributeArray, boolean); - index += 1; - boolean = ((access(cPathName, W_OK)) == 0 - ? trueObject() - : falseObject()); - storePointerofObjectwithValue(index, attributeArray, boolean); - index += 1; - boolean = ((access(cPathName, X_OK)) == 0 - ? trueObject() - : falseObject()); - storePointerofObjectwithValue(index, attributeArray, boolean); - return 0; -} - - /* Answer an ExternalAddress object which represents aMachineAddress */ /* FileAttributesPlugin>>#addressObjectFor: */ @@ -272,7 +219,7 @@ addressObjectFor(void *aMachineAddress) Caution: This may invoke the garbage collector. */ /* FileAttributesPlugin>>#byteArrayFromCString:to: */ -static sqInt +EXPORT(sqInt) byteArrayFromCStringto(const char *aCString, sqInt *byteArrayOop) { unsigned char *byteArrayPtr; @@ -282,7 +229,7 @@ byteArrayFromCStringto(const char *aCString, sqInt *byteArrayOop) /* We never return strings longer than PATH_MAX */ len = strlen(aCString); - if (len > PATH_MAX) { + if (len >= FA_PATH_MAX) { return -1 /* stringTooLong */; } newByteArray = instantiateClassindexableSize(classByteArray(), len); @@ -383,144 +330,24 @@ convertWinToSqueakTime(SYSTEMTIME st) #endif /* _WIN32 */ -/* Convert the supplied Unix (UTC) time to Squeak time. - - Squeak time has an epoch of 1901 and uses local time - i.e. timezone + daylight savings - - Answer an sqLong which is guaranteed to be 64 bits on all platforms. - */ - - /* FileAttributesPlugin>>#faConvertUnixToLongSqueakTime: */ -static sqLong -faConvertUnixToLongSqueakTime(time_t unixTime) -{ - sqLong squeakTime; - - -# if defined(_WIN32) - squeakTime = 0; -# else /* defined(_WIN32) */ - squeakTime = unixTime; - -# if defined(HAVE_TM_GMTOFF) - squeakTime += localtime(&unixTime)->tm_gmtoff; -# else /* defined(HAVE_TM_GMTOFF) */ - -# if defined(HAVE_TIMEZONE) - squeakTime += (daylight*60*60) - timezone; -# else /* defined(HAVE_TIMEZONE) */ - -#error: cannot determine timezone correction -# endif /* defined(HAVE_TIMEZONE) */ -# endif /* defined(HAVE_TM_GMTOFF) */ - squeakTime += (52*365UL + 17*366UL) * 24*60*60UL; -# endif /* defined(_WIN32) */ - return squeakTime; -} - - -/* Get the creationDate for the supplied file. */ - - /* FileAttributesPlugin>>#fileCreationTimeFor:length:to: */ -#if _WIN32 -static sqInt -fileCreationTimeForlengthto(char *pathString, sqInt pathLength, sqLong *creationDate) -{ - sqInt status; - WIN32_FILE_ATTRIBUTE_DATA winAttrs; - - - /* Get the file attributes */ - status = winFileAttributesForlengthto(pathString, pathLength, (&winAttrs)); - if (!(status == 0)) { - return status; - } - status = winFileCreationTimeForto((&winAttrs), creationDate); - if (!(status == 0)) { - return status; - } - return 0; -} -#endif /* _WIN32 */ - - -/* Get the creationDate for the supplied file. */ - - /* FileAttributesPlugin>>#fileLastAccessTimeFor:length:to: */ -#if _WIN32 -static sqInt -fileLastAccessTimeForlengthto(char *pathString, sqInt pathLength, sqLong *creationDate) -{ - sqInt status; - WIN32_FILE_ATTRIBUTE_DATA winAttrs; - - - /* Get the file attributes */ - status = winFileAttributesForlengthto(pathString, pathLength, (&winAttrs)); - if (!(status == 0)) { - return status; - } - status = winFileLastAccessTimeForto((&winAttrs), creationDate); - if (!(status == 0)) { - return status; - } - return 0; -} -#endif /* _WIN32 */ - - -/* Get the creationDate for the supplied file. */ - - /* FileAttributesPlugin>>#fileLastWriteTimeFor:length:to: */ -#if _WIN32 -static sqInt -fileLastWriteTimeForlengthto(char *pathString, sqInt pathLength, sqLong *creationDate) -{ - sqInt status; - WIN32_FILE_ATTRIBUTE_DATA winAttrs; - - - /* Get the file attributes */ - status = winFileAttributesForlengthto(pathString, pathLength, (&winAttrs)); - if (!(status == 0)) { - return status; - } - status = winFileLastWriteTimeForto((&winAttrs), creationDate); - if (!(status == 0)) { - return status; - } - return 0; -} -#endif /* _WIN32 */ - - /* Answer a file attribute array from pathNameOop. */ /* FileAttributesPlugin>>#fileToAttributeArray:mask:array: */ static int -fileToAttributeArraymaskarray(char *cPathName, sqInt attributeMask, sqInt *attributeArray) +fileToAttributeArraymaskarray(fapath *faPath, sqInt attributeMask, sqInt *attributeArray) { sqInt accessArray; sqLong attributeDate; - sqInt boolean; - char cLinkName[PATH_MAX]; sqInt combinedArray; sqInt fileNameOop; int getAccess; int getStats; - sqInt index; - sqInt len; sqInt sizeIfFile; sqInt statArray; struct stat statBuf; struct stat *statBufPointer; - struct stat *statBufPointer1; - struct stat *statBufPointer2; sqInt status; sqInt status1; - sqInt status2; - sqInt status3; int useLstat; @@ -542,91 +369,50 @@ fileToAttributeArraymaskarray(char *cPathName, sqInt attributeMask, sqInt *attri if (!(statArray)) { return primitiveFailFor(PrimErrNoMemory); } - if (useLstat) { - /* begin putLStatFor:intoBuffer:targetName: */ - statBufPointer2 = ((struct stat *) ((&statBuf))); - -# if HAVE_LSTAT == 1 - status3 = lstat(cPathName, statBufPointer2); - if (status3 != 0) { - /* begin cantStatPath */ - status = -3; - goto l5; - } - if ((S_ISLNK((statBufPointer2->st_mode))) == 0) { - ((&fileNameOop))[0] = (nilObject()); - } - else { - len = readLinkintomaxLength(cPathName, cLinkName, PATH_MAX); - if (len < 0) { - status = len; - goto l5; - } - status3 = byteArrayFromCStringto(cLinkName, (&fileNameOop)); - } -# else /* HAVE_LSTAT == 1 */ - - /* #HAVE_LSTAT = 1 */ - /* begin invalidRequest */ - status3 = -11; -# endif /* HAVE_LSTAT == 1 */ - status = status3; - l5: /* end putLStatFor:intoBuffer:targetName: */; - } - else { - /* begin putStatFor:intoBuffer:targetName: */ - statBufPointer = ((struct stat *) ((&statBuf))); - status1 = stat(cPathName, statBufPointer); - if (status1 != 0) { - /* begin cantStatPath */ - status = -3; - goto l1; - } - ((&fileNameOop))[0] = (nilObject()); - status = 0; - l1: /* end putStatFor:intoBuffer:targetName: */; - } + status = (useLstat + ? faLinkStat(faPath, (&statBuf), (&fileNameOop)) + : faStat(faPath, (&statBuf), (&fileNameOop))); if (status != 0) { return status; } /* begin statArrayFor:toArray:from:fileName: */ - statBufPointer1 = ((struct stat *) ((&statBuf))); - sizeIfFile = ((S_ISDIR((statBufPointer1->st_mode))) == 0 - ? (statBufPointer1->st_size) + statBufPointer = ((struct stat *) ((&statBuf))); + sizeIfFile = ((S_ISDIR((statBufPointer->st_mode))) == 0 + ? (statBufPointer->st_size) : 0); storePointerofObjectwithValue(0, statArray, fileNameOop); storePointerofObjectwithValue(1, statArray, (BytesPerWord == 8 - ? positive64BitIntegerFor((statBufPointer1->st_mode)) - : positive32BitIntegerFor((statBufPointer1->st_mode)))); - storePointerofObjectwithValue(2, statArray, positive64BitIntegerFor((statBufPointer1->st_ino))); - storePointerofObjectwithValue(3, statArray, positive64BitIntegerFor((statBufPointer1->st_dev))); - storePointerofObjectwithValue(4, statArray, positive64BitIntegerFor((statBufPointer1->st_nlink))); + ? positive64BitIntegerFor((statBufPointer->st_mode)) + : positive32BitIntegerFor((statBufPointer->st_mode)))); + storePointerofObjectwithValue(2, statArray, positive64BitIntegerFor((statBufPointer->st_ino))); + storePointerofObjectwithValue(3, statArray, positive64BitIntegerFor((statBufPointer->st_dev))); + storePointerofObjectwithValue(4, statArray, positive64BitIntegerFor((statBufPointer->st_nlink))); storePointerofObjectwithValue(5, statArray, (BytesPerWord == 8 - ? positive64BitIntegerFor((statBufPointer1->st_uid)) - : positive32BitIntegerFor((statBufPointer1->st_uid)))); + ? positive64BitIntegerFor((statBufPointer->st_uid)) + : positive32BitIntegerFor((statBufPointer->st_uid)))); storePointerofObjectwithValue(6, statArray, (BytesPerWord == 8 - ? positive64BitIntegerFor((statBufPointer1->st_gid)) - : positive32BitIntegerFor((statBufPointer1->st_gid)))); + ? positive64BitIntegerFor((statBufPointer->st_gid)) + : positive32BitIntegerFor((statBufPointer->st_gid)))); storePointerofObjectwithValue(7, statArray, positive64BitIntegerFor(sizeIfFile)); # if defined(_WIN32) - status2 = winFileTimesForto(cPathName, statArray); + status1 = winFileTimesForto(faPath, statArray); # else /* defined(_WIN32) */ /* begin posixFileTimesFrom:to: */ # if defined(_WIN32) # else /* defined(_WIN32) */ - attributeDate = faConvertUnixToLongSqueakTime((statBufPointer1->st_atime)); + attributeDate = faConvertUnixToLongSqueakTime((statBufPointer->st_atime)); storePointerofObjectwithValue(8, statArray, signed64BitIntegerFor(attributeDate)); - attributeDate = faConvertUnixToLongSqueakTime((statBufPointer1->st_mtime)); + attributeDate = faConvertUnixToLongSqueakTime((statBufPointer->st_mtime)); storePointerofObjectwithValue(9, statArray, signed64BitIntegerFor(attributeDate)); - attributeDate = faConvertUnixToLongSqueakTime((statBufPointer1->st_ctime)); + attributeDate = faConvertUnixToLongSqueakTime((statBufPointer->st_ctime)); storePointerofObjectwithValue(10, statArray, signed64BitIntegerFor(attributeDate)); storePointerofObjectwithValue(11, statArray, nilObject()); # endif /* defined(_WIN32) */ - status2 = 0; + status1 = 0; # endif /* defined(_WIN32) */ - status = status2; + status = status1; if (status != 0) { return status; } @@ -637,25 +423,7 @@ fileToAttributeArraymaskarray(char *cPathName, sqInt attributeMask, sqInt *attri if (!(accessArray)) { return primitiveFailFor(PrimErrNoMemory); } - /* begin accessAttributesForFilename:into:startingAt: */ - index = 0; - if ((access(cPathName, R_OK)) == 0) { - boolean = trueObject(); - } - else { - boolean = falseObject(); - } - storePointerofObjectwithValue(index, accessArray, boolean); - index += 1; - boolean = ((access(cPathName, W_OK)) == 0 - ? trueObject() - : falseObject()); - storePointerofObjectwithValue(index, accessArray, boolean); - index += 1; - boolean = ((access(cPathName, X_OK)) == 0 - ? trueObject() - : falseObject()); - storePointerofObjectwithValue(index, accessArray, boolean); + faAccessAttributes(faPath, accessArray, 0); attributeArray[0] = accessArray; } if (getStats @@ -694,35 +462,6 @@ initialiseModule(void) } -/* Set resultOop to a boolean indicating whether cPathName is a symbolic - link. Answer status (0 = success) */ - - /* FileAttributesPlugin>>#isSymlink:boolean: */ -static sqInt -isSymlinkboolean(char *cPathName, sqInt *resultOop) -{ - struct stat statBuf; - sqInt status; - - -# if HAVE_LSTAT == 1 - status = lstat(cPathName, (&statBuf)); - if (status != 0) { - /* begin cantStatPath */ - return -3; - } - if ((S_ISLNK((statBuf.st_mode))) == 0) { - resultOop[0] = (falseObject()); - } - else { - resultOop[0] = (trueObject()); - } - return 0; -# endif /* HAVE_LSTAT == 1 */ - return -13 /* unsupportedOperation */; -} - - /* Copy the supplied path name string object to the supplied c string buffer */ /* FileAttributesPlugin>>#pathOop:toBuffer:maxLen: */ @@ -747,42 +486,6 @@ pathOoptoBuffermaxLen(sqInt pathNameOop, char *cPathName, sqInt maxLen) } -/* Convert the supplied cPathString to a ByteArray. - cPathString is encoded using the host OS conventions, e.g. decomposed UTF8 - on MacOS. - */ - - /* FileAttributesPlugin>>#platformPathToOop: */ -static sqInt -platformPathToOop(char *cPathString) -{ - sqInt pathOop; - sqInt status; - char uxName[PATH_MAX+1]; - sqInt val; - - val = 0; - if ((strlen(cPathString)) > (PATH_MAX+1)) { - return primitiveFailForOSError(-1 /* stringTooLong */); - } - pathOop = 0; - -# if _WIN32 - status = byteArrayFromCStringto(cPathString, (&pathOop)); -# else /* _WIN32 */ - status = ux2sqPath(cPathString, strlen(cPathString), uxName, PATH_MAX, 1); - if (status == 0) { - return primitiveFailForOSError(-6 /* invalidArguments */); - } - status = byteArrayFromCStringto(uxName, (&pathOop)); -# endif /* _WIN32 */ - if (status != 0) { - return primitiveFailForOSError(status); - } - return pathOop; -} - - /* Answer the machine address contained in anExternalAddressOop. */ /* FileAttributesPlugin>>#pointerFrom: */ @@ -847,12 +550,12 @@ primitiveChangeMode(void) || (!(isBytes(fileNameOop)))) { return primitiveFailFor(PrimErrBadArgument); } + +# if HAVE_CHMOD squeakPathtoPlatformmaxLen(fileNameOop, cString, PATH_MAX); if (failed()) { return primitiveFailForOSError(primitiveFailureCode()); } - -# if HAVE_CHMOD status = chmod(cString, newMode); if (status != 0) { return primitiveFailForOSError(errno); @@ -882,12 +585,12 @@ primitiveChangeOwner(void) || (!(isBytes(fileNameOop)))) { return primitiveFailFor(PrimErrBadArgument); } + +# if HAVE_CHOWN squeakPathtoPlatformmaxLen(fileNameOop, cString, PATH_MAX); if (failed()) { return primitiveFailForOSError(primitiveFailureCode()); } - -# if HAVE_CHOWN status = chown(cString, ownerId, groupId); if (status != 0) { return primitiveFailForOSError(errno); @@ -909,21 +612,19 @@ EXPORT(sqInt) primitiveClosedir(void) { sqInt dirPointerOop; - osdir *dirStream; + void * faPath; sqInt result; dirPointerOop = stackValue(0); - dirStream = pointerFrom(dirPointerOop); - if (!(dirStream)) { + faPath = pointerFrom(dirPointerOop); + if (!(faPath)) { return primitiveFailFor(PrimErrBadArgument); } - fprintf(stderr, "Closedir: %p\n", (void *)dirStream); - fflush(stderr); - result = faCloseDirectory(dirStream); + result = faCloseDirectory(faPath); if (!(result == 0)) { return primitiveFailForOSError(result); } - free(dirStream); + free(faPath); popthenPush(2, dirPointerOop); return 0; } @@ -945,32 +646,11 @@ primitiveClosedir(void) EXPORT(sqInt) primitiveFileAttribute(void) { - sqLong attributeDate; sqInt attributeNumber; - char cPathName[PATH_MAX+1]; + fapath *faPath; sqInt fileName; - sqInt fileNameOop; - sqInt mode; sqInt resultOop; - sqInt *resultOop1; - sqInt sizeIfFile; - struct stat statBuf; - struct stat statBuf1; - struct stat *statBufPointer; - sqInt status; - sqInt status1; - sqInt status2; - sqInt val; - usqIntptr_t value; - usqIntptr_t value1; - usqIntptr_t value2; - attributeDate = 0; - fileNameOop = 0; - mode = 0; - val = 0; - fprintf(stderr, "primitiveFileAttribute\n"); - fflush(stderr); fileName = stackObjectValue(1); attributeNumber = stackIntegerValue(0); if ((failed()) @@ -978,192 +658,24 @@ primitiveFileAttribute(void) || (!(isBytes(fileName))))) { return primitiveFailFor(PrimErrBadArgument); } - squeakPathtoPlatformmaxLen(fileName, cPathName, PATH_MAX); + faPath = (fapath *) calloc(1, sizeof(fapath)); + if (faPath == null) { + return primitiveFailForOSError(-10 /* cantAllocateMemory */); + } + faSetStPathOop(faPath, fileName); if (failed()) { return primitiveFailureCode(); } - resultOop = 0; - fprintf(stderr, "File fileAttribute: '%s' number: %ld.\n", - cPathName, attributeNumber); - fflush(stderr); - if (attributeNumber < 12) { - - /* Get requested stat entry */ - /* begin putStatFor:intoBuffer:targetName: */ - statBufPointer = ((struct stat *) ((&statBuf))); - status2 = stat(cPathName, statBufPointer); - if (status2 != 0) { - /* begin cantStatPath */ - status = -3; - goto l9; - } - ((&fileNameOop))[0] = (nilObject()); - status = 0; - l9: /* end putStatFor:intoBuffer:targetName: */; - if (status != 0) { - fprintf(stderr, "stat() failed: %ld\n", status); - fflush(stderr); - return primitiveFailForOSError(status); - } - if (attributeNumber == 1) { - resultOop = fileNameOop; - } - if (attributeNumber == 2) { - /* begin positiveMachineIntegerFor: */ - value = (statBuf.st_mode); - resultOop = (BytesPerWord == 8 - ? positive64BitIntegerFor(value) - : positive32BitIntegerFor(value)); - } - if (attributeNumber == 3) { - resultOop = positive64BitIntegerFor((statBuf.st_ino)); - } - if (attributeNumber == 4) { - resultOop = positive64BitIntegerFor((statBuf.st_dev)); - } - if (attributeNumber == 5) { - resultOop = positive64BitIntegerFor((statBuf.st_nlink)); - } - if (attributeNumber == 6) { - /* begin positiveMachineIntegerFor: */ - value1 = (statBuf.st_uid); - resultOop = (BytesPerWord == 8 - ? positive64BitIntegerFor(value1) - : positive32BitIntegerFor(value1)); - } - if (attributeNumber == 7) { - /* begin positiveMachineIntegerFor: */ - value2 = (statBuf.st_gid); - resultOop = (BytesPerWord == 8 - ? positive64BitIntegerFor(value2) - : positive32BitIntegerFor(value2)); - } - if (attributeNumber == 8) { - sizeIfFile = ((S_ISDIR((statBuf.st_mode))) == 0 - ? (statBuf.st_size) - : 0); - /* begin positiveMachineIntegerFor: */ - resultOop = (BytesPerWord == 8 - ? positive64BitIntegerFor(sizeIfFile) - : positive32BitIntegerFor(sizeIfFile)); - } - if (attributeNumber == 9) { - - /* Access Time */ - -# if defined(_WIN32) - status = fileLastAccessTimeForlengthto(cPathName, strlen(cPathName), (&attributeDate)); - if (status != 0) { - return primitiveFailForOSError(status); - } - resultOop = signed64BitIntegerFor(attributeDate); -# else /* defined(_WIN32) */ - attributeDate = faConvertUnixToLongSqueakTime((statBuf.st_atime)); - resultOop = signed64BitIntegerFor(attributeDate); -# endif /* defined(_WIN32) */ - } - if (attributeNumber == 10) { - - /* Modified Time */ - -# if defined(_WIN32) - status = fileLastWriteTimeForlengthto(cPathName, strlen(cPathName), (&attributeDate)); - if (status != 0) { - return primitiveFailForOSError(status); - } - resultOop = signed64BitIntegerFor(attributeDate); -# else /* defined(_WIN32) */ - attributeDate = faConvertUnixToLongSqueakTime((statBuf.st_mtime)); - resultOop = signed64BitIntegerFor(attributeDate); -# endif /* defined(_WIN32) */ - } - if (attributeNumber == 11) { - - /* Change Time */ - -# if defined(_WIN32) - resultOop = nilObject(); -# else /* defined(_WIN32) */ - attributeDate = faConvertUnixToLongSqueakTime((statBuf.st_ctime)); - resultOop = signed64BitIntegerFor(attributeDate); -# endif /* defined(_WIN32) */ - } - } - else { - if (attributeNumber == 12) { - - /* Creation Time */ - -# if defined(_WIN32) - status = fileCreationTimeForlengthto(cPathName, strlen(cPathName), (&attributeDate)); - if (status != 0) { - return primitiveFailForOSError(status); - } - resultOop = signed64BitIntegerFor(attributeDate); -# else /* defined(_WIN32) */ - resultOop = nilObject(); -# endif /* defined(_WIN32) */ - } - else { - if (attributeNumber < 16) { - - /* Get requested access entry */ - if (attributeNumber == 13) { - /* begin fileReadableFlag */ - mode = R_OK; - } - if (attributeNumber == 14) { - /* begin fileWriteableFlag */ - mode = W_OK; - } - if (attributeNumber == 15) { - /* begin fileExecutableFlag */ - mode = X_OK; - } - resultOop = ((access(cPathName, mode)) == 0 - ? trueObject() - : falseObject()); - } - else { - - /* attributeNumber = 16, #isSymlink */ - /* begin isSymlink:boolean: */ - resultOop1 = ((sqInt *) ((&resultOop))); - -# if HAVE_LSTAT == 1 - status1 = lstat(cPathName, (&statBuf1)); - if (status1 != 0) { - /* begin cantStatPath */ - status = -3; - goto l8; - } - if ((S_ISLNK((statBuf1.st_mode))) == 0) { - resultOop1[0] = (falseObject()); - } - else { - resultOop1[0] = (trueObject()); - } - status = 0; - goto l8; -# endif /* HAVE_LSTAT == 1 */ - status = -13 /* unsupportedOperation */; - l8: /* end isSymlink:boolean: */; - if (status != 0) { - return primitiveFailForOSError(status); - } - } - } + resultOop = faFileAttribute(faPath, attributeNumber); + if (failed()) { + return primitiveFailureCode(); } if (resultOop == 0) { /* It shouldn't be possible to get here */ - fprintf(stderr, "unexpected error\n"); - fflush(stderr); primitiveFailForOSError(-14 /* unexpectedError */); } else { - fprintf(stderr, "primitiveFileAttribute normal return\n"); - fflush(stderr); popthenPush(3, resultOop); } return 0; @@ -1185,35 +697,32 @@ primitiveFileAttributes(void) { sqInt attributeArray; sqInt attributeMask; - char cPathName[PATH_MAX+1]; + fapath *faPath; sqInt fileName; int status; sqInt val; attributeArray = 0; val = 0; - fprintf(stderr, "primitiveFileAttributes\n"); - fflush(stderr); fileName = stackObjectValue(1); attributeMask = stackIntegerValue(0); if ((failed()) || (!(isBytes(fileName)))) { return primitiveFailFor(PrimErrBadArgument); } - squeakPathtoPlatformmaxLen(fileName, cPathName, PATH_MAX); + faPath = (fapath *) calloc(1, sizeof(fapath)); + if (faPath == null) { + return primitiveFailForOSError(-10 /* cantAllocateMemory */); + } + faSetStPathOop(faPath, fileName); if (failed()) { return primitiveFailureCode(); } - fprintf(stderr, "File fileAttributes: '%s' mask: %ld.\n", - cPathName, attributeMask); - fflush(stderr); - status = fileToAttributeArraymaskarray(cPathName, attributeMask, (&attributeArray)); + status = fileToAttributeArraymaskarray(faPath, attributeMask, (&attributeArray)); if (status != 0) { primitiveFailForOSError(status); } else { - fprintf(stderr, "primitiveFileAttributes normal return\n"); - fflush(stderr); popthenPush(3, attributeArray); } return 0; @@ -1226,25 +735,22 @@ primitiveFileAttributes(void) EXPORT(sqInt) primitiveFileExists(void) { - sqInt accessFlag; - char cString[PATH_MAX+1]; + fapath *faPath; sqInt fileNameOop; fileNameOop = stackObjectValue(0); if (!(isBytes(fileNameOop))) { return primitiveFailFor(PrimErrBadArgument); } - squeakPathtoPlatformmaxLen(fileNameOop, cString, PATH_MAX); + faPath = (fapath *) calloc(1, sizeof(fapath)); + if (faPath == null) { + return primitiveFailForOSError(-10 /* cantAllocateMemory */); + } + faSetStPathOop(faPath, fileNameOop); if (failed()) { return primitiveFailureCode(); } - fprintf(stderr, "File exists: '%s'.\n", cString); - fflush(stderr); - accessFlag = access(cString, F_OK); - popthenPush(2, (accessFlag == 0 - ? trueObject() - : falseObject())); - return 0; + return methodReturnValue(faExists(faPath)); } @@ -1318,11 +824,9 @@ primitiveLogicalDrives(void) EXPORT(sqInt) primitiveOpendir(void) { - char cPathName[PATH_MAX+1]; - osdir *dir; sqInt dirName; sqInt dirOop; - sqInt len; + fapath *faPath; sqInt resultOop; sqInt status; @@ -1330,47 +834,38 @@ primitiveOpendir(void) if (!(isBytes(dirName))) { return primitiveFailFor(PrimErrBadArgument); } - squeakPathtoPlatformmaxLen(dirName, cPathName, PATH_MAX); - if (failed()) { - return primitiveFailureCode(); - } - len = strlen(cPathName); - fprintf(stderr, "File primOpendir: '%s'.\n", cPathName); - fflush(stderr); - if (len > (PATH_MAX - 2)) { - return primitiveFailForOSError(-1 /* stringTooLong */); + faPath = (fapath *) calloc(1, sizeof(fapath)); + if (faPath == null) { + return primitiveFailForOSError(-10 /* cantAllocateMemory */); } - if (!(canOpenDirectoryStreamForlength(cPathName, len))) { + faSetStDirOop(faPath, dirName); + if (!(canOpenDirectoryStreamForlength(faGetStPath(faPath), faGetStPathLen(faPath)))) { + free(faPath); return primitiveFailForOSError(-9 /* cantOpenDir */); } - dir = (osdir *) malloc(sizeof(osdir)); - fprintf(stderr, "malloc(%d) -> %p\n", sizeof(osdir), (void *)dir); - if (dir == null) { - return primitiveFailForOSError(-10 /* cantAllocateMemory */); - } - memcpy((dir->path), cPathName, len); - if (dir->path[len-1] != PATH_SEPARATOR) - dir->path[len++] = PATH_SEPARATOR; - dir->path_file = dir->path + len; - dir->max_file_len = PATH_MAX-len; - dir->path_file[0] = '\0'; - dir->path_len = len; - status = faOpenDirectory(dir); + status = faOpenDirectory(faPath); if (status == 1 /* noMoreData */) { return popthenPush(2, nilObject()); } if (status < 0) { - free(dir); + free(faPath); return primitiveFailForOSError(status); } - resultOop = processDirectory(dir); + resultOop = processDirectory(faPath); if (failed()) { - free(dir); + free(faPath); return primitiveFailureCode(); } - fprintf(stderr, "Opendir: %p\n", (void *)dir); - fflush(stderr); - dirOop = addressObjectFor(dir); + +#if SPURVM + dirOop = addressObjectFor(faPath); + +#else /* SPURVM */ + pushRemappableOop(resultOop); + dirOop = addressObjectFor(faPath); + resultOop = popRemappableOop() +#endif /* SPURVM */ +; return (storePointerofObjectwithValue(2, resultOop, dirOop), popthenPush(2, resultOop)); } @@ -1382,7 +877,43 @@ primitiveOpendir(void) EXPORT(sqInt) primitivePathMax(void) { - return popthenPush(1, integerObjectOf(PATH_MAX)); + return popthenPush(1, integerObjectOf(FA_PATH_MAX)); +} + + +/* Convert the supplied file name (platform encoded) to the St UTF8 encoded + byte array + */ + + /* FileAttributesPlugin>>#primitivePlatToStPath */ +EXPORT(sqInt) +primitivePlatToStPath(void) +{ + unsigned char *byteArrayPtr; + fapath *faPath; + sqInt fileName; + sqInt resultOop; + + fileName = stackObjectValue(0); + if ((failed()) + || (!(isBytes(fileName)))) { + return primitiveFailFor(PrimErrBadArgument); + } + faPath = (fapath *) calloc(1, sizeof(fapath)); + if (faPath == null) { + return primitiveFailForOSError(-10 /* cantAllocateMemory */); + } + faSetPlatPathOop(faPath, fileName); + if (failed()) { + return primitiveFailureCode(); + } + resultOop = instantiateClassindexableSize(classByteArray(), faGetStPathLen(faPath)); + if (!(resultOop)) { + return primitiveFailFor(PrimErrNoMemory); + } + byteArrayPtr = arrayValueOf(resultOop); + memcpy(byteArrayPtr, faGetStPath(faPath), faGetStPathLen(faPath)); + return methodReturnValue(resultOop); } @@ -1396,25 +927,23 @@ EXPORT(sqInt) primitiveReaddir(void) { sqInt dirPointerOop; - osdir *dirStream; + fapath *faPath; sqInt resultArray; sqInt status; dirPointerOop = stackValue(0); - dirStream = pointerFrom(dirPointerOop); - if (!(dirStream)) { + faPath = pointerFrom(dirPointerOop); + if (!(faPath)) { return primitiveFailFor(PrimErrBadArgument); } - fprintf(stderr, "Readdir 0x%p\n", (void *)dirStream); - fflush(stderr); - status = faReadDirectory(dirStream); + status = faReadDirectory(faPath); if (status == 1 /* noMoreData */) { return popthenPush(2, nilObject()); } if (status < 0) { return primitiveFailForOSError(status); } - resultArray = processDirectory(dirStream); + resultArray = processDirectory(faPath); if (failed()) { return primitiveFailureCode(); } @@ -1430,17 +959,53 @@ EXPORT(sqInt) primitiveRewinddir(void) { sqInt dirPointerOop; - osdir *dirStream; + fapath *faPath; dirPointerOop = stackValue(0); - dirStream = pointerFrom(dirPointerOop); - if (!(dirStream)) { + faPath = pointerFrom(dirPointerOop); + if (!(faPath)) { return primitiveFailFor(PrimErrBadArgument); } return primitiveFailForOSError(-14 /* unexpectedError */); } +/* Convert the supplied file name (UTF8 encoded) to the platform encoded byte + array + */ + + /* FileAttributesPlugin>>#primitiveStToPlatPath */ +EXPORT(sqInt) +primitiveStToPlatPath(void) +{ + unsigned char *byteArrayPtr; + fapath *faPath; + sqInt fileName; + sqInt resultOop; + + fileName = stackObjectValue(0); + if ((failed()) + || (!(isBytes(fileName)))) { + return primitiveFailFor(PrimErrBadArgument); + } + faPath = (fapath *) calloc(1, sizeof(fapath)); + if (faPath == null) { + return primitiveFailForOSError(-10 /* cantAllocateMemory */); + } + faSetStPathOop(faPath, fileName); + if (failed()) { + return primitiveFailureCode(); + } + resultOop = instantiateClassindexableSize(classByteArray(), faGetPlatPathByteCount(faPath)); + if (!(resultOop)) { + return primitiveFailFor(PrimErrNoMemory); + } + byteArrayPtr = arrayValueOf(resultOop); + memcpy(byteArrayPtr, faGetPlatPath(faPath), faGetPlatPathByteCount(faPath)); + return methodReturnValue(resultOop); +} + + /* Set the owner of the supplied file using chown(). */ /* FileAttributesPlugin>>#primitiveSymlinkChangeOwner */ @@ -1482,29 +1047,30 @@ primitiveSymlinkChangeOwner(void) EXPORT(sqInt) primitiveVersionString(void) { - popthenPush(1, stringFromCString("1.4.0d04")); + popthenPush(1, stringFromCString("1.4.0d08")); return 0; } /* FileAttributesPlugin>>#processDirectory: */ static sqInt -processDirectory(osdir *dirStream) +processDirectory(fapath *faPath) { sqInt attributeArray; sqInt entryName; sqInt resultArray; - int status; + sqInt status; sqInt val; attributeArray = 0; + entryName = 0; val = 0; - entryName = platformPathToOop((dirStream->path_file)); - if (failed()) { - return 0; + status = byteArrayFromCStringto(faGetStFile(faPath), (&entryName)); + if (status != 0) { + return primitiveFailForOSError(status); } /* If the stat() fails, still return the filename, just no attributes */ - status = fileToAttributeArraymaskarray((dirStream->path), 1, (&attributeArray)); + status = fileToAttributeArraymaskarray(faPath, 1, (&attributeArray)); if (status != 0) { attributeArray = nilObject(); } @@ -1635,7 +1201,6 @@ setInterpreter(struct VirtualMachine*anInterpreter) classByteArray = interpreterProxy->classByteArray; classString = interpreterProxy->classString; failed = interpreterProxy->failed; - falseObject = interpreterProxy->falseObject; instantiateClassindexableSize = interpreterProxy->instantiateClassindexableSize; integerObjectOf = interpreterProxy->integerObjectOf; ioLoadFunctionFrom = interpreterProxy->ioLoadFunctionFrom; @@ -1658,7 +1223,6 @@ setInterpreter(struct VirtualMachine*anInterpreter) stackObjectValue = interpreterProxy->stackObjectValue; stackValue = interpreterProxy->stackValue; storePointerofObjectwithValue = interpreterProxy->storePointerofObjectwithValue; - trueObject = interpreterProxy->trueObject; #endif /* !defined(SQUEAK_BUILTIN_PLUGIN) */ } return ok; @@ -1679,9 +1243,9 @@ static sqInt squeakPathtoPlatformmaxLen(sqInt pathOop, char *cPathString, sqInt maxLength) { int status; - char uxName[PATH_MAX+1]; + char uxName[FA_PATH_MAX]; - if (maxLength > (PATH_MAX+1)) { + if (maxLength >= (FA_PATH_MAX)) { return primitiveFailForOSError(-6 /* invalidArguments */); } @@ -1708,7 +1272,7 @@ squeakPathtoPlatformmaxLen(sqInt pathOop, char *cPathString, sqInt maxLength) /* FileAttributesPlugin>>#statArrayFor:toArray:from:fileName: */ static sqInt -statArrayFortoArrayfromfileName(char *cPathName, sqInt attributeArray, struct stat *statBufPointer, sqInt fileNameOop) +statArrayFortoArrayfromfileName(fapath *faPath, sqInt attributeArray, struct stat *statBufPointer, sqInt fileNameOop) { sqLong attributeDate; sqInt sizeIfFile; @@ -1733,7 +1297,7 @@ statArrayFortoArrayfromfileName(char *cPathName, sqInt attributeArray, struct st storePointerofObjectwithValue(7, attributeArray, positive64BitIntegerFor(sizeIfFile)); # if defined(_WIN32) - status = winFileTimesForto(cPathName, attributeArray); + status = winFileTimesForto(faPath, attributeArray); # else /* defined(_WIN32) */ /* begin posixFileTimesFrom:to: */ @@ -1773,26 +1337,6 @@ stringFromCString(const char *aCString) } -/* Populate the supplied Win32 file attribute structure */ - - /* FileAttributesPlugin>>#winFileAttributesFor:length:to: */ -#if _WIN32 -static sqInt -winFileAttributesForlengthto(char *pathString, sqInt pathLength, WIN32_FILE_ATTRIBUTE_DATA *winAttrs) -{ - WCHAR *win32Path; - - win32Path = 0; - ALLOC_WIN32_PATH(win32Path, pathString, pathLength); - if ((GetFileAttributesExW(win32Path, GetFileExInfoStandard, winAttrs)) == 0) { - /* begin getAttributesFailed */ - return -4; - } - return 0; -} -#endif /* _WIN32 */ - - /* Set the file creation time from the supplied attributes. */ /* FileAttributesPlugin>>#winFileCreationTimeFor:to: */ @@ -1867,20 +1411,19 @@ winFileLastWriteTimeForto(WIN32_FILE_ATTRIBUTE_DATA *winAttrs, sqLong *writeDate /* FileAttributesPlugin>>#winFileTimesFor:to: */ #if _WIN32 static sqInt -winFileTimesForto(char *cPathName, sqInt attributeArray) +winFileTimesForto(fapath *faPath, sqInt attributeArray) { sqLong attributeDate; sqInt status; - sqInt val; WIN32_FILE_ATTRIBUTE_DATA winAttrs; /* Get the file attributes */ attributeDate = 0; - val = 0; - status = winFileAttributesForlengthto(cPathName, strlen(cPathName), (&winAttrs)); - if (!(status == 0)) { - return status; + status = GetFileAttributesExW(faGetPlatPath2(faPath), GetFileExInfoStandard, &winAttrs); + if (status == 0) { + /* begin getAttributesFailed */ + return -4; } status = winFileLastAccessTimeForto((&winAttrs), (&attributeDate)); if (!(status == 0)) { @@ -1907,20 +1450,23 @@ winFileTimesForto(char *cPathName, sqInt attributeArray) static char _m[] = "FileAttributesPlugin"; void* FileAttributesPlugin_exports[][3] = { + {(void*)_m, "byteArrayFromCStringto", (void*)byteArrayFromCStringto}, {(void*)_m, "getModuleName", (void*)getModuleName}, {(void*)_m, "initialiseModule", (void*)initialiseModule}, {(void*)_m, "primitiveChangeMode\000\001", (void*)primitiveChangeMode}, {(void*)_m, "primitiveChangeOwner\000\001", (void*)primitiveChangeOwner}, {(void*)_m, "primitiveClosedir\000\001", (void*)primitiveClosedir}, - {(void*)_m, "primitiveFileAttribute\000\001", (void*)primitiveFileAttribute}, + {(void*)_m, "primitiveFileAttribute\000\000", (void*)primitiveFileAttribute}, {(void*)_m, "primitiveFileAttributes\000\001", (void*)primitiveFileAttributes}, - {(void*)_m, "primitiveFileExists\000\001", (void*)primitiveFileExists}, + {(void*)_m, "primitiveFileExists\000\000", (void*)primitiveFileExists}, {(void*)_m, "primitiveFileMasks\000\377", (void*)primitiveFileMasks}, {(void*)_m, "primitiveLogicalDrives\000\377", (void*)primitiveLogicalDrives}, - {(void*)_m, "primitiveOpendir\000\001", (void*)primitiveOpendir}, + {(void*)_m, "primitiveOpendir\000\000", (void*)primitiveOpendir}, {(void*)_m, "primitivePathMax\000\377", (void*)primitivePathMax}, + {(void*)_m, "primitivePlatToStPath\000\000", (void*)primitivePlatToStPath}, {(void*)_m, "primitiveReaddir\000\002", (void*)primitiveReaddir}, {(void*)_m, "primitiveRewinddir\000\001", (void*)primitiveRewinddir}, + {(void*)_m, "primitiveStToPlatPath\000\000", (void*)primitiveStToPlatPath}, {(void*)_m, "primitiveSymlinkChangeOwner\000\001", (void*)primitiveSymlinkChangeOwner}, {(void*)_m, "primitiveVersionString\000\377", (void*)primitiveVersionString}, {(void*)_m, "setInterpreter", (void*)setInterpreter}, @@ -1932,12 +1478,14 @@ void* FileAttributesPlugin_exports[][3] = { signed char primitiveChangeModeAccessorDepth = 1; signed char primitiveChangeOwnerAccessorDepth = 1; signed char primitiveClosedirAccessorDepth = 1; -signed char primitiveFileAttributeAccessorDepth = 1; +signed char primitiveFileAttributeAccessorDepth = 0; signed char primitiveFileAttributesAccessorDepth = 1; -signed char primitiveFileExistsAccessorDepth = 1; -signed char primitiveOpendirAccessorDepth = 1; +signed char primitiveFileExistsAccessorDepth = 0; +signed char primitiveOpendirAccessorDepth = 0; +signed char primitivePlatToStPathAccessorDepth = 0; signed char primitiveReaddirAccessorDepth = 2; signed char primitiveRewinddirAccessorDepth = 1; +signed char primitiveStToPlatPathAccessorDepth = 0; signed char primitiveSymlinkChangeOwnerAccessorDepth = 1; #endif /* ifdef SQ_BUILTIN_PLUGIN */