@@ -506,24 +506,29 @@ void DeviceWrapperFatPartition::updateDirEntry(struct dir_entry *dirEntry)
506
506
struct dir_entry iterEntry;
507
507
508
508
openDir ();
509
+ quint64 oldOffset = _offset;
510
+
509
511
while (readDir (&iterEntry))
510
512
{
511
513
/* Look for existing entry with same short filename */
512
514
if (!(iterEntry.DIR_Attr & ATTR_LONG_NAME)
513
515
&& memcmp (dirEntry->DIR_Name , iterEntry.DIR_Name , sizeof (iterEntry.DIR_Name )) == 0 )
514
516
{
515
517
/* seek() back and write out new entry */
516
- _offset -= sizeof (*dirEntry) ;
518
+ _offset = oldOffset ;
517
519
write ((char *) dirEntry, sizeof (*dirEntry));
518
520
return ;
519
521
}
522
+
523
+ oldOffset = _offset;
520
524
}
521
525
522
526
throw std::runtime_error (" Error locating existing directory entry" );
523
527
}
524
528
525
529
void DeviceWrapperFatPartition::writeDirEntryAtCurrentPos (struct dir_entry *dirEntry)
526
530
{
531
+ // qDebug() << "Write new entry" << QByteArray((char *) dirEntry->DIR_Name, 11);
527
532
write ((char *) dirEntry, sizeof (*dirEntry));
528
533
529
534
if (_type == FAT32)
@@ -532,15 +537,23 @@ void DeviceWrapperFatPartition::writeDirEntryAtCurrentPos(struct dir_entry *dirE
532
537
{
533
538
/* We reached the end of the cluster, allocate/seek to next cluster */
534
539
uint32_t nextCluster = getFAT (_fat32_currentRootDirCluster);
535
- /* FIXME: should we check for circular cluster references? */
536
540
537
541
if (nextCluster > 0xFFFFFF7 )
538
542
{
539
543
nextCluster = allocateCluster (_fat32_currentRootDirCluster);
540
544
}
541
545
546
+ if (_currentDirClusters.contains (nextCluster))
547
+ throw std::runtime_error (" Circular cluster references in FAT32 directory detected" );
548
+ _currentDirClusters.append (nextCluster);
549
+
542
550
_fat32_currentRootDirCluster = nextCluster;
543
551
seekCluster (_fat32_currentRootDirCluster);
552
+
553
+ /* Zero out entire new cluster, as fsck.fat does not stop reading entries at end-of-directory marker */
554
+ QByteArray zeroes (_bytesPerCluster, 0 );
555
+ write (zeroes.data (), zeroes.length () );
556
+ seekCluster (_fat32_currentRootDirCluster);
544
557
}
545
558
}
546
559
else if (pos () > (_fat16_firstRootDirSector+_fat16_rootDirSectors)*_bytesPerSector)
@@ -560,6 +573,10 @@ void DeviceWrapperFatPartition::openDir()
560
573
{
561
574
_fat32_currentRootDirCluster = _fat32_firstRootDirCluster;
562
575
seekCluster (_fat32_currentRootDirCluster);
576
+ /* Keep track of directory clusters we seeked to, to be able
577
+ to detect circular references */
578
+ _currentDirClusters.clear ();
579
+ _currentDirClusters.append (_fat32_currentRootDirCluster);
563
580
}
564
581
}
565
582
@@ -581,11 +598,13 @@ bool DeviceWrapperFatPartition::readDir(struct dir_entry *result)
581
598
{
582
599
/* We reached the end of the cluster, seek to next cluster */
583
600
uint32_t nextCluster = getFAT (_fat32_currentRootDirCluster);
584
- /* FIXME: should we check for circular cluster references? */
585
601
586
602
if (nextCluster > 0xFFFFFF7 )
587
603
throw std::runtime_error (" Reached end of FAT32 root directory, but no end-of-directory marker found" );
588
604
605
+ if (_currentDirClusters.contains (nextCluster))
606
+ throw std::runtime_error (" Circular cluster references in FAT32 directory detected" );
607
+ _currentDirClusters.append (nextCluster);
589
608
_fat32_currentRootDirCluster = nextCluster;
590
609
seekCluster (_fat32_currentRootDirCluster);
591
610
}
0 commit comments