Made possible to run ntfsundelete on systems with no regex.h

The filtering of files to undelete is usually done through the regex
library. This patch offers an alternate way when such a library is
not readily available (typically on Windows).
edge.strict_endians
Jean-Pierre André 2013-02-09 11:56:09 +01:00
parent c972652876
commit b2e1dbbf38
2 changed files with 149 additions and 2 deletions

View File

@ -422,7 +422,7 @@ AC_HEADER_STDC
AC_CHECK_HEADERS([ctype.h fcntl.h libgen.h libintl.h limits.h locale.h \
mntent.h stddef.h stdint.h stdlib.h stdio.h stdarg.h string.h \
strings.h errno.h time.h unistd.h utime.h wchar.h getopt.h features.h \
endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \
regex.h endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \
sys/param.h sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h \
sys/vfs.h sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h \
linux/hdreg.h machine/endian.h windows.h syslog.h pwd.h malloc.h])

View File

@ -68,12 +68,18 @@
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#if !defined(REG_NOERROR) || (REG_NOERROR != 0)
#define REG_NOERROR 0
#endif
#ifndef REG_NOMATCH
#define REG_NOMATCH 1
#endif
#include "ntfsundelete.h"
#include "bootsect.h"
#include "mft.h"
@ -106,6 +112,132 @@ static short avoid_duplicate_printing; /* Flag No duplicate printing of file in
static range *ranges; /* Array containing all Inode-Ranges for undelete */
static long nr_entries; /* Number of range entries */
#ifndef HAVE_REGEX_H
/*
* Pattern matching routing for systems with no regex.
*/
typedef struct REGEX {
ntfschar *upcase;
u32 upcase_len;
int flags;
int pattern_len;
ntfschar pattern[1];
} *regex_t;
enum { REG_NOSUB = 1, REG_ICASE = 2 };
static BOOL patmatch(regex_t *re, const ntfschar *f, int flen,
const ntfschar *p, int plen, BOOL dot)
{
regex_t pre;
BOOL ok;
BOOL anyextens;
int i;
unsigned int c;
pre = *re;
if (pre->flags & REG_ICASE) {
while ((flen > 0) && (plen > 0)
&& ((*f == *p)
|| (*p == const_cpu_to_le16('?'))
|| ((c = le16_to_cpu(*f)) < pre->upcase_len
? pre->upcase[c] : c) == *p)) {
flen--;
if (*f++ == const_cpu_to_le16('.'))
dot = TRUE;
plen--;
p++;
}
} else {
while ((flen > 0) && (plen > 0)
&& ((*f == *p) || (*p == const_cpu_to_le16('?')))) {
flen--;
if (*f++ == const_cpu_to_le16('.'))
dot = TRUE;
plen--;
p++;
}
}
if ((flen <= 0) && (plen <= 0))
ok = TRUE;
else {
ok = FALSE;
plen--;
if (*p++ == const_cpu_to_le16('*')) {
/* special case "*.*" requires the end or a dot */
anyextens = FALSE;
if ((plen == 2)
&& (p[0] == const_cpu_to_le16('.'))
&& (p[1] == const_cpu_to_le16('*'))
&& !dot) {
for (i=0; (i<flen) && !anyextens; i++)
if (f[i] == const_cpu_to_le16('.'))
anyextens = TRUE;
}
if (!plen || anyextens)
ok = TRUE;
else
while ((flen > 0) && !ok)
if (patmatch(re,f,flen,p,plen,dot))
ok = TRUE;
else {
flen--;
f++;
}
}
}
return (ok);
}
static int regcomp(regex_t *re, const char *pattern, int flags)
{
regex_t pre;
ntfschar *rp;
ntfschar *p;
unsigned int c;
int lth;
int i;
pre = (regex_t)malloc(sizeof(struct REGEX)
+ strlen(pattern)*sizeof(ntfschar));
*re = pre;
if (pre) {
pre->flags = flags;
pre->upcase_len = 0;
rp = pre->pattern;
lth = ntfs_mbstoucs(pattern, &rp);
pre->pattern_len = lth;
p = pre->pattern;
if (flags & REG_ICASE) {
for (i=0; i<lth; i++) {
c = le16_to_cpu(*p);
if (c < pre->upcase_len)
*p = pre->upcase[c];
p++;
}
}
}
return (*re && (lth > 0) ? 0 : -1);
}
static int regexec(regex_t *re, const ntfschar *uname, int len,
char *q __attribute__((unused)), int r __attribute__((unused)))
{
BOOL m;
m = patmatch(re, uname, len, (*re)->pattern, (*re)->pattern_len, FALSE);
return (m ? REG_NOERROR : REG_NOMATCH);
}
static void regfree(regex_t *re)
{
free(*re);
}
#endif
/**
* parse_inode_arg - parses the inode expression
*
@ -292,7 +424,10 @@ static void usage(void)
static int transform(const char *pattern, char **regex)
{
char *result;
int length, i, j;
int length, i;
#ifdef HAVE_REGEX_H
int j;
#endif
if (!pattern || !regex)
return 0;
@ -314,6 +449,7 @@ static int transform(const char *pattern, char **regex)
return 0;
}
#ifdef HAVE_REGEX_H
result[0] = '^';
for (i = 0, j = 1; pattern[i]; i++, j++) {
@ -336,6 +472,9 @@ static int transform(const char *pattern, char **regex)
result[j+1] = 0;
ntfs_log_debug("Pattern '%s' replaced with regex '%s'.\n", pattern,
result);
#else
strcpy(result, pattern);
#endif
*regex = result;
return 1;
@ -1578,7 +1717,11 @@ static int name_match(regex_t *re, struct ufile *file)
if (!f->name)
continue;
#ifdef HAVE_REGEX_H
result = regexec(re, f->name, 0, NULL, 0);
#else
result = regexec(re, f->uname, f->uname_len, NULL, 0);
#endif
if (result < 0) {
ntfs_log_perror("Couldn't compare filename with regex");
return 0;
@ -2032,6 +2175,10 @@ static int scan_disk(ntfs_volume *vol)
ntfs_log_error("ERROR: Couldn't create a regex.\n");
goto out;
}
#ifndef HAVE_REGEX_H
re->upcase = vol->upcase;
re->upcase_len = vol->upcase_len;
#endif
}
nr_mft_records = vol->mft_na->initialized_size >>