+NTSTATUS parse_dos_attribute_blob(struct smb_filename *smb_fname,
+ DATA_BLOB blob,
+ uint32_t *pattr)
+{
+ struct xattr_DOSATTRIB dosattrib;
+ enum ndr_err_code ndr_err;
+ uint32_t dosattr;
+
+ ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib,
+ (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DBG_WARNING("bad ndr decode "
+ "from EA on file %s: Error = %s\n",
+ smb_fname_str_dbg(smb_fname),
+ ndr_errstr(ndr_err));
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ DBG_DEBUG("%s attr = %s\n",
+ smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex);
+
+ switch (dosattrib.version) {
+ case 0xFFFF:
+ dosattr = dosattrib.info.compatinfoFFFF.attrib;
+ break;
+ case 1:
+ dosattr = dosattrib.info.info1.attrib;
+ if (!null_nttime(dosattrib.info.info1.create_time)) {
+ struct timespec create_time =
+ nt_time_to_unix_timespec(
+ dosattrib.info.info1.create_time);
+
+ update_stat_ex_create_time(&smb_fname->st,
+ create_time);
+
+ DBG_DEBUG("file %s case 1 set btime %s\n",
+ smb_fname_str_dbg(smb_fname),
+ time_to_asc(convert_timespec_to_time_t(
+ create_time)));
+ }
+ break;
+ case 2:
+ dosattr = dosattrib.info.oldinfo2.attrib;
+ /* Don't know what flags to check for this case. */
+ break;
+ case 3:
+ dosattr = dosattrib.info.info3.attrib;
+ if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
+ !null_nttime(dosattrib.info.info3.create_time)) {
+ struct timespec create_time =
+ nt_time_to_full_timespec(
+ dosattrib.info.info3.create_time);
+
+ update_stat_ex_create_time(&smb_fname->st,
+ create_time);
+
+ DBG_DEBUG("file %s case 3 set btime %s\n",
+ smb_fname_str_dbg(smb_fname),
+ time_to_asc(convert_timespec_to_time_t(
+ create_time)));
+ }
+ break;
+ case 4:
+ {
+ struct xattr_DosInfo4 *info = &dosattrib.info.info4;
+
+ dosattr = info->attrib;
+
+ if ((info->valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
+ !null_nttime(info->create_time))
+ {
+ struct timespec creat_time;
+
+ creat_time = nt_time_to_full_timespec(info->create_time);
+ update_stat_ex_create_time(&smb_fname->st, creat_time);
+
+ DBG_DEBUG("file [%s] creation time [%s]\n",
+ smb_fname_str_dbg(smb_fname),
+ nt_time_string(talloc_tos(), info->create_time));
+ }
+
+ if (info->valid_flags & XATTR_DOSINFO_ITIME) {
+ struct timespec itime;
+ uint64_t file_id;
+
+ itime = nt_time_to_unix_timespec(info->itime);
+ if (smb_fname->st.st_ex_iflags &
+ ST_EX_IFLAG_CALCULATED_ITIME)
+ {
+ update_stat_ex_itime(&smb_fname->st, itime);
+ }
+
+ file_id = make_file_id_from_itime(&smb_fname->st);
+ if (smb_fname->st.st_ex_iflags &
+ ST_EX_IFLAG_CALCULATED_FILE_ID)
+ {
+ update_stat_ex_file_id(&smb_fname->st, file_id);
+ }
+
+ DBG_DEBUG("file [%s] itime [%s] fileid [%"PRIx64"]\n",
+ smb_fname_str_dbg(smb_fname),
+ nt_time_string(talloc_tos(), info->itime),
+ file_id);
+ }
+ break;
+ }
+ default:
+ DBG_WARNING("Badly formed DOSATTRIB on file %s - %s\n",
+ smb_fname_str_dbg(smb_fname), blob.data);
+ /* Should this be INTERNAL_ERROR? */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ dosattr |= FILE_ATTRIBUTE_DIRECTORY;
+ }
+
+ /* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */
+ *pattr |= (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
+
+ dos_mode_debug_print(__func__, *pattr);
+
+ return NT_STATUS_OK;
+}
+