📄 volume.c
字号:
* * On success return 0. * * On error return -1 with errno set to the error code. */int ntfs_logfile_reset(ntfs_volume *vol, progress *prog, int progidx){ ntfs_inode *ni; ntfs_attr *na; int eo; if (!vol) { errno = EINVAL; return -1; } if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) { ntfs_log_perror("Failed to open inode FILE_LogFile."); return -1; } if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) { eo = errno; ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); goto error_exit; } if (ntfs_empty_logfile(na, prog, progidx)) { eo = errno; ntfs_log_perror("Failed to empty $FILE_LogFile/$DATA"); ntfs_attr_close(na); goto error_exit; } ntfs_attr_close(na); return ntfs_inode_close(ni);error_exit: ntfs_inode_close(ni); errno = eo; return -1;}/** * ntfs_volume_write_flags - set the flags of an ntfs volume * @vol: ntfs volume where we set the volume flags * @flags: new flags * * Set the on-disk volume flags in the mft record of $Volume and * on volume @vol to @flags. * * Return 0 if successful and -1 if not with errno set to the error code. */int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags){ ATTR_RECORD *a; VOLUME_INFORMATION *c; ntfs_attr_search_ctx *ctx; int ret = -1; /* failure */ if (!vol || !vol->vol_ni) { errno = EINVAL; return -1; } /* Get a pointer to the volume information attribute. */ ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL); if (!ctx) { ntfs_log_perror("Failed to allocate attribute search context"); return -1; } if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { ntfs_log_debug("Error: Attribute $VOLUME_INFORMATION was not found " "in $Volume!\n"); goto err_out; } a = ctx->attr; /* Sanity check. */ if (a->non_resident) { ntfs_log_debug("Error: Attribute $VOLUME_INFORMATION must be " "resident (and it isn't)!\n"); errno = EIO; goto err_out; } /* Get a pointer to the value of the attribute. */ c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a); /* Sanity checks. */ if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec + le32_to_cpu(ctx->mrec->bytes_in_use) || le16_to_cpu(a->value_offset) + le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) { ntfs_log_debug("Error: Attribute $VOLUME_INFORMATION in $Volume is " "corrupt!\n"); errno = EIO; goto err_out; } /* Set the volume flags. */ vol->flags = c->flags = flags & VOLUME_FLAGS_MASK; /* Write them to disk. */ ntfs_inode_mark_dirty(vol->vol_ni); if (ntfs_inode_sync(vol->vol_ni)) { ntfs_log_perror("Error writing $Volume"); goto err_out; } ret = 0; /* success */err_out: ntfs_attr_put_search_ctx(ctx); return ret;}#ifndef __VISOPSYS__#ifdef NTFS_RICH#include "tree.h"#include "rich.h"/** * utils_valid_device - Perform some safety checks on the device before we start * @name: Full pathname of the device/file to work with * @force: Continue regardless of problems * * Check that the name refers to a device and that is isn't already mounted. * These checks can be overridden by using the force option. * * Return: 1 Success, we can continue * 0 Error, we cannot use this device */int utils_valid_device(const char *name, int force){ unsigned long mnt_flags = 0; struct stat st;#ifdef __CYGWIN32__ /* FIXME: This doesn't work for Cygwin, so just return success for now... */ return 1;#endif if (!name) { errno = EINVAL; return 0; } ntfs_log_trace ("\n"); if (stat(name, &st) == -1) { if (errno == ENOENT) { ntfs_log_error("The device %s doesn't exist\n", name); } else { ntfs_log_perror("Error getting information about %s", name); } return 0; } if (!S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode)) { ntfs_log_warning("%s is not a block device, " "nor regular file.\n", name); if (!force) { ntfs_log_error("Use the force option to work with other" " file types, for your own risk!\n"); return 0; } ntfs_log_warning("Forced to continue.\n"); } /* Make sure the file system is not mounted. */ if (ntfs_check_if_mounted(name, &mnt_flags)) { ntfs_log_perror("Failed to determine whether %s is mounted", name); if (!force) { ntfs_log_error("Use the force option to ignore this error.\n"); return 0; } ntfs_log_warning("Forced to continue.\n"); } else if (mnt_flags & NTFS_MF_MOUNTED) { ntfs_log_warning("The device %s, is mounted.\n", name); if (!force) { ntfs_log_error("Use the force option to work a mounted filesystem.\n"); return 0; } ntfs_log_warning("Forced to continue.\n"); } return 1;}/** * utils_mount_volume - Mount an NTFS volume * @device: * @flags: * @force: * * Description... * * Returns: */ntfs_volume * utils_mount_volume(const char *device, unsigned long flags, BOOL force){ ntfs_volume *vol; if (!device) { errno = EINVAL; return NULL; } ntfs_log_trace ("\n"); if (!utils_valid_device(device, force)) return NULL; vol = ntfs_mount(device, flags); if (!vol) { int err; err = errno; ntfs_log_perror("Couldn't mount device '%s'", device); if (err == EPERM) ntfs_log_error("Windows was hibernated. Try to mount " "volume in windows, shut down and try " "again.\n"); if (err == EOPNOTSUPP) ntfs_log_error("Windows did not shut down properly. " "Try to mount volume in windows, " "shut down and try again.\n"); return NULL; } if (vol->flags & VOLUME_IS_DIRTY) { ntfs_log_warning("Volume is dirty.\n"); if (!force) { ntfs_log_error("Run chkdsk and try again, or use the " "force option.\n"); ntfs_umount(vol, FALSE); return NULL; } ntfs_log_quiet("Forced to continue.\n"); } return vol;}/** * ntfs_volume_commit - Write to disk the in-memory volume changes * @vol: * * Description... * * Returns: */int ntfs_volume_commit(ntfs_volume *vol){ if (!vol) return -1; ntfs_log_trace ("\n"); ntfs_log_debug("commit volume\n"); if (ntfs_bmp_commit(vol->private_bmp1) < 0) return -1; if (ntfs_bmp_commit(vol->private_bmp2) < 0) return -1; if (ntfs_dir_commit(vol->private_data) < 0) return -1; return 0;}/** * ntfs_volume_rollback - Discard the in-memory volume changes * @vol: * * Description... * * Returns: */int ntfs_volume_rollback(ntfs_volume *vol){ if (!vol) return -1; ntfs_log_trace ("\n"); if (ntfs_bmp_rollback(vol->private_bmp1) < 0) return -1; if (ntfs_bmp_rollback(vol->private_bmp2) < 0) return -1; if (ntfs_dir_rollback(vol->private_data) < 0) return -1; return 0;}/** * ntfs_volume_umount2 - Unmount an NTFS volume, using the new directory support * @vol: * @force: * * Description... * * Returns: */int ntfs_volume_umount2(ntfs_volume *vol, const BOOL force){ struct ntfs_dir *dir; struct ntfs_bmp *bmp; if (!vol) return 0; ntfs_log_trace ("\n"); ntfs_volume_rollback(vol); dir = (struct ntfs_dir *) vol->private_data; vol->private_data = NULL; ntfs_dir_free(dir); bmp = (struct ntfs_bmp *) vol->private_bmp1; vol->private_bmp1 = NULL; ntfs_bmp_free(bmp); bmp = (struct ntfs_bmp *) vol->private_bmp2; vol->private_bmp2 = NULL; ntfs_bmp_free(bmp); return ntfs_umount(vol, force);}/** * ntfs_volume_mount2 - Mount an NTFS volume, using the new directory support * @device: * @flags: * @force: * * Description... * * Returns: */ntfs_volume * ntfs_volume_mount2(const char *device, unsigned long flags, BOOL force){ // XXX can we replace these and search by mft number? Hmm... NO. // unless I have a recursive search for an MFT number static ntfschar bmp[8] = { const_cpu_to_le16('$'), const_cpu_to_le16('B'), const_cpu_to_le16('i'), const_cpu_to_le16('t'), const_cpu_to_le16('m'), const_cpu_to_le16('a'), const_cpu_to_le16('p'), const_cpu_to_le16(0) }; static ntfschar mft[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('M'), const_cpu_to_le16('F'), const_cpu_to_le16('T'), const_cpu_to_le16(0) }; static ntfschar mftmirr[9] = { const_cpu_to_le16('$'), const_cpu_to_le16('M'), const_cpu_to_le16('F'), const_cpu_to_le16('T'), const_cpu_to_le16('M'), const_cpu_to_le16('i'), const_cpu_to_le16('r'), const_cpu_to_le16('r'), const_cpu_to_le16(0) }; static ntfschar dot[2] = { const_cpu_to_le16('.'), const_cpu_to_le16(0) }; ntfs_volume *vol; struct ntfs_dir *dir; struct ntfs_dt *root; struct ntfs_dt *found; int num; ntfs_log_trace ("\n"); vol = utils_mount_volume(device, flags, force); if (!vol) return NULL; vol->lcnbmp_ni ->ref_count = 1; vol->mft_ni ->ref_count = 1; vol->mftmirr_ni->ref_count = 1; vol->lcnbmp_ni ->private_data = NULL; vol->mft_ni ->private_data = NULL; vol->mftmirr_ni->private_data = NULL; dir = ntfs_dir_create(vol, FILE_root); if (!dir) { ntfs_volume_umount2(vol, FALSE); vol = NULL; goto done; } dir->index = ntfs_dt_create(dir, NULL, -1); root = dir->index; //$Bitmap num = -1; found = ntfs_dt_find2(root, bmp, (sizeof(bmp)/sizeof(ntfschar)) - 1, &num); if ((!found) || (num < 0)) { ntfs_log_debug("can't find $Bitmap\n"); ntfs_volume_umount2(vol, FALSE); vol = NULL; goto done; } vol->lcnbmp_ni->ref_count++; vol->lcnbmp_ni->private_data = found->dir; found->inodes[num] = vol->lcnbmp_ni; //$MFT num = -1; found = ntfs_dt_find2(root, mft, (sizeof(mft)/sizeof(ntfschar)) - 1, &num); if ((!found) || (num < 0)) { ntfs_log_debug("can't find $MFT\n"); ntfs_volume_umount2(vol, FALSE); vol = NULL; goto done; } vol->mft_ni->ref_count++; vol->mft_ni->private_data = found->dir; found->inodes[num] = vol->mft_ni; //$MFTMirr num = -1; found = ntfs_dt_find2(root, mftmirr, (sizeof(mftmirr)/sizeof(ntfschar)) - 1, &num); if ((!found) || (num < 0)) { ntfs_log_debug("can't find $MFTMirr\n"); ntfs_volume_umount2(vol, FALSE); vol = NULL; goto done; } vol->mftmirr_ni->ref_count++; vol->mftmirr_ni->private_data = found->dir; found->inodes[num] = vol->mftmirr_ni; // root directory num = -1; found = ntfs_dt_find2(root, dot, (sizeof(dot)/sizeof(ntfschar)) - 1, &num); if ((!found) || (num < 0)) { ntfs_log_debug("can't find the root directory\n"); ntfs_volume_umount2(vol, FALSE); vol = NULL; goto done; } vol->private_data = found->dir; found->inodes[num] = dir->inode; dir->inode->private_data = found; dir->inode->ref_count = 2; vol->private_bmp1 = ntfs_bmp_create(vol->mft_ni, AT_BITMAP, NULL, 0); vol->private_bmp2 = ntfs_bmp_create(vol->lcnbmp_ni, AT_DATA, NULL, 0); if (!vol->private_bmp1 || !vol->private_bmp2) { ntfs_log_debug("can't find the bitmaps\n"); ntfs_volume_umount2(vol, FALSE); vol = NULL; goto done; }done: return vol;}#endif /* NTFS_RICH */#endif /* __VISOPSYS__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -