dirfile.c revision 0b332824
123a0898aSmrg/* 223a0898aSmrg 323a0898aSmrgCopyright 1991, 1998 The Open Group 423a0898aSmrg 523a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its 623a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that 723a0898aSmrgthe above copyright notice appear in all copies and that both that 823a0898aSmrgcopyright notice and this permission notice appear in supporting 923a0898aSmrgdocumentation. 1023a0898aSmrg 1123a0898aSmrgThe above copyright notice and this permission notice shall be included in 1223a0898aSmrgall copies or substantial portions of the Software. 1323a0898aSmrg 1423a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1523a0898aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1623a0898aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1723a0898aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1823a0898aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1923a0898aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2023a0898aSmrg 2123a0898aSmrgExcept as contained in this notice, the name of The Open Group shall not be 2223a0898aSmrgused in advertising or otherwise to promote the sale, use or other dealings 2323a0898aSmrgin this Software without prior written authorization from The Open Group. 2423a0898aSmrg 2523a0898aSmrg*/ 2623a0898aSmrg 2723a0898aSmrg/* 2823a0898aSmrg * Author: Keith Packard, MIT X Consortium 2923a0898aSmrg */ 3023a0898aSmrg 3123a0898aSmrg/* 3223a0898aSmrg * dirfile.c 3323a0898aSmrg * 3423a0898aSmrg * Read fonts.dir and fonts.alias files 3523a0898aSmrg */ 3623a0898aSmrg 3723a0898aSmrg#ifdef HAVE_CONFIG_H 3823a0898aSmrg#include <config.h> 3923a0898aSmrg#endif 4023a0898aSmrg#include <X11/fonts/fntfilst.h> 4123a0898aSmrg#include <stdio.h> 4223a0898aSmrg#include <sys/types.h> 4323a0898aSmrg#include <sys/stat.h> 4423a0898aSmrg#include <errno.h> 459d21a897Sspz#include <limits.h> 4623a0898aSmrg 4723a0898aSmrgstatic Bool AddFileNameAliases ( FontDirectoryPtr dir ); 4823a0898aSmrgstatic int ReadFontAlias ( char *directory, Bool isFile, 4923a0898aSmrg FontDirectoryPtr *pdir ); 5023a0898aSmrgstatic int lexAlias ( FILE *file, char **lexToken ); 5123a0898aSmrgstatic int lexc ( FILE *file ); 5223a0898aSmrg 530b332824Ssnj#pragma GCC diagnostic ignored "-Wformat-nonliteral" 540b332824Ssnj 5523a0898aSmrgint 560b332824SsnjFontFileReadDirectory (const char *directory, FontDirectoryPtr *pdir) 5723a0898aSmrg{ 5823a0898aSmrg char file_name[MAXFONTFILENAMELEN]; 5923a0898aSmrg char font_name[MAXFONTNAMELEN]; 6023a0898aSmrg char dir_file[MAXFONTFILENAMELEN]; 6123a0898aSmrg char dir_path[MAXFONTFILENAMELEN]; 6223a0898aSmrg char *ptr; 6323a0898aSmrg FILE *file; 6423a0898aSmrg int count, 6523a0898aSmrg num_fonts, 6623a0898aSmrg status; 6723a0898aSmrg struct stat statb; 6823a0898aSmrg static char format[24] = ""; 697f7f5e4eSmrg#if defined(WIN32) 707f7f5e4eSmrg int i; 717f7f5e4eSmrg#endif 7223a0898aSmrg 7323a0898aSmrg FontDirectoryPtr dir = NullFontDirectory; 7423a0898aSmrg 7523a0898aSmrg if (strlen(directory) + 1 + sizeof(FontDirFile) > sizeof(dir_file)) 7623a0898aSmrg return BadFontPath; 7723a0898aSmrg 7823a0898aSmrg /* Check for font directory attributes */ 797f7f5e4eSmrg#if !defined(WIN32) 8023a0898aSmrg if ((ptr = strchr(directory, ':'))) { 8123a0898aSmrg#else 8223a0898aSmrg /* OS/2 and WIN32 path might start with a drive letter, don't clip this */ 8323a0898aSmrg if ((ptr = strchr(directory+2, ':'))) { 8423a0898aSmrg#endif 8523a0898aSmrg strncpy(dir_path, directory, ptr - directory); 8623a0898aSmrg dir_path[ptr - directory] = '\0'; 8723a0898aSmrg } else { 8823a0898aSmrg strcpy(dir_path, directory); 8923a0898aSmrg } 9023a0898aSmrg strcpy(dir_file, dir_path); 9123a0898aSmrg if (dir_file[strlen(dir_file) - 1] != '/') 9223a0898aSmrg strcat(dir_file, "/"); 9323a0898aSmrg strcat(dir_file, FontDirFile); 9423a0898aSmrg file = fopen(dir_file, "rt"); 9523a0898aSmrg if (file) { 9641c30155Smrg#ifndef WIN32 9723a0898aSmrg if (fstat (fileno(file), &statb) == -1) 9823a0898aSmrg#else 9923a0898aSmrg if (stat (dir_file, &statb) == -1) 10023a0898aSmrg#endif 10123a0898aSmrg { 10223a0898aSmrg fclose(file); 10323a0898aSmrg return BadFontPath; 10423a0898aSmrg } 10523a0898aSmrg count = fscanf(file, "%d\n", &num_fonts); 10623a0898aSmrg if ((count == EOF) || (count != 1)) { 10723a0898aSmrg fclose(file); 10823a0898aSmrg return BadFontPath; 10923a0898aSmrg } 11023a0898aSmrg dir = FontFileMakeDir(directory, num_fonts); 11123a0898aSmrg if (dir == NULL) { 11223a0898aSmrg fclose(file); 11323a0898aSmrg return BadFontPath; 11423a0898aSmrg } 11523a0898aSmrg dir->dir_mtime = statb.st_mtime; 11623a0898aSmrg if (format[0] == '\0') 11723a0898aSmrg sprintf(format, "%%%ds %%%d[^\n]\n", 11823a0898aSmrg MAXFONTFILENAMELEN-1, MAXFONTNAMELEN-1); 11923a0898aSmrg 12023a0898aSmrg while ((count = fscanf(file, format, file_name, font_name)) != EOF) { 1217f7f5e4eSmrg#if defined(WIN32) 12223a0898aSmrg /* strip any existing trailing CR */ 12323a0898aSmrg for (i=0; i<strlen(font_name); i++) { 12423a0898aSmrg if (font_name[i]=='\r') font_name[i] = '\0'; 12523a0898aSmrg } 12623a0898aSmrg#endif 12723a0898aSmrg if (count != 2) { 12823a0898aSmrg FontFileFreeDir (dir); 12923a0898aSmrg fclose(file); 13023a0898aSmrg return BadFontPath; 13123a0898aSmrg } 13223a0898aSmrg 13323a0898aSmrg /* 13423a0898aSmrg * We blindly try to load all the font files specified. 13523a0898aSmrg * In theory, we might want to warn that some of the fonts 13623a0898aSmrg * couldn't be loaded. 13723a0898aSmrg */ 13823a0898aSmrg FontFileAddFontFile (dir, font_name, file_name); 13923a0898aSmrg } 14023a0898aSmrg fclose(file); 14141c30155Smrg 14223a0898aSmrg } else if (errno != ENOENT) { 14323a0898aSmrg return BadFontPath; 14423a0898aSmrg } 14523a0898aSmrg status = ReadFontAlias(dir_path, FALSE, &dir); 14623a0898aSmrg if (status != Successful) { 14723a0898aSmrg if (dir) 14823a0898aSmrg FontFileFreeDir (dir); 14923a0898aSmrg return status; 15023a0898aSmrg } 15123a0898aSmrg if (!dir) 15223a0898aSmrg return BadFontPath; 15323a0898aSmrg 15423a0898aSmrg FontFileSortDir(dir); 15523a0898aSmrg 15623a0898aSmrg *pdir = dir; 15723a0898aSmrg return Successful; 15823a0898aSmrg} 15923a0898aSmrg 16023a0898aSmrgBool 16123a0898aSmrgFontFileDirectoryChanged(FontDirectoryPtr dir) 16223a0898aSmrg{ 16323a0898aSmrg char dir_file[MAXFONTFILENAMELEN]; 16423a0898aSmrg struct stat statb; 16523a0898aSmrg 16623a0898aSmrg if (strlen(dir->directory) + sizeof(FontDirFile) > sizeof(dir_file)) 16723a0898aSmrg return FALSE; 16823a0898aSmrg 16923a0898aSmrg strcpy (dir_file, dir->directory); 17023a0898aSmrg strcat (dir_file, FontDirFile); 17123a0898aSmrg if (stat (dir_file, &statb) == -1) 17223a0898aSmrg { 17323a0898aSmrg if (errno != ENOENT || dir->dir_mtime != 0) 17423a0898aSmrg return TRUE; 17523a0898aSmrg return FALSE; /* doesn't exist and never did: no change */ 17623a0898aSmrg } 17723a0898aSmrg if (dir->dir_mtime != statb.st_mtime) 17823a0898aSmrg return TRUE; 1797f7f5e4eSmrg 1807f7f5e4eSmrg if ((strlen(dir->directory) + sizeof(FontAliasFile)) > sizeof(dir_file)) 1817f7f5e4eSmrg return FALSE; 18223a0898aSmrg strcpy (dir_file, dir->directory); 18323a0898aSmrg strcat (dir_file, FontAliasFile); 18423a0898aSmrg if (stat (dir_file, &statb) == -1) 18523a0898aSmrg { 18623a0898aSmrg if (errno != ENOENT || dir->alias_mtime != 0) 18723a0898aSmrg return TRUE; 18823a0898aSmrg return FALSE; /* doesn't exist and never did: no change */ 18923a0898aSmrg } 19023a0898aSmrg if (dir->alias_mtime != statb.st_mtime) 19123a0898aSmrg return TRUE; 19223a0898aSmrg return FALSE; 19323a0898aSmrg} 19441c30155Smrg 19523a0898aSmrg/* 19623a0898aSmrg * Make each of the file names an automatic alias for each of the files. 19723a0898aSmrg */ 19823a0898aSmrg 19923a0898aSmrgstatic Bool 20023a0898aSmrgAddFileNameAliases(FontDirectoryPtr dir) 20123a0898aSmrg{ 20223a0898aSmrg int i; 20323a0898aSmrg char copy[MAXFONTFILENAMELEN]; 20423a0898aSmrg char *fileName; 20523a0898aSmrg FontTablePtr table; 20623a0898aSmrg FontRendererPtr renderer; 20723a0898aSmrg int len; 20823a0898aSmrg FontNameRec name; 20923a0898aSmrg 21023a0898aSmrg table = &dir->nonScalable; 21123a0898aSmrg for (i = 0; i < table->used; i++) { 21223a0898aSmrg if (table->entries[i].type != FONT_ENTRY_BITMAP) 21323a0898aSmrg continue; 21423a0898aSmrg fileName = table->entries[i].u.bitmap.fileName; 21523a0898aSmrg renderer = FontFileMatchRenderer (fileName); 21623a0898aSmrg if (!renderer) 21723a0898aSmrg continue; 21841c30155Smrg 21923a0898aSmrg len = strlen (fileName) - renderer->fileSuffixLen; 22023a0898aSmrg if (len >= sizeof(copy)) 22123a0898aSmrg continue; 22223a0898aSmrg CopyISOLatin1Lowered (copy, fileName, len); 22323a0898aSmrg copy[len] = '\0'; 22423a0898aSmrg name.name = copy; 22523a0898aSmrg name.length = len; 22623a0898aSmrg name.ndashes = FontFileCountDashes (copy, len); 22723a0898aSmrg 22823a0898aSmrg if (!FontFileFindNameInDir(table, &name)) { 22923a0898aSmrg if (!FontFileAddFontAlias (dir, copy, table->entries[i].name.name)) 23023a0898aSmrg return FALSE; 23123a0898aSmrg } 23223a0898aSmrg } 23323a0898aSmrg return TRUE; 23423a0898aSmrg} 23523a0898aSmrg 23623a0898aSmrg/* 23723a0898aSmrg * parse the font.alias file. Format is: 23823a0898aSmrg * 23923a0898aSmrg * alias font-name 24023a0898aSmrg * 24123a0898aSmrg * To imbed white-space in an alias name, enclose it like "font name" 24223a0898aSmrg * in double quotes. \ escapes and character, so 24323a0898aSmrg * "font name \"With Double Quotes\" \\ and \\ back-slashes" 24423a0898aSmrg * works just fine. 24523a0898aSmrg * 24623a0898aSmrg * A line beginning with a ! denotes a newline-terminated comment. 24723a0898aSmrg */ 24823a0898aSmrg 24923a0898aSmrg/* 25023a0898aSmrg * token types 25123a0898aSmrg */ 25223a0898aSmrg 25323a0898aSmrg#define NAME 0 25423a0898aSmrg#define NEWLINE 1 25523a0898aSmrg#define DONE 2 25623a0898aSmrg#define EALLOC 3 25723a0898aSmrg 25823a0898aSmrgstatic int 25923a0898aSmrgReadFontAlias(char *directory, Bool isFile, FontDirectoryPtr *pdir) 26023a0898aSmrg{ 26123a0898aSmrg char alias[MAXFONTNAMELEN]; 26223a0898aSmrg char font_name[MAXFONTNAMELEN]; 26323a0898aSmrg char alias_file[MAXFONTFILENAMELEN]; 26423a0898aSmrg FILE *file; 26523a0898aSmrg FontDirectoryPtr dir; 26623a0898aSmrg int token; 26723a0898aSmrg char *lexToken; 26823a0898aSmrg int status = Successful; 26923a0898aSmrg struct stat statb; 27023a0898aSmrg 27123a0898aSmrg if (strlen(directory) >= sizeof(alias_file)) 27223a0898aSmrg return BadFontPath; 27323a0898aSmrg dir = *pdir; 27423a0898aSmrg strcpy(alias_file, directory); 27523a0898aSmrg if (!isFile) { 27623a0898aSmrg if (strlen(directory) + 1 + sizeof(FontAliasFile) > sizeof(alias_file)) 27723a0898aSmrg return BadFontPath; 27823a0898aSmrg if (directory[strlen(directory) - 1] != '/') 27923a0898aSmrg strcat(alias_file, "/"); 28023a0898aSmrg strcat(alias_file, FontAliasFile); 28123a0898aSmrg } 28223a0898aSmrg file = fopen(alias_file, "rt"); 28323a0898aSmrg if (!file) 28423a0898aSmrg return ((errno == ENOENT) ? Successful : BadFontPath); 28523a0898aSmrg if (!dir) 28623a0898aSmrg *pdir = dir = FontFileMakeDir(directory, 10); 28723a0898aSmrg if (!dir) 28823a0898aSmrg { 28923a0898aSmrg fclose (file); 29023a0898aSmrg return AllocError; 29123a0898aSmrg } 29223a0898aSmrg#ifndef WIN32 29323a0898aSmrg if (fstat (fileno (file), &statb) == -1) 29423a0898aSmrg#else 29523a0898aSmrg if (stat (alias_file, &statb) == -1) 29623a0898aSmrg#endif 29723a0898aSmrg { 29823a0898aSmrg fclose (file); 29923a0898aSmrg return BadFontPath; 30023a0898aSmrg } 30123a0898aSmrg dir->alias_mtime = statb.st_mtime; 30223a0898aSmrg while (status == Successful) { 30323a0898aSmrg token = lexAlias(file, &lexToken); 30423a0898aSmrg switch (token) { 30523a0898aSmrg case NEWLINE: 30623a0898aSmrg break; 30723a0898aSmrg case DONE: 30823a0898aSmrg fclose(file); 30923a0898aSmrg return Successful; 31023a0898aSmrg case EALLOC: 31123a0898aSmrg status = AllocError; 31223a0898aSmrg break; 31323a0898aSmrg case NAME: 31423a0898aSmrg if (strlen(lexToken) >= sizeof(alias)) { 31523a0898aSmrg status = BadFontPath; 31623a0898aSmrg break; 31723a0898aSmrg } 31823a0898aSmrg strcpy(alias, lexToken); 31923a0898aSmrg token = lexAlias(file, &lexToken); 32023a0898aSmrg switch (token) { 32123a0898aSmrg case NEWLINE: 32223a0898aSmrg if (strcmp(alias, "FILE_NAMES_ALIASES")) 32323a0898aSmrg status = BadFontPath; 32423a0898aSmrg else if (!AddFileNameAliases(dir)) 32523a0898aSmrg status = AllocError; 32623a0898aSmrg break; 32723a0898aSmrg case DONE: 32823a0898aSmrg status = BadFontPath; 32923a0898aSmrg break; 33023a0898aSmrg case EALLOC: 33123a0898aSmrg status = AllocError; 33223a0898aSmrg break; 33323a0898aSmrg case NAME: 33423a0898aSmrg if (strlen(lexToken) >= sizeof(font_name)) { 33523a0898aSmrg status = BadFontPath; 33623a0898aSmrg break; 33723a0898aSmrg } 33823a0898aSmrg CopyISOLatin1Lowered(alias, alias, strlen(alias)); 33923a0898aSmrg CopyISOLatin1Lowered(font_name, lexToken, strlen(lexToken)); 34023a0898aSmrg if (!FontFileAddFontAlias (dir, alias, font_name)) 34123a0898aSmrg status = AllocError; 34223a0898aSmrg break; 34323a0898aSmrg } 34423a0898aSmrg } 34523a0898aSmrg } 34623a0898aSmrg fclose(file); 34723a0898aSmrg return status; 34823a0898aSmrg} 34923a0898aSmrg 35023a0898aSmrg#define QUOTE 0 35123a0898aSmrg#define WHITE 1 35223a0898aSmrg#define NORMAL 2 35323a0898aSmrg#define END 3 35423a0898aSmrg#define NL 4 35523a0898aSmrg#define BANG 5 35623a0898aSmrg 35723a0898aSmrgstatic int charClass; 35823a0898aSmrg 35923a0898aSmrgstatic int 36023a0898aSmrglexAlias(FILE *file, char **lexToken) 36123a0898aSmrg{ 36223a0898aSmrg int c; 36323a0898aSmrg char *t; 36423a0898aSmrg enum state { 36523a0898aSmrg Begin, Normal, Quoted, Comment 36623a0898aSmrg } state; 36723a0898aSmrg int count; 36823a0898aSmrg 36923a0898aSmrg static char *tokenBuf = (char *) NULL; 37023a0898aSmrg static int tokenSize = 0; 37123a0898aSmrg 37223a0898aSmrg t = tokenBuf; 37323a0898aSmrg count = 0; 37423a0898aSmrg state = Begin; 37523a0898aSmrg for (;;) { 37623a0898aSmrg if (count == tokenSize) { 37723a0898aSmrg int nsize; 37823a0898aSmrg char *nbuf; 37923a0898aSmrg 3807673729aSmrg if (tokenSize >= (INT_MAX >> 2)) 3817673729aSmrg /* Stop before we overflow */ 3827673729aSmrg return EALLOC; 38323a0898aSmrg nsize = tokenSize ? (tokenSize << 1) : 64; 3847f7f5e4eSmrg nbuf = realloc(tokenBuf, nsize); 38523a0898aSmrg if (!nbuf) 38623a0898aSmrg return EALLOC; 38723a0898aSmrg tokenBuf = nbuf; 38823a0898aSmrg tokenSize = nsize; 38923a0898aSmrg t = tokenBuf + count; 39023a0898aSmrg } 39123a0898aSmrg c = lexc(file); 39223a0898aSmrg switch (charClass) { 39323a0898aSmrg case QUOTE: 39423a0898aSmrg switch (state) { 39523a0898aSmrg case Begin: 39623a0898aSmrg case Normal: 39723a0898aSmrg state = Quoted; 39823a0898aSmrg break; 39923a0898aSmrg case Quoted: 40023a0898aSmrg state = Normal; 40123a0898aSmrg break; 40223a0898aSmrg case Comment: 40323a0898aSmrg break; 40423a0898aSmrg } 40523a0898aSmrg break; 40623a0898aSmrg case WHITE: 40723a0898aSmrg switch (state) { 40823a0898aSmrg case Begin: 40923a0898aSmrg case Comment: 41023a0898aSmrg continue; 41123a0898aSmrg case Normal: 41223a0898aSmrg *t = '\0'; 41323a0898aSmrg *lexToken = tokenBuf; 41423a0898aSmrg return NAME; 41523a0898aSmrg case Quoted: 41623a0898aSmrg break; 41723a0898aSmrg } 41823a0898aSmrg /* fall through */ 41923a0898aSmrg case NORMAL: 42023a0898aSmrg switch (state) { 42123a0898aSmrg case Begin: 42223a0898aSmrg state = Normal; 42323a0898aSmrg break; 42423a0898aSmrg case Comment: 42523a0898aSmrg continue; 42623a0898aSmrg default: 42723a0898aSmrg break; 42823a0898aSmrg } 42923a0898aSmrg *t++ = c; 43023a0898aSmrg ++count; 43123a0898aSmrg break; 43223a0898aSmrg case END: 43323a0898aSmrg case NL: 43423a0898aSmrg switch (state) { 43523a0898aSmrg case Begin: 43623a0898aSmrg case Comment: 43723a0898aSmrg *lexToken = (char *) NULL; 43823a0898aSmrg return charClass == END ? DONE : NEWLINE; 43923a0898aSmrg default: 44023a0898aSmrg *t = '\0'; 44123a0898aSmrg *lexToken = tokenBuf; 44223a0898aSmrg ungetc(c, file); 44323a0898aSmrg return NAME; 44423a0898aSmrg } 44523a0898aSmrg break; 44623a0898aSmrg case BANG: 44723a0898aSmrg switch (state) { 44823a0898aSmrg case Begin: 44923a0898aSmrg state = Comment; 45023a0898aSmrg break; 45123a0898aSmrg case Comment: 45223a0898aSmrg break; 45323a0898aSmrg default: 45423a0898aSmrg *t++ = c; 45523a0898aSmrg ++count; 45623a0898aSmrg } 45723a0898aSmrg break; 45823a0898aSmrg } 45923a0898aSmrg } 46023a0898aSmrg} 46123a0898aSmrg 46223a0898aSmrgstatic int 46323a0898aSmrglexc(FILE *file) 46423a0898aSmrg{ 46523a0898aSmrg int c; 46623a0898aSmrg 46723a0898aSmrg c = getc(file); 46823a0898aSmrg switch (c) { 46923a0898aSmrg case EOF: 47023a0898aSmrg charClass = END; 47123a0898aSmrg break; 47223a0898aSmrg case '\\': 47323a0898aSmrg c = getc(file); 47423a0898aSmrg if (c == EOF) 47523a0898aSmrg charClass = END; 47623a0898aSmrg else 47723a0898aSmrg charClass = NORMAL; 47823a0898aSmrg break; 47923a0898aSmrg case '"': 48023a0898aSmrg charClass = QUOTE; 48123a0898aSmrg break; 48223a0898aSmrg case ' ': 48323a0898aSmrg case '\t': 48423a0898aSmrg charClass = WHITE; 48523a0898aSmrg break; 48623a0898aSmrg case '\r': 48723a0898aSmrg case '\n': 48823a0898aSmrg charClass = NL; 48923a0898aSmrg break; 49023a0898aSmrg case '!': 49123a0898aSmrg charClass = BANG; 49223a0898aSmrg break; 49323a0898aSmrg default: 49423a0898aSmrg charClass = NORMAL; 49523a0898aSmrg break; 49623a0898aSmrg } 49723a0898aSmrg return c; 49823a0898aSmrg} 499