--- orig/dosfsck/lfn.c	2005-03-13 04:05:44.000000000 +1300
+++ dosfsck/lfn.c	2008-06-26 22:49:36.000000000 +1200
@@ -143,34 +143,37 @@ void lfn_reset( void )
 }
 
 
 /* This function is only called with de->attr == VFAT_LN_ATTR. It stores part
  * of the long name. */
 void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
 {
     LFN_ENT *lfn = (LFN_ENT *)de;
+    int slot = lfn->id & LFN_ID_SLOTMASK;
     unsigned offset;
 
+    if (lfn_slot == 0) lfn_check_orphaned();
+
     if (de->attr != VFAT_LN_ATTR)
 	die("lfn_add_slot called with non-LFN directory entry");
 
-    if (lfn->id & LFN_ID_START) {
+    if (lfn->id & LFN_ID_START && slot != 0) {
 	if (lfn_slot != -1) {
 	    int can_clear = 0;
 	    /* There is already a LFN "in progess", so it is an error that a
 	     * new start entry is here. */
 	    /* Causes: 1) if slot# == expected: start bit set mysteriously, 2)
 	     *         old LFN overwritten by new one */
 	    /* Fixes: 1) delete previous LFN 2) if slot# == expected and
 	     *        checksum ok: clear start bit */
 	    /* XXX: Should delay that until next LFN known (then can better
 	     * display the name) */
 	    printf( "A new long file name starts within an old one.\n" );
-	    if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot &&
+	    if (slot == lfn_slot &&
 		lfn->alias_checksum == lfn_checksum) {
 		char *part1 = CNV_THIS_PART(lfn);
 		char *part2 = CNV_PARTS_SO_FAR();
 		printf( "  It could be that the LFN start bit is wrong here\n"
 			"  if \"%s\" seems to match \"%s\".\n", part1, part2 );
 		free( part1 );
 		free( part2 );
 		can_clear = 1;
@@ -192,102 +195,102 @@ void lfn_add_slot( DIR_ENT *de, loff_t d
 		  case '3':
 		    lfn->id &= ~LFN_ID_START;
 		    fs_write( dir_offset+offsetof(LFN_ENT,id),
 			      sizeof(lfn->id), &lfn->id );
 		    break;
 		}
 	    }
 	}
-	lfn_slot = lfn->id & LFN_ID_SLOTMASK;
+	lfn_slot = slot;
 	lfn_checksum = lfn->alias_checksum;
 	lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
 	lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
 	lfn_parts = 0;
     }
-    else if (lfn_slot == -1) {
+    else if (lfn_slot == -1 && slot != 0) {
 	/* No LFN in progress, but slot found; start bit missing */
 	/* Causes: 1) start bit got lost, 2) Previous slot with start bit got
 	 *         lost */
 	/* Fixes: 1) delete LFN, 2) set start bit */
 	char *part = CNV_THIS_PART(lfn);
 	printf( "Long filename fragment \"%s\" found outside a LFN "
 		"sequence.\n  (Maybe the start bit is missing on the "
 		"last fragment)\n", part );
 	if (interactive) {
 	    printf( "1: Delete fragment\n2: Leave it as it is.\n"
 		    "3: Set start bit\n" );
 	}
 	else printf( "  Not auto-correcting this.\n" );
-	if (interactive) {
-	    switch( get_key( "123", "?" )) {
-	      case '1':
-		if (!lfn_offsets)
-		    lfn_offsets = alloc( sizeof(loff_t) );
-		lfn_offsets[0] = dir_offset;
-		clear_lfn_slots( 0, 0 );
-		lfn_reset();
-		return;
-	      case '2':
-		lfn_reset();
-		return;
-	      case '3':
-		lfn->id |= LFN_ID_START;
-		fs_write( dir_offset+offsetof(LFN_ENT,id),
-			  sizeof(lfn->id), &lfn->id );
-		lfn_slot = lfn->id & LFN_ID_SLOTMASK;
-		lfn_checksum = lfn->alias_checksum;
-		lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
-		lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
-		lfn_parts = 0;
-		break;
-	    }
+	switch( interactive ? get_key( "123", "?" ) : '2') {
+	  case '1':
+	    if (!lfn_offsets)
+	        lfn_offsets = alloc( sizeof(loff_t) );
+	    lfn_offsets[0] = dir_offset;
+	    clear_lfn_slots( 0, 0 );
+	    lfn_reset();
+	    return;
+	  case '2':
+	    lfn_reset();
+	    return;
+	  case '3':
+	    lfn->id |= LFN_ID_START;
+	    fs_write( dir_offset+offsetof(LFN_ENT,id),
+		      sizeof(lfn->id), &lfn->id );
+	    lfn_slot = slot;
+	    lfn_checksum = lfn->alias_checksum;
+	    lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
+	    lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
+	    lfn_parts = 0;
+	    break;
 	}
     }
-    else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) {
+    else if (slot != lfn_slot) {
 	/* wrong sequence number */
 	/* Causes: 1) seq-no destroyed */
 	/* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
 	 *        are ok?, maybe only if checksum is ok?) (Attention: space
 	 *        for name was allocated before!) */
 	int can_fix = 0;
 	printf( "Unexpected long filename sequence number "
 		"(%d vs. expected %d).\n",
-		(lfn->id & LFN_ID_SLOTMASK), lfn_slot );
-	if (lfn->alias_checksum == lfn_checksum) {
+		slot, lfn_slot );
+	if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) {
 	    char *part1 = CNV_THIS_PART(lfn);
 	    char *part2 = CNV_PARTS_SO_FAR();
 	    printf( "  It could be that just the number is wrong\n"
 		    "  if \"%s\" seems to match \"%s\".\n", part1, part2 );
 	    free( part1 );
 	    free( part2 );
 	    can_fix = 1;
 	}
 	if (interactive) {
 	    printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" );
 	    if (can_fix)
 		printf( "3: Correct sequence number\n" );
 	}
 	else printf( "  Not auto-correcting this.\n" );
-	if (interactive) {
-	    switch( get_key( can_fix ? "123" : "12", "?" )) {
-	      case '1':
-		lfn_offsets[lfn_parts++] = dir_offset;
-		clear_lfn_slots( 0, lfn_parts-1 );
-		lfn_reset();
-		return;
-	      case '2':
-		lfn_reset();
-		return;
-	      case '3':
-		lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot;
-		fs_write( dir_offset+offsetof(LFN_ENT,id),
-			  sizeof(lfn->id), &lfn->id );
-		break;
+	switch( interactive ? get_key( can_fix ? "123" : "12", "?" ) : '2') {
+	  case '1':
+	    if (!lfn_offsets) {
+	        lfn_offsets = alloc( sizeof(loff_t) );
+		lfn_parts = 0;
 	    }
+	    lfn_offsets[lfn_parts++] = dir_offset;
+	    clear_lfn_slots( 0, lfn_parts-1 );
+	    lfn_reset();
+	    return;
+	  case '2':
+	    lfn_reset();
+	    return;
+	  case '3':
+	    lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot;
+	    fs_write( dir_offset+offsetof(LFN_ENT,id),
+		      sizeof(lfn->id), &lfn->id );
+	    break;
 	}
     }
 
     if (lfn->alias_checksum != lfn_checksum) {
 	/* checksum mismatch */
 	/* Causes: 1) checksum field here destroyed */
 	/* Fixes: 1) delete LFN, 2) fix checksum */
 	printf( "Checksum in long filename part wrong "
@@ -385,35 +388,33 @@ char *lfn_get( DIR_ENT *de )
 		long_name, short_name );
 	free( long_name );
 	if (interactive) {
 	    printf( "1: Delete LFN\n2: Leave it as it is.\n"
 		    "3: Fix numbering (truncates long name and attaches "
 		    "it to short name %s)\n", short_name );
 	}
 	else printf( "  Not auto-correcting this.\n" );
-	if (interactive) {
-	    switch( get_key( "123", "?" )) {
-	      case '1':
-		clear_lfn_slots( 0, lfn_parts-1 );
-		lfn_reset();
-		return NULL;
-	      case '2':
-		lfn_reset();
-		return NULL;
-	      case '3':
-		for( i = 0; i < lfn_parts; ++i ) {
-		    __u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0);
-		    fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id),
-			      sizeof(id), &id );
-		}
-		memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2,
-			 lfn_parts*CHARS_PER_LFN*2 );
-		break;
+	switch( interactive ? get_key( "123", "?" ) : '2') {
+	  case '1':
+	    clear_lfn_slots( 0, lfn_parts-1 );
+	    lfn_reset();
+	    return NULL;
+	  case '2':
+	    lfn_reset();
+	    return NULL;
+	  case '3':
+	    for( i = 0; i < lfn_parts; ++i ) {
+	        __u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0);
+		fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id),
+			  sizeof(id), &id );
 	    }
+	    memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2,
+		     lfn_parts*CHARS_PER_LFN*2 );
+	    break;
 	}
     }
 
     for (sum = 0, i = 0; i < 11; i++)
 	sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i];
     if (sum != lfn_checksum) {
 	/* checksum doesn't match, long name doesn't apply to this alias */
 	/* Causes: 1) alias renamed */
