88/* Some code was taken from u-boot, https://github.com/u-boot/u-boot/tree/master/fs/btrfs */
99
1010#include <freeldr.h>
11+ #include "fs/stat.h"
1112
1213#include <debug.h>
1314DBG_DEFAULT_CHANNEL (FILESYSTEM );
@@ -1051,15 +1052,16 @@ static inline const char *skip_current_directories(const char *cur)
10511052
10521053static u64 btrfs_lookup_path (PBTRFS_INFO BtrFsInfo ,
10531054 const struct btrfs_root_item * root , u64 inr , const char * path ,
1054- u8 * type_p , struct btrfs_inode_item * inode_item_p , int symlink_limit )
1055+ u8 * type_p , struct btrfs_inode_item * inode_item_p , int symlink_limit ,
1056+ _Out_opt_ PCHAR filename_buffer , _Inout_ PULONG filename_length )
10551057{
10561058 struct btrfs_dir_item item ;
10571059 struct btrfs_inode_item inode_item ;
10581060 u8 type = BTRFS_FT_DIR ;
10591061 int len , have_inode = 0 ;
10601062 const char * cur = path ;
1061- struct btrfs_disk_key key ;
1062- char * link_target = NULL ;
1063+ const char * last_elem ;
1064+ int last_elem_len ;
10631065
10641066 if (* cur == '/' || * cur == '\\' )
10651067 {
@@ -1078,6 +1080,10 @@ static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo,
10781080 return INVALID_INODE ;
10791081 }
10801082
1083+ /* Save the pointer/length of the current path element */
1084+ last_elem = cur ;
1085+ last_elem_len = len ;
1086+
10811087 if (len == 1 && cur [0 ] == '.' )
10821088 break ;
10831089
@@ -1109,6 +1115,8 @@ static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo,
11091115
11101116 if (type == BTRFS_FT_SYMLINK && symlink_limit >= 0 )
11111117 {
1118+ char * link_target = NULL ;
1119+
11121120 if (!symlink_limit )
11131121 {
11141122 TRACE ("%s: Too much symlinks!\n" );
@@ -1119,7 +1127,9 @@ static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo,
11191127 if (!btrfs_readlink (BtrFsInfo , root , item .location .objectid , & link_target ))
11201128 return INVALID_INODE ;
11211129
1122- inr = btrfs_lookup_path (BtrFsInfo , root , inr , link_target , & type , & inode_item , symlink_limit - 1 );
1130+ inr = btrfs_lookup_path (BtrFsInfo , root , inr , link_target ,
1131+ & type , & inode_item , symlink_limit - 1 ,
1132+ NULL , NULL );
11231133
11241134 FrLdrTempFree (link_target , TAG_BTRFS_LINK );
11251135
@@ -1144,6 +1154,7 @@ static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo,
11441154 {
11451155 if (!have_inode )
11461156 {
1157+ struct btrfs_disk_key key ;
11471158 key .objectid = inr ;
11481159 key .type = BTRFS_INODE_ITEM_KEY ;
11491160 key .offset = 0 ;
@@ -1155,6 +1166,13 @@ static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo,
11551166 * inode_item_p = inode_item ;
11561167 }
11571168
1169+ if (filename_buffer )
1170+ {
1171+ /* Copy the file name, perhaps truncated */
1172+ * filename_length = min (* filename_length , last_elem_len );
1173+ RtlCopyMemory (filename_buffer , last_elem , * filename_length );
1174+ }
1175+
11581176 return inr ;
11591177}
11601178
@@ -1176,6 +1194,14 @@ ARC_STATUS BtrFsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
11761194 Information -> EndingAddress .QuadPart = phandle -> inode .size ;
11771195 Information -> CurrentAddress .QuadPart = phandle -> position ;
11781196
1197+ /* Set the ARC file attributes */
1198+ Information -> Attributes = phandle -> Attributes ;
1199+
1200+ /* Copy the file name, perhaps truncated, and NUL-terminated */
1201+ Information -> FileNameLength = min (phandle -> FileNameLength , sizeof (Information -> FileName ) - 1 );
1202+ RtlCopyMemory (Information -> FileName , phandle -> FileName , Information -> FileNameLength );
1203+ Information -> FileName [Information -> FileNameLength ] = ANSI_NULL ;
1204+
11791205 TRACE ("BtrFsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n" ,
11801206 FileId , Information -> EndingAddress .QuadPart , Information -> CurrentAddress .QuadPart );
11811207
@@ -1186,6 +1212,7 @@ ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
11861212{
11871213 PBTRFS_INFO BtrFsInfo ;
11881214 ULONG DeviceId ;
1215+ ULONG FileNameLength ;
11891216 u64 inr ;
11901217 u8 type ;
11911218
@@ -1202,22 +1229,43 @@ ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
12021229 DeviceId = FsGetDeviceId (* FileId );
12031230 BtrFsInfo = BtrFsVolumes [DeviceId ];
12041231
1232+ temp_file_info .FileNameLength = 0 ;
1233+ temp_file_info .FileName [0 ] = ANSI_NULL ;
1234+ FileNameLength = sizeof (temp_file_info .FileName ) - 1 ;
1235+
12051236 inr = btrfs_lookup_path (BtrFsInfo , & BtrFsInfo -> FsRoot ,
12061237 BtrFsInfo -> FsRoot .root_dirid ,
1207- Path , & type , & temp_file_info .inode , 40 );
1208-
1238+ Path , & type , & temp_file_info .inode , 40 ,
1239+ temp_file_info . FileName , & FileNameLength );
12091240 if (inr == INVALID_INODE )
12101241 {
12111242 TRACE ("Cannot lookup file %s\n" , Path );
12121243 return ENOENT ;
12131244 }
1214-
12151245 if (type != BTRFS_FT_REG_FILE )
12161246 {
12171247 TRACE ("Not a regular file: %s\n" , Path );
12181248 return EISDIR ;
12191249 }
12201250
1251+ temp_file_info .FileNameLength = FileNameLength ;
1252+
1253+ /* Map the attributes to ARC file attributes. NOTE: We don't look
1254+ * at the "user.DOSATTRIB" (EA_DOSATTRIB) WinBtrfs-compatible XATTR. */
1255+ temp_file_info .Attributes = 0 ;
1256+ if (!(temp_file_info .inode .mode & (_S_IWUSR | _S_IWGRP | _S_IWOTH )))
1257+ temp_file_info .Attributes |= ReadOnlyFile ;
1258+ if (_S_ISDIR (temp_file_info .inode .mode ))
1259+ temp_file_info .Attributes |= DirectoryFile ;
1260+
1261+ /* Set hidden attribute for all entries starting with '.' */
1262+ if ((temp_file_info .FileNameLength >= 2 && temp_file_info .FileName [0 ] == '.' ) &&
1263+ ((temp_file_info .FileNameLength == 2 && temp_file_info .FileName [1 ] != '.' ) ||
1264+ temp_file_info .FileNameLength >= 3 ))
1265+ {
1266+ temp_file_info .Attributes |= HiddenFile ;
1267+ }
1268+
12211269 TRACE ("found inode inr=%llu size=%llu\n" , inr , temp_file_info .inode .size );
12221270
12231271 temp_file_info .inr = inr ;
0 commit comments