Patch XLS files to mask out variable data

This workaround the Excel behaviour to write the last
access time inside the files as they are opened.
This commit is contained in:
Andrea Mazzoleni 2015-11-29 17:21:41 +01:00
parent 4209f0cec3
commit 1da8660498
2 changed files with 64 additions and 0 deletions

View file

@ -21,6 +21,62 @@
#include "support.h"
#include "handle.h"
/****************************************************************************/
/* xls */
static unsigned char XLS_MAGIC[8] = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
/**
* Patch XLS files to clear hidden modification made by Excel.
*
* Excel modifies .XLS files even when just opening them, restoring
* the timestamp to its original value.
*
* To avoid that this operation invalidates the parity, we here patches
* the XLS files, clearing the date/time data usually modified.
*
* How to prevent Excel from modifying the file on exit?
* http://superuser.com/questions/664549/how-to-prevent-excel-from-modifying-the-file-on-exit
*/
void xls_patch(unsigned char* data, unsigned size)
{
unsigned char* p;
unsigned char* end;
if (size < 512)
return;
/* check the header magic */
if (memcmp(data, XLS_MAGIC, 8) != 0)
return;
/* check the endianess */
if (data[0x1c] != 0xfe || data[0x1d] != 0xff)
return;
/* walk all the records */
end = data + size;
p = data;
while (p + 4 <= end) {
unsigned id = p[0] + ((unsigned)p[1] << 8);
unsigned len = p[2] + ((unsigned)p[3] << 8);
p += 4;
/* check if the record is complely in the block */
if (p + len > end)
return;
/* search for the USRINFO 193h record */
if (id == 0x193 && len >= 33) {
/* clear the data/time information */
memset(p + 24,0, 8);
}
p += len;
}
}
/****************************************************************************/
/* handle */
@ -161,6 +217,9 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int
return 0;
}
/* identify Excel files (FNM_CASEFOLD is case insensitive) */
handle->xls = fnmatch("*.xls", file->sub, FNM_CASEFOLD) == 0;
pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
/* for sure not created */
@ -309,6 +368,10 @@ int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned c
memset(block_buffer + read_size, 0, block_size - read_size);
}
/* if it's an xls file, patch the header */
if (handle->xls && file_pos == 0)
xls_patch(block_buffer, block_size);
/* Here isn't needed to call posix_fadvise(..., POSIX_FADV_DONTNEED) */
/* because we already advised sequential access with POSIX_FADV_SEQUENTIAL. */
/* In Linux 2.6.33 it's enough to ensure that data is not kept in the cache. */

View file

@ -32,6 +32,7 @@ struct snapraid_handle {
struct stat st; /**< Stat info of the opened file. */
data_off_t valid_size; /**< Size of the valid data. */
int created; /**< If the file was created, otherwise it was already existing. */
int xls; /**< If it's an .xls name file. */
};
/**