int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size) { REPARSE_POINT *reparse_attr; s64 attr_size; attr_size = 0; /* default to no data and no error */ if (ni) { if (ni->flags & FILE_ATTR_REPARSE_POINT) { reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); if (reparse_attr) { if (attr_size <= (s64)size) { if (value) memcpy(value,reparse_attr, attr_size); else errno = EINVAL; } free(reparse_attr); } } else errno = ENODATA; } return (attr_size ? (int)attr_size : -errno); }
int ntfs_get_efs_info(const char *path, char *value, size_t size, ntfs_inode *ni) { EFS_ATTR_HEADER *efs_info; s64 attr_size = 0; if (ni) { if (ni->flags & FILE_ATTR_ENCRYPTED) { efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni, AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0, &attr_size); if (efs_info && (le32_to_cpu(efs_info->length) == attr_size)) { if (attr_size <= (s64)size) { if (value) memcpy(value,efs_info,attr_size); else { errno = EFAULT; attr_size = 0; } } else if (size) { errno = ERANGE; attr_size = 0; } free (efs_info); } else { if (efs_info) { free(efs_info); ntfs_log_info("Bad efs_info for file %s\n",path); } else { ntfs_log_info("Could not get efsinfo" " for file %s\n", path); } errno = EIO; attr_size = 0; } } else { errno = ENODATA; ntfs_log_info("File %s is not encrypted",path); } } return (attr_size ? (int)attr_size : -errno); }
BOOL ntfs_possible_symlink(ntfs_inode *ni) { s64 attr_size = 0; REPARSE_POINT *reparse_attr; BOOL possible; possible = FALSE; reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); if (reparse_attr && attr_size) { switch (reparse_attr->reparse_tag) { case IO_REPARSE_TAG_MOUNT_POINT : case IO_REPARSE_TAG_SYMLINK : possible = TRUE; default : ; } free(reparse_attr); } return (possible); }
/** * ntfs_inode_fek_get - */ static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode, ntfs_rsa_private_key rsa_key, char *thumbprint, int thumbprint_size, NTFS_DF_TYPES df_type) { EFS_ATTR_HEADER *efs; EFS_DF_ARRAY_HEADER *df_array = NULL; ntfs_fek *fek = NULL; /* Obtain the $EFS contents. */ efs = ntfs_attr_readall(inode, AT_LOGGED_UTILITY_STREAM, EFS, 4, NULL); if (!efs) { ntfs_log_perror("Failed to read $EFS attribute"); return NULL; } /* * Depending on whether the key is a normal key or a data recovery key, * iterate through the DDF or DRF array, respectively. */ if (df_type == DF_TYPE_DDF) { if (efs->offset_to_ddf_array) df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs + le32_to_cpu(efs->offset_to_ddf_array)); else ntfs_log_error("There are no entries in the DDF " "array.\n"); } else if (df_type == DF_TYPE_DRF) { if (efs->offset_to_drf_array) df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs + le32_to_cpu(efs->offset_to_drf_array)); else ntfs_log_error("There are no entries in the DRF " "array.\n"); } else ntfs_log_error("Invalid DF type.\n"); if (df_array) fek = ntfs_df_array_fek_get(df_array, rsa_key, thumbprint, thumbprint_size); free(efs); return fek; }
int ntfs_get_ntfs_object_id(ntfs_inode *ni, char *value, size_t size) { OBJECT_ID_ATTR full_objectid; OBJECT_ID_ATTR *objectid_attr; s64 attr_size; int full_size; full_size = 0; /* default to no data and some error to be defined */ if (ni) { objectid_attr = (OBJECT_ID_ATTR*)ntfs_attr_readall(ni, AT_OBJECT_ID,(ntfschar*)NULL, 0, &attr_size); if (objectid_attr) { /* restrict to only GUID present in attr */ if (attr_size == sizeof(GUID)) { memcpy(&full_objectid.object_id, objectid_attr,sizeof(GUID)); full_size = sizeof(GUID); /* get data from index, if any */ if (!merge_index_data(ni, objectid_attr, &full_objectid)) { full_size = sizeof(OBJECT_ID_ATTR); } if (full_size <= (s64)size) { if (value) memcpy(value,&full_objectid, full_size); else errno = EINVAL; } } else { /* unexpected size, better return unsupported */ errno = ENOTSUP; full_size = 0; } free(objectid_attr); } else errno = ENODATA; } return (full_size ? (int)full_size : -errno); }
static VCN ntfs_ibm_get_free(ntfs_index_context *icx) { u8 *bm; int bit; s64 vcn, byte, size; ntfs_log_trace("Entering\n"); bm = ntfs_attr_readall(icx->ni, AT_BITMAP, icx->name, icx->name_len, &size); if (!bm) return (VCN)-1; for (byte = 0; byte < size; byte++) { if (bm[byte] == 255) continue; for (bit = 0; bit < 8; bit++) { if (!(bm[byte] & (1 << bit))) { vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit); goto out; } } } vcn = ntfs_ibm_pos_to_vcn(icx, size * 8); out: ntfs_log_trace("allocated vcn: %lld\n", (long long)vcn); if (ntfs_ibm_set(icx, vcn)) vcn = (VCN)-1; free(bm); return vcn; }
char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point, int *pattr_size) { s64 attr_size = 0; char *target; unsigned int offs; unsigned int lth; ntfs_volume *vol; REPARSE_POINT *reparse_attr; struct MOUNT_POINT_REPARSE_DATA *mount_point_data; struct SYMLINK_REPARSE_DATA *symlink_data; enum { FULL_TARGET, ABS_TARGET, REL_TARGET } kind; ntfschar *p; BOOL bad; BOOL isdir; target = (char*)NULL; bad = TRUE; isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); vol = ni->vol; reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); if (reparse_attr && attr_size && valid_reparse_data(ni, reparse_attr, attr_size)) { switch (reparse_attr->reparse_tag) { case IO_REPARSE_TAG_MOUNT_POINT : mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*) reparse_attr->reparse_data; offs = le16_to_cpu(mount_point_data->subst_name_offset); lth = le16_to_cpu(mount_point_data->subst_name_length); /* reparse data consistency has been checked */ target = ntfs_get_fulllink(vol, (ntfschar*)&mount_point_data->path_buffer[offs], lth/2, mnt_point, isdir); if (target) bad = FALSE; break; case IO_REPARSE_TAG_SYMLINK : symlink_data = (struct SYMLINK_REPARSE_DATA*) reparse_attr->reparse_data; offs = le16_to_cpu(symlink_data->subst_name_offset); lth = le16_to_cpu(symlink_data->subst_name_length); p = (ntfschar*)&symlink_data->path_buffer[offs]; /* * Predetermine the kind of target, * the called function has to make a full check */ if (*p++ == const_cpu_to_le16('\\')) { if ((*p == const_cpu_to_le16('?')) || (*p == const_cpu_to_le16('\\'))) kind = FULL_TARGET; else kind = ABS_TARGET; } else if (*p == const_cpu_to_le16(':')) kind = ABS_TARGET; else kind = REL_TARGET; p--; /* reparse data consistency has been checked */ switch (kind) { case FULL_TARGET : if (!(symlink_data->flags & const_cpu_to_le32(1))) { target = ntfs_get_fulllink(vol, p, lth/2, mnt_point, isdir); if (target) bad = FALSE; } break; case ABS_TARGET : if (symlink_data->flags & const_cpu_to_le32(1)) { target = ntfs_get_abslink(vol, p, lth/2, mnt_point, isdir); if (target) bad = FALSE; } break; case REL_TARGET : if (symlink_data->flags & const_cpu_to_le32(1)) { target = ntfs_get_rellink(ni, p, lth/2); if (target) bad = FALSE; } break; } break; } free(reparse_attr); } *pattr_size = attr_size; if (bad) errno = EOPNOTSUPP; return (target); }