Source
x
// SPDX-License-Identifier: GPL-2.0
/*
* linux/fs/isofs/dir.c
*
* (C) 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem.
*
* (C) 1991 Linus Torvalds - minix filesystem
*
* Steve Beynon : Missing last directory entries fixed
* (stephen@askone.demon.co.uk) : 21st June 1996
*
* isofs directory handling functions
*/
int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
{
char * old = de->name;
int len = de->name_len[0];
int i;
for (i = 0; i < len; i++) {
unsigned char c = old[i];
if (!c)
break;
if (c >= 'A' && c <= 'Z')
c |= 0x20; /* lower case */
/* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
break;
/* Drop trailing ';1' */
if (c == ';' && i == len - 2 && old[i + 1] == '1')
break;
/* Convert remaining ';' to '.' */
/* Also '/' to '.' (broken Acorn-generated ISO9660 images) */
if (c == ';' || c == '/')
c = '.';
new[i] = c;
}
return i;
}
/* Acorn extensions written by Matthew Wilcox <willy@infradead.org> 1998 */
int get_acorn_filename(struct iso_directory_record *de,
char *retname, struct inode *inode)
{
int std;
unsigned char *chr;
int retnamlen = isofs_name_translate(de, retname, inode);
if (retnamlen == 0)
return 0;
std = sizeof(struct iso_directory_record) + de->name_len[0];
if (std & 1)
std++;
if (de->length[0] - std != 32)
return retnamlen;
chr = ((unsigned char *) de) + std;
if (strncmp(chr, "ARCHIMEDES", 10))
return retnamlen;
if ((*retname == '_') && ((chr[19] & 1) == 1))
*retname = '!';
if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
&& ((chr[12] & 0xf0) == 0xf0)) {
retname[retnamlen] = ',';
sprintf(retname+retnamlen+1, "%3.3x",
((chr[12] & 0xf) << 8) | chr[11]);
retnamlen += 4;
}
return retnamlen;
}
/*
* This should _really_ be cleaned up some day..
*/
static int do_isofs_readdir(struct inode *inode, struct file *file,
struct dir_context *ctx,
char *tmpname, struct iso_directory_record *tmpde)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
unsigned long block, offset, block_saved, offset_saved;
unsigned long inode_number = 0; /* Quiet GCC */
struct buffer_head *bh = NULL;
int len;
int map;