Modify LFN direntries when file is renamed or deleted, see
Debian bug #596329. Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
parent
e56ff72c16
commit
ea41797c7a
21
src/check.c
21
src/check.c
@ -311,12 +311,29 @@ static int bad_name(DOS_FILE *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lfn_remove(loff_t from, loff_t to)
|
||||
{
|
||||
int i;
|
||||
DIR_ENT empty;
|
||||
|
||||
/* New dir entry is zeroed except first byte, which is set to 0xe5.
|
||||
* This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading
|
||||
* a directory at the first zero entry...
|
||||
*/
|
||||
memset( &empty, 0, sizeof(empty) );
|
||||
empty.name[0] = DELETED_FLAG;
|
||||
|
||||
for( ; from < to; from += sizeof(empty) ) {
|
||||
fs_write( from, sizeof(DIR_ENT), &empty );
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_file(DOS_FS *fs,DOS_FILE *file)
|
||||
{
|
||||
unsigned long cluster;
|
||||
|
||||
MODIFY(file,name[0],DELETED_FLAG);
|
||||
if (file->lfn) lfn_remove(file->lfn_offset, file->offset);
|
||||
for (cluster = FSTART(file,fs); cluster > 0 && cluster <
|
||||
fs->clusters+2; cluster = next_cluster(fs,cluster))
|
||||
set_owner(fs,cluster,NULL);
|
||||
@ -361,6 +378,7 @@ static void auto_rename(DOS_FILE *file)
|
||||
name,MSDOS_NAME)) break;
|
||||
if (!walk) {
|
||||
fs_write(file->offset,MSDOS_NAME,file->dir_ent.name);
|
||||
if (file->lfn) lfn_fix_checksum(file->lfn_offset, file->offset, file->dir_ent.name);
|
||||
return;
|
||||
}
|
||||
number++;
|
||||
@ -392,6 +410,7 @@ static void rename_file(DOS_FILE *file)
|
||||
for (walk = name; *walk == ' ' || *walk == '\t'; walk++);
|
||||
if (file_cvt(walk,file->dir_ent.name)) {
|
||||
fs_write(file->offset,MSDOS_NAME,file->dir_ent.name);
|
||||
if (file->lfn) lfn_fix_checksum(file->lfn_offset, file->offset, file->dir_ent.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -862,7 +881,7 @@ static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
|
||||
return;
|
||||
}
|
||||
new = qalloc(&mem_queue,sizeof(DOS_FILE));
|
||||
new->lfn = lfn_get(&de);
|
||||
new->lfn = lfn_get(&de, &new->lfn_offset);
|
||||
new->offset = offset;
|
||||
memcpy(&new->dir_ent,&de,sizeof(de));
|
||||
new->next = new->first = NULL;
|
||||
|
||||
@ -155,6 +155,7 @@ typedef struct _dos_file {
|
||||
DIR_ENT dir_ent;
|
||||
char *lfn;
|
||||
loff_t offset;
|
||||
loff_t lfn_offset;
|
||||
struct _dos_file *parent; /* parent directory */
|
||||
struct _dos_file *next; /* next entry */
|
||||
struct _dos_file *first; /* first entry (directory only) */
|
||||
|
||||
16
src/lfn.c
16
src/lfn.c
@ -148,6 +148,18 @@ static void clear_lfn_slots( int start, int end )
|
||||
}
|
||||
}
|
||||
|
||||
void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name)
|
||||
{
|
||||
int i;
|
||||
__u8 sum;
|
||||
for (sum = 0, i = 0; i < 11; i++)
|
||||
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + short_name[i];
|
||||
|
||||
for( ; from < to; from += sizeof(LFN_ENT) ) {
|
||||
fs_write( from + offsetof(LFN_ENT,alias_checksum), sizeof(sum), &sum );
|
||||
}
|
||||
}
|
||||
|
||||
void lfn_reset( void )
|
||||
{
|
||||
if (lfn_unicode)
|
||||
@ -374,12 +386,13 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
|
||||
/* This function is always called when de->attr != VFAT_LN_ATTR is found, to
|
||||
* retrieve the previously constructed LFN. */
|
||||
char *lfn_get( DIR_ENT *de )
|
||||
char *lfn_get( DIR_ENT *de, loff_t *lfn_offset )
|
||||
{
|
||||
char *lfn;
|
||||
__u8 sum;
|
||||
int i;
|
||||
|
||||
*lfn_offset = 0;
|
||||
if (de->attr == VFAT_LN_ATTR)
|
||||
die("lfn_get called with LFN directory entry");
|
||||
|
||||
@ -467,6 +480,7 @@ char *lfn_get( DIR_ENT *de )
|
||||
}
|
||||
}
|
||||
|
||||
*lfn_offset = lfn_offsets[0];
|
||||
lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 );
|
||||
lfn_reset();
|
||||
return( lfn );
|
||||
|
||||
@ -28,9 +28,11 @@ void lfn_reset( void );
|
||||
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset );
|
||||
/* Process a dir slot that is a VFAT LFN entry. */
|
||||
|
||||
char *lfn_get( DIR_ENT *de );
|
||||
char *lfn_get( DIR_ENT *de, loff_t *lfn_offset );
|
||||
/* Retrieve the long name for the proper dir entry. */
|
||||
|
||||
void lfn_check_orphaned(void);
|
||||
|
||||
void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user