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