static int stat2(const char *file, struct stat *sb, uint64_t *winattr) { HANDLE h=INVALID_HANDLE_VALUE; int rval=0; char tmpbuf[5000]; conv_unix_to_win32_path(file, tmpbuf, 5000); DWORD attr=(DWORD)-1; if(p_GetFileAttributesW) { char* pwszBuf=sm_get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf); attr=p_GetFileAttributesW((LPCWSTR) pwszBuf); if(p_CreateFileW) h=CreateFileW((LPCWSTR)pwszBuf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); sm_free_pool_memory(pwszBuf); } else if(p_GetFileAttributesA) { attr=p_GetFileAttributesA(tmpbuf); h=CreateFileA(tmpbuf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); } if(attr==(DWORD)-1) { const char *err=errorString(); LocalFree((void *)err); if(h!=INVALID_HANDLE_VALUE) CloseHandle(h); errno=b_errno_win32; return -1; } if(h==INVALID_HANDLE_VALUE) { const char *err=errorString(); LocalFree((void *)err); errno=b_errno_win32; return -1; } rval=do_fstat((intptr_t)h, sb, winattr); CloseHandle(h); if(attr & FILE_ATTRIBUTE_DIRECTORY && file[1]==':' && file[2]) rval = statDir(file, sb, winattr); return rval; }
ReturnStatus FileMetaDAO::getDir2(const std::string &path, std::list<EDEntry> *pEntryList) { assert(pEntryList); Channel* pDataChannel = ChannelManager::getInstance()->Mapping(m_BucketId); NameSpace *DataNS = pDataChannel->m_DataNS; int rt = 0; int error = 0; std::string entryName; std::string npath; Args st; rt = DataNS->OpenDir(path.c_str(), &st); if (false == st.valid) { error = errno; ERROR_LOG("path %s, opendir() error, %s.", path.c_str(), strerror(errno)); if (ENOTDIR == error) { return ReturnStatus(MU_FAILED, NOT_DIRECTORY); } else if (ENOENT == error) { return checkPrefix(path); } } FileMeta meta; ReturnStatus rs; Dirent dirent; while(DataNS->ReadDirNext(&st, &dirent)){ entryName = dirent.filetype; npath = path + PATH_SEPARATOR_STRING + entryName; // omit "." and ".." // omit user info file in user root dir if (entryName == DENTRY_CURRENT_DIR || entryName == DENTRY_PARENT_DIR || entryName == USER_INFO_FILE_NAME) { continue; } EDEntry ent; ent.m_Name = entryName; if (MU_DIRECTORY == dirent.filetype) { ent.m_Type = MU_DIRECTORY; rs = statDir(npath, &meta); if (!rs.success()) { ERROR_LOG("path %s, statDir() error", npath.c_str()); return rs; } ent.m_Mode = meta.m_Attr.m_Mode; ent.m_CTime = meta.m_Attr.m_CTime; ent.m_MTime = meta.m_Attr.m_MTime; ent.m_Size = meta.m_Attr.m_Size; } else { // clear data of last entry meta.m_BlockList.clear(); rs = getFile(npath, &meta); if (!rs.success()) { ERROR_LOG("path %s, getFile() error", npath.c_str()); return rs; } ent.m_Mode = meta.m_Attr.m_Mode; ent.m_CTime = meta.m_Attr.m_CTime; ent.m_MTime = meta.m_Attr.m_MTime; ent.m_Size = meta.m_Attr.m_Size; ent.m_Version = meta.m_Attr.m_Version; ent.m_Type = meta.m_Attr.m_Type; ent.m_BlockList = meta.m_BlockList; } pEntryList->push_back(ent); } return ReturnStatus(MU_SUCCESS); }
static int do_stat(const char *file, struct stat *sb, uint64_t *winattr) { WIN32_FILE_ATTRIBUTE_DATA data; errno=0; memset(sb, 0, sizeof(*sb)); memset(winattr, 0, sizeof(*winattr)); if(p_GetFileAttributesExW) { // Dynamically allocate enough space for UCS2 filename. char *pwszBuf=sm_get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, file); BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard, &data); sm_free_pool_memory(pwszBuf); if(!b) return stat2(file, sb, winattr); } else if(p_GetFileAttributesExA) { if(!p_GetFileAttributesExA(file, GetFileExInfoStandard, &data)) return stat2(file, sb, winattr); } else return stat2(file, sb, winattr); *winattr=(int64_t)data.dwFileAttributes; /* Graham says: all the following stuff seems rather complicated. It is probably not all needed anymore, since I have added *winattr above, which bacula did not do. One reason for keeping it is that some of the values get converted to unix-style permissions that show up in the long list functionality. I think I would prefer to remove it all though. */ sb->st_mode = 0777; // Start with everything. if(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); if(data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) sb->st_mode &= ~S_IRWXO; // Remove everything for other. if(data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) sb->st_mode |= S_ISVTX; // use sticky bit -> hidden. if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) sb->st_mode |= S_IFDIR; else sb->st_mode |= S_IFREG; // Use st_rdev to store reparse attribute. sb->st_rdev=(data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)?1:0; sb->st_nlink=1; sb->st_size=data.nFileSizeHigh; sb->st_size<<=32; sb->st_size|=data.nFileSizeLow; sb->st_blksize=4096; sb->st_blocks=(uint32_t)(sb->st_size + 4095)/4096; sb->st_atime=cvt_ftime_to_utime(data.ftLastAccessTime); sb->st_mtime=cvt_ftime_to_utime(data.ftLastWriteTime); sb->st_ctime=cvt_ftime_to_utime(data.ftCreationTime); /* If we are not at the root, then to distinguish a reparse point from a mount point, we must call FindFirstFile() to get the WIN32_FIND_DATA, which has the bit that indicates that this directory is a mount point -- aren't Win32 APIs wonderful? (sarcasm). The code exists in the statDir subroutine. */ if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && file[1]==':' && file[2]) statDir(file, sb, winattr); return 0; }