Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 76883 invoked from network); 11 Oct 2009 10:11:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 11 Oct 2009 10:11:40 -0000 Received: (qmail 20384 invoked by uid 500); 11 Oct 2009 10:11:40 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 20302 invoked by uid 500); 11 Oct 2009 10:11:39 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 20293 invoked by uid 99); 11 Oct 2009 10:11:39 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 Oct 2009 10:11:39 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 Oct 2009 10:11:29 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id DFD722388901; Sun, 11 Oct 2009 10:10:37 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r824046 - in /commons/sandbox/runtime/trunk/src/main/native: Makefile.msc.in include/acr_file.h include/arch/windows/acr_arch.h os/unix/finfo.c os/win32/dir.c os/win32/dirent.c os/win32/finfo.c Date: Sun, 11 Oct 2009 10:10:37 -0000 To: commits@commons.apache.org From: mturk@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091011101037.DFD722388901@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: mturk Date: Sun Oct 11 10:10:37 2009 New Revision: 824046 URL: http://svn.apache.org/viewvc?rev=824046&view=rev Log: Implement windows FileInfo and Directory API Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h commons/sandbox/runtime/trunk/src/main/native/os/unix/finfo.c commons/sandbox/runtime/trunk/src/main/native/os/win32/dir.c commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c commons/sandbox/runtime/trunk/src/main/native/os/win32/finfo.c Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in Sun Oct 11 10:10:37 2009 @@ -118,7 +118,6 @@ $(SRCDIR)/os/win32/fsysio.$(OBJ) \ $(SRCDIR)/os/win32/main.$(OBJ) \ $(SRCDIR)/os/win32/platform.$(OBJ) \ - $(SRCDIR)/os/win32/pipe.$(OBJ) \ $(SRCDIR)/os/win32/proc.$(OBJ) \ $(SRCDIR)/os/win32/os.$(OBJ) \ $(SRCDIR)/os/win32/ios.$(OBJ) \ Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h Sun Oct 11 10:10:37 2009 @@ -298,8 +298,11 @@ * @param fname FileInfo.Name field. * @param type FileInfo.Type field. */ -ACR_DECLARE(jobject) ACR_NewFileInfoObject(JNIEnv *env, - const acr_pchar_t *fname, int type); +ACR_DECLARE(jobject) ACR_NewFileInfoObjectA(JNIEnv *env, + const char *fname, int type); + +ACR_DECLARE(jobject) ACR_NewFileInfoObjectW(JNIEnv *env, + const wchar_t *fname, int type); #ifdef __cplusplus } Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h Sun Oct 11 10:10:37 2009 @@ -308,6 +308,17 @@ return; } +static ACR_INLINE void FileTimeToMsecTime(acr_time_t *result, LPFILETIME input) +{ + /* Convert FILETIME one 64 bit number so we can work with it. */ + *result = ((LARGE_INTEGER *)input)->QuadPart; + /* Convert from 100 nano-sec periods to micro-seconds. */ + *result /= 10000; + /* Convert from Windows epoch to Unix epoch */ + *result -= ACR_DELTA_EPOCH_IN_USEC; + return; +} + static ACR_INLINE void UsecTimeToFileTime(LPFILETIME result, acr_time_t t) { @@ -315,6 +326,12 @@ return; } +static ACR_INLINE void MsecTimeToFileTime(LPFILETIME result, acr_time_t t) +{ + ((LARGE_INTEGER *)result)->QuadPart = (t + ACR_DELTA_EPOCH_IN_USEC) * 10000; + return; +} + static ACR_INLINE void x_free(void *p) { if (p != NULL) { @@ -419,6 +436,17 @@ */ } DIR; +/** Dirent API + */ +DIR *opendir(const char *); +int closedir(DIR *); +void rewinddir(DIR *); +off_t telldir(DIR *); +int readdir_r(DIR *, struct dirent *, struct dirent **r); +void seekdir(DIR *, off_t); + + + #define _NSIG 32 /* counting 0; could be 33 (mask is 1-32) */ #define SIGHUP 1 /* hangup */ Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/finfo.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/finfo.c?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/finfo.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/finfo.c Sun Oct 11 10:10:37 2009 @@ -165,8 +165,8 @@ ACR_UnloadClass(_E, &_clazzn); } -ACR_DECLARE(jobject) ACR_NewFileInfoObject(JNIEnv *_E, const char *fname, - int type) +ACR_DECLARE(jobject) ACR_NewFileInfoObjectA(JNIEnv *_E, const char *fname, + int type) { jstring name; if ((name = ACR_NewJavaStringA(_E, fname))) @@ -175,6 +175,16 @@ return NULL; } +ACR_DECLARE(jobject) ACR_NewFileInfoObjectW(JNIEnv *_E, const wchar_t *fname, + int type) +{ + jstring name; + if ((name = ACR_NewJavaStringW(_E, fname))) + return (*_E)->NewObject(_E, _clazzn.i, J4MID(0001), type); + else + return NULL; +} + static void _fill0(ACR_JNISTDARGS, struct_stat_t *info, jboolean full) { SET_IFIELD_I(0000, _O, ACR_UnixModeToPerms(info->st_mode)); Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/dir.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/dir.c?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/dir.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/dir.c Sun Oct 11 10:10:37 2009 @@ -1,19 +1,3 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - #include "acr.h" #include "acr_private.h" #include "acr_arch.h" @@ -25,6 +9,280 @@ #include "acr_port.h" /** - * Windows file info functions + * Windows directory functions * */ + +static int descriptor_cleanup(ACR_JNISTDARGS, + acr_descriptor_cb_type_e cm, + acr_descriptor_cb_t *dp) +{ + int rc = ACR_SUCCESS; + switch (cm) { + case ACR_DESC_FINALIZE: + case ACR_DESC_CLOSE: + if (dp->dp != NULL) { + if (closedir((DIR *)dp->dp)) + rc = ACR_GET_OS_ERROR(); + } + else + rc = ACR_EBADF; + break; + default: + rc = ACR_ENOTIMPL; + break; + } + return rc; +} + +ACR_IO_EXPORT_DECLARE(jobject, Directory, open0)(ACR_JNISTDARGS, jstring name) +{ + DIR *dir; + jobject dd = NULL; + int rc = 0; + + WITH_CSTR(name) { + if ((dir = opendir(J2S(name)))) { + dd = ACR_DescriptorCreate(_E, ACR_DT_DIR, -1, dir, + descriptor_cleanup); + } + else + rc = ACR_GET_OS_ERROR(); + } END_WITH_CSTR(name); + ACR_THROW_IO_IF_ERR(rc); + return dd; +} + +ACR_IO_EXPORT_DECLARE(jstring, Directory, read0)(ACR_JNISTDARGS, jobject dd) +{ + DIR *dir; + int rc = 0; + jstring rv = NULL; + + dir = (DIR *)ACR_DescriptorGetPtr(_E, dd); + if (dir) { + struct dirent ds; + struct dirent *dp; + for (;;) { + if (!readdir_r(dir, &ds, &dp)) { + if (dp) { + if (*(dp->d_name) == '.' && (*(dp->d_name + 1) == '\0' || + (*(dp->d_name + 1) == '.' && + *(dp->d_name + 2) == '\0'))) { + /* Skip . and .. directory entires + */ + continue; + } + /* Not at end of dir */ + rv = ACR_NewJavaStringA(_E, dp->d_name); + } + else + break; + } + else { + /* readdir_r failed */ + rc = ACR_GET_OS_ERROR(); + break; + } + } + } + ACR_THROW_IO_IF_ERR(rc); + return rv; +} + +ACR_IO_EXPORT_DECLARE(jobject, Directory, read1)(ACR_JNISTDARGS, jobject dd) +{ + DIR *dir; + int rc = 0; + jobject rv = NULL; + + dir = (DIR *)ACR_DescriptorGetPtr(_E, dd); + if (dir) { + struct dirent ds; + struct dirent *dp; + for (;;) { + if (!readdir_r(dir, &ds, &dp)) { + if (dp) { + int type; + if (*(dp->d_name) == '.' && (*(dp->d_name + 1) == '\0' || + (*(dp->d_name + 1) == '.' && + *(dp->d_name + 2) == '\0'))) { + /* Skip . and .. directory entires + */ + continue; + } + /* Determine the type of the enty + */ + if (dp->d_type & FILE_ATTRIBUTE_DIRECTORY) + type = ACR_FT_DIR; + else if (dp->d_type & FILE_ATTRIBUTE_REPARSE_POINT) + type = ACR_FT_LNK; + else if (dp->d_type & FILE_ATTRIBUTE_DEVICE) + type = ACR_FT_CHR; + else + type = ACR_FT_REG; + rv = ACR_NewFileInfoObjectA(_E, dp->d_name, type); + } + else + break; + } + else { + /* readdir_r failed */ + rc = ACR_GET_OS_ERROR(); + break; + } + } + } + ACR_THROW_IO_IF_ERR(rc); + return rv; +} + +ACR_IO_EXPORT_DECLARE(void, Directory, rewind0)(ACR_JNISTDARGS, jobject dd) +{ + DIR *dir; + if (( dir = (DIR *)ACR_DescriptorGetPtr(_E, dd))) { + rewinddir(dir); + } +} + +ACR_IO_EXPORT_DECLARE(jlong, Directory, tell0)(ACR_JNISTDARGS, jobject dd) +{ + DIR *dir; + off_t pos = -1; + int rc = 0; + + if (( dir = (DIR *)ACR_DescriptorGetPtr(_E, dd))) { + pos = telldir(dir); + if (pos == -1) + rc = ACR_GET_OS_ERROR(); + } + else + rc = ACR_EBADF; + ACR_THROW_IO_IF_ERR(rc); + return (jlong)pos; +} + +ACR_IO_EXPORT_DECLARE(void, Directory, seek0)(ACR_JNISTDARGS, jobject dd, + jlong off) +{ + DIR *dir; + + if (( dir = (DIR *)ACR_DescriptorGetPtr(_E, dd))) { + seekdir(dir, (off_t)off); + } +} + +static int _mkdir0(const wchar_t *name, int perms) +{ + SECURITY_ATTRIBUTES sa; + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + /* Allow access only to owner and Administrators Group */ + sa.lpSecurityDescriptor = ACR_StdSecurityDescriptor(INVALID_HANDLE_VALUE, + ACR_DT_FILE, perms); + + if (CreateDirectoryW(name, &sa)) + return 0; + else + return ACR_GET_OS_ERROR(); +} + +static __inline void FS2BS(wchar_t *path) +{ + while (*path) { + if (*path == L'/') + *path = L'\\'; + path++; + } +} + +static int _mkdir1(const wchar_t *name, int perms) +{ + int rc; + + rc = _mkdir0(name, perms); + if (rc == ERROR_ALREADY_EXISTS) + return 0; + if (rc == ERROR_PATH_NOT_FOUND) { /* Missing an intermediate dir */ + wchar_t *pos; + wchar_t *dir = ACR_StrdupW(INVALID_HANDLE_VALUE, THROW_NMARK, name); + if (!dir) + return ACR_ENOMEM; + FS2BS(dir); + if ((pos = wcsrchr(dir, L'\\'))) { + *pos = L'\0'; + if (*dir) { + rc = _mkdir1(dir, perms); + } + } + x_free(dir); + } + return rc; +} + +ACR_IO_EXPORT_DECLARE(jint, Directory, mkdir0)(ACR_JNISTDARGS, jstring name, + jint perms) +{ + int rc = 0; + + WITH_WSTR(name) { + rc = _mkdir0(J2W(name), perms); + } END_WITH_WSTR(name); + return rc; +} + +ACR_IO_EXPORT_DECLARE(jint, Directory, mkdir1)(ACR_JNISTDARGS, jstring name, + jint perms) +{ + int rc = 0; + + WITH_WSTR(name) { + rc = _mkdir1(J2W(name), perms); + } END_WITH_WSTR(name); + return rc; +} + +ACR_IO_EXPORT_DECLARE(jstring, Directory, tmpdir0)(ACR_JNISTDARGS, jstring path, + jstring prefix) +{ + int rc = 0; + wchar_t *tmpd = NULL; + + UNREFERENCED_O; + + WITH_ZWSTR(path) { + WITH_ZWSTR(prefix) { + /* Provide INVALID_HANDLE_VALUE for JNIEnv + * so that in case of failure, exception doesn't get thrown + */ + tmpd = ACR_TempDirMake(INVALID_HANDLE_VALUE, J2W(path), J2W(prefix)); + if (!tmpd) + rc = ACR_GET_OS_ERROR(); + } END_WITH_WSTR(prefix); + } END_WITH_WSTR(path); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + return NULL; + } + else { + jstring rv = ACR_NewJavaStringW(_E, tmpd); + x_free(tmpd); + return rv; + } +} + +ACR_IO_EXPORT_DECLARE(jstring, Directory, tmpdir1)(ACR_JNISTDARGS, + jstring paths) +{ + const wchar_t *tmpd = NULL; + + UNREFERENCED_O; + + WITH_ZWSTR(paths) { + tmpd = ACR_TempPathGet(INVALID_HANDLE_VALUE, J2W(paths)); + } END_WITH_WSTR(paths); + if (tmpd) + return ACR_NewJavaStringW(_E, tmpd); + else + return NULL; +} Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c Sun Oct 11 10:10:37 2009 @@ -181,7 +181,7 @@ if (mblen == 0 || mblen > 1024) return GetLastError(); entry->d_ino = 0; - entry->d_type = 0; + entry->d_type = wfind.dwFileAttributes; entry->d_off = dir->d_stat; entry->d_reclen = (unsigned short)(mblen - 1); *result = entry; Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/finfo.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/finfo.c?rev=824046&r1=824045&r2=824046&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/finfo.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/finfo.c Sun Oct 11 10:10:37 2009 @@ -14,15 +14,17 @@ * limitations under the License. */ + #include "acr.h" #include "acr_private.h" #include "acr_arch.h" +#include "acr_clazz.h" +#include "acr_descriptor.h" #include "acr_port.h" #include "acr_error.h" #include "acr_string.h" -#include "acr_descriptor.h" +#include "acr_users.h" #include "acr_file.h" -#include "acr_port.h" /** * Windows file info functions @@ -121,6 +123,12 @@ J_DECLARE_M_ID(0001) = { NULL, + "", + "(Ljava/lang/String;I)V" +}; + +J_DECLARE_M_ID(0002) = { + NULL, "setType", "(I)V" }; @@ -146,6 +154,7 @@ J_LOAD_IFIELD(0012); J_LOAD_METHOD(0000); J_LOAD_METHOD(0001); + J_LOAD_METHOD(0002); return ACR_SUCCESS; } @@ -154,3 +163,348 @@ { ACR_UnloadClass(_E, &_clazzn); } + +ACR_DECLARE(jobject) ACR_NewFileInfoObjectA(JNIEnv *_E, const char *fname, + int type) +{ + jstring name; + if ((name = ACR_NewJavaStringA(_E, fname))) + return (*_E)->NewObject(_E, _clazzn.i, J4MID(0001), type); + else + return NULL; +} + +ACR_DECLARE(jobject) ACR_NewFileInfoObjectW(JNIEnv *_E, const wchar_t *fname, + int type) +{ + jstring name; + if ((name = ACR_NewJavaStringW(_E, fname))) + return (*_E)->NewObject(_E, _clazzn.i, J4MID(0001), type); + else + return NULL; +} + +static void _fill0(ACR_JNISTDARGS, BY_HANDLE_FILE_INFORMATION *info) +{ + acr_time_t time; + ULARGE_INTEGER u; + + SET_IFIELD_I(0003, _O, info->nNumberOfLinks); + u.LowPart = info->nFileSizeLow; + u.HighPart = info->nFileSizeHigh; + SET_IFIELD_J(0004, _O, u.QuadPart); + SET_IFIELD_J(0005, _O, u.QuadPart); + FileTimeToMsecTime(&time, &info->ftLastAccessTime); + SET_IFIELD_J(0006, _O, time); + FileTimeToMsecTime(&time, &info->ftLastWriteTime); + SET_IFIELD_J(0007, _O, time); + FileTimeToMsecTime(&time, &info->ftCreationTime); + SET_IFIELD_J(0008, _O, time); + u.LowPart = info->nFileIndexLow; + u.HighPart = info->nFileIndexHigh; + u.QuadPart += ((UINT64)info->dwVolumeSerialNumber << 30); + SET_IFIELD_J(0011, _O, u.QuadPart); + SET_IFIELD_J(0012, _O, info->dwVolumeSerialNumber); + +} + +extern PSID acr_everyone_sid; + +/* Left bit shifts from World scope to given scope */ +typedef enum prot_scope_e { + prot_scope_world = 0, + prot_scope_group = 4, + prot_scope_user = 8 +} prot_scope_e; + +static int convert_prot(ACCESS_MASK acc, prot_scope_e scope) +{ + /* These choices are based on the single filesystem bit that controls + * the given behavior. They are -not- recommended for any set protection + * function, such a function should -set- use GENERIC_READ/WRITE/EXECUTE + */ + int prot = 0; + if (acc & FILE_EXECUTE) + prot |= ACR_FPROT_WEXECUTE; + if (acc & FILE_WRITE_DATA) + prot |= ACR_FPROT_WWRITE; + if (acc & FILE_READ_DATA) + prot |= ACR_FPROT_WREAD; + return (prot << scope); +} + +static int resolve_prot(PSID user, PSID group, PACL dacl) +{ + TRUSTEE_W ident = { NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID }; + ACCESS_MASK acc; + int protection = 0; + /* + * This function is only invoked for WinNT, + * there is no reason for os_level testing here. + */ + if (user) { + ident.TrusteeType = TRUSTEE_IS_USER; + ident.ptstrName = user; + /* GetEffectiveRightsFromAcl isn't supported under Win9x, + * which shouldn't come as a surprize. Since we are passing + * TRUSTEE_IS_SID, always skip the A->W layer. + */ + if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { + protection |= convert_prot(acc, prot_scope_user); + } + } + /* Windows NT: did not return group rights. + * Windows 2000 returns group rights information. + * Since WinNT kernels don't follow the unix model of + * group associations, this all all pretty mute. + */ + if (group) { + ident.TrusteeType = TRUSTEE_IS_GROUP; + ident.ptstrName = group; + if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { + protection |= convert_prot(acc, prot_scope_group); + } + } + if (acr_everyone_sid) { + ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ident.ptstrName = acr_everyone_sid; + if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { + protection |= convert_prot(acc, prot_scope_world); + } + } + return protection; +} + +static int _fill1(ACR_JNISTDARGS, HANDLE ih, DWORD attrs, jboolean full) +{ + int rc; + int prot; + PSID usr = NULL; + PSID grp = NULL; + PACL acl = NULL; + SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; + PSECURITY_DESCRIPTOR sd = NULL; + + if (full) + si |= (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION); + rc = GetSecurityInfo(ih, + SE_FILE_OBJECT, + si, + full ? &usr : NULL, + full ? &grp : NULL, + &acl, + NULL, + &sd); + if (rc != ERROR_SUCCESS) { + return rc; + } + if (full) { + SET_IFIELD_O(0001, _O, ACR_UserObjectCreateFromId(_E, usr)); + SET_IFIELD_O(0002, _O, ACR_GroupObjectCreateFromId(_E, grp)); + } + prot = resolve_prot(usr, grp, acl); + if (attrs & FILE_ATTRIBUTE_READONLY) { + /* Clear any WRITE attributes */ + prot &= ~ACR_FPROT_UWRITE; + prot &= ~ACR_FPROT_GWRITE; + prot &= ~ACR_FPROT_WWRITE; + } + if (attrs & FILE_ATTRIBUTE_HIDDEN) { + /* XXX: Hidden files are non-executable? */ + prot &= ~ACR_FPROT_UEXECUTE; + prot &= ~ACR_FPROT_GEXECUTE; + prot &= ~ACR_FPROT_WEXECUTE; + } + SET_IFIELD_I(0000, _O, prot); + + LocalFree(sd); + return 0; +} + +static int _ftype0(DWORD attrs) +{ + int type = ACR_FT_REG; + + if (attrs & FILE_ATTRIBUTE_DIRECTORY) + type = ACR_FT_DIR; + else if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) + type = ACR_FT_LNK; + else if (attrs & FILE_ATTRIBUTE_DEVICE) + type = ACR_FT_CHR; + return type; +} + +static jobject _stat0(JNIEnv *_E, const wchar_t *fname, + jboolean link, jboolean full) +{ + jobject fi; + BY_HANDLE_FILE_INFORMATION info; + HANDLE ih; + int rc = 0; + int type; + + ih = CreateFileW(fname, + 0, /* Query attributes without accessing the file */ + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (IS_INVALID_HANDLE(ih)) { + ACR_THROW_IO_ERRNO(); + return NULL; + } + if (!GetFileInformationByHandle(ih, &info)) { + rc = ACR_GET_OS_ERROR(); + goto finally; + } + type = _ftype0(info.dwFileAttributes); + + fi = (*_E)->NewObject(_E, _clazzn.i, J4MID(0000), type); + if (!fi) { + CloseHandle(ih); + return NULL; + } + if (full) { + /* Resolve full path name + */ + wchar_t *path; + wchar_t *name = acr_GetAbsolutePath(_E, ih, fname); + SET_IFIELD_W(0009, fi, name); + if ((path = wcsrchr(name, L'\\'))) + SET_IFIELD_W(0010, fi, path); + else { + if ((path = wcsrchr(name, L'/'))) + SET_IFIELD_W(0010, fi, path); + else + SET_IFIELD_W(0010, fi, name); + } + x_free(name); + } + _fill0(_E, fi, &info); + rc = _fill1(_E, fi, ih, info.dwFileAttributes, full); + +finally: + CloseHandle(ih); + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + fi = NULL; + } + return fi; +} + +static jobject _stat1(JNIEnv *_E, int file, jboolean full) +{ + jobject fi; + BY_HANDLE_FILE_INFORMATION info; + int rc = 0; + int type; + acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file); + + if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) { + ACR_THROW_IO_IF_ERR(ACR_EFTYPE); + return NULL; + } + if (IS_INVALID_HANDLE(f)) { + ACR_THROW_IO_IF_ERR(ACR_EBADF); + return NULL; + } + + + if (!GetFileInformationByHandle(f->fd, &info)) { + rc = ACR_GET_OS_ERROR(); + goto finally; + } + type = _ftype0(info.dwFileAttributes); + + fi = (*_E)->NewObject(_E, _clazzn.i, J4MID(0000), type); + if (!fi) { + return NULL; + } + if (full) { + /* Resolve base name + */ + wchar_t *path; + SET_IFIELD_W(0009, fi, f->name); + if ((path = wcsrchr(f->name, L'\\'))) + SET_IFIELD_W(0010, fi, path + 1); + else { + if ((path = wcsrchr(f->name, L'/'))) + SET_IFIELD_W(0010, fi, path + 1); + else + SET_IFIELD_W(0010, fi, f->name); + } + } + _fill0(_E, fi, &info); + rc = _fill1(_E, fi, f->fd, info.dwFileAttributes, full); + +finally: + if (rc) { + ACR_THROW_IO_IF_ERR(rc); + fi = NULL; + } + return fi; +} + +static int _stat2(ACR_JNISTDARGS, const wchar_t *fname, jboolean link) +{ + BY_HANDLE_FILE_INFORMATION info; + HANDLE ih; + int rc = 0; + + ih = CreateFileW(fname, + 0, /* Query attributes without accessing the file */ + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (IS_INVALID_HANDLE(ih)) { + return ACR_GET_OS_ERROR(); + } + if (!GetFileInformationByHandle(ih, &info)) { + rc = ACR_GET_OS_ERROR(); + goto finally; + } + CALL_VMETHOD1(0002, _O, _ftype0(info.dwFileAttributes)); + _fill0(_E, _O, &info); + rc = _fill1(_E, _O, ih, info.dwFileAttributes, JNI_TRUE); + +finally: + CloseHandle(ih); + return rc; +} + + +ACR_IO_EXPORT_DECLARE(jobject, File, stat0)(ACR_JNISTDARGS, + jstring fname, + jboolean link, + jboolean full) +{ + jobject fi = NULL; + WITH_WSTR(fname) { + fi = _stat0(_E, J2W(fname), link, full); + } END_WITH_WSTR(fname); + + return fi; +} + + +ACR_IO_EXPORT_DECLARE(jint, FileInfo, stat0)(ACR_JNISTDARGS, + jstring fname, + jboolean link) +{ + int rc = 0; + WITH_WSTR(fname) { + rc = _stat2(_E, _O, J2W(fname), link); + } END_WITH_WSTR(fname); + + return rc; +} + +ACR_IO_EXPORT_DECLARE(jobject, FileWrapper, stat0)(ACR_JNISTDARGS, + jint fd, + jboolean full) +{ + return _stat1(_E, fd, full); +}