Skip to content

Commit

Permalink
Some filesystems violate against the POSIX rules.
Browse files Browse the repository at this point in the history
when backing up a filesystem mounted to a linux host via ntfs, we get an
assertion error:

backup-sd-fd: bfile.c:1031-0 open file
/bacula-mounts/INEZ/part2/Users/<username>/AppData/Local/Packages/WinStore_cw5n1h2txyewy/AC/Microsoft/Windows
Store/Cache/0/0-Featured-https∺∯∯next-services.apps.microsoft.com∯browse∯6.2.9200-1∯667∯c∯DE∯Featured∯10895826.dat
backup-sd-fd: backup.c:983-0 Send data to SD len=6552
backup-sd-fd: find_one.c:756-0 Failed ASSERT: name_max+1 >
(int)sizeof(struct dirent) + (int)NAMELEN(entry)

Fixes #250: bareos-fd asserts when reading a file from ntfs volume mounted on linux
  • Loading branch information
Marco van Wieringen committed Nov 16, 2013
1 parent da29b79 commit d330f87
Showing 1 changed file with 39 additions and 22 deletions.
61 changes: 39 additions & 22 deletions src/findlib/find_one.c
Expand Up @@ -299,30 +299,30 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt)
}

if (statp.st_mtime != ff_pkt->statp.st_mtime) {
Jmsg(jcr, M_ERROR, 0, _("%s mtime changed during backup.\n"), ff_pkt->fname);
Jmsg(jcr, M_ERROR, 0, _("%s: mtime changed during backup.\n"), ff_pkt->fname);
Dmsg3(50, "%s mtime (%lld) changed during backup (%lld).\n", ff_pkt->fname,
(int64_t)ff_pkt->statp.st_mtime, (int64_t)statp.st_mtime);
return true;
}

if (statp.st_ctime != ff_pkt->statp.st_ctime) {
Jmsg(jcr, M_ERROR, 0, _("%s ctime changed during backup.\n"), ff_pkt->fname);
Jmsg(jcr, M_ERROR, 0, _("%s: ctime changed during backup.\n"), ff_pkt->fname);
Dmsg3(50, "%s ctime (%lld) changed during backup (%lld).\n", ff_pkt->fname,
(int64_t)ff_pkt->statp.st_ctime, (int64_t)statp.st_ctime);
return true;
}

if (statp.st_size != ff_pkt->statp.st_size) {
/* TODO: add size change */
Jmsg(jcr, M_ERROR, 0, _("%s size changed during backup.\n"),ff_pkt->fname);
Jmsg(jcr, M_ERROR, 0, _("%s: size changed during backup.\n"),ff_pkt->fname);
Dmsg3(50, "%s size (%lld) changed during backup (%lld).\n", ff_pkt->fname,
(int64_t)ff_pkt->statp.st_size, (int64_t)statp.st_size);
return true;
}

if ((statp.st_blksize != ff_pkt->statp.st_blksize) ||
(statp.st_blocks != ff_pkt->statp.st_blocks)) {
Jmsg(jcr, M_ERROR, 0, _("%s size changed during backup.\n"),ff_pkt->fname);
Jmsg(jcr, M_ERROR, 0, _("%s: size changed during backup.\n"),ff_pkt->fname);
Dmsg3(50, "%s size (%lld) changed during backup (%lld).\n", ff_pkt->fname,
(int64_t)ff_pkt->statp.st_blocks, (int64_t)statp.st_blocks);
return true;
Expand Down Expand Up @@ -720,8 +720,7 @@ static inline int process_directory(JCR *jcr, FF_PKT *ff_pkt,
ff_pkt->link = ff_pkt->fname; /* reset "link" */

/*
* Descend into or "recurse" into the directory to read
* all the files in it.
* Descend into or "recurse" into the directory to read all the files in it.
*/
errno = 0;
if ((directory = opendir(fname)) == NULL) {
Expand All @@ -742,44 +741,62 @@ static inline int process_directory(JCR *jcr, FF_PKT *ff_pkt,
* before traversing it.
*/
rtn_stat = 1;

/*
* Allocate some extra room so an overflow of the d_name with more then
* name_max bytes doesn't kill us right away. We check in the loop if
* an overflow has not happened.
*/
entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
for ( ; !job_canceled(jcr); ) {
char *p, *q;
int i;
while (!job_canceled(jcr)) {
int name_length;

status = readdir_r(directory, entry, &result);
status = readdir_r(directory, entry, &result);
if (status != 0 || result == NULL) {
// Dmsg2(99, "readdir returned stat=%d result=0x%x\n",
// status, (long)result);
break;
}
ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
p = entry->d_name;

name_length = (int)NAMELEN(entry);

/*
* Skip `.', `..', and excluded file names.
* Some filesystems violate against the rules and return filenames
* longer then _PC_NAME_MAX. Log the error and continue.
*/
if (p[0] == '\0' || (p[0] == '.' && (p[1] == '\0' ||
(p[1] == '.' && p[2] == '\0')))) {
if ((name_max + 1) <= ((int)sizeof(struct dirent) + name_length)) {
Jmsg2(jcr, M_ERROR, 0, _("%s: File name too long [%d]\n"), entry->d_name, name_length);
continue;
}

if ((int)NAMELEN(entry) + len >= link_len) {
link_len = len + NAMELEN(entry) + 1;
link = (char *)brealloc(link, link_len + 1);
/*
* Skip `.', `..', and excluded file names.
*/
if (entry->d_name[0] == '\0' ||
(entry->d_name[0] == '.' && (entry->d_name[1] == '\0' ||
(entry->d_name[1] == '.' && entry->d_name[2] == '\0')))) {
continue;
}
q = link + len;
for (i=0; i < (int)NAMELEN(entry); i++) {
*q++ = *p++;

/*
* Make sure there is enough room to store the whole name.
*/
if (name_length + len >= link_len) {
link_len = len + name_length + 1;
link = (char *)brealloc(link, link_len + 1);
}
*q = 0;

memcpy(link + len, entry->d_name, name_length);
link[len + name_length] = '\0';

if (!file_is_excluded(ff_pkt, link)) {
rtn_stat = find_one_file(jcr, ff_pkt, handle_file, link, our_device, false);
if (ff_pkt->linked) {
ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
}
}
}

closedir(directory);
free(link);
free(entry);
Expand Down

0 comments on commit d330f87

Please sign in to comment.