- Support journals which have been modified by chkdsk. (Anton, Szaka)
- Support journals ($LogFile) with only one restart page as well as journals with two different restart pages. (Anton, Szaka)edge.strict_endians
parent
054d6777d5
commit
24de91b8fa
|
@ -42,6 +42,9 @@ xx/xx/2005 - 1.12.0-WIP
|
|||
libntfs/volume.c. Needed to compile on DOS with djgpp. (Christophe)
|
||||
- Switch ntfsmount to use getopt_long. (Yuval, minor fixes by Yura)
|
||||
- ntfsmount: Fix 'df' output. (Yuval)
|
||||
- Support journals which have been modified by chkdsk. (Anton, Szaka)
|
||||
- Support journals ($LogFile) with only one restart page as well as
|
||||
journals with two different restart pages. (Anton, Szaka)
|
||||
|
||||
08/08/2005 - 1.11.2 - ntfsdecrypt now works and lots of fixes and improvements.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* logfile.h - Exports for $LogFile handling. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2000-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2000-2005 Anton Altaparmakov
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -376,8 +376,8 @@ typedef struct {
|
|||
} __attribute__((__packed__)) lcn_list[0];
|
||||
} __attribute__ ((__packed__)) LOG_RECORD;
|
||||
|
||||
extern BOOL ntfs_check_logfile(ntfs_attr *log_na);
|
||||
extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na);
|
||||
extern BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp);
|
||||
extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp);
|
||||
extern int ntfs_empty_logfile(ntfs_attr *na);
|
||||
|
||||
#endif /* defined _NTFS_LOGFILE_H */
|
||||
|
|
|
@ -112,7 +112,7 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
|
|||
*/
|
||||
if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) {
|
||||
ntfs_error(vi->i_sb, "$LogFile restart page is not modified "
|
||||
"chkdsk but a chkdsk LSN is specified.");
|
||||
"by chkdsk but a chkdsk LSN is specified.");
|
||||
return FALSE;
|
||||
}
|
||||
ntfs_debug("Done.");
|
||||
|
@ -301,10 +301,12 @@ err_out:
|
|||
* @log_na: opened ntfs attribute for journal $LogFile
|
||||
* @rp: restart page to check
|
||||
* @pos: position in @log_na at which the restart page resides
|
||||
* @wrp: copy of the multi sector transfer deprotected restart page
|
||||
* @wrp: [OUT] copy of the multi sector transfer deprotected restart page
|
||||
* @lsn: [OUT] set to the current logfile lsn on success
|
||||
*
|
||||
* Check the restart page @rp for consistency and return TRUE if it is
|
||||
* consistent and FALSE otherwise.
|
||||
* Check the restart page @rp for consistency and return 0 if it is consistent
|
||||
* and errno otherwise. The restart page may have been modified by chkdsk in
|
||||
* which case its magic is CHKD instead of RSTR.
|
||||
*
|
||||
* This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
|
||||
* require the full restart page.
|
||||
|
@ -312,24 +314,33 @@ err_out:
|
|||
* If @wrp is not NULL, on success, *@wrp will point to a buffer containing a
|
||||
* copy of the complete multi sector transfer deprotected page. On failure,
|
||||
* *@wrp is undefined.
|
||||
*
|
||||
* Simillarly, if @lsn is not NULL, on succes *@lsn will be set to the current
|
||||
* logfile lsn according to this restart page. On failure, *@lsn is undefined.
|
||||
*
|
||||
* The following error codes are defined:
|
||||
* EINVAL - The restart page is inconsistent.
|
||||
* ENOMEM - Not enough memory to load the restart page.
|
||||
* EIO - Failed to reading from $LogFile.
|
||||
*/
|
||||
static BOOL ntfs_check_and_load_restart_page(ntfs_attr *log_na,
|
||||
RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp)
|
||||
static int ntfs_check_and_load_restart_page(ntfs_attr *log_na,
|
||||
RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp,
|
||||
LSN *lsn)
|
||||
{
|
||||
RESTART_AREA *ra;
|
||||
RESTART_PAGE_HEADER *trp;
|
||||
BOOL ret;
|
||||
int err;
|
||||
|
||||
ntfs_debug("Entering.");
|
||||
/* Check the restart page header for consistency. */
|
||||
if (!ntfs_check_restart_page_header(rp, pos)) {
|
||||
/* Error output already done inside the function. */
|
||||
return FALSE;
|
||||
return EINVAL;
|
||||
}
|
||||
/* Check the restart area for consistency. */
|
||||
if (!ntfs_check_restart_area(rp)) {
|
||||
/* Error output already done inside the function. */
|
||||
return FALSE;
|
||||
return EINVAL;
|
||||
}
|
||||
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
|
||||
/*
|
||||
|
@ -340,7 +351,7 @@ static BOOL ntfs_check_and_load_restart_page(ntfs_attr *log_na,
|
|||
if (!trp) {
|
||||
ntfs_error(vi->i_sb, "Failed to allocate memory for $LogFile "
|
||||
"restart page buffer.");
|
||||
return FALSE;
|
||||
return ENOMEM;
|
||||
}
|
||||
/*
|
||||
* Read the whole of the restart page into the buffer. If it fits
|
||||
|
@ -353,36 +364,67 @@ static BOOL ntfs_check_and_load_restart_page(ntfs_attr *log_na,
|
|||
if (ntfs_attr_pread(log_na, pos, le32_to_cpu(
|
||||
rp->system_page_size), trp) !=
|
||||
le32_to_cpu(rp->system_page_size)) {
|
||||
err = errno;
|
||||
ntfs_error(, "Failed to read whole restart page into "
|
||||
"the buffer.");
|
||||
if (err != ENOMEM)
|
||||
err = EIO;
|
||||
goto err_out;
|
||||
}
|
||||
/* Perform the multi sector transfer deprotection on the buffer. */
|
||||
if (ntfs_mst_post_read_fixup((NTFS_RECORD*)trp,
|
||||
le32_to_cpu(rp->system_page_size))) {
|
||||
ntfs_error(vi->i_sb, "Multi sector transfer error detected in "
|
||||
"$LogFile restart page.");
|
||||
goto err_out;
|
||||
/*
|
||||
* A multi sector tranfer error was detected. We only need to
|
||||
* abort if the restart page contents exceed the multi sector
|
||||
* transfer fixup of the first sector.
|
||||
*/
|
||||
if (le16_to_cpu(rp->restart_area_offset) +
|
||||
le16_to_cpu(ra->restart_area_length) >
|
||||
NTFS_BLOCK_SIZE - sizeof(u16)) {
|
||||
ntfs_error(vi->i_sb, "Multi sector transfer error "
|
||||
"detected in $LogFile restart page.");
|
||||
err = EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If the restart page is modified by chkdsk or there are no active
|
||||
* logfile clients, the logfile is consistent. Otherwise, need to
|
||||
* check the log client records for consistency, too.
|
||||
*/
|
||||
err = 0;
|
||||
if (ntfs_is_rstr_record(rp->magic) &&
|
||||
ra->client_in_use_list != LOGFILE_NO_CLIENT) {
|
||||
if (!ntfs_check_log_client_array(trp)) {
|
||||
err = EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
if (lsn) {
|
||||
if (ntfs_is_rstr_record(rp->magic))
|
||||
*lsn = sle64_to_cpu(ra->current_lsn);
|
||||
else /* if (ntfs_is_chkd_record(rp->magic)) */
|
||||
*lsn = sle64_to_cpu(rp->chkdsk_lsn);
|
||||
}
|
||||
/* Check the log client records for consistency. */
|
||||
ret = ntfs_check_log_client_array(trp);
|
||||
if (ret && wrp)
|
||||
*wrp = trp;
|
||||
else
|
||||
free(trp);
|
||||
ntfs_debug("Done.");
|
||||
return ret;
|
||||
if (wrp)
|
||||
*wrp = trp;
|
||||
else {
|
||||
err_out:
|
||||
free(trp);
|
||||
return FALSE;
|
||||
free(trp);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_check_logfile - check in the journal if the volume is consistent
|
||||
* @log_na: ntfs attribute of loaded journal $LogFile to check
|
||||
* @rp: [OUT] on success this is a copy of the current restart page
|
||||
*
|
||||
* Check the $LogFile journal for consistency and return TRUE if it is
|
||||
* consistent and FALSE if not.
|
||||
* consistent and FALSE if not. On success, the current restart page is
|
||||
* returned in *@rp. Caller must call ntfs_free(*@rp) when finished with it.
|
||||
*
|
||||
* At present we only check the two restart pages and ignore the log record
|
||||
* pages.
|
||||
|
@ -392,17 +434,16 @@ err_out:
|
|||
* if the $LogFile was created on a system with a different page size to ours
|
||||
* yet and mst deprotection would fail if our page size is smaller.
|
||||
*/
|
||||
BOOL ntfs_check_logfile(ntfs_attr *log_na)
|
||||
BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
|
||||
{
|
||||
s64 size, pos, rstr1_pos, rstr2_pos;
|
||||
s64 size, pos;
|
||||
LSN rstr1_lsn, rstr2_lsn;
|
||||
ntfs_volume *vol = log_na->ni->vol;
|
||||
u8 *buf = NULL;
|
||||
u8 *kaddr = NULL;
|
||||
RESTART_PAGE_HEADER *rstr1_ph = NULL;
|
||||
RESTART_PAGE_HEADER *rstr2_ph = NULL;
|
||||
int log_page_size, log_page_mask, ofs;
|
||||
int log_page_size, log_page_mask, err;
|
||||
BOOL logfile_is_empty = TRUE;
|
||||
BOOL rstr1_found = FALSE;
|
||||
BOOL rstr2_found = FALSE;
|
||||
u8 log_page_bits;
|
||||
|
||||
ntfs_debug("Entering.");
|
||||
|
@ -432,8 +473,8 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na)
|
|||
return FALSE;
|
||||
}
|
||||
/* Allocate memory for restart page. */
|
||||
buf = malloc(NTFS_BLOCK_SIZE);
|
||||
if (!buf) {
|
||||
kaddr = malloc(NTFS_BLOCK_SIZE);
|
||||
if (!kaddr) {
|
||||
ntfs_error(, "Not enough memory.");
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -449,7 +490,7 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na)
|
|||
/*
|
||||
* Read first NTFS_BLOCK_SIZE bytes of potential restart page.
|
||||
*/
|
||||
if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, buf) !=
|
||||
if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, kaddr) !=
|
||||
NTFS_BLOCK_SIZE) {
|
||||
ntfs_error(, "Failed to read first NTFS_BLOCK_SIZE "
|
||||
"bytes of potential restart page.");
|
||||
|
@ -461,7 +502,7 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na)
|
|||
* empty block after a non-empty block has been encountered
|
||||
* means we are done.
|
||||
*/
|
||||
if (!ntfs_is_empty_recordp((le32*)buf))
|
||||
if (!ntfs_is_empty_recordp((le32*)kaddr))
|
||||
logfile_is_empty = FALSE;
|
||||
else if (!logfile_is_empty)
|
||||
break;
|
||||
|
@ -469,59 +510,53 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na)
|
|||
* A log record page means there cannot be a restart page after
|
||||
* this so no need to continue searching.
|
||||
*/
|
||||
if (ntfs_is_rcrd_recordp((le32*)buf))
|
||||
if (ntfs_is_rcrd_recordp((le32*)kaddr))
|
||||
break;
|
||||
/*
|
||||
* A modified by chkdsk restart page means we cannot handle
|
||||
* this log file.
|
||||
*/
|
||||
if (ntfs_is_chkd_recordp((le32*)buf)) {
|
||||
ntfs_error(vol->sb, "$LogFile has been modified by "
|
||||
"chkdsk. Mount this volume in "
|
||||
"Windows.");
|
||||
goto err_out;
|
||||
}
|
||||
/* If not a restart page, continue. */
|
||||
if (!ntfs_is_rstr_recordp((le32*)buf)) {
|
||||
/* Skip to the minimum page size for the next one. */
|
||||
/* If not a (modified by chkdsk) restart page, continue. */
|
||||
if (!ntfs_is_rstr_recordp((le32*)kaddr) &&
|
||||
!ntfs_is_chkd_recordp((le32*)kaddr)) {
|
||||
if (!pos)
|
||||
pos = NTFS_BLOCK_SIZE >> 1;
|
||||
continue;
|
||||
}
|
||||
/* We now know we have a restart page. */
|
||||
if (!pos) {
|
||||
rstr1_found = TRUE;
|
||||
rstr1_pos = pos;
|
||||
} else {
|
||||
if (rstr2_found) {
|
||||
ntfs_error(vol->sb, "Found more than two "
|
||||
"restart pages in $LogFile.");
|
||||
goto err_out;
|
||||
/*
|
||||
* Check the (modified by chkdsk) restart page for consistency
|
||||
* and get a copy of the complete multi sector transfer
|
||||
* deprotected restart page.
|
||||
*/
|
||||
err = ntfs_check_and_load_restart_page(log_na,
|
||||
(RESTART_PAGE_HEADER*)kaddr, pos,
|
||||
!rstr1_ph ? &rstr1_ph : &rstr2_ph,
|
||||
!rstr1_ph ? &rstr1_lsn : &rstr2_lsn);
|
||||
if (!err) {
|
||||
/*
|
||||
* If we have now found the first (modified by chkdsk)
|
||||
* restart page, continue looking for the second one.
|
||||
*/
|
||||
if (!pos) {
|
||||
pos = NTFS_BLOCK_SIZE >> 1;
|
||||
continue;
|
||||
}
|
||||
rstr2_found = TRUE;
|
||||
rstr2_pos = pos;
|
||||
/*
|
||||
* We have now found the second (modified by chkdsk)
|
||||
* restart page, so we can stop looking.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check the restart page for consistency and get a copy of the
|
||||
* complete multi sector transfer deprotected restart page.
|
||||
*/
|
||||
if (!ntfs_check_and_load_restart_page(log_na,
|
||||
(RESTART_PAGE_HEADER*)buf, pos,
|
||||
!pos ? &rstr1_ph : &rstr2_ph)) {
|
||||
/* Error output already done inside the function. */
|
||||
goto err_out;
|
||||
}
|
||||
/*
|
||||
* We have a valid restart page. The next one must be after
|
||||
* a whole system page size as specified by the valid restart
|
||||
* page.
|
||||
* Error output already done inside the function. Note, we do
|
||||
* not abort if the restart page was invalid as we might still
|
||||
* find a valid one further in the file.
|
||||
*/
|
||||
if (err != EINVAL)
|
||||
goto err_out;
|
||||
/* Continue looking. */
|
||||
if (!pos)
|
||||
pos = le32_to_cpu(rstr1_ph->system_page_size) >> 1;
|
||||
pos = NTFS_BLOCK_SIZE >> 1;
|
||||
}
|
||||
if (buf) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
if (kaddr) {
|
||||
free(kaddr);
|
||||
kaddr = NULL;
|
||||
}
|
||||
if (logfile_is_empty) {
|
||||
NVolSetLogFileEmpty(vol);
|
||||
|
@ -529,31 +564,37 @@ is_empty:
|
|||
ntfs_debug("Done. ($LogFile is empty.)");
|
||||
return TRUE;
|
||||
}
|
||||
if (!rstr1_found || !rstr2_found) {
|
||||
ntfs_error(vol->sb, "Did not find two restart pages in "
|
||||
"$LogFile.");
|
||||
goto err_out;
|
||||
if (!rstr1_ph) {
|
||||
if (rstr2_ph)
|
||||
ntfs_error(vol->sb, "BUG: rstr2_ph isn't NULL!");
|
||||
ntfs_error(vol->sb, "Did not find any restart pages in "
|
||||
"$LogFile and it was not empty.");
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* The two restart areas must be identical except for the update
|
||||
* sequence number.
|
||||
*/
|
||||
ofs = le16_to_cpu(rstr1_ph->usa_ofs);
|
||||
if (memcmp(rstr1_ph, rstr2_ph, ofs) || (ofs += sizeof(u16),
|
||||
memcmp((u8*)rstr1_ph + ofs, (u8*)rstr2_ph + ofs,
|
||||
le32_to_cpu(rstr1_ph->system_page_size) - ofs))) {
|
||||
ntfs_error(vol->sb, "The two restart pages in $LogFile do not "
|
||||
"match.");
|
||||
goto err_out;
|
||||
/* If both restart pages were found, use the more recent one. */
|
||||
if (rstr2_ph) {
|
||||
/*
|
||||
* If the second restart area is more recent, switch to it.
|
||||
* Otherwise just throw it away.
|
||||
*/
|
||||
if (rstr2_lsn > rstr1_lsn) {
|
||||
free(rstr1_ph);
|
||||
rstr1_ph = rstr2_ph;
|
||||
/* rstr1_lsn = rstr2_lsn; */
|
||||
} else
|
||||
free(rstr2_ph);
|
||||
rstr2_ph = NULL;
|
||||
}
|
||||
free(rstr1_ph);
|
||||
free(rstr2_ph);
|
||||
/* All consistency checks passed. */
|
||||
if (rp)
|
||||
*rp = rstr1_ph;
|
||||
else
|
||||
free(rstr1_ph);
|
||||
ntfs_debug("Done.");
|
||||
return TRUE;
|
||||
err_out:
|
||||
if (buf)
|
||||
free(buf);
|
||||
if (kaddr)
|
||||
free(kaddr);
|
||||
if (rstr1_ph)
|
||||
free(rstr1_ph);
|
||||
if (rstr2_ph)
|
||||
|
@ -564,6 +605,7 @@ err_out:
|
|||
/**
|
||||
* ntfs_is_logfile_clean - check in the journal if the volume is clean
|
||||
* @log_na: ntfs attribute of loaded journal $LogFile to check
|
||||
* @rp: copy of the current restart page
|
||||
*
|
||||
* Analyze the $LogFile journal and return TRUE if it indicates the volume was
|
||||
* shutdown cleanly and FALSE if not.
|
||||
|
@ -580,9 +622,8 @@ err_out:
|
|||
* is empty this function requires that NVolLogFileEmpty() is true otherwise an
|
||||
* empty volume will be reported as dirty.
|
||||
*/
|
||||
BOOL ntfs_is_logfile_clean(ntfs_attr *log_na)
|
||||
BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp)
|
||||
{
|
||||
RESTART_PAGE_HEADER *rp;
|
||||
RESTART_AREA *ra;
|
||||
|
||||
ntfs_debug("Entering.");
|
||||
|
@ -591,29 +632,19 @@ BOOL ntfs_is_logfile_clean(ntfs_attr *log_na)
|
|||
ntfs_debug("Done. ($LogFile is empty.)");
|
||||
return TRUE;
|
||||
}
|
||||
/* Allocate memory. */
|
||||
rp = malloc(NTFS_BLOCK_SIZE);
|
||||
if (!rp) {
|
||||
ntfs_error(, "Not enough memory.");
|
||||
ntfs_error(, "Restart page header is NULL.");
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* Read the first restart page. It will be possibly incomplete and
|
||||
* will not be multi sector transfer deprotected but we only need the
|
||||
* first NTFS_BLOCK_SIZE bytes so it does not matter.
|
||||
*/
|
||||
if (ntfs_attr_pread(log_na, 0, NTFS_BLOCK_SIZE, rp) !=
|
||||
NTFS_BLOCK_SIZE) {
|
||||
ntfs_error(, "Failed to read first restart page.");
|
||||
goto err_out;
|
||||
}
|
||||
if (!ntfs_is_rstr_record(rp->magic)) {
|
||||
ntfs_error(vol->sb, "No restart page found at offset zero in "
|
||||
"$LogFile. This is probably a bug in that "
|
||||
"the $LogFile should have been consistency "
|
||||
"checked before calling this function.");
|
||||
goto err_out;
|
||||
if (!ntfs_is_rstr_record(rp->magic) &&
|
||||
!ntfs_is_chkd_record(rp->magic)) {
|
||||
ntfs_error(vol->sb, "Restart page buffer is invalid. This is "
|
||||
"probably a bug in that the $LogFile should "
|
||||
"have been consistency checked before calling "
|
||||
"this function.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
|
||||
/*
|
||||
* If the $LogFile has active clients, i.e. it is open, and we do not
|
||||
|
@ -623,15 +654,11 @@ BOOL ntfs_is_logfile_clean(ntfs_attr *log_na)
|
|||
if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
|
||||
!(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
|
||||
ntfs_debug("Done. $LogFile indicates a dirty shutdown.");
|
||||
goto err_out;
|
||||
return FALSE;
|
||||
}
|
||||
free(rp);
|
||||
/* $LogFile indicates a clean shutdown. */
|
||||
ntfs_debug("Done. $LogFile indicates a clean shutdown.");
|
||||
return TRUE;
|
||||
err_out:
|
||||
free(rp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* volume.c - NTFS volume handling code. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2000-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2000-2005 Anton Altaparmakov
|
||||
* Copyright (c) 2002-2005 Szabolcs Szakacsits
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
|
@ -566,6 +566,7 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
|
|||
{
|
||||
ntfs_inode *ni;
|
||||
ntfs_attr *na = NULL;
|
||||
RESTART_PAGE_HEADER *rp = NULL;
|
||||
int err = 0;
|
||||
|
||||
if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) {
|
||||
|
@ -578,8 +579,10 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
|
|||
err = EIO;
|
||||
goto exit;
|
||||
}
|
||||
if (!ntfs_check_logfile(na) || !ntfs_is_logfile_clean(na))
|
||||
if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
|
||||
err = EOPNOTSUPP;
|
||||
if (rp)
|
||||
free(rp);
|
||||
exit:
|
||||
if (na)
|
||||
ntfs_attr_close(na);
|
||||
|
|
Loading…
Reference in New Issue