dirfile.c revision 7673729a
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 5323a0898aSmrgint 5423a0898aSmrgFontFileReadDirectory (char *directory, FontDirectoryPtr *pdir) 5523a0898aSmrg{ 5623a0898aSmrg char file_name[MAXFONTFILENAMELEN]; 5723a0898aSmrg char font_name[MAXFONTNAMELEN]; 5823a0898aSmrg char dir_file[MAXFONTFILENAMELEN]; 5923a0898aSmrg char dir_path[MAXFONTFILENAMELEN]; 6023a0898aSmrg char *ptr; 6123a0898aSmrg FILE *file; 6223a0898aSmrg int count, 6323a0898aSmrg num_fonts, 6423a0898aSmrg status; 6523a0898aSmrg struct stat statb; 6623a0898aSmrg static char format[24] = ""; 677f7f5e4eSmrg#if defined(WIN32) 687f7f5e4eSmrg int i; 697f7f5e4eSmrg#endif 7023a0898aSmrg 7123a0898aSmrg FontDirectoryPtr dir = NullFontDirectory; 7223a0898aSmrg 7323a0898aSmrg if (strlen(directory) + 1 + sizeof(FontDirFile) > sizeof(dir_file)) 7423a0898aSmrg return BadFontPath; 7523a0898aSmrg 7623a0898aSmrg /* Check for font directory attributes */ 777f7f5e4eSmrg#if !defined(WIN32) 7823a0898aSmrg if ((ptr = strchr(directory, ':'))) { 7923a0898aSmrg#else 8023a0898aSmrg /* OS/2 and WIN32 path might start with a drive letter, don't clip this */ 8123a0898aSmrg if ((ptr = strchr(directory+2, ':'))) { 8223a0898aSmrg#endif 8323a0898aSmrg strncpy(dir_path, directory, ptr - directory); 8423a0898aSmrg dir_path[ptr - directory] = '\0'; 8523a0898aSmrg } else { 8623a0898aSmrg strcpy(dir_path, directory); 8723a0898aSmrg } 8823a0898aSmrg strcpy(dir_file, dir_path); 8923a0898aSmrg if (dir_file[strlen(dir_file) - 1] != '/') 9023a0898aSmrg strcat(dir_file, "/"); 9123a0898aSmrg strcat(dir_file, FontDirFile); 9223a0898aSmrg file = fopen(dir_file, "rt"); 9323a0898aSmrg if (file) { 9441c30155Smrg#ifndef WIN32 9523a0898aSmrg if (fstat (fileno(file), &statb) == -1) 9623a0898aSmrg#else 9723a0898aSmrg if (stat (dir_file, &statb) == -1) 9823a0898aSmrg#endif 9923a0898aSmrg { 10023a0898aSmrg fclose(file); 10123a0898aSmrg return BadFontPath; 10223a0898aSmrg } 10323a0898aSmrg count = fscanf(file, "%d\n", &num_fonts); 10423a0898aSmrg if ((count == EOF) || (count != 1)) { 10523a0898aSmrg fclose(file); 10623a0898aSmrg return BadFontPath; 10723a0898aSmrg } 10823a0898aSmrg dir = FontFileMakeDir(directory, num_fonts); 10923a0898aSmrg if (dir == NULL) { 11023a0898aSmrg fclose(file); 11123a0898aSmrg return BadFontPath; 11223a0898aSmrg } 11323a0898aSmrg dir->dir_mtime = statb.st_mtime; 11423a0898aSmrg if (format[0] == '\0') 11523a0898aSmrg sprintf(format, "%%%ds %%%d[^\n]\n", 11623a0898aSmrg MAXFONTFILENAMELEN-1, MAXFONTNAMELEN-1); 11723a0898aSmrg 11823a0898aSmrg while ((count = fscanf(file, format, file_name, font_name)) != EOF) { 1197f7f5e4eSmrg#if defined(WIN32) 12023a0898aSmrg /* strip any existing trailing CR */ 12123a0898aSmrg for (i=0; i<strlen(font_name); i++) { 12223a0898aSmrg if (font_name[i]=='\r') font_name[i] = '\0'; 12323a0898aSmrg } 12423a0898aSmrg#endif 12523a0898aSmrg if (count != 2) { 12623a0898aSmrg FontFileFreeDir (dir); 12723a0898aSmrg fclose(file); 12823a0898aSmrg return BadFontPath; 12923a0898aSmrg } 13023a0898aSmrg 13123a0898aSmrg /* 13223a0898aSmrg * We blindly try to load all the font files specified. 13323a0898aSmrg * In theory, we might want to warn that some of the fonts 13423a0898aSmrg * couldn't be loaded. 13523a0898aSmrg */ 13623a0898aSmrg FontFileAddFontFile (dir, font_name, file_name); 13723a0898aSmrg } 13823a0898aSmrg fclose(file); 13941c30155Smrg 14023a0898aSmrg } else if (errno != ENOENT) { 14123a0898aSmrg return BadFontPath; 14223a0898aSmrg } 14323a0898aSmrg status = ReadFontAlias(dir_path, FALSE, &dir); 14423a0898aSmrg if (status != Successful) { 14523a0898aSmrg if (dir) 14623a0898aSmrg FontFileFreeDir (dir); 14723a0898aSmrg return status; 14823a0898aSmrg } 14923a0898aSmrg if (!dir) 15023a0898aSmrg return BadFontPath; 15123a0898aSmrg 15223a0898aSmrg FontFileSortDir(dir); 15323a0898aSmrg 15423a0898aSmrg *pdir = dir; 15523a0898aSmrg return Successful; 15623a0898aSmrg} 15723a0898aSmrg 15823a0898aSmrgBool 15923a0898aSmrgFontFileDirectoryChanged(FontDirectoryPtr dir) 16023a0898aSmrg{ 16123a0898aSmrg char dir_file[MAXFONTFILENAMELEN]; 16223a0898aSmrg struct stat statb; 16323a0898aSmrg 16423a0898aSmrg if (strlen(dir->directory) + sizeof(FontDirFile) > sizeof(dir_file)) 16523a0898aSmrg return FALSE; 16623a0898aSmrg 16723a0898aSmrg strcpy (dir_file, dir->directory); 16823a0898aSmrg strcat (dir_file, FontDirFile); 16923a0898aSmrg if (stat (dir_file, &statb) == -1) 17023a0898aSmrg { 17123a0898aSmrg if (errno != ENOENT || dir->dir_mtime != 0) 17223a0898aSmrg return TRUE; 17323a0898aSmrg return FALSE; /* doesn't exist and never did: no change */ 17423a0898aSmrg } 17523a0898aSmrg if (dir->dir_mtime != statb.st_mtime) 17623a0898aSmrg return TRUE; 1777f7f5e4eSmrg 1787f7f5e4eSmrg if ((strlen(dir->directory) + sizeof(FontAliasFile)) > sizeof(dir_file)) 1797f7f5e4eSmrg return FALSE; 18023a0898aSmrg strcpy (dir_file, dir->directory); 18123a0898aSmrg strcat (dir_file, FontAliasFile); 18223a0898aSmrg if (stat (dir_file, &statb) == -1) 18323a0898aSmrg { 18423a0898aSmrg if (errno != ENOENT || dir->alias_mtime != 0) 18523a0898aSmrg return TRUE; 18623a0898aSmrg return FALSE; /* doesn't exist and never did: no change */ 18723a0898aSmrg } 18823a0898aSmrg if (dir->alias_mtime != statb.st_mtime) 18923a0898aSmrg return TRUE; 19023a0898aSmrg return FALSE; 19123a0898aSmrg} 19241c30155Smrg 19323a0898aSmrg/* 19423a0898aSmrg * Make each of the file names an automatic alias for each of the files. 19523a0898aSmrg */ 19623a0898aSmrg 19723a0898aSmrgstatic Bool 19823a0898aSmrgAddFileNameAliases(FontDirectoryPtr dir) 19923a0898aSmrg{ 20023a0898aSmrg int i; 20123a0898aSmrg char copy[MAXFONTFILENAMELEN]; 20223a0898aSmrg char *fileName; 20323a0898aSmrg FontTablePtr table; 20423a0898aSmrg FontRendererPtr renderer; 20523a0898aSmrg int len; 20623a0898aSmrg FontNameRec name; 20723a0898aSmrg 20823a0898aSmrg table = &dir->nonScalable; 20923a0898aSmrg for (i = 0; i < table->used; i++) { 21023a0898aSmrg if (table->entries[i].type != FONT_ENTRY_BITMAP) 21123a0898aSmrg continue; 21223a0898aSmrg fileName = table->entries[i].u.bitmap.fileName; 21323a0898aSmrg renderer = FontFileMatchRenderer (fileName); 21423a0898aSmrg if (!renderer) 21523a0898aSmrg continue; 21641c30155Smrg 21723a0898aSmrg len = strlen (fileName) - renderer->fileSuffixLen; 21823a0898aSmrg if (len >= sizeof(copy)) 21923a0898aSmrg continue; 22023a0898aSmrg CopyISOLatin1Lowered (copy, fileName, len); 22123a0898aSmrg copy[len] = '\0'; 22223a0898aSmrg name.name = copy; 22323a0898aSmrg name.length = len; 22423a0898aSmrg name.ndashes = FontFileCountDashes (copy, len); 22523a0898aSmrg 22623a0898aSmrg if (!FontFileFindNameInDir(table, &name)) { 22723a0898aSmrg if (!FontFileAddFontAlias (dir, copy, table->entries[i].name.name)) 22823a0898aSmrg return FALSE; 22923a0898aSmrg } 23023a0898aSmrg } 23123a0898aSmrg return TRUE; 23223a0898aSmrg} 23323a0898aSmrg 23423a0898aSmrg/* 23523a0898aSmrg * parse the font.alias file. Format is: 23623a0898aSmrg * 23723a0898aSmrg * alias font-name 23823a0898aSmrg * 23923a0898aSmrg * To imbed white-space in an alias name, enclose it like "font name" 24023a0898aSmrg * in double quotes. \ escapes and character, so 24123a0898aSmrg * "font name \"With Double Quotes\" \\ and \\ back-slashes" 24223a0898aSmrg * works just fine. 24323a0898aSmrg * 24423a0898aSmrg * A line beginning with a ! denotes a newline-terminated comment. 24523a0898aSmrg */ 24623a0898aSmrg 24723a0898aSmrg/* 24823a0898aSmrg * token types 24923a0898aSmrg */ 25023a0898aSmrg 25123a0898aSmrg#define NAME 0 25223a0898aSmrg#define NEWLINE 1 25323a0898aSmrg#define DONE 2 25423a0898aSmrg#define EALLOC 3 25523a0898aSmrg 25623a0898aSmrgstatic int 25723a0898aSmrgReadFontAlias(char *directory, Bool isFile, FontDirectoryPtr *pdir) 25823a0898aSmrg{ 25923a0898aSmrg char alias[MAXFONTNAMELEN]; 26023a0898aSmrg char font_name[MAXFONTNAMELEN]; 26123a0898aSmrg char alias_file[MAXFONTFILENAMELEN]; 26223a0898aSmrg FILE *file; 26323a0898aSmrg FontDirectoryPtr dir; 26423a0898aSmrg int token; 26523a0898aSmrg char *lexToken; 26623a0898aSmrg int status = Successful; 26723a0898aSmrg struct stat statb; 26823a0898aSmrg 26923a0898aSmrg if (strlen(directory) >= sizeof(alias_file)) 27023a0898aSmrg return BadFontPath; 27123a0898aSmrg dir = *pdir; 27223a0898aSmrg strcpy(alias_file, directory); 27323a0898aSmrg if (!isFile) { 27423a0898aSmrg if (strlen(directory) + 1 + sizeof(FontAliasFile) > sizeof(alias_file)) 27523a0898aSmrg return BadFontPath; 27623a0898aSmrg if (directory[strlen(directory) - 1] != '/') 27723a0898aSmrg strcat(alias_file, "/"); 27823a0898aSmrg strcat(alias_file, FontAliasFile); 27923a0898aSmrg } 28023a0898aSmrg file = fopen(alias_file, "rt"); 28123a0898aSmrg if (!file) 28223a0898aSmrg return ((errno == ENOENT) ? Successful : BadFontPath); 28323a0898aSmrg if (!dir) 28423a0898aSmrg *pdir = dir = FontFileMakeDir(directory, 10); 28523a0898aSmrg if (!dir) 28623a0898aSmrg { 28723a0898aSmrg fclose (file); 28823a0898aSmrg return AllocError; 28923a0898aSmrg } 29023a0898aSmrg#ifndef WIN32 29123a0898aSmrg if (fstat (fileno (file), &statb) == -1) 29223a0898aSmrg#else 29323a0898aSmrg if (stat (alias_file, &statb) == -1) 29423a0898aSmrg#endif 29523a0898aSmrg { 29623a0898aSmrg fclose (file); 29723a0898aSmrg return BadFontPath; 29823a0898aSmrg } 29923a0898aSmrg dir->alias_mtime = statb.st_mtime; 30023a0898aSmrg while (status == Successful) { 30123a0898aSmrg token = lexAlias(file, &lexToken); 30223a0898aSmrg switch (token) { 30323a0898aSmrg case NEWLINE: 30423a0898aSmrg break; 30523a0898aSmrg case DONE: 30623a0898aSmrg fclose(file); 30723a0898aSmrg return Successful; 30823a0898aSmrg case EALLOC: 30923a0898aSmrg status = AllocError; 31023a0898aSmrg break; 31123a0898aSmrg case NAME: 31223a0898aSmrg if (strlen(lexToken) >= sizeof(alias)) { 31323a0898aSmrg status = BadFontPath; 31423a0898aSmrg break; 31523a0898aSmrg } 31623a0898aSmrg strcpy(alias, lexToken); 31723a0898aSmrg token = lexAlias(file, &lexToken); 31823a0898aSmrg switch (token) { 31923a0898aSmrg case NEWLINE: 32023a0898aSmrg if (strcmp(alias, "FILE_NAMES_ALIASES")) 32123a0898aSmrg status = BadFontPath; 32223a0898aSmrg else if (!AddFileNameAliases(dir)) 32323a0898aSmrg status = AllocError; 32423a0898aSmrg break; 32523a0898aSmrg case DONE: 32623a0898aSmrg status = BadFontPath; 32723a0898aSmrg break; 32823a0898aSmrg case EALLOC: 32923a0898aSmrg status = AllocError; 33023a0898aSmrg break; 33123a0898aSmrg case NAME: 33223a0898aSmrg if (strlen(lexToken) >= sizeof(font_name)) { 33323a0898aSmrg status = BadFontPath; 33423a0898aSmrg break; 33523a0898aSmrg } 33623a0898aSmrg CopyISOLatin1Lowered(alias, alias, strlen(alias)); 33723a0898aSmrg CopyISOLatin1Lowered(font_name, lexToken, strlen(lexToken)); 33823a0898aSmrg if (!FontFileAddFontAlias (dir, alias, font_name)) 33923a0898aSmrg status = AllocError; 34023a0898aSmrg break; 34123a0898aSmrg } 34223a0898aSmrg } 34323a0898aSmrg } 34423a0898aSmrg fclose(file); 34523a0898aSmrg return status; 34623a0898aSmrg} 34723a0898aSmrg 34823a0898aSmrg#define QUOTE 0 34923a0898aSmrg#define WHITE 1 35023a0898aSmrg#define NORMAL 2 35123a0898aSmrg#define END 3 35223a0898aSmrg#define NL 4 35323a0898aSmrg#define BANG 5 35423a0898aSmrg 35523a0898aSmrgstatic int charClass; 35623a0898aSmrg 35723a0898aSmrgstatic int 35823a0898aSmrglexAlias(FILE *file, char **lexToken) 35923a0898aSmrg{ 36023a0898aSmrg int c; 36123a0898aSmrg char *t; 36223a0898aSmrg enum state { 36323a0898aSmrg Begin, Normal, Quoted, Comment 36423a0898aSmrg } state; 36523a0898aSmrg int count; 36623a0898aSmrg 36723a0898aSmrg static char *tokenBuf = (char *) NULL; 36823a0898aSmrg static int tokenSize = 0; 36923a0898aSmrg 37023a0898aSmrg t = tokenBuf; 37123a0898aSmrg count = 0; 37223a0898aSmrg state = Begin; 37323a0898aSmrg for (;;) { 37423a0898aSmrg if (count == tokenSize) { 37523a0898aSmrg int nsize; 37623a0898aSmrg char *nbuf; 37723a0898aSmrg 3787673729aSmrg if (tokenSize >= (INT_MAX >> 2)) 3797673729aSmrg /* Stop before we overflow */ 3807673729aSmrg return EALLOC; 38123a0898aSmrg nsize = tokenSize ? (tokenSize << 1) : 64; 3827f7f5e4eSmrg nbuf = realloc(tokenBuf, nsize); 38323a0898aSmrg if (!nbuf) 38423a0898aSmrg return EALLOC; 38523a0898aSmrg tokenBuf = nbuf; 38623a0898aSmrg tokenSize = nsize; 38723a0898aSmrg t = tokenBuf + count; 38823a0898aSmrg } 38923a0898aSmrg c = lexc(file); 39023a0898aSmrg switch (charClass) { 39123a0898aSmrg case QUOTE: 39223a0898aSmrg switch (state) { 39323a0898aSmrg case Begin: 39423a0898aSmrg case Normal: 39523a0898aSmrg state = Quoted; 39623a0898aSmrg break; 39723a0898aSmrg case Quoted: 39823a0898aSmrg state = Normal; 39923a0898aSmrg break; 40023a0898aSmrg case Comment: 40123a0898aSmrg break; 40223a0898aSmrg } 40323a0898aSmrg break; 40423a0898aSmrg case WHITE: 40523a0898aSmrg switch (state) { 40623a0898aSmrg case Begin: 40723a0898aSmrg case Comment: 40823a0898aSmrg continue; 40923a0898aSmrg case Normal: 41023a0898aSmrg *t = '\0'; 41123a0898aSmrg *lexToken = tokenBuf; 41223a0898aSmrg return NAME; 41323a0898aSmrg case Quoted: 41423a0898aSmrg break; 41523a0898aSmrg } 41623a0898aSmrg /* fall through */ 41723a0898aSmrg case NORMAL: 41823a0898aSmrg switch (state) { 41923a0898aSmrg case Begin: 42023a0898aSmrg state = Normal; 42123a0898aSmrg break; 42223a0898aSmrg case Comment: 42323a0898aSmrg continue; 42423a0898aSmrg default: 42523a0898aSmrg break; 42623a0898aSmrg } 42723a0898aSmrg *t++ = c; 42823a0898aSmrg ++count; 42923a0898aSmrg break; 43023a0898aSmrg case END: 43123a0898aSmrg case NL: 43223a0898aSmrg switch (state) { 43323a0898aSmrg case Begin: 43423a0898aSmrg case Comment: 43523a0898aSmrg *lexToken = (char *) NULL; 43623a0898aSmrg return charClass == END ? DONE : NEWLINE; 43723a0898aSmrg default: 43823a0898aSmrg *t = '\0'; 43923a0898aSmrg *lexToken = tokenBuf; 44023a0898aSmrg ungetc(c, file); 44123a0898aSmrg return NAME; 44223a0898aSmrg } 44323a0898aSmrg break; 44423a0898aSmrg case BANG: 44523a0898aSmrg switch (state) { 44623a0898aSmrg case Begin: 44723a0898aSmrg state = Comment; 44823a0898aSmrg break; 44923a0898aSmrg case Comment: 45023a0898aSmrg break; 45123a0898aSmrg default: 45223a0898aSmrg *t++ = c; 45323a0898aSmrg ++count; 45423a0898aSmrg } 45523a0898aSmrg break; 45623a0898aSmrg } 45723a0898aSmrg } 45823a0898aSmrg} 45923a0898aSmrg 46023a0898aSmrgstatic int 46123a0898aSmrglexc(FILE *file) 46223a0898aSmrg{ 46323a0898aSmrg int c; 46423a0898aSmrg 46523a0898aSmrg c = getc(file); 46623a0898aSmrg switch (c) { 46723a0898aSmrg case EOF: 46823a0898aSmrg charClass = END; 46923a0898aSmrg break; 47023a0898aSmrg case '\\': 47123a0898aSmrg c = getc(file); 47223a0898aSmrg if (c == EOF) 47323a0898aSmrg charClass = END; 47423a0898aSmrg else 47523a0898aSmrg charClass = NORMAL; 47623a0898aSmrg break; 47723a0898aSmrg case '"': 47823a0898aSmrg charClass = QUOTE; 47923a0898aSmrg break; 48023a0898aSmrg case ' ': 48123a0898aSmrg case '\t': 48223a0898aSmrg charClass = WHITE; 48323a0898aSmrg break; 48423a0898aSmrg case '\r': 48523a0898aSmrg case '\n': 48623a0898aSmrg charClass = NL; 48723a0898aSmrg break; 48823a0898aSmrg case '!': 48923a0898aSmrg charClass = BANG; 49023a0898aSmrg break; 49123a0898aSmrg default: 49223a0898aSmrg charClass = NORMAL; 49323a0898aSmrg break; 49423a0898aSmrg } 49523a0898aSmrg return c; 49623a0898aSmrg} 497