Ticket #137: rough.patch

File rough.patch, 113.8 KB (added by takkaria, 10 years ago)

This compiles and works on Linux (at least). Contains unit tests.

  • init.h

     
    4040 
    4141typedef errr (*parse_info_txt_func)(char *buf, header *head); 
    4242typedef errr (*eval_info_power_func)(header *head); 
    43 typedef errr (*emit_info_txt_index_func)(FILE *fp, header *head, int i); 
    44 typedef errr (*emit_info_txt_always_func)(FILE *fp, header *head); 
     43typedef errr (*emit_info_txt_index_func)(ang_file *fp, header *head, int i); 
     44typedef errr (*emit_info_txt_always_func)(ang_file *fp, header *head); 
    4545 
    4646/* 
    4747 * Template file header information (see "init.c").  16 bytes. 
     
    102102         
    103103}; 
    104104 
    105 extern errr init_info_txt(FILE *fp, char *buf, header *head, 
     105extern errr init_info_txt(ang_file *fp, char *buf, header *head, 
    106106                          parse_info_txt_func parse_info_txt_line); 
    107107 
    108108extern errr eval_info(eval_info_power_func eval_info_process, header *head); 
    109109 
    110 extern errr emit_info_txt(FILE *fp, FILE *template, char *buf, header *head, 
     110extern errr emit_info_txt(ang_file *fp, ang_file *template, char *buf, header *head, 
    111111   emit_info_txt_index_func emit_info_txt_index, emit_info_txt_always_func emit_info_txt_always); 
    112112 
    113113#ifdef ALLOW_TEMPLATES 
  • h-basic.h

     
    4949 
    5050 
    5151/* 
    52  * Everyone except RISC OS has fcntl.h 
     52 * Everyone except RISC OS has fcntl.h and sys/stat.h 
    5353 */ 
    5454#ifndef RISCOS 
    5555# define HAVE_FCNTL_H 
     56# define HAVE_STAT 
    5657#endif 
    5758 
    5859#endif /* HAVE_CONFIG_H */ 
     
    107108#endif 
    108109 
    109110 
    110 /* 
    111  * Mac support 
    112  */ 
    113 #ifdef MACH_O_CARBON 
    114  
    115 /* OS X uses filetypes when creating files. */ 
    116 # define FILE_TYPE_TEXT 'TEXT' 
    117 # define FILE_TYPE_DATA 'DATA' 
    118 # define FILE_TYPE_SAVE 'SAVE' 
    119 # define FILE_TYPE(X) (_ftype = (X)) 
    120  
    121 #else 
    122  
    123 # define FILE_TYPE(X) ((void)0) 
    124  
    125 #endif 
    126  
    127  
    128  
    129111/*** Include the library header files ***/ 
    130112 
    131113/* Use various POSIX functions if available */ 
  • util.c

     
    22972297                        /* Output the indent */ 
    22982298                        for (i = 0; i < text_out_indent; i++) 
    22992299                        { 
    2300                                 fputc(' ', text_out_file); 
     2300                                file_writec(text_out_file, ' '); 
    23012301                                pos++; 
    23022302                        } 
    23032303                } 
     
    23282328                        else 
    23292329                        { 
    23302330                                /* Begin a new line */ 
    2331                                 fputc('\n', text_out_file); 
     2331                                file_writec(text_out_file, '\n'); 
    23322332 
    23332333                                /* Reset */ 
    23342334                                pos = 0; 
     
    23522352                        ch = (isprint((unsigned char) s[n]) ? s[n] : ' '); 
    23532353 
    23542354                        /* Write out the character */ 
    2355                         fputc(ch, text_out_file); 
     2355                        file_writec(text_out_file, ch); 
    23562356 
    23572357                        /* Increment */ 
    23582358                        pos++; 
     
    23682368                if (*s == '\n') s++; 
    23692369 
    23702370                /* Begin a new line */ 
    2371                 fputc('\n', text_out_file); 
     2371                file_writec(text_out_file, '\n'); 
    23722372 
    23732373                /* Reset */ 
    23742374                pos = 0; 
  • Makefile.std

     
    8181LIBS += $(patsubst -D%,,$(patsubst -I%,, $(MODULES))) 
    8282 
    8383 
    84 # Extract system we're running on 
    85 uname = $(shell uname -s) 
    86  
    87 # Enable linux-specific modules, if requested. 
    88 ifeq ($(uname),Linux) 
    89   CFLAGS += -DHAVE_MKSTEMP 
    90 endif 
    91  
    92  
    9384# Object definitions 
    9485X11OBJS = maid-x11.o main-x11.o main-xaw.o main-gtk.o 
    9586MAINOBJS = main.o main-gcu.o main-sdl.o snd-sdl.o $(X11OBJS) 
  • z-file.c

     
    22 * File: z-file.c 
    33 * Purpose: Low-level file (and directory) handling 
    44 * 
    5  * Copyright (c) 1997-2007 Ben Harrison, pelpel, Andrew Sidwell 
     5 * Copyright (c) 1997-2007 Ben Harrison, pelpel, Andrew Sidwell, Matthew Jones 
    66 * 
    77 * This work is free software; you can redistribute it and/or modify it 
    88 * under the terms of either: 
     
    1515 *    and not for profit purposes provided that this copyright and statement 
    1616 *    are included in all such copies.  Other copyrights may also apply. 
    1717 */ 
    18 #include "angband.h" 
    1918#include "z-file.h" 
     19#include "z-virt.h" 
     20#include "z-util.h" 
     21#include "z-form.h" 
    2022 
    2123#ifndef RISCOS 
    2224# include <sys/types.h> 
    23 # include <sys/stat.h> 
    2425#endif 
    2526 
    2627#ifdef WINDOWS 
     28# include <windows.h> 
    2729# include <io.h> 
    2830#endif 
    2931 
     32#ifdef HAVE_FCNTL_H 
     33# include <fcntl.h> 
     34#endif 
    3035 
     36#ifdef HAVE_DIRENT_H 
     37# include <sys/types.h> 
     38# include <dirent.h> 
     39#endif 
    3140 
     41#ifdef HAVE_STAT 
     42# include <sys/stat.h> 
     43#endif 
     44 
    3245/* 
     46 * Player info 
     47 */ 
     48int player_uid; 
     49int player_egid; 
     50 
     51 
     52 
     53#ifdef MACH_O_CARBON 
     54extern u32b _fcreator; 
     55extern void fsetfileinfo(cptr path, u32b fcreator, u32b ftype); 
     56#endif 
     57 
     58 
     59 
     60/* 
    3361 * Drop permissions 
    3462 */ 
    3563void safe_setuid_drop(void) 
     
    72100 
    73101 
    74102 
     103 
    75104/* 
    76  * The concept of the file routines is that all file handling should be done 
    77  * using as few routines as possible, since every machine is slightly 
    78  * different, but these routines always have the same semantics. 
    79  * 
    80  * Prhaps we should use "path_parse()" to convert from "canonical" filenames 
    81  * (optional leading tildes, internal wildcards, slash as the path seperator, 
    82  * etc) to "system" filenames (no special symbols, system-specific path 
    83  * seperator, etc).  This would allow the program itself to assume that all 
    84  * filenames are "Unix" filenames, and explicitly "extract" such filenames if 
    85  * needed (by "path_parse()", or perhaps "path_canon()"). XXX 
    86  * 
    87  * path_temp() should probably return a "canonical" filename.  XXX 
    88  * 
    89  * Note that "my_fopen()" and "my_open()" and "my_make()" and "my_kill()" 
    90  * and "my_move()" and "my_copy()" should all take "canonical" filenames. 
    91  * 
    92  * Canonical filenames use a leading slash to indicate an absolute path, and a 
    93  * leading tilde to indicate a special directory.  They default to a relative 
    94  * path.  DOS/Windows uses a leading "drivename plus colon" to indicate the 
    95  * use of a "special drive", and then the rest of the path is parsed normally, 
    96  * and MACINTOSH uses a leading colon to indicate a relative path, and an 
    97  * embedded colon to indicate a "drive plus absolute path", and finally 
    98  * defaults to a file in the current working directory, which may or may 
    99  * not be defined. 
     105 * Apply special system-specific processing before dealing with a filename. 
    100106 */ 
     107static errr path_parse(char *buf, size_t max, cptr file) 
     108{ 
     109        /* Accept the filename */ 
     110        my_strcpy(buf, file, max); 
    101111 
     112#ifdef RISCOS 
    102113 
    103 #ifdef HAVE_MKSTEMP 
     114        /* Defined in main-ros.c */ 
     115        char *riscosify_name(const char *path); 
     116        my_strcpy(buf, riscosify_name(path), max); 
    104117 
    105 FILE *my_fopen_temp(char *buf, size_t max) 
     118#endif 
     119 
     120        /* Success */ 
     121        return (0); 
     122} 
     123 
     124 
     125 
     126static void path_process(char *buf, size_t len, size_t *cur_len, const char *path) 
    106127{ 
    107         int fd; 
     128#if defined(SET_UID) || defined(USE_PRIVATE_PATHS) 
    108129 
    109         /* Prepare the buffer for mkstemp */ 
    110         my_strcpy(buf, "/tmp/anXXXXXX", max); 
     130        /* Home directory on Unixes */ 
     131        if (path[0] == '~') 
     132        { 
     133                const char *s; 
     134                const char *username = path + 1; 
    111135 
    112         /* Secure creation of a temporary file */ 
    113         fd = mkstemp(buf); 
     136                struct passwd *pw; 
     137                char user[128]; 
    114138 
    115         /* Check the file-descriptor */ 
    116         if (fd < 0) return (NULL); 
     139                /* Look for non-user portion of the file */ 
     140                s = strstr(username, PATH_SEP); 
     141                if (s) 
     142                { 
     143                        int i; 
    117144 
    118         /* Return a file stream */ 
    119         return (fdopen(fd, "w")); 
    120 } 
     145                        /* Keep username a decent length */ 
     146                        if (s >= username + sizeof(user)) return; 
    121147 
    122 #else /* HAVE_MKSTEMP */ 
     148                        for (i = 0; username < s; ++i) user[i] = *username++; 
     149                        user[i] = '\0'; 
     150                        username = user; 
     151                } 
    123152 
    124 /* 
    125  * Consider rewriting this so it uses its own buffer. 
    126  */ 
    127 FILE *my_fopen_temp(char *buf, size_t max) 
    128 { 
    129         const char *s; 
     153                /* Fallback -- try the "current" user */ 
     154                if (username[0] == '\0') 
     155                        username = getlogin(); 
    130156 
    131         /* Temp file */ 
    132         s = tmpnam(NULL); 
     157                /* Look up a user (or "current" user) */ 
     158                if (username) pw = getpwnam(username); 
     159                else          pw = getpwuid(getuid()); 
    133160 
    134         /* Oops */ 
    135         if (!s) return (NULL); 
     161                if (!pw) return; 
    136162 
    137         /* Copy to buffer */ 
    138         my_strcpy(buf, s, max); 
     163                /* Copy across */ 
     164                strnfcat(buf, len, cur_len, "%s%s", pw->pw_dir, PATH_SEP); 
     165                if (s) strnfcat(buf, len, cur_len, "%s", s); 
     166        } 
     167        else 
    139168 
    140         /* Open the file */ 
    141         return (my_fopen(buf, "w")); 
     169#endif 
     170 
     171        { 
     172                strnfcat(buf, len, cur_len, "%s", path); 
     173        } 
    142174} 
    143175 
    144 #endif /* HAVE_MKSTEMP */ 
    145176 
    146177 
     178 
    147179/* 
    148  * Hack -- replacement for "fgets()" 
     180 * Create a new path string by appending a 'leaf' to 'base'. 
    149181 * 
    150  * Read a string, without a newline, to a file 
     182 * On Unixes, we convert a tidle at the beginning of a basename to mean the 
     183 * directory, complicating things a little, but better now than later. 
    151184 * 
    152  * Process tabs, strip internal non-printables 
     185 * Remember to free the return value. 
    153186 */ 
    154 #define TAB_COLUMNS   8 
    155  
    156 errr my_fgets(FILE *fff, char *buf, size_t n) 
     187size_t path_build(char *buf, size_t len, const char *base, const char *leaf) 
    157188{ 
    158         u16b i = 0; 
    159         char *s = buf; 
    160         int len; 
    161          
    162 #ifdef MACH_O_CARBON 
    163          
    164         /* For the \r vs. \r\n vs \n handling code below */ 
    165         bool seen_cr = FALSE; 
     189        size_t cur_len = 0; 
     190        buf[0] = '\0'; 
    166191 
    167 #endif /* MACH_O_CARBON */ 
     192        if (!leaf || !leaf[0]) 
     193        { 
     194                if (base && base[0]) 
     195                        path_process(buf, len, &cur_len, base); 
    168196 
    169         /* Paranoia */ 
    170         if (n <= 0) return (1); 
     197                return cur_len; 
     198        } 
    171199 
    172         /* Enforce historical upper bound */ 
    173         if (n > 1024) n = 1024; 
    174200 
    175         /* Leave a byte for terminating null */ 
    176         len = n - 1; 
    177  
    178         /* While there's room left in the buffer */ 
    179         while (i < len) 
     201        /* 
     202         * If the leafname starts with the seperator, 
     203         *   or with the tilde (on Unix), 
     204         *   or there's no base path, 
     205         * We use the leafname only. 
     206         */ 
     207#if defined(SET_UID) || defined(USE_PRIVATE_PATHS) 
     208        if ((!base || !base[0]) || prefix(leaf, PATH_SEP) || leaf[0] == '~') 
     209#else 
     210        if ((!base || !base[0]) || prefix(leaf, PATH_SEP)) 
     211#endif 
    180212        { 
    181                 int c; 
     213                path_process(buf, len, &cur_len, leaf); 
     214                return cur_len; 
     215        } 
    182216 
    183                 /* 
    184                  * Read next character - stdio buffers I/O, so there's no 
    185                  * need to buffer it again using fgets. 
    186                  */ 
    187                 c = fgetc(fff); 
    188217 
    189                 /* End of file */ 
    190                 if (c == EOF) 
    191                 { 
    192                         /* No characters read -- signal error */ 
    193                         if (i == 0) break; 
     218        /* There is both a relative leafname and a base path from which it is relative */ 
     219        path_process(buf, len, &cur_len, base); 
     220        strnfcat(buf, len, &cur_len, "%s", PATH_SEP); 
     221        path_process(buf, len, &cur_len, leaf); 
    194222 
    195                         /* 
    196                          * Be nice to DOS/Windows, where a last line of a file isn't 
    197                          * always \n terminated. 
    198                          */ 
    199                         *s = '\0'; 
     223        return cur_len; 
     224} 
    200225 
    201                         /* Success */ 
    202                         return (0); 
    203                 } 
    204226 
    205 #ifdef MACH_O_CARBON 
    206227 
    207                 /* 
    208                  * Be nice to the Macintosh, where a file can have Mac or Unix 
    209                  * end of line, especially since the introduction of OS X. 
    210                  * MPW tools were also very tolerant to the Unix EOL. 
    211                  * 
    212                  * Watch for \r; when found, set flag and advance. 
    213                  * If the next character isn't \n, rewind the file one character  
    214                  * and act like we found \n anyway to end the line. 
    215                  */ 
    216                 if (c == '\r')  
    217                 { 
    218                         seen_cr = TRUE; 
    219                         continue; 
    220                 } 
    221                 else 
    222                         seen_cr = FALSE; 
    223                          
    224                 if (seen_cr && c != '\n') 
    225                 { 
    226                         fseek(fff, -1, SEEK_CUR); 
    227                          
    228                         /* Put a fake newline in to end the line */ 
    229                         c = '\n'; 
    230                 } 
    231228 
    232 #endif /* MACH_O_CARBON */ 
     229/*** File-handling API ***/ 
    233230 
    234                 /* End of line */ 
    235                 if (c == '\n') 
    236                 { 
    237                         /* Null terminate */ 
    238                         *s = '\0'; 
     231/* On Windows, fwrite() and fread() are broken. */ 
     232#if defined(WINDOWS) || defined(SET_UID) 
     233# define HAVE_WRITE 
     234# define HAVE_READ 
     235#endif 
    239236 
    240                         /* Success */ 
    241                         return (0); 
    242                 } 
    243237 
    244                 /* Expand a tab into spaces */ 
    245                 if (c == '\t') 
    246                 { 
    247                         int tabstop; 
     238/* Private structure to hold file pointers and useful info. */ 
     239struct ang_file 
     240{ 
     241        FILE *fh; 
     242        char *fname; 
     243        file_mode mode; 
     244        bool temp; 
     245}; 
    248246 
    249                         /* Next tab stop */ 
    250                         tabstop = ((i + TAB_COLUMNS) / TAB_COLUMNS) * TAB_COLUMNS; 
    251247 
    252                         /* Bounds check */ 
    253                         if (tabstop >= len) break; 
    254248 
    255                         /* Convert it to spaces */ 
    256                         while (i < tabstop) 
    257                         { 
    258                                 /* Store space */ 
    259                                 *s++ = ' '; 
     249/** Utility functions **/ 
    260250 
    261                                 /* Count */ 
    262                                 i++; 
    263                         } 
    264                 } 
    265  
    266                 /* Ignore non-printables */ 
    267                 else if (isprint(c)) 
    268                 { 
    269                         /* Store character in the buffer */ 
    270                         *s++ = c; 
    271  
    272                         /* Count number of characters in the buffer */ 
    273                         i++; 
    274                 } 
    275         } 
    276  
    277         /* Buffer overflow or EOF - return an empty string */ 
    278         buf[0] = '\0'; 
    279  
    280         /* Error */ 
    281         return (1); 
    282 } 
    283  
    284  
    285251/* 
    286  * Hack -- replacement for "fputs()" 
    287  * 
    288  * Dump a string, plus a newline, to a file 
    289  * 
    290  * Perhaps this function should handle internal weirdness. 
     252 * Delete file 'fname'. 
    291253 */ 
    292 errr my_fputs(FILE *fff, cptr buf, size_t n) 
     254bool file_delete(const char *fname)  
    293255{ 
    294         /* Unused paramter */ 
    295         (void)n; 
     256        char buf[1024]; 
    296257 
    297         /* Dump, ignore errors */ 
    298         (void)fprintf(fff, "%s\n", buf); 
     258        /* Get the system-specific paths */ 
     259        if (path_parse(buf, sizeof(buf), fname)) return FALSE; 
    299260 
    300         /* Success */ 
    301         return (0); 
     261        return (remove(buf) == 0); 
    302262} 
    303263 
    304  
    305264/* 
    306  * Check to see if a file exists, by opening it read-only. 
    307  * 
    308  * Return TRUE if it does, FALSE if it does not. 
     265 * Delete file 'fname' to 'newname'. 
    309266 */ 
    310 bool my_fexists(const char *fname) 
     267bool file_move(const char *fname, const char *newname) 
    311268{ 
    312         int fd; 
     269        char buf[1024]; 
     270        char aux[1024]; 
    313271 
    314         /* Try to open it */ 
    315         fd = fd_open(fname, O_RDONLY); 
     272        /* Get the system-specific paths */ 
     273        if (path_parse(buf, sizeof(buf), fname)) return (-1); 
     274        if (path_parse(aux, sizeof(aux), newname)) return (-1); 
    316275 
    317         /* It worked */ 
    318         if (fd >= 0) 
    319         { 
    320                 fd_close(fd); 
    321                 return TRUE; 
    322         } 
    323         else 
    324         { 
    325                 return FALSE; 
    326         } 
     276        return (rename(buf, aux) == 0); 
    327277} 
    328278 
    329279 
    330  
    331 /* The file routines for RISC OS are in main-ros.c. */ 
    332 #ifndef RISCOS 
    333  
    334  
    335 #if defined(SET_UID) || defined(USE_PRIVATE_PATHS) 
    336  
    337280/* 
    338  * Extract a "parsed" path from an initial filename 
    339  * Normally, we simply copy the filename into the buffer 
    340  * But leading tilde symbols must be handled in a special way 
    341  * Replace "~user/" by the home directory of the user named "user" 
    342  * Replace "~/" by the home directory of the current user 
     281 * Decide whether a file exists or not. 
    343282 */ 
    344 errr path_parse(char *buf, size_t max, cptr file) 
    345 { 
    346         cptr u, s; 
    347         struct passwd   *pw; 
    348         char user[128]; 
     283bool file_exists(const char *fname); 
    349284 
     285#if defined(HAVE_STAT) 
    350286 
    351         /* Assume no result */ 
    352         buf[0] = '\0'; 
     287bool file_exists(const char *fname) 
     288{ 
     289        struct stat st; 
     290        return (stat(fname, &st) == 0); 
     291} 
    353292 
    354         /* No file? */ 
    355         if (!file) return (-1); 
     293#elif defined(WINDOWS) 
    356294 
    357         /* File needs no parsing */ 
    358         if (file[0] != '~') 
    359         { 
    360                 my_strcpy(buf, file, max); 
    361                 return (0); 
    362         } 
     295bool file_exists(const char *fname) 
     296{ 
     297        char path[MAX_PATH]; 
     298        DWORD attrib; 
    363299 
    364         /* Point at the user */ 
    365         u = file+1; 
     300        /* API says we mustn't pass anything larger than MAX_PATH */ 
     301        my_strcpy(path, s, sizeof(path)); 
    366302 
    367         /* Look for non-user portion of the file */ 
    368         s = strstr(u, PATH_SEP); 
     303        attrib = GetFileAttributes(path); 
     304        if (attrib == INVALID_FILE_NAME) return FALSE; 
     305        if (attrib & FILE_ATTRIBUTE_DIRECTORY) return FALSE; 
    369306 
    370         /* Hack -- no long user names */ 
    371         if (s && (s >= u + sizeof(user))) return (1); 
     307        return TRUE; 
     308} 
    372309 
    373         /* Extract a user name */ 
    374         if (s) 
    375         { 
    376                 int i; 
    377                 for (i = 0; u < s; ++i) user[i] = *u++; 
    378                 user[i] = '\0'; 
    379                 u = user; 
    380         } 
     310#else 
    381311 
    382         /* Look up the "current" user */ 
    383         if (u[0] == '\0') u = getlogin(); 
     312bool file_exists(const char *fname) 
     313{ 
     314        ang_file *f = file_open(fname, MODE_READ, 0); 
    384315 
    385         /* Look up a user (or "current" user) */ 
    386         if (u) pw = getpwnam(u); 
    387         else pw = getpwuid(getuid()); 
    388  
    389         /* Nothing found? */ 
    390         if (!pw) return (1); 
    391  
    392         /* Make use of the info */ 
    393         my_strcpy(buf, pw->pw_dir, max); 
    394  
    395         /* Append the rest of the filename, if any */ 
    396         if (s) my_strcat(buf, s, max); 
    397  
    398         /* Success */ 
    399         return (0); 
     316        if (f) file_close(f); 
     317        return (f ? TRUE : FALSE); 
    400318} 
    401319 
     320#endif 
    402321 
    403 #else /* SET_UID */ 
    404322 
     323#ifndef RISCOS 
     324#ifdef HAVE_STAT 
    405325 
    406326/* 
    407  * Extract a "parsed" path from an initial filename 
    408  * 
    409  * This requires no special processing on simple machines, 
    410  * except for verifying the size of the filename. 
     327 * Return TRUE if first is newer than second, FALSE otherwise. 
    411328 */ 
    412 errr path_parse(char *buf, size_t max, cptr file) 
     329bool file_newer(const char *first, const char *second) 
    413330{ 
    414         /* Accept the filename */ 
    415         my_strcpy(buf, file, max); 
     331        struct stat first_stat, second_stat; 
    416332 
    417 # ifdef MACH_O_CARBON 
     333        bool second_exists = stat(second, &second_stat) ? FALSE : TRUE; 
     334        bool first_exists = stat(first, &first_stat) ? FALSE : TRUE; 
    418335 
    419         /* Fix it according to the current operating system */ 
    420         convert_pathname(buf); 
     336        /* 
     337         * If the first doesn't exist, the first is not newer; 
     338         * If the second doesn't exist, the first is always newer. 
     339         */ 
     340        if (!first_exists)  return FALSE; 
     341        if (!second_exists) return TRUE; 
    421342 
    422 # endif 
     343        if (first_stat.st_mtime >= second_stat.st_mtime) 
     344                return TRUE; 
    423345 
    424         /* Success */ 
    425         return (0); 
     346        return FALSE; 
    426347} 
    427348 
     349#else /* HAVE_STAT */ 
    428350 
    429 #endif /* SET_UID */ 
     351bool file_newer(const char *first, const char *second) 
     352{ 
     353        /* Assume newer */ 
     354        return FALSE; 
     355} 
    430356 
     357#endif /* HAVE_STAT */ 
     358#endif /* RISCOS */ 
    431359 
    432360 
    433361 
     362 
     363/** File-handle functions **/ 
     364 
    434365/* 
    435  * Create a new path by appending a file (or directory) to a path 
    436  * 
    437  * This requires no special processing on simple machines, except 
    438  * for verifying the size of the filename, but note the ability to 
    439  * bypass the given "path" with certain special file-names. 
    440  * 
    441  * Note that the "file" may actually be a "sub-path", including 
    442  * a path and a file. 
    443  * 
    444  * Note that this function yields a path which must be "parsed" 
    445  * using the "parse" function above. 
     366 * Open file 'fname', in mode 'mode', with filetype 'ftype'. 
     367 * Returns file handle or NULL. 
    446368 */ 
    447 errr path_build(char *buf, size_t max, cptr path, cptr file) 
     369ang_file *file_open(const char *fname, file_mode mode, file_type ftype) 
    448370{ 
    449         /* Special file */ 
    450         if (file[0] == '~') 
    451         { 
    452                 /* Use the file itself */ 
    453                 my_strcpy(buf, file, max); 
    454         } 
     371        ang_file *f = ZNEW(ang_file); 
     372        char modestr[3] = "__"; 
     373        char buf[1024]; 
    455374 
    456         /* Absolute file, on "normal" systems */ 
    457         else if (prefix(file, PATH_SEP) && !streq(PATH_SEP, "")) 
    458         { 
    459                 /* Use the file itself */ 
    460                 my_strcpy(buf, file, max); 
    461         } 
     375        /* Get the system-specific path */ 
     376        if (path_parse(buf, sizeof(buf), fname)) 
     377                return NULL; 
    462378 
    463         /* No path given */ 
    464         else if (!path[0]) 
     379        switch (mode) 
    465380        { 
    466                 /* Use the file itself */ 
    467                 my_strcpy(buf, file, max); 
     381                case MODE_WRITE: 
     382                        modestr[0] = 'w'; 
     383                        modestr[1] = 'b'; 
     384                        break; 
     385                case MODE_READ: 
     386                        modestr[0] = 'r'; 
     387                        modestr[1] = 'b'; 
     388                        break; 
     389                case MODE_APPEND: 
     390                        modestr[0] = 'w'; 
     391                        modestr[1] = 'a'; 
     392                        break; 
     393                default: 
     394                        break; 
    468395        } 
    469396 
    470         /* Path and File */ 
    471         else 
     397        f->fh = fopen(buf, modestr); 
     398 
     399        if (f->fh == NULL) 
    472400        { 
    473                 /* Build the new path */ 
    474                 strnfmt(buf, max, "%s%s%s", path, PATH_SEP, file); 
     401                FREE(f); 
     402                return NULL; 
    475403        } 
    476404 
    477         /* Success */ 
    478         return (0); 
    479 } 
     405        f->fname = string_make(buf); 
     406        f->mode = mode; 
    480407 
     408#if 0 
    481409 
    482 /* 
    483  * Hack -- replacement for "fopen()" 
    484  */ 
    485 FILE *my_fopen(cptr file, cptr mode) 
    486 { 
    487         char buf[1024]; 
    488         FILE *fff; 
     410This needs a whole bunch of work.  Essentially, each port should 
     411be checking the type paramater and converting it to the 
     412system-specific filetype. 
    489413 
    490         /* Hack -- Try to parse the path */ 
    491         if (path_parse(buf, sizeof(buf), file)) return (NULL); 
     414#ifdef MACH_O_CARBON 
     415        /* OS X uses its own kind of filetypes */ 
     416        if (mode != MODE_READ) 
     417                fsetfileinfo(buf, _fcreator, ftype); 
     418#endif 
    492419 
    493         /* Attempt to fopen the file anyway */ 
    494         fff = fopen(buf, mode); 
    495  
    496 #if defined(MACH_O_CARBON) 
    497  
    498         /* Set file creator and type */ 
    499         if (fff && strchr(mode, 'w')) fsetfileinfo(buf, _fcreator, _ftype); 
    500  
     420#if defined(RISCOS) && 0 
     421        /* do something for RISC OS here? */ 
     422        if (mode != MODE_READ) 
     423                File_SetType(n, ftype); 
    501424#endif 
     425#endif 
    502426 
    503         /* Return open file or NULL */ 
    504         return (fff); 
     427        return f; 
    505428} 
    506429 
    507  
    508430/* 
    509  * Hack -- replacement for "fclose()" 
     431 * Close file handle 'f'. 
    510432 */ 
    511 errr my_fclose(FILE *fff) 
     433bool file_close(ang_file *f) 
    512434{ 
    513         /* Require a file */ 
    514         if (!fff) return (-1); 
     435        if (fclose(f->fh) != 0) 
     436                return FALSE; 
    515437 
    516         /* Close, check for error */ 
    517         if (fclose(fff) == EOF) return (1); 
     438        if (f->temp) 
     439                file_delete(f->fname); 
    518440 
    519         /* Success */ 
    520         return (0); 
     441        FREE(f->fname); 
     442        FREE(f); 
     443        return TRUE; 
    521444} 
    522445 
    523446 
    524447/* 
    525  * Hack -- attempt to delete a file 
     448 * Create a temporary file handle, which is deleted when closing the file. 
    526449 */ 
    527 errr fd_kill(cptr file) 
    528 { 
    529         char buf[1024]; 
     450ang_file *file_temp(void); 
    530451 
    531         /* Hack -- Try to parse the path */ 
    532         if (path_parse(buf, sizeof(buf), file)) return (-1); 
     452#ifdef HAVE_MKSTEMP 
    533453 
    534         /* Remove, return 0 on success, non-zero on failure */ 
    535         return (remove(buf)); 
    536 } 
    537  
    538  
    539 /* 
    540  * Hack -- attempt to move a file 
    541  */ 
    542 errr fd_move(cptr file, cptr what) 
     454ang_file *file_temp(void) 
    543455{ 
     456        ang_file *f; 
    544457        char buf[1024]; 
    545         char aux[1024]; 
     458        int fd; 
    546459 
    547         /* Hack -- Try to parse the path */ 
    548         if (path_parse(buf, sizeof(buf), file)) return (-1); 
     460        my_strcpy(buf, "/tmp/anXXXXXX", sizeof(buf)); 
     461        fd = mkstemp(buf); 
     462        if (fd < 0) return NULL; 
    549463 
    550         /* Hack -- Try to parse the path */ 
    551         if (path_parse(aux, sizeof(aux), what)) return (-1); 
     464        /* Allocate */ 
     465        f = ZNEW(ang_file); 
     466        f->fh = fdopen(fd, "a+"); 
    552467 
    553         /* Rename, return 0 on success, non-zero on failure */ 
    554         return (rename(buf, aux)); 
     468        if (f->fh == NULL) 
     469        { 
     470                FREE(f); 
     471                close(fd); 
     472                return NULL; 
     473        } 
     474 
     475        f->temp = TRUE; 
     476        f->fname = string_make(buf); 
     477        f->mode = MODE_READ;            /* Should really be MODE_RDWR */ 
     478 
     479        return f; 
    555480} 
    556481 
     482#else /* HAVE_MKSTEMP */ 
    557483 
    558 /* 
    559  * Hack -- attempt to open a file descriptor (create file) 
    560  * 
    561  * This function should fail if the file already exists 
    562  * 
    563  * Note that we assume that the file should be "binary" 
    564  */ 
    565 int fd_make(cptr file, int mode) 
     484ang_file *my_fopen_temp(char *buf, size_t max) 
    566485{ 
    567         char buf[1024]; 
    568         int fd; 
     486        ang_file *f; 
     487        const char *tempname; 
    569488 
    570         /* Hack -- Try to parse the path */ 
    571         if (path_parse(buf, sizeof(buf), file)) return (-1); 
     489        tempname = tmpnam(NULL); 
     490        if (!tempname) return NULL; 
    572491 
    573         /* Create the file, fail if exists, write-only, binary */ 
    574         fd = open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode); 
     492        f = ZNEW(ang_file); 
     493        f->fh = fopen(tempname, "a+"); 
    575494 
    576 #ifdef MACH_O_CARBON 
     495        if (f->fh == NULL) 
     496        { 
     497                FREE(f); 
     498                return NULL; 
     499        } 
    577500 
    578         /* Set file creator and type */ 
    579         if (fd >= 0) fsetfileinfo(buf, _fcreator, _ftype); 
     501        f->temp = TRUE; 
     502        f->fname = string_make(tempname); 
     503        f->mode = MODE_READ;            /* Should really be MODE_RDWR */ 
    580504 
    581 #endif 
    582  
    583         /* Return descriptor */ 
    584         return (fd); 
     505        return f; 
    585506} 
    586507 
     508#endif /* HAVE_MKSTEMP */ 
    587509 
     510 
     511 
     512/** Locking functions **/ 
     513 
    588514/* 
    589  * Hack -- attempt to open a file descriptor (existing file) 
    590  * 
    591  * Note that we assume that the file should be "binary" 
     515 * Lock a file using POSIX locks, on platforms where this is supported. 
    592516 */ 
    593 int fd_open(cptr file, int flags) 
     517void file_lock(ang_file *f) 
    594518{ 
    595         char buf[1024]; 
    596  
    597         /* Hack -- Try to parse the path */ 
    598         if (path_parse(buf, sizeof(buf), file)) return (-1); 
    599  
    600         /* Attempt to open the file */ 
    601         return (open(buf, flags | O_BINARY, 0)); 
     519#if defined(HAVE_FCNTL_H) && defined(SET_UID) 
     520        struct flock lock; 
     521        lock.l_type = (f->mode == MODE_READ ? F_RDLCK : F_WRLCK); 
     522        lock.l_whence = SEEK_SET; 
     523        lock.l_start = 0; 
     524        lock.l_len = 0; 
     525        lock.l_pid = 0; 
     526        fcntl(fileno(f->fh), F_SETLKW, &lock); 
     527#endif /* HAVE_FCNTL_H && SET_UID */ 
    602528} 
    603529 
    604  
    605530/* 
    606  * Attempt to lock a file descriptor 
    607  * 
    608  * Legal lock types -- F_UNLCK, F_RDLCK, F_WRLCK 
     531 * Unlock a file locked using file_lock(). 
    609532 */ 
    610 errr fd_lock(int fd, int what) 
     533void file_unlock(ang_file *f) 
    611534{ 
    612535#if defined(HAVE_FCNTL_H) && defined(SET_UID) 
    613  
    614536        struct flock lock; 
     537        lock.l_type = F_UNLCK; 
     538        lock.l_whence = SEEK_SET; 
     539        lock.l_start = 0; 
     540        lock.l_len = 0; 
     541        lock.l_pid = 0; 
     542        fcntl(fileno(f->fh), F_SETLK, &lock); 
     543#endif /* HAVE_FCNTL_H && SET_UID */ 
     544} 
    615545 
    616         /* Verify the fd */ 
    617         if (fd < 0) return (-1); 
    618546 
    619         lock.l_type = what; 
    620         lock.l_start = 0; /* Lock the entire file */ 
    621         lock.l_whence = SEEK_SET; /* Lock the entire file */ 
    622         lock.l_len = 0; /* Lock the entire file */ 
     547/** Byte-based IO and functions **/ 
    623548 
    624         /* Wait for access and set lock status */ 
    625         /* 
    626          * Change F_SETLKW to F_SETLK if it's preferable to return 
    627          * without locking and reporting an error instead of waiting. 
    628          */ 
    629         return (fcntl(fd, F_SETLKW, &lock)); 
    630  
    631 #else /* HAVE_FCNTL_H */ 
    632  
    633         /* Unused parameters */ 
    634         (void)fd; 
    635         (void)what; 
    636  
    637         /* Success */ 
    638         return (0); 
    639  
    640 #endif /* SET_UID */ 
    641  
     549/* 
     550 * Seek to location 'pos' in file 'f'. 
     551 */ 
     552bool file_seek(ang_file *f, u32b pos) 
     553{ 
     554        return (fseek(f->fh, pos, SEEK_SET) == 0); 
    642555} 
    643556 
    644  
    645557/* 
    646  * Hack -- attempt to seek on a file descriptor 
     558 * Read a single, 8-bit character from file 'f'. 
    647559 */ 
    648 errr fd_seek(int fd, long n) 
     560bool file_readc(ang_file *f, byte *b) 
    649561{ 
    650         long p; 
     562        int i = fgetc(f->fh); 
    651563 
    652         /* Verify fd */ 
    653         if (fd < 0) return (-1); 
     564        if (i == EOF) 
     565                return FALSE; 
    654566 
    655         /* Seek to the given position */ 
    656         p = lseek(fd, n, SEEK_SET); 
     567        *b = (byte)i; 
     568        return TRUE; 
     569} 
    657570 
    658         /* Failure */ 
    659         if (p < 0) return (1); 
    660  
    661         /* Failure */ 
    662         if (p != n) return (1); 
    663  
    664         /* Success */ 
    665         return (0); 
     571/*  
     572 * Write a single, 8-bit character 'b' to file 'f'. 
     573 */ 
     574bool file_writec(ang_file *f, byte b) 
     575{ 
     576        return (fputc((int)b, f->fh) != EOF); 
    666577} 
    667578 
     579/* 
     580 * Read 'n' bytes from file 'f' into array 'buf'. 
     581 */ 
     582size_t file_read(ang_file *f, char *buf, size_t n); 
    668583 
     584#ifdef HAVE_READ 
     585 
    669586#ifndef SET_UID 
    670 #define FILE_BUF_SIZE 16384 
     587# define READ_BUF_SIZE 16384 
    671588#endif 
    672589 
    673  
    674 /* 
    675  * Hack -- attempt to read data from a file descriptor 
    676  */ 
    677 errr fd_read(int fd, char *buf, size_t n) 
     590size_t file_read(ang_file *f, char *buf, size_t n) 
    678591{ 
    679         /* Verify the fd */ 
    680         if (fd < 0) return (-1); 
     592        int fd = fileno(f->fh); 
    681593 
    682594#ifndef SET_UID 
    683595 
    684         /* Read pieces */ 
    685         while (n >= FILE_BUF_SIZE) 
     596        while (n >= READ_BUF_SIZE) 
    686597        { 
    687                 /* Read a piece */ 
    688                 if (read(fd, buf, FILE_BUF_SIZE) != FILE_BUF_SIZE) return (1); 
     598                if (read(fd, buf, FILE_BUF_SIZE) != READ_BUF_SIZE) 
     599                        return FALSE; 
    689600 
    690                 /* Shorten the task */ 
    691                 buf += FILE_BUF_SIZE; 
    692  
    693                 /* Shorten the task */ 
    694                 n -= FILE_BUF_SIZE; 
     601                buf += READ_BUF_SIZE; 
     602                n -= READ_BUF_SIZE; 
    695603        } 
    696604 
    697 #endif 
     605#endif /* !SET_UID */ 
    698606 
    699         /* Read the final piece */ 
    700         if (read(fd, buf, n) != (int)n) return (1); 
     607        if (read(fd, buf, n) != (int)n) 
     608                return FALSE; 
    701609 
    702         /* Success */ 
    703         return (0); 
     610        return TRUE; 
    704611} 
    705612 
     613#else 
    706614 
     615size_t file_read(ang_file *f, char *buf, size_t n) 
     616{ 
     617        return fread(buf, 1, n, f->fh); 
     618} 
     619 
     620#endif 
     621 
     622 
    707623/* 
    708  * Hack -- Attempt to write data to a file descriptor 
     624 * Append 'n' bytes of array 'buf' to file 'f'. 
    709625 */ 
    710 errr fd_write(int fd, cptr buf, size_t n) 
     626bool file_write(ang_file *f, const char *buf, size_t n); 
     627 
     628#ifdef HAVE_WRITE 
     629 
     630#ifndef SET_UID 
     631# define WRITE_BUF_SIZE 16384 
     632#endif 
     633 
     634bool file_write(ang_file *f, const char *buf, size_t n) 
    711635{ 
    712         /* Verify the fd */ 
    713         if (fd < 0) return (-1); 
     636        int fd = fileno(f->fh); 
    714637 
    715638#ifndef SET_UID 
    716639 
    717         /* Write pieces */ 
    718         while (n >= FILE_BUF_SIZE) 
     640        while (n >= WRITE_BUF_SIZE) 
    719641        { 
    720                 /* Write a piece */ 
    721                 if (write(fd, buf, FILE_BUF_SIZE) != FILE_BUF_SIZE) return (1); 
     642                if (write(fd, buf, WRITE_BUF_SIZE) != WRITe_BUF_SIZE) 
     643                        return FALSE; 
    722644 
    723                 /* Shorten the task */ 
    724                 buf += FILE_BUF_SIZE; 
    725  
    726                 /* Shorten the task */ 
    727                 n -= FILE_BUF_SIZE; 
     645                buf += WRITE_BUF_SIZE; 
     646                n -= WRITE_BUF_SIZE; 
    728647        } 
    729648 
    730 #endif 
     649#endif /* !SET_UID */ 
    731650 
    732         /* Write the final piece */ 
    733         if (write(fd, buf, n) != (int)n) return (1); 
     651        if (write(fd, buf, n) != (int)n) 
     652                return FALSE; 
    734653 
    735         /* Success */ 
    736         return (0); 
     654        return TRUE; 
    737655} 
    738656 
     657#else 
    739658 
     659bool file_write(ang_file *f, const char *buf, size_t n) 
     660{ 
     661        return (fwrite(buf, 1, n, f->fh) == n); 
     662} 
     663 
     664#endif  
     665 
     666 
     667/** Line-based IO **/ 
     668 
    740669/* 
    741  * Hack -- attempt to close a file descriptor 
     670 * Read a line of text from file 'f' into buffer 'buf' of size 'n' bytes. 
     671 * 
     672 * Support both \r\n and \n as line endings, but not the outdated \r that used 
     673 * to be used on Macs.  Replace non-printables with '?', and \ts with ' '. 
    742674 */ 
    743 errr fd_close(int fd) 
     675#define TAB_COLUMNS 4 
     676 
     677bool file_getl(ang_file *f, char *buf, size_t len) 
    744678{ 
    745         /* Verify the fd */ 
    746         if (fd < 0) return (-1); 
     679        bool seen_cr = FALSE; 
     680        byte b; 
     681        size_t i = 0; 
    747682 
    748         /* Close, return 0 on success, -1 on failure */ 
    749         return (close(fd)); 
    750 } 
     683        /* Leave a byte for the terminating 0 */ 
     684        size_t max_len = len - 1; 
    751685 
     686        while (i < max_len) 
     687        { 
     688                char c; 
    752689 
    753 #if defined(CHECK_MODIFICATION_TIME) 
     690                if (!file_readc(f, &b)) 
     691                { 
     692                        buf[i] = '\0'; 
     693                        return (i == 0) ? FALSE : TRUE; 
     694                } 
    754695 
    755 errr check_modification_date(int fd, cptr template_file) 
    756 { 
    757         char buf[1024]; 
     696                c = (char) b; 
    758697 
    759         struct stat txt_stat, raw_stat; 
     698                if (c == '\r') 
     699                { 
     700                        seen_cr = TRUE; 
     701                        continue; 
     702                } 
    760703 
    761         /* Build the filename */ 
    762         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file); 
     704                if (seen_cr && c != '\n') 
     705                { 
     706                        fseek(f->fh, -1, SEEK_CUR); 
     707                        buf[i] = '\0'; 
     708                        return TRUE; 
     709                } 
    763710 
    764         /* Access stats on text file */ 
    765         if (stat(buf, &txt_stat)) 
    766         { 
    767                 /* No text file - continue */ 
    768         } 
     711                if (c == '\n') 
     712                { 
     713                        buf[i] = '\0'; 
     714                        return TRUE; 
     715                } 
    769716 
    770         /* Access stats on raw file */ 
    771         else if (fstat(fd, &raw_stat)) 
    772         { 
    773                 /* Error */ 
    774                 return (-1); 
    775         } 
     717                /* Expand tabs */ 
     718                if (c == '\t') 
     719                { 
     720                        /* Next tab stop */ 
     721                        size_t tabstop = ((i + TAB_COLUMNS) / TAB_COLUMNS) * TAB_COLUMNS; 
     722                        if (tabstop >= len) break; 
    776723 
    777         /* Ensure text file is not newer than raw file */ 
    778         else if (txt_stat.st_mtime > raw_stat.st_mtime) 
    779         { 
    780                 /* Reprocess text file */ 
    781                 return (-1); 
    782         } 
     724                        /* Convert to spaces */ 
     725                        while (i < tabstop) 
     726                                buf[i++] = ' '; 
    783727 
    784         return (0); 
    785 } 
     728                        continue; 
     729                } 
    786730 
    787 #endif /* CHECK_MODIFICATION_TIME */ 
     731                /* Ignore non-printables */ 
     732                if (!isprint((unsigned char) c)) 
     733                { 
     734                        buf[i++] = '?'; 
     735                        continue; 
     736                } 
    788737 
    789 #endif /* RISCOS */ 
     738                buf[i++] = c; 
     739        } 
    790740 
    791 /*** Directory scanning code ***/ 
     741        return TRUE; 
     742} 
    792743 
    793744/* 
    794  * This code was originally written for the SDL port so it could scan for fonts 
    795  * without needing a fontlist text file. 
     745 * Append a line of text 'buf' to the end of file 'f', using system-dependent 
     746 * line ending. 
    796747 */ 
     748bool file_put(ang_file *f, const char *buf) 
     749{ 
     750        return file_write(f, buf, strlen(buf)); 
     751} 
    797752 
     753/* 
     754 * Append a formatted line of text to the end of file 'f'. 
     755 */ 
     756bool file_putf(ang_file *f, const char *fmt, ...) 
     757{ 
     758        char buf[1024]; 
     759        va_list vp; 
    798760 
     761        va_start(vp, fmt); 
     762        (void)vstrnfmt(buf, sizeof(buf), fmt, vp); 
     763        va_end(vp); 
     764 
     765        return file_put(f, buf); 
     766} 
     767 
     768 
     769 
     770/*** Directory scanning API ***/ 
     771 
    799772/* 
    800773 * Opens a directory handle. 
    801774 *  
     
    829802 
    830803#ifdef WINDOWS 
    831804 
    832 /* Include Windows header */ 
    833 #include <windows.h> 
    834805 
    835806/* System-specific struct */ 
    836807struct ang_dir 
     
    853824        if (h == INVALID_HANDLE_VALUE) 
    854825                return NULL; 
    855826 
    856         /* Allocate for the handle */ 
     827        /* Set up the handle */ 
    857828        dir = ZNEW(ang_dir); 
    858         if (!dir) return NULL; 
    859  
    860         /* Remember details */ 
    861829        dir->h = h; 
    862830        dir->first_file = string_make(fd.cFileName); 
    863831 
     
    876844        { 
    877845                /* Copy the string across, then free it */ 
    878846                my_strcpy(fname, dir->first_file, len); 
    879                 string_free(dir->first_file); 
    880                 dir->first_file = NULL; 
     847                FREE(dir->first_file); 
    881848 
    882849                /* Wild success */ 
    883850                return TRUE; 
     
    912879                FindClose(dir->h); 
    913880 
    914881        /* Free memory */ 
     882        FREE(dir->first_file); 
    915883        FREE(dir); 
    916884} 
    917885 
     
    920888 
    921889#ifdef HAVE_DIRENT_H 
    922890 
    923 /* Include relevant types */ 
    924 #include <sys/types.h> 
    925 #include <dirent.h> 
    926  
    927891/* Define our ang_dir type */ 
    928892struct ang_dir 
    929893{ 
     
    962926{ 
    963927        struct dirent *entry; 
    964928        struct stat filedata; 
    965         char path[1024] = ""; 
     929        char path[1024]; 
    966930 
    967931        assert(dir != NULL); 
    968932 
     
    996960{ 
    997961        /* Close directory */ 
    998962        if (dir->d) 
    999         { 
    1000963                closedir(dir->d); 
    1001                 string_free(dir->dirname); 
    1002         } 
    1003964 
    1004965        /* Free memory */ 
     966        FREE(dir->dirname); 
    1005967        FREE(dir); 
    1006968} 
    1007969 
    1008970#endif /* HAVE_DIRENT_H */ 
    1009  
  • cmd4.c

     
    212212static void place_visual_list_cursor(int col, int row, byte a, 
    213213                                byte c, byte attr_top, byte char_left); 
    214214 
    215 static void dump_pref_file(void (*dump)(FILE*), const char *title, int row); 
     215static void dump_pref_file(void (*dump)(ang_file *), const char *title, int row); 
    216216 
    217217/* 
    218218 * Clipboard variables for copy&paste in visual mode 
     
    25372537 
    25382538 
    25392539/* 
    2540  *  Header and footer marker string for pref file dumps 
     2540 * Header and footer marker string for pref file dumps 
    25412541 */ 
    25422542static cptr dump_separator = "#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#"; 
    25432543 
     
    25452545/* 
    25462546 * Remove old lines from pref files 
    25472547 */ 
    2548 static void remove_old_dump(const char *orig_file, const char *mark) 
     2548static void remove_old_dump(const char *cur_fname, const char *mark) 
    25492549{ 
    2550         FILE *tmp_fff, *orig_fff; 
    2551  
    2552         char tmp_file[1024]; 
    2553         char buf[1024]; 
    25542550        bool between_marks = FALSE; 
    25552551        bool changed = FALSE; 
    2556         char expected_line[1024]; 
    25572552 
     2553        char buf[1024]; 
    25582554 
    2559         /* Open an old dump file in read-only mode */ 
    2560         orig_fff = my_fopen(orig_file, "r"); 
     2555        char start_line[1024]; 
     2556        char end_line[1024]; 
    25612557 
    2562         /* If original file does not exist, nothing to do */ 
    2563         if (!orig_fff) return; 
     2558        char new_fname[1024]; 
    25642559 
    2565         /* Open a new temporary file */ 
    2566         tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file)); 
     2560        ang_file *new_file; 
     2561        ang_file *cur_file; 
    25672562 
    2568         if (!tmp_fff) 
    2569         { 
    2570                         msg_format("Failed to create temporary file %s.", tmp_file); 
    2571                         msg_print(NULL); 
    2572                         return; 
    2573         } 
    25742563 
     2564        /* Format up some filenames */ 
     2565        strnfmt(new_fname, sizeof(new_fname), "%s.new", cur_fname); 
     2566 
    25752567        /* Work out what we expect to find */ 
    2576         strnfmt(expected_line, sizeof(expected_line), "%s begin %s", dump_separator, mark); 
     2568        strnfmt(start_line, sizeof(start_line), "%s begin %s", dump_separator, mark); 
     2569        strnfmt(end_line,   sizeof(end_line),   "%s end %s",   dump_separator, mark); 
    25772570 
     2571 
     2572 
     2573        /* Open current file */ 
     2574        cur_file = file_open(cur_fname, MODE_READ, -1); 
     2575        if (!cur_file) return; 
     2576 
     2577        /* Open new file */ 
     2578        new_file = file_open(new_fname, MODE_WRITE, FTYPE_TEXT); 
     2579        if (!new_file) 
     2580        { 
     2581                msg_format("Failed to create file %s", new_fname); 
     2582                return; 
     2583        } 
     2584 
    25782585        /* Loop for every line */ 
    2579         while (TRUE) 
     2586        while (file_getl(cur_file, buf, sizeof(buf))) 
    25802587        { 
    2581                 /* Read a line */ 
    2582                 if (my_fgets(orig_fff, buf, sizeof(buf))) 
     2588                /* If we find the start line, turn on */ 
     2589                if (!strcmp(buf, start_line)) 
    25832590                { 
    2584                         /* End of file but no end marker */ 
    2585                         if (between_marks) changed = FALSE; 
    2586  
    2587                         break; 
     2591                        between_marks = TRUE; 
    25882592                } 
    25892593 
    2590                 /* Is this line a header/footer? */ 
    2591                 if (strncmp(buf, dump_separator, strlen(dump_separator)) == 0) 
     2594                /* If we find the finish line, turn off */ 
     2595                else if (!strcmp(buf, end_line)) 
    25922596                { 
    2593                         /* Found the expected line? */ 
    2594                         if (strcmp(buf, expected_line) == 0) 
    2595                         { 
    2596                                 if (!between_marks) 
    2597                                 { 
    2598                                         /* Expect the footer next */ 
    2599                                         strnfmt(expected_line, sizeof(expected_line), 
    2600                                                 "%s end %s", dump_separator, mark); 
    2601  
    2602                                         between_marks = TRUE; 
    2603  
    2604                                         /* There are some changes */ 
    2605                                         changed = TRUE; 
    2606                                 } 
    2607                                 else 
    2608                                 { 
    2609                                         /* Expect a header next - XXX shouldn't happen */ 
    2610                                         strnfmt(expected_line, sizeof(expected_line), 
    2611                                                 "%s begin %s", dump_separator, mark); 
    2612  
    2613                                         between_marks = FALSE; 
    2614  
    2615                                         /* Next line */ 
    2616                                         continue; 
    2617                                 } 
    2618                         } 
    2619  
    2620                         /* Found a different line */ 
    2621                         else 
    2622                         { 
    2623                                 /* Expected a footer and got something different? */ 
    2624                                 if (between_marks) 
    2625                                 { 
    2626                                         /* Abort */ 
    2627                                         changed = FALSE; 
    2628                                         break; 
    2629                                 } 
    2630                         } 
     2597                        between_marks = FALSE; 
     2598                        changed = TRUE; 
    26312599                } 
    26322600 
    26332601                if (!between_marks) 
    26342602                { 
    26352603                        /* Copy orginal line */ 
    2636                         fprintf(tmp_fff, "%s\n", buf); 
     2604                        file_putf(new_file, "%s\n", buf); 
    26372605                } 
    26382606        } 
    26392607 
    26402608        /* Close files */ 
    2641         my_fclose(orig_fff); 
    2642         my_fclose(tmp_fff); 
     2609        file_close(cur_file); 
     2610        file_close(new_file); 
    26432611 
    2644         /* If there are changes, overwrite the original file with the new one */ 
     2612        /* If there are changes, move things around */ 
    26452613        if (changed) 
    26462614        { 
    2647                 /* Copy contents of temporary file */ 
    2648                 tmp_fff = my_fopen(tmp_file, "r"); 
    2649                 orig_fff = my_fopen(orig_file, "w"); 
     2615                char old_fname[1024]; 
     2616                strnfmt(old_fname, sizeof(old_fname), "%s.old", cur_fname); 
    26502617 
    2651                 while (!my_fgets(tmp_fff, buf, sizeof(buf))) 
    2652                         fprintf(orig_fff, "%s\n", buf); 
    2653  
    2654                 my_fclose(orig_fff); 
    2655                 my_fclose(tmp_fff); 
     2618                if (file_move(cur_fname, old_fname)) 
     2619                { 
     2620                        file_move(new_fname, cur_fname); 
     2621                        file_delete(old_fname); 
     2622                } 
    26562623        } 
    26572624 
    2658         /* Kill the temporary file */ 
    2659         fd_kill(tmp_file); 
     2625        /* Otherwise just destroy the new file */ 
     2626        else 
     2627        { 
     2628                file_delete(new_fname); 
     2629        } 
    26602630} 
    26612631 
    26622632 
    26632633/* 
    26642634 * Output the header of a pref-file dump 
    26652635 */ 
    2666 static void pref_header(FILE *fff, const char *mark) 
     2636static void pref_header(ang_file *fff, const char *mark) 
    26672637{ 
    26682638        /* Start of dump */ 
    2669         fprintf(fff, "%s begin %s\n", dump_separator, mark); 
     2639        file_putf(fff, "%s begin %s\n", dump_separator, mark); 
    26702640 
    2671         fprintf(fff, "# *Warning!*  The lines below are an automatic dump.\n"); 
    2672         fprintf(fff, "# Don't edit them; changes will be deleted and replaced automatically.\n"); 
     2641        file_putf(fff, "# *Warning!*  The lines below are an automatic dump.\n"); 
     2642        file_putf(fff, "# Don't edit them; changes will be deleted and replaced automatically.\n"); 
    26732643} 
    26742644 
    26752645/* 
    26762646 * Output the footer of a pref-file dump 
    26772647 */ 
    2678 static void pref_footer(FILE *fff, const char *mark) 
     2648static void pref_footer(ang_file *fff, const char *mark) 
    26792649{ 
    2680         fprintf(fff, "# *Warning!*  The lines above are an automatic dump.\n"); 
    2681         fprintf(fff, "# Don't edit them; changes will be deleted and replaced automatically.\n"); 
     2650        file_putf(fff, "# *Warning!*  The lines above are an automatic dump.\n"); 
     2651        file_putf(fff, "# Don't edit them; changes will be deleted and replaced automatically.\n"); 
    26822652 
    26832653        /* End of dump */ 
    2684         fprintf(fff, "%s end %s\n", dump_separator, mark); 
     2654        file_putf(fff, "%s end %s\n", dump_separator, mark); 
    26852655} 
    26862656 
    26872657 
     
    26922662 * - dump(FILE *) needs to emit only the raw data for the dump. 
    26932663 *   Comments are generated automatically 
    26942664 */ 
    2695 static void dump_pref_file(void (*dump)(FILE*), const char *title, int row) 
     2665static void dump_pref_file(void (*dump)(ang_file *), const char *title, int row) 
    26962666{ 
    26972667        char ftmp[80]; 
    26982668        char buf[1025]; 
    2699         FILE *fff; 
     2669        ang_file *fff; 
    27002670 
    27012671        /* Prompt */ 
    27022672        prt(format("%s to a pref file", title), row, 0); 
     
    27132683        /* Build the filename */ 
    27142684        path_build(buf, 1024, ANGBAND_DIR_USER, ftmp); 
    27152685 
    2716         FILE_TYPE(FILE_TYPE_TEXT); 
    2717  
    27182686        /* Remove old macros */ 
    27192687        remove_old_dump(buf, title); 
    27202688 
    27212689        /* Append to the file */ 
    2722         fff = my_fopen(buf, "a"); 
    2723  
    2724         /* Failure */ 
     2690        fff = file_open(buf, MODE_APPEND, FTYPE_TEXT); 
    27252691        if (!fff) 
    27262692        { 
    27272693                prt("", 0, 0); 
     
    27332699        pref_header(fff, title); 
    27342700 
    27352701        /* Skip some lines */ 
    2736         fprintf(fff, "\n\n"); 
     2702        file_putf(fff, "\n\n"); 
    27372703 
    27382704        /* Start dumping */ 
    2739         fprintf(fff, "# %s definitions\n\n", strstr(title, " ")); 
     2705        file_putf(fff, "# %s definitions\n\n", strstr(title, " ")); 
    27402706         
    27412707        dump(fff); 
    27422708 
    27432709        /* All done */ 
    2744         fprintf(fff, "\n\n\n"); 
     2710        file_putf(fff, "\n\n\n"); 
    27452711 
    27462712        /* Output footer */ 
    27472713        pref_footer(fff, title); 
    27482714 
    27492715        /* Close */ 
    2750         my_fclose(fff); 
     2716        file_close(fff); 
    27512717 
    27522718        /* Message */ 
    27532719        prt("", 0, 0); 
     
    27572723/* 
    27582724 * Save autoinscription data to a pref file. 
    27592725 */ 
    2760 static void autoinsc_dump(FILE *fff) 
     2726static void autoinsc_dump(ang_file *fff) 
    27612727{ 
    27622728        int i; 
     2729        if (!inscriptions) return; 
    27632730 
    2764         if (!inscriptions) 
    2765                 return; 
     2731        file_putf(fff, "# Autoinscription settings\n"); 
     2732        file_putf(fff, "# B:item kind:inscription\n\n"); 
    27662733 
    2767         /* Start dumping */ 
    2768         fprintf(fff, "# Autoinscription settings"); 
    2769         fprintf(fff, "# B:item kind:inscription\n\n"); 
    2770  
    27712734        for (i = 0; i < inscriptions_count; i++) 
    27722735        { 
    27732736                object_kind *k_ptr = &k_info[inscriptions[i].kind_idx]; 
    27742737 
    2775                 /* Describe and write */ 
    2776                 fprintf(fff, "# Autoinscription for %s\n", k_name + k_ptr->name); 
    2777                 fprintf(fff, "B:%d:%s\n\n", inscriptions[i].kind_idx, 
     2738                file_putf(fff, "# Autoinscription for %s\n", k_name + k_ptr->name); 
     2739                file_putf(fff, "B:%d:%s\n\n", inscriptions[i].kind_idx, 
    27782740                        quark_str(inscriptions[i].inscription_idx)); 
    27792741        } 
    27802742 
    2781         /* All done */ 
    2782         fprintf(fff, "\n"); 
     2743        file_putf(fff, "\n"); 
    27832744} 
    27842745 
    27852746/* 
    27862747 * Save squelch data to a pref file. 
    27872748 */ 
    2788 static void squelch_dump(FILE *fff) 
     2749static void squelch_dump(ang_file *fff) 
    27892750{ 
    27902751        int i; 
    2791         int tval, sval; 
    2792         bool squelch; 
     2752        file_putf(fff, "# Squelch settings\n"); 
    27932753 
    2794         /* Start dumping */ 
    2795         fprintf(fff, "\n\n"); 
    2796         fprintf(fff, "# Squelch bits\n\n"); 
    2797  
    2798         /* Dump squelch bits */ 
    27992754        for (i = 1; i < z_info->k_max; i++) 
    28002755        { 
    2801                 tval = k_info[i].tval; 
    2802                 sval = k_info[i].sval; 
    2803                 squelch = k_info[i].squelch; 
     2756                int tval = k_info[i].tval; 
     2757                int sval = k_info[i].sval; 
     2758                bool squelch = k_info[i].squelch; 
    28042759 
    28052760                /* Dump the squelch info */ 
    28062761                if (tval || sval) 
    2807                         fprintf(fff, "Q:%d:%d:%d:%d\n", i, tval, sval, squelch); 
     2762                        file_putf(fff, "Q:%d:%d:%d:%d\n", i, tval, sval, squelch); 
    28082763        } 
    28092764 
    2810         /* All done */ 
    2811         fprintf(fff, "\n"); 
     2765        file_putf(fff, "\n"); 
    28122766} 
    28132767 
    28142768/* 
    28152769 * Write all current options to a user preference file. 
    28162770 */ 
    2817 static void option_dump(FILE *fff) 
     2771static void option_dump(ang_file *fff) 
    28182772{ 
    28192773        int i, j; 
    28202774 
     
    28252779                if (!name) continue; 
    28262780 
    28272781                /* Comment */ 
    2828                 fprintf(fff, "# Option '%s'\n", option_desc(i)); 
     2782                file_putf(fff, "# Option '%s'\n", option_desc(i)); 
    28292783 
    28302784                /* Dump the option */ 
    28312785                if (op_ptr->opt[i]) 
    2832                         fprintf(fff, "Y:%s\n", name); 
     2786                        file_putf(fff, "Y:%s\n", name); 
    28332787                else 
    2834                         fprintf(fff, "X:%s\n", name); 
     2788                        file_putf(fff, "X:%s\n", name); 
    28352789 
    28362790                /* Skip a line */ 
    2837                 fprintf(fff, "\n"); 
     2791                file_putf(fff, "\n"); 
    28382792        } 
    28392793 
    28402794        /* Dump window flags */ 
     
    28502804                        if (!window_flag_desc[j]) continue; 
    28512805 
    28522806                        /* Comment */ 
    2853                         fprintf(fff, "# Window '%s', Flag '%s'\n", 
     2807                        file_putf(fff, "# Window '%s', Flag '%s'\n", 
    28542808                                angband_term_name[i], window_flag_desc[j]); 
    28552809 
    28562810                        /* Dump the flag */ 
    28572811                        if (op_ptr->window_flag[i] & (1L << j)) 
    2858                         { 
    2859                                 fprintf(fff, "W:%d:%d:1\n", i, j); 
    2860                         } 
     2812                                file_putf(fff, "W:%d:%d:1\n", i, j); 
    28612813                        else 
    2862                         { 
    2863                                 fprintf(fff, "W:%d:%d:0\n", i, j); 
    2864                         } 
     2814                                file_putf(fff, "W:%d:%d:0\n", i, j); 
    28652815 
    28662816                        /* Skip a line */ 
    2867                         fprintf(fff, "\n"); 
     2817                        file_putf(fff, "\n"); 
    28682818                } 
    28692819        } 
    28702820 
     
    28772827#ifdef ALLOW_MACROS 
    28782828 
    28792829/* 
    2880  * append all current macros to the given file 
     2830 * Append all current macros to the given file 
    28812831 */ 
    2882 static void macro_dump(FILE *fff) 
     2832static void macro_dump(ang_file *fff) 
    28832833{ 
    28842834        int i; 
    28852835        char buf[1024]; 
     
    28882838        for (i = 0; i < macro__num; i++) 
    28892839        { 
    28902840                /* Start the macro */ 
    2891                 fprintf(fff, "# Macro '%d'\n\n", i); 
     2841                file_putf(fff, "# Macro '%d'\n", i); 
    28922842 
    28932843                /* Extract the macro action */ 
    28942844                ascii_to_text(buf, sizeof(buf), macro__act[i]); 
     2845                file_putf(fff, "A:%s\n", buf); 
    28952846 
    2896                 /* Dump the macro action */ 
    2897                 fprintf(fff, "A:%s\n", buf); 
    2898  
    28992847                /* Extract the macro pattern */ 
    29002848                ascii_to_text(buf, sizeof(buf), macro__pat[i]); 
     2849                file_putf(fff, "P:%s\n", buf); 
    29012850 
    2902                 /* Dump the macro pattern */ 
    2903                 fprintf(fff, "P:%s\n", buf); 
    2904  
    2905                 /* End the macro */ 
    2906                 fprintf(fff, "\n\n"); 
     2851                file_putf(fff, "\n"); 
    29072852        } 
    29082853} 
    29092854 
     
    30062951 * 
    30072952 * Hack -- We only append the keymaps for the "active" mode. 
    30082953 */ 
    3009 static void keymap_dump(FILE *fff) 
     2954static void keymap_dump(ang_file *fff) 
    30102955{ 
    3011         int i; 
     2956        size_t i; 
    30122957        int mode; 
    30132958        char buf[1024]; 
    30142959 
    3015         /* Roguelike */ 
    30162960        if (rogue_like_commands) 
    3017         { 
    30182961                mode = KEYMAP_MODE_ROGUE; 
    3019         } 
    3020  
    3021         /* Original */ 
    30222962        else 
    3023         { 
    30242963                mode = KEYMAP_MODE_ORIG; 
    3025         } 
    30262964 
    3027         for (i = 0; i < (int)N_ELEMENTS(keymap_act[mode]); i++) 
     2965        for (i = 0; i < N_ELEMENTS(keymap_act[mode]); i++) 
    30282966        { 
    30292967                char key[2] = "?"; 
    3030  
    30312968                cptr act; 
    30322969 
    30332970                /* Loop up the keymap */ 
     
    30402977                ascii_to_text(buf, sizeof(buf), act); 
    30412978 
    30422979                /* Dump the keymap action */ 
    3043                 fprintf(fff, "A:%s\n", buf); 
     2980                file_putf(fff, "A:%s\n", buf); 
    30442981 
    30452982                /* Convert the key into a string */ 
    30462983                key[0] = i; 
     
    30492986                ascii_to_text(buf, sizeof(buf), key); 
    30502987 
    30512988                /* Dump the keymap pattern */ 
    3052                 fprintf(fff, "C:%d:%s\n", mode, buf); 
     2989                file_putf(fff, "C:%d:%s\n", mode, buf); 
    30532990 
    30542991                /* Skip a line */ 
    3055                 fprintf(fff, "\n"); 
     2992                file_putf(fff, "\n"); 
    30562993        } 
    30572994 
    30582995} 
     
    30983035 
    30993036        region loc = {0, 0, 0, 12}; 
    31003037 
    3101         /* Roguelike */ 
    31023038        if (rogue_like_commands) 
    3103         { 
    31043039                mode = KEYMAP_MODE_ROGUE; 
    3105         } 
    3106  
    3107         /* Original */ 
    31083040        else 
    3109         { 
    31103041                mode = KEYMAP_MODE_ORIG; 
    3111         } 
    31123042 
    31133043 
    3114         /* File type is "TEXT" */ 
    3115         FILE_TYPE(FILE_TYPE_TEXT); 
    3116  
    31173044        screen_save(); 
    31183045 
    31193046        menu_layout(&macro_menu, &loc); 
     
    33973324 
    33983325 
    33993326/* Dump monsters */ 
    3400 static void dump_monsters(FILE *fff) 
     3327static void dump_monsters(ang_file *fff) 
    34013328{ 
    34023329        int i; 
     3330 
    34033331        for (i = 0; i < z_info->r_max; i++) 
    34043332        { 
    34053333                monster_race *r_ptr = &r_info[i]; 
     3334                byte attr = r_ptr->x_attr; 
     3335                byte chr = r_ptr->x_char; 
    34063336 
    34073337                /* Skip non-entries */ 
    34083338                if (!r_ptr->name) continue; 
    34093339 
    3410                 /* Dump a comment */ 
    3411                 fprintf(fff, "# %s\n", (r_name + r_ptr->name)); 
    3412  
    3413                 /* Dump the monster attr/char info */ 
    3414                 fprintf(fff, "R:%d:0x%02X:0x%02X\n\n", i, 
    3415                         (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char)); 
     3340                file_putf(fff, "# Monster: %s\n", (r_name + r_ptr->name)); 
     3341                file_putf(fff, "R:%d:0x%02X:0x%02X\n", i, attr, chr); 
    34163342        } 
    34173343} 
    34183344 
    34193345/* Dump objects */ 
    3420 static void dump_objects(FILE *fff) 
     3346static void dump_objects(ang_file *fff) 
    34213347{ 
    34223348        int i; 
     3349 
    34233350        for (i = 0; i < z_info->k_max; i++) 
    34243351        { 
    34253352                object_kind *k_ptr = &k_info[i]; 
     3353                byte attr = k_ptr->x_attr; 
     3354                byte chr = k_ptr->x_char; 
    34263355 
    34273356                /* Skip non-entries */ 
    34283357                if (!k_ptr->name) continue; 
    34293358 
    3430                 /* Dump a comment */ 
    3431                 fprintf(fff, "# %s\n", (k_name + k_ptr->name)); 
    3432  
    3433                 /* Dump the object attr/char info */ 
    3434                 fprintf(fff, "K:%d:0x%02X:0x%02X\n\n", i, 
    3435                                         (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char)); 
     3359                file_putf(fff, "# Object: %s\n", (k_name + k_ptr->name)); 
     3360                file_putf(fff, "K:%d:0x%02X:0x%02X\n", i, attr, chr); 
    34363361        } 
    34373362} 
    34383363 
    34393364/* Dump features */ 
    3440 static void dump_features(FILE *fff) 
     3365static void dump_features(ang_file *fff) 
    34413366{ 
    34423367        int i; 
     3368 
    34433369        for (i = 0; i < z_info->f_max; i++) 
    34443370        { 
    34453371                feature_type *f_ptr = &f_info[i]; 
     3372                byte attr = f_ptr->x_attr; 
     3373                byte chr = f_ptr->x_char; 
    34463374 
    34473375                /* Skip non-entries */ 
    34483376                if (!f_ptr->name) continue; 
     
    34503378                /* Skip mimic entries -- except invisible trap */ 
    34513379                if ((f_ptr->mimic != i) && (i != FEAT_INVIS)) continue; 
    34523380 
    3453                 /* Dump a comment */ 
    3454                 fprintf(fff, "# %s\n", (f_name + f_ptr->name)); 
    3455  
    3456                 /* Dump the feature attr/char info */ 
    3457                 /* Dump the feature attr/char info */ 
    3458                 fprintf(fff, "F:%d:0x%02X:0x%02X\n\n", i, 
    3459                                                 (byte)(f_ptr->x_attr), (byte)(f_ptr->x_char)); 
    3460  
    3461  
     3381                file_putf(fff, "# Terrain: %s\n", (f_name + f_ptr->name)); 
     3382                file_putf(fff, "F:%d:0x%02X:0x%02X\n", i, attr, chr); 
    34623383        } 
    34633384} 
    34643385 
    34653386/* Dump flavors */ 
    3466 static void dump_flavors(FILE *fff) 
     3387static void dump_flavors(ang_file *fff) 
    34673388{ 
    34683389        int i; 
     3390 
    34693391        for (i = 0; i < z_info->flavor_max; i++) 
    34703392        { 
    34713393                flavor_type *x_ptr = &flavor_info[i]; 
     3394                byte attr = x_ptr->x_attr; 
     3395                byte chr = x_ptr->x_char; 
    34723396 
    3473                 /* Dump a comment */ 
    3474                 fprintf(fff, "# %s\n", (flavor_text + x_ptr->text)); 
    3475  
    3476                 /* Dump the flavor attr/char info */ 
    3477                 fprintf(fff, "L:%d:0x%02X:0x%02X\n\n", i, 
    3478                         (byte)(x_ptr->x_attr), (byte)(x_ptr->x_char)); 
     3397                file_putf(fff, "# Item flavor: %s\n", (flavor_text + x_ptr->text)); 
     3398                file_putf(fff, "L:%d:0x%02X:0x%02X\n\n", i, attr, chr); 
    34793399        } 
    34803400} 
    34813401 
    34823402/* Dump colors */ 
    3483 static void dump_colors(FILE *fff) 
     3403static void dump_colors(ang_file *fff) 
    34843404{ 
    34853405        int i; 
     3406 
    34863407        for (i = 0; i < MAX_COLORS; i++) 
    34873408        { 
    34883409                int kv = angband_color_table[i][0]; 
     
    34983419                /* Extract the color name */ 
    34993420                if (i < BASIC_COLORS) name = color_names[i]; 
    35003421 
    3501                 /* Dump a comment */ 
    3502                 fprintf(fff, "# Color '%s'\n", name); 
    3503  
     3422                file_putf(fff, "# Color: %s\n", name); 
     3423                file_putf(fff, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n", i, kv, rv, gv, bv); 
    35043424        } 
    35053425} 
    35063426 
     
    38003720        int cx; 
    38013721        int cursor = 0; 
    38023722 
    3803         /* File type is "TEXT" */ 
    3804         FILE_TYPE(FILE_TYPE_TEXT); 
    3805  
    3806         /* Save screen */ 
    38073723        screen_save(); 
    38083724 
    38093725        menu_layout(&color_menu, &SCREEN_REGION); 
     
    44394355 
    44404356        bool okay = TRUE; 
    44414357 
    4442         FILE *fp; 
     4358        ang_file *fp; 
    44434359 
    44444360        char buf[1024]; 
    44454361 
    44464362 
    44474363        /* Build the filename */ 
    44484364        path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); 
    4449  
    4450         /* Open the file */ 
    4451         fp = my_fopen(buf, "r"); 
    4452  
    4453         /* Oops */ 
     4365        fp = file_open(buf, MODE_READ, -1); 
    44544366        if (!fp) return; 
    44554367 
    44564368 
     
    44664378        for (y = 0; okay && (y < 24); y++) 
    44674379        { 
    44684380                /* Get a line of data */ 
    4469                 if (my_fgets(fp, buf, sizeof(buf))) okay = FALSE; 
     4381                if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; 
    44704382 
    44714383 
    44724384                /* Show each row */ 
     
    44784390        } 
    44794391 
    44804392        /* Get the blank line */ 
    4481         if (my_fgets(fp, buf, sizeof(buf))) okay = FALSE; 
     4393        if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; 
    44824394 
    44834395 
    44844396        /* Dump the screen */ 
    44854397        for (y = 0; okay && (y < 24); y++) 
    44864398        { 
    44874399                /* Get a line of data */ 
    4488                 if (my_fgets(fp, buf, sizeof(buf))) okay = FALSE; 
     4400                if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; 
    44894401 
    44904402                /* Dump each row */ 
    44914403                for (x = 0; x < 79; x++) 
     
    45074419 
    45084420 
    45094421        /* Close it */ 
    4510         my_fclose(fp); 
     4422        file_close(fp); 
    45114423 
    45124424 
    45134425        /* Message */ 
     
    45304442        byte a = 0; 
    45314443        char c = ' '; 
    45324444 
    4533         FILE *fff; 
     4445        ang_file *fff; 
    45344446 
    45354447        char buf[1024]; 
    45364448 
    45374449        /* Build the filename */ 
    45384450        path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); 
    4539  
    4540         /* File type is "DATA" -- needs to be opened in Angband to view */ 
    4541         FILE_TYPE(FILE_TYPE_DATA); 
    4542  
    4543         /* Append to the file */ 
    4544         fff = my_fopen(buf, "w"); 
    4545  
    4546         /* Oops */ 
     4451        fff = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
    45474452        if (!fff) return; 
    45484453 
    45494454 
     
    45684473                buf[x] = '\0'; 
    45694474 
    45704475                /* End the row */ 
    4571                 fprintf(fff, "%s\n", buf); 
     4476                file_putf(fff, "%s\n", buf); 
    45724477        } 
    45734478 
    45744479        /* Skip a line */ 
    4575         fprintf(fff, "\n"); 
     4480        file_putf(fff, "\n"); 
    45764481 
    45774482 
    45784483        /* Dump the screen */ 
     
    45924497                buf[x] = '\0'; 
    45934498 
    45944499                /* End the row */ 
    4595                 fprintf(fff, "%s\n", buf); 
     4500                file_putf(fff, "%s\n", buf); 
    45964501        } 
    45974502 
    45984503        /* Skip a line */ 
    4599         fprintf(fff, "\n"); 
     4504        file_putf(fff, "\n"); 
    46004505 
    46014506 
    46024507        /* Close it */ 
    4603         my_fclose(fff); 
     4508        file_close(fff); 
    46044509 
    46054510 
    46064511        /* Message */ 
     
    46204525{ 
    46214526        size_t i; 
    46224527 
    4623         FILE *fff; 
     4528        ang_file *fff; 
    46244529        char file_name[1024]; 
    46254530        char tmp_val[256]; 
    46264531 
    4627         typedef void (*dump_func)(FILE *); 
     4532        typedef void (*dump_func)(ang_file *); 
    46284533        dump_func dump_visuals [] =  
    46294534                { dump_monsters, dump_features, dump_objects, dump_flavors, dump_colors }; 
    46304535 
    4631         /* File type is "TEXT" */ 
    4632         FILE_TYPE(FILE_TYPE_TEXT); 
    46334536 
     4537        if (mode == 0) 
     4538                my_strcpy(tmp_val, "dump.html", sizeof(tmp_val)); 
     4539        else 
     4540                my_strcpy(tmp_val, "dump.txt", sizeof(tmp_val)); 
     4541 
    46344542        /* Ask for a file */ 
    4635         if (mode == 0) my_strcpy(tmp_val, "dump.html", sizeof(tmp_val)); 
    4636         else my_strcpy(tmp_val, "dump.txt", sizeof(tmp_val)); 
    46374543        if (!get_string("File: ", tmp_val, sizeof(tmp_val))) return; 
    46384544 
    46394545        /* Save current preferences */ 
    46404546        path_build(file_name, 1024, ANGBAND_DIR_USER, "dump.prf"); 
    4641         fff = my_fopen(file_name, "w"); 
     4547        fff = file_open(file_name, MODE_WRITE, (mode == 0 ? FTYPE_HTML : FTYPE_TEXT)); 
    46424548 
    46434549        /* Check for failure */ 
    46444550        if (!fff) 
     
    46524558        for (i = 0; i < N_ELEMENTS(dump_visuals); i++) 
    46534559                dump_visuals[i](fff); 
    46544560 
    4655         my_fclose(fff); 
     4561        file_close(fff); 
    46564562 
    46574563        /* Dump the screen with raw character attributes */ 
    46584564        reset_visuals(FALSE); 
     
    46624568        /* Recover current graphics settings */ 
    46634569        reset_visuals(TRUE); 
    46644570        process_pref_file(file_name); 
    4665         fd_kill(file_name); 
     4571        file_delete(file_name); 
    46664572        do_cmd_redraw(); 
    46674573 
    46684574        msg_print("HTML screen dump saved."); 
  • z-file.h

     
    11#ifndef INCLUDED_Z_FILE_H 
    22#define INCLUDED_Z_FILE_H 
    33 
    4 /*** Various system-specific fixes ***/ 
     4#include "h-basic.h" 
    55 
    6 /* 
    7  * Use POSIX file control where we can, otherwise help out other platforms 
    8  */ 
    9 #ifdef HAVE_FCNTL_H 
    10 # include <fcntl.h> 
    11 #else 
    12 # define O_RDONLY   0 
    13 # define O_WRONLY   1 
    14 # define O_RDWR     2 
    15 #endif 
     6extern int player_uid; 
     7extern int player_egid; 
    168 
     9void safe_setuid_drop(void); 
     10void safe_setuid_grab(void); 
    1711 
    18 /* 
    19  * Several systems have no "O_BINARY" flag 
    20  */ 
    21 #ifndef O_BINARY 
    22 # define O_BINARY 0 
    23 #endif /* O_BINARY */ 
     12size_t path_build(char *buf, size_t len, const char *base, const char *leaf); 
    2413 
     14/* File code */ 
     15typedef struct ang_file ang_file; 
    2516 
    26 /* 
    27  * Hack -- force definitions -- see fd_lock()  XXX 
    28  */ 
    29 #ifndef F_UNLCK 
    30 # define F_UNLCK    0 
    31 #endif 
    32 #ifndef F_RDLCK 
    33 # define F_RDLCK    1 
    34 #endif 
    35 #ifndef F_WRLCK 
    36 # define F_WRLCK    2 
    37 #endif 
     17typedef enum 
     18{ 
     19        MODE_WRITE, 
     20        MODE_READ, 
     21        MODE_APPEND, 
     22} file_mode; 
    3823 
     24typedef enum 
     25{ 
     26        FTYPE_TEXT = 1, /* -> FILE_TYPE_TEXT */ 
     27        FTYPE_SAVE, 
     28        FTYPE_RAW,              /* -> FILE_TYPE_DATA */ 
     29        FTYPE_HTML 
     30} file_type; 
    3931 
    40 /*** Functions provided in the package ***/ 
     32bool file_exists(const char *fname); 
     33bool file_delete(const char *fname); 
     34bool file_move(const char *fname, const char *newname); 
     35bool file_newer(const char *first, const char *second); 
    4136 
    42 extern errr path_parse(char *buf, size_t max, cptr file); 
    43 extern errr path_build(char *buf, size_t max, cptr path, cptr file); 
    44 extern FILE *my_fopen(cptr file, cptr mode); 
    45 extern FILE *my_fopen_temp(char *buf, size_t max); 
    46 extern errr my_fclose(FILE *fff); 
    47 extern errr my_fgets(FILE *fff, char *buf, size_t n); 
    48 extern errr my_fputs(FILE *fff, cptr buf, size_t n); 
    49 extern bool my_fexists(const char *fname); 
    50 extern errr fd_kill(cptr file); 
    51 extern errr fd_move(cptr file, cptr what); 
    52 extern int fd_make(cptr file, int mode); 
    53 extern int fd_open(cptr file, int flags); 
    54 extern errr fd_lock(int fd, int what); 
    55 extern errr fd_seek(int fd, long n); 
    56 extern errr fd_read(int fd, char *buf, size_t n); 
    57 extern errr fd_write(int fd, cptr buf, size_t n); 
    58 extern errr fd_close(int fd); 
    59 extern errr check_modification_date(int fd, cptr template_file); 
     37ang_file *file_open(const char *buf, file_mode mode, file_type ftype); 
     38ang_file *file_temp(); 
     39bool file_close(ang_file *f); 
    6040 
     41void file_lock(ang_file *f); 
     42void file_unlock(ang_file *f); 
    6143 
     44bool file_getl(ang_file *f, char *buf, size_t n); 
     45bool file_put(ang_file *f, const char *buf); 
     46bool file_putf(ang_file *f, const char *fmt, ...); 
     47 
     48bool file_seek(ang_file *f, u32b pos); 
     49size_t file_read(ang_file *f, char *buf, size_t n); 
     50bool file_write(ang_file *f, const char *buf, size_t n); 
     51bool file_readc(ang_file *f, byte *b); 
     52bool file_writec(ang_file *f, byte b); 
     53 
     54 
     55 
     56/* Directory code */ 
    6257typedef struct ang_dir ang_dir; 
    6358 
    6459ang_dir *my_dopen(const char *dirname); 
    6560bool my_dread(ang_dir *dir, char *fname, size_t len); 
    6661void my_dclose(ang_dir *dir); 
    6762 
    68  
    6963#endif 
  • dungeon.c

     
    19131913        } 
    19141914         
    19151915        /* Check if we're overwriting a savefile */ 
    1916         while (!reusing_savefile && my_fexists(savefile)) 
     1916        while (!reusing_savefile && file_exists(savefile)) 
    19171917        { 
    19181918                /* Ask for confirmation */ 
    19191919                bool overwrite = get_check("Continuing will overwrite an existing savefile.  Overwrite? "); 
  • files.c

     
    854854 */ 
    855855static errr process_pref_file_aux(cptr name) 
    856856{ 
    857         FILE *fp; 
     857        ang_file *fp; 
    858858 
    859859        char buf[1024]; 
    860  
    861860        char old[1024]; 
    862861 
    863862        int line = -1; 
     
    868867 
    869868 
    870869        /* Open the file */ 
    871         fp = my_fopen(name, "r"); 
    872  
    873         /* No such file */ 
     870        fp = file_open(name, MODE_READ, -1); 
    874871        if (!fp) return (-1); 
    875872 
    876873 
    877874        /* Process the file */ 
    878         while (0 == my_fgets(fp, buf, sizeof(buf))) 
     875        while (file_getl(fp, buf, sizeof(buf))) 
    879876        { 
    880877                /* Count lines */ 
    881878                line++; 
     
    885882                if (!buf[0]) continue; 
    886883 
    887884                /* Skip "blank" lines */ 
    888                 if (isspace((unsigned char)buf[0])) continue; 
     885                if (isspace((unsigned char) buf[0])) continue; 
    889886 
    890887                /* Skip comments */ 
    891888                if (buf[0] == '#') continue; 
     
    949946        } 
    950947 
    951948        /* Close the file */ 
    952         my_fclose(fp); 
     949        file_close(fp); 
    953950 
    954951        /* Result */ 
    955952        return (err); 
     
    17431740        byte a; 
    17441741        char c; 
    17451742 
    1746         FILE *fff = NULL; 
     1743        ang_file *fp; 
    17471744 
    17481745        store_type *st_ptr = &store[STORE_HOME]; 
    17491746 
     
    17581755        /* Build the filename */ 
    17591756        path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name); 
    17601757 
    1761         /* File type is "TEXT" */ 
    1762         FILE_TYPE(FILE_TYPE_TEXT); 
    1763  
    17641758        /* Check if the file currently exists */ 
    1765         if (my_fexists(buf)) 
     1759        if (file_exists(buf)) 
    17661760        { 
    17671761                char out_val[160]; 
    17681762 
     
    17741768                        return -1; 
    17751769        } 
    17761770 
    1777  
    17781771        /* Open the file for writing */ 
    1779         fff = my_fopen(buf, "w"); 
     1772        fp = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
     1773        if (!fp) return (-1); 
    17801774 
    1781         /* Invalid file */ 
    1782         if (!fff) return (-1); 
    17831775 
    1784  
    17851776        text_out_hook = text_out_to_file; 
    1786         text_out_file = fff; 
     1777        text_out_file = fp; 
    17871778 
    17881779        /* Begin dump */ 
    1789         fprintf(fff, "  [%s %s Character Dump]\n\n", 
     1780        file_putf(fp, "  [%s %s Character Dump]\n\n", 
    17901781                VERSION_NAME, VERSION_STRING); 
    17911782 
    17921783 
     
    18131804                buf[x] = '\0'; 
    18141805 
    18151806                /* End the row */ 
    1816                 fprintf(fff, "%s\n", buf); 
     1807                file_putf(fp, "%s\n", buf); 
    18171808        } 
    18181809 
    18191810        /* Skip a line */ 
    1820         fprintf(fff, "\n"); 
     1811        file_putf(fp, "\n"); 
    18211812 
    18221813        /* Display player */ 
    18231814        display_player(1); 
     
    18421833                buf[x] = '\0'; 
    18431834 
    18441835                /* End the row */ 
    1845                 fprintf(fff, "%s\n", buf); 
     1836                file_putf(fp, "%s\n", buf); 
    18461837        } 
    18471838 
    18481839        /* Skip a line */ 
    1849         fprintf(fff, "\n"); 
     1840        file_putf(fp, "\n"); 
    18501841 
    18511842        /* Dump part of the screen */ 
    18521843        for (y = 11; y < 20; y++) 
     
    18681859                buf[x] = '\0'; 
    18691860 
    18701861                /* End the row */ 
    1871                 fprintf(fff, "%s\n", buf); 
     1862                file_putf(fp, "%s\n", buf); 
    18721863        } 
    18731864 
    18741865        /* Skip some lines */ 
    1875         fprintf(fff, "\n\n"); 
     1866        file_putf(fp, "\n\n"); 
    18761867 
    18771868 
    18781869        /* If dead, dump last messages -- Prfnoff */ 
     
    18801871        { 
    18811872                i = message_num(); 
    18821873                if (i > 15) i = 15; 
    1883                 fprintf(fff, "  [Last Messages]\n\n"); 
     1874                file_putf(fp, "  [Last Messages]\n\n"); 
    18841875                while (i-- > 0) 
    18851876                { 
    1886                         fprintf(fff, "> %s\n", message_str((s16b)i)); 
     1877                        file_putf(fp, "> %s\n", message_str((s16b)i)); 
    18871878                } 
    1888                 fprintf(fff, "\n\n"); 
     1879                file_putf(fp, "\n\n"); 
    18891880        } 
    18901881 
    18911882        /* Dump the equipment */ 
    18921883        if (p_ptr->equip_cnt) 
    18931884        { 
    1894                 fprintf(fff, "  [Character Equipment]\n\n"); 
     1885                file_putf(fp, "  [Character Equipment]\n\n"); 
    18951886                for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) 
    18961887                { 
    18971888                        object_desc(o_name, sizeof(o_name), &inventory[i], TRUE, 3); 
    1898                         fprintf(fff, "%c) %s\n", 
     1889                        file_putf(fp, "%c) %s\n", 
    18991890                                index_to_label(i), o_name); 
    19001891 
    19011892                        /* Describe random object attributes */ 
    19021893                        identify_random_gen(&inventory[i]); 
    19031894                } 
    1904                 fprintf(fff, "\n\n"); 
     1895                file_putf(fp, "\n\n"); 
    19051896        } 
    19061897 
    19071898        /* Dump the inventory */ 
    1908         fprintf(fff, "  [Character Inventory]\n\n"); 
     1899        file_putf(fp, "  [Character Inventory]\n\n"); 
    19091900        for (i = 0; i < INVEN_PACK; i++) 
    19101901        { 
    19111902                if (!inventory[i].k_idx) break; 
    19121903 
    19131904                object_desc(o_name, sizeof(o_name), &inventory[i], TRUE, 3); 
    1914                 fprintf(fff, "%c) %s\n", 
     1905                file_putf(fp, "%c) %s\n", 
    19151906                        index_to_label(i), o_name); 
    19161907 
    19171908                /* Describe random object attributes */ 
    19181909                identify_random_gen(&inventory[i]); 
    19191910        } 
    1920         fprintf(fff, "\n\n"); 
     1911        file_putf(fp, "\n\n"); 
    19211912 
    19221913 
    19231914        /* Dump the Home -- if anything there */ 
    19241915        if (st_ptr->stock_num) 
    19251916        { 
    19261917                /* Header */ 
    1927                 fprintf(fff, "  [Home Inventory]\n\n"); 
     1918                file_putf(fp, "  [Home Inventory]\n\n"); 
    19281919 
    19291920                /* Dump all available items */ 
    19301921                for (i = 0; i < st_ptr->stock_num; i++) 
    19311922                { 
    19321923                        object_desc(o_name, sizeof(o_name), &st_ptr->stock[i], TRUE, 3); 
    1933                         fprintf(fff, "%c) %s\n", I2A(i), o_name); 
     1924                        file_putf(fp, "%c) %s\n", I2A(i), o_name); 
    19341925 
    19351926                        /* Describe random object attributes */ 
    19361927                        identify_random_gen(&st_ptr->stock[i]); 
    19371928                } 
    19381929 
    19391930                /* Add an empty line */ 
    1940                 fprintf(fff, "\n\n"); 
     1931                file_putf(fp, "\n\n"); 
    19411932        } 
    19421933 
    19431934 
    19441935        /* Dump options */ 
    1945         fprintf(fff, "  [Options]\n\n"); 
     1936        file_putf(fp, "  [Options]\n\n"); 
    19461937 
    19471938        /* Dump options */ 
    19481939        for (i = OPT_ADULT; i < OPT_MAX; i++) 
    19491940        { 
    19501941                if (option_name(i)) 
    19511942                { 
    1952                         fprintf(fff, "%-45s: %s (%s)\n", 
     1943                        file_putf(fp, "%-45s: %s (%s)\n", 
    19531944                                option_desc(i), 
    19541945                                op_ptr->opt[i] ? "yes" : "no ", 
    19551946                                option_name(i)); 
     
    19571948        } 
    19581949 
    19591950        /* Skip some lines */ 
    1960         fprintf(fff, "\n\n"); 
     1951        file_putf(fp, "\n\n"); 
    19611952 
     1953        file_close(fp); 
    19621954 
    1963         /* Close it */ 
    1964         my_fclose(fff); 
    19651955 
    1966  
    19671956        /* Success */ 
    19681957        return (0); 
    19691958} 
     
    20212010        bool case_sensitive = FALSE; 
    20222011 
    20232012        /* Current help file */ 
    2024         FILE *fff = NULL; 
     2013        ang_file *fff = NULL; 
    20252014 
    20262015        /* Find this string (if any) */ 
    20272016        char *find = NULL; 
     
    20862075        /* Hack XXX XXX XXX */ 
    20872076        if (what) 
    20882077        { 
    2089                 /* Caption */ 
    20902078                my_strcpy(caption, what, sizeof(caption)); 
    20912079 
    2092                 /* Get the filename */ 
    20932080                my_strcpy(path, name, sizeof(path)); 
    2094  
    2095                 /* Open */ 
    2096                 fff = my_fopen(path, "r"); 
     2081                fff = file_open(path, MODE_READ, -1); 
    20972082        } 
    20982083 
    20992084        /* Look in "help" */ 
    21002085        if (!fff) 
    21012086        { 
    2102                 /* Caption */ 
    21032087                strnfmt(caption, sizeof(caption), "Help file '%s'", name); 
    21042088 
    2105                 /* Build the filename */ 
    21062089                path_build(path, sizeof(path), ANGBAND_DIR_HELP, name); 
    2107  
    2108                 /* Open the file */ 
    2109                 fff = my_fopen(path, "r"); 
     2090                fff = file_open(path, MODE_READ, -1); 
    21102091        } 
    21112092 
    21122093        /* Look in "info" */ 
    21132094        if (!fff) 
    21142095        { 
    2115                 /* Caption */ 
    21162096                strnfmt(caption, sizeof(caption), "Info file '%s'", name); 
    21172097 
    2118                 /* Build the filename */ 
    21192098                path_build(path, sizeof(path), ANGBAND_DIR_INFO, name); 
    2120  
    2121                 /* Open the file */ 
    2122                 fff = my_fopen(path, "r"); 
     2099                fff = file_open(path, MODE_READ, -1); 
    21232100        } 
    21242101 
    21252102        /* Oops */ 
     
    21382115        while (TRUE) 
    21392116        { 
    21402117                /* Read a line or stop */ 
    2141                 if (my_fgets(fff, buf, sizeof(buf))) break; 
     2118                if (!file_getl(fff, buf, sizeof(buf))) break; 
    21422119 
    21432120                /* XXX Parse "menu" items */ 
    21442121                if (prefix(buf, "***** ")) 
     
    22052182                if (next > line) 
    22062183                { 
    22072184                        /* Close it */ 
    2208                         my_fclose(fff); 
     2185                        file_close(fff); 
    22092186 
    22102187                        /* Hack -- Re-Open the file */ 
    2211                         fff = my_fopen(path, "r"); 
    2212  
    2213                         /* Oops */ 
     2188                        fff = file_open(path, MODE_READ, -1); 
    22142189                        if (!fff) return (TRUE); 
    22152190 
    22162191                        /* File has been restarted */ 
     
    22222197                while (next < line) 
    22232198                { 
    22242199                        /* Get a line */ 
    2225                         if (my_fgets(fff, buf, sizeof(buf))) break; 
     2200                        if (!file_getl(fff, buf, sizeof(buf))) break; 
    22262201 
    22272202                        /* Skip tags/links */ 
    22282203                        if (prefix(buf, "***** ")) continue; 
     
    22392214                        if (!i) line = next; 
    22402215 
    22412216                        /* Get a line of the file or stop */ 
    2242                         if (my_fgets(fff, buf, sizeof(buf))) break; 
     2217                        if (!file_getl(fff, buf, sizeof(buf))) break; 
    22432218 
    22442219                        /* Hack -- skip "special" lines */ 
    22452220                        if (prefix(buf, "***** ")) continue; 
     
    24412416        } 
    24422417 
    24432418        /* Close the file */ 
    2444         my_fclose(fff); 
     2419        file_close(fff); 
    24452420 
    24462421        /* Done */ 
    24472422        return (ch != '?'); 
     
    27462721 
    27472722        char buf[1024]; 
    27482723 
    2749         FILE *fp; 
     2724        ang_file *fp; 
    27502725 
    27512726 
    27522727        /* Clear screen */ 
    27532728        Term_clear(); 
    27542729 
    2755         /* Build the filename */ 
     2730        /* Open the death file */ 
    27562731        path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, "dead.txt"); 
     2732        fp = file_open(buf, MODE_READ, -1); 
    27572733 
    2758         /* Open the News file */ 
    2759         fp = my_fopen(buf, "r"); 
    2760  
    27612734        /* Dump */ 
    27622735        if (fp) 
    27632736        { 
    27642737                int i = 0; 
    27652738 
    27662739                /* Dump the file to the screen */ 
    2767                 while (0 == my_fgets(fp, buf, sizeof(buf))) 
    2768                 { 
    2769                         /* Display and advance */ 
     2740                while (file_getl(fp, buf, sizeof(buf))) 
    27702741                        put_str(buf, i++, 0); 
    2771                 } 
    27722742 
    2773                 /* Close */ 
    2774                 my_fclose(fp); 
     2743                file_close(fp); 
    27752744        } 
    27762745 
    27772746 
     
    30052974 
    30062975 
    30072976 
    3008 /* 
    3009  * The "highscore" file descriptor, if available. 
    3010  */ 
    3011 static int highscore_fd = -1; 
    30122977 
    3013  
    30142978/* 
    30152979 * Seek score 'i' in the highscore file 
    30162980 */ 
    3017 static int highscore_seek(int i) 
     2981static bool highscore_seek(ang_file *f, int i) 
    30182982{ 
    30192983        /* Seek for the requested record */ 
    3020         return (fd_seek(highscore_fd, i * sizeof(high_score))); 
     2984        return (file_seek(f, i * sizeof(high_score))); 
    30212985} 
    30222986 
    30232987 
    30242988/* 
    30252989 * Read one score from the highscore file 
    30262990 */ 
    3027 static errr highscore_read(high_score *score) 
     2991static bool highscore_read(ang_file *f, high_score *score) 
    30282992{ 
    30292993        /* Read the record, note failure */ 
    3030         return (fd_read(highscore_fd, (char*)(score), sizeof(high_score))); 
     2994        return (file_read(f, (char *)score, sizeof(high_score)) > 0); 
    30312995} 
    30322996 
    3033  
    30342997/* 
    3035  * Write one score to the highscore file 
    3036  */ 
    3037 static int highscore_write(const high_score *score) 
    3038 { 
    3039         /* Write the record, note failure */ 
    3040         return (fd_write(highscore_fd, (cptr)(score), sizeof(high_score))); 
    3041 } 
    3042  
    3043  
    3044  
    3045  
    3046 /* 
    30472998 * Just determine where a new score *would* be placed 
    30482999 * Return the location (0 is best) or -1 on failure 
    30493000 */ 
    3050 static int highscore_where(const high_score *score) 
     3001static int highscore_where(ang_file *f, const high_score *score) 
    30513002{ 
    30523003        int i; 
    3053  
    30543004        high_score the_score; 
    30553005 
    3056         /* Paranoia -- it may not have opened */ 
    3057         if (highscore_fd < 0) return (-1); 
    3058  
    30593006        /* Go to the start of the highscore file */ 
    3060         if (highscore_seek(0)) return (-1); 
     3007        if (!highscore_seek(f, 0)) return (-1); 
    30613008 
    30623009        /* Read until we get to a higher score */ 
    30633010        for (i = 0; i < MAX_HISCORES; i++) 
    30643011        { 
    3065                 if (highscore_read(&the_score)) return (i); 
     3012                if (!highscore_read(f, &the_score)) return (i); 
    30663013                if (strcmp(the_score.pts, score->pts) < 0) return (i); 
    30673014        } 
    30683015 
     
    30703017        return (MAX_HISCORES - 1); 
    30713018} 
    30723019 
    3073  
    30743020/* 
    30753021 * Actually place an entry into the high score file 
    30763022 * Return the location (0 is best) or -1 on "failure" 
     
    30783024static int highscore_add(const high_score *score) 
    30793025{ 
    30803026        int i, slot; 
    3081         bool done = FALSE; 
     3027        bool error = FALSE; 
    30823028 
    3083         high_score the_score, tmpscore; 
     3029        high_score tmpscore; 
    30843030 
     3031        ang_file *old, *new, *lok; 
     3032        char cur_name[1024]; 
     3033        char old_name[1024]; 
     3034        char new_name[1024]; 
     3035        char lok_name[1024]; 
    30853036 
    3086         /* Paranoia -- it may not have opened */ 
    3087         if (highscore_fd < 0) return (-1); 
     3037        path_build(cur_name, sizeof(cur_name), ANGBAND_DIR_APEX, "scores.raw"); 
     3038        path_build(old_name, sizeof(old_name), ANGBAND_DIR_APEX, "scores.old"); 
     3039        path_build(new_name, sizeof(new_name), ANGBAND_DIR_APEX, "scores.new"); 
     3040        path_build(lok_name, sizeof(lok_name), ANGBAND_DIR_APEX, "scores.lok"); 
    30883041 
    3089         /* Determine where the score should go */ 
    3090         slot = highscore_where(score); 
    30913042 
    3092         /* Hack -- Not on the list */ 
    3093         if (slot < 0) return (-1); 
     3043        old = file_open(cur_name, MODE_READ, -1); 
    30943044 
    3095         /* Hack -- prepare to dump the new score */ 
    3096         the_score = (*score); 
     3045        safe_setuid_grab(); 
     3046        new = file_open(new_name, MODE_WRITE, FTYPE_RAW); 
     3047        lok = file_open(lok_name, MODE_WRITE, FTYPE_RAW); 
     3048        file_lock(lok); 
     3049        safe_setuid_drop(); 
    30973050 
    3098         /* Slide all the scores down one */ 
    3099         for (i = slot; !done && (i < MAX_HISCORES); i++) 
     3051 
     3052        /* Determine where the score should go */ 
     3053        slot = highscore_where(old, score); 
     3054 
     3055        /* Read entries from the old and write them to the new */ 
     3056        for (i = 0; (i < MAX_HISCORES) && !error; i++) 
    31003057        { 
    3101                 /* Read the old guy, note errors */ 
    3102                 if (highscore_seek(i)) return (-1); 
    3103                 if (highscore_read(&tmpscore)) done = TRUE; 
     3058                if (!highscore_seek(old, i)) return (-1); 
    31043059 
    3105                 /* Back up and dump the score we were holding */ 
    3106                 if (highscore_seek(i)) return (-1); 
    3107                 if (highscore_write(&the_score)) return (-1); 
     3060                /* Insert the new one at the right slot */ 
     3061                if (i == slot) 
     3062                { 
     3063                        if (!file_write(new, (const char *)score, sizeof(high_score))) 
     3064                        { 
     3065                                error = TRUE; 
     3066                                slot = -1; 
     3067                        } 
     3068                } 
    31083069 
    3109                 /* Hack -- Save the old score, for the next pass */ 
    3110                 the_score = tmpscore; 
     3070                /* Read old one, write again */ 
     3071                if (highscore_read(old, &tmpscore)) 
     3072                { 
     3073                        if (!file_write(new, (const char *)&tmpscore, sizeof(high_score))) 
     3074                        { 
     3075                                error = TRUE; 
     3076                                slot = -1; 
     3077                        } 
     3078                } 
    31113079        } 
    31123080 
     3081        file_close(new); 
     3082        file_close(old); 
     3083 
     3084        /* Move things around */ 
     3085        safe_setuid_grab(); 
     3086 
     3087        file_delete(old_name); 
     3088 
     3089        file_move(cur_name, old_name); 
     3090        file_move(new_name, cur_name); 
     3091        file_delete(old_name); 
     3092 
     3093        file_close(lok); 
     3094        safe_setuid_drop(); 
     3095 
    31133096        /* Return location used */ 
    31143097        return (slot); 
    31153098} 
     
    31373120 
    31383121        byte attr; 
    31393122 
     3123        ang_file *f; 
     3124        char buf[1024]; 
    31403125 
    3141         /* Paranoia -- it may not have opened */ 
    3142         if (highscore_fd < 0) return; 
    31433126 
     3127        path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); 
     3128        f = file_open(buf, MODE_READ, -1); 
     3129        if (!f) return; 
    31443130 
     3131 
    31453132        /* Assume we will show the first 10 */ 
    31463133        if (from < 0) from = 0; 
    31473134        if (to < 0) to = 10; 
    31483135        if (to > MAX_HISCORES) to = MAX_HISCORES; 
    31493136 
    31503137 
    3151         /* Seek to the beginning */ 
    3152         if (highscore_seek(0)) return; 
    3153  
    31543138        /* Hack -- Count the high scores */ 
    31553139        for (count = 0; count < MAX_HISCORES; count++) 
    31563140        { 
    3157                 if (highscore_read(&the_score)) break; 
     3141                if (!highscore_read(f, &the_score)) break; 
    31583142        } 
    31593143 
    31603144        /* Hack -- allow "fake" entry to be last */ 
     
    31633147        /* Forget about the last entries */ 
    31643148        if (count > to) count = to; 
    31653149 
    3166  
    31673150        /* Show 5 per page, until "done" */ 
    31683151        for (k = from, j = from, place = k+1; k < count; k += 5) 
    31693152        { 
     
    31713154                Term_clear(); 
    31723155 
    31733156                /* Title */ 
    3174                 put_str(format("                %s Hall of Fame", VERSION_NAME), 
    3175                         0, 0); 
     3157                put_str(format("%s Hall of Fame", VERSION_NAME), 18, 0); 
    31763158 
     3159 
    31773160                /* Indicate non-top scores */ 
    31783161                if (k > 0) 
    31793162                { 
     
    32073190                        else 
    32083191                        { 
    32093192                                /* Read the proper record */ 
    3210                                 if (highscore_seek(j)) break; 
    3211                                 if (highscore_read(&the_score)) break; 
     3193                                if (!highscore_seek(f, j)) break; 
     3194                                if (!highscore_read(f, &the_score)) break; 
    32123195                        } 
    32133196 
    32143197                        /* Extract the race/class */ 
     
    32843267                /* Hack -- notice Escape */ 
    32853268                if (ch == ESCAPE) break; 
    32863269        } 
     3270 
     3271        file_close(f); 
     3272        return; 
    32873273} 
    32883274 
    32893275 
     
    32953281 */ 
    32963282void display_scores(int from, int to) 
    32973283{ 
    3298         char buf[1024]; 
    3299  
    3300         /* Build the filename */ 
    3301         path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); 
    3302  
    3303         /* Open the binary high score file, for reading */ 
    3304         highscore_fd = fd_open(buf, O_RDONLY); 
    3305  
    3306         /* Clear screen */ 
    3307         Term_clear(); 
    3308  
    3309         /* Title */ 
    3310         put_str(format("                %s Hall of Fame", VERSION_NAME), 0, 0); 
    3311  
    3312         /* Display the scores */ 
    33133284        display_scores_aux(from, to, -1, NULL); 
    33143285 
    3315         /* Shut the high score file */ 
    3316         fd_close(highscore_fd); 
    3317  
    3318         /* Forget the high score fd */ 
    3319         highscore_fd = -1; 
    3320  
    3321         /* Wait for response */ 
    33223286        prt("[Press any key to exit.]", 23, 17); 
    33233287        (void)inkey(); 
    3324         prt("", 23, 0); 
    33253288 
    3326         /* Quit */ 
    33273289        quit(NULL); 
    33283290} 
    33293291 
     
    33423304static errr enter_score(void) 
    33433305{ 
    33443306        int j; 
    3345  
    33463307        high_score the_score; 
    33473308 
    3348  
    3349         /* No score file */ 
    3350         if (highscore_fd < 0) 
    3351         { 
    3352                 return (0); 
    3353         } 
    3354  
    33553309        /* Wizard-mode pre-empts scoring */ 
    33563310        if (p_ptr->noscore & NOSCORE_WIZARD) 
    33573311        { 
     
    34423396        /* Save the cause of death (31 chars) */ 
    34433397        strnfmt(the_score.how, sizeof(the_score.how), "%-.31s", p_ptr->died_from); 
    34443398 
    3445         /* Grab permissions */ 
    3446         safe_setuid_grab(); 
    3447  
    3448         /* Lock (for writing) the highscore file, or fail */ 
    3449         if (fd_lock(highscore_fd, F_WRLCK)) return (1); 
    3450  
    3451         /* Drop permissions */ 
    3452         safe_setuid_drop(); 
    3453  
    34543399        /* Add a new entry to the score list, see where it went */ 
    34553400        score_idx = highscore_add(&the_score); 
    34563401 
    3457         /* Grab permissions */ 
    3458         safe_setuid_grab(); 
    3459  
    3460         /* Unlock the highscore file, or fail */ 
    3461         if (fd_lock(highscore_fd, F_UNLCK)) return (1); 
    3462  
    3463         /* Drop permissions */ 
    3464         safe_setuid_drop(); 
    3465  
    34663402        /* Success */ 
    34673403        return (0); 
    34683404} 
     
    34753411 * 
    34763412 * Assumes "signals_ignore_tstp()" has been called. 
    34773413 */ 
    3478 static void top_twenty(void) 
     3414static void top_twenty() 
    34793415{ 
    34803416        /* Clear screen */ 
    34813417        Term_clear(); 
    34823418 
    3483         /* No score file */ 
    3484         if (highscore_fd < 0) 
    3485         { 
    3486                 msg_print("Score file unavailable."); 
    3487                 message_flush(); 
    3488                 return; 
    3489         } 
    3490  
    34913419        /* Player's score unavailable */ 
    34923420        if (score_idx == -1) 
    3493         { 
    34943421                display_scores_aux(0, 10, -1, NULL); 
    3495                 return; 
    3496         } 
    34973422 
    34983423        /* Hack -- Display the top fifteen scores */ 
    34993424        else if (score_idx < 10) 
    3500         { 
    35013425                display_scores_aux(0, 15, score_idx, NULL); 
    3502         } 
    35033426 
    35043427        /* Display the scores surrounding the player */ 
    35053428        else 
     
    35073430                display_scores_aux(0, 5, score_idx, NULL); 
    35083431                display_scores_aux(score_idx - 2, score_idx + 7, score_idx, NULL); 
    35093432        } 
    3510  
    3511  
    3512         /* Success */ 
    3513         return; 
    35143433} 
    35153434 
    35163435 
     
    35193438 */ 
    35203439static errr predict_score(void) 
    35213440{ 
    3522         int j; 
     3441        ang_file *f; 
     3442        char buf[1024]; 
    35233443 
     3444        int j; 
    35243445        high_score the_score; 
    35253446 
    3526  
    3527         /* No score file */ 
    3528         if (highscore_fd < 0) 
    3529         { 
    3530                 msg_print("Score file unavailable."); 
    3531                 message_flush(); 
    3532                 return (0); 
    3533         } 
    3534  
    3535  
    35363447        /* Save the version */ 
    35373448        strnfmt(the_score.what, sizeof(the_score.what), "%s", VERSION_STRING); 
    35383449 
     
    35673478        my_strcpy(the_score.how, "nobody (yet!)", sizeof(the_score.how)); 
    35683479 
    35693480 
     3481 
     3482        /* Open the highscore file */ 
     3483        path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); 
     3484        f = file_open(buf, MODE_READ, -1); 
     3485        if (!f) return -1; 
     3486 
    35703487        /* See where the entry would be placed */ 
    3571         j = highscore_where(&the_score); 
     3488        j = highscore_where(f, &the_score); 
    35723489 
     3490        file_close(f); 
    35733491 
     3492 
    35743493        /* Hack -- Display the top fifteen scores */ 
    35753494        if (j < 10) 
    35763495        { 
     
    35923511 
    35933512void show_scores(void) 
    35943513{ 
    3595         char buf[1024]; 
     3514        screen_save(); 
    35963515 
    3597         /* Build the filename */ 
    3598         path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); 
    3599  
    3600         /* Open the binary high score file, for reading */ 
    3601         highscore_fd = fd_open(buf, O_RDONLY); 
    3602  
    3603         /* Paranoia -- No score file */ 
    3604         if (highscore_fd < 0) 
    3605         { 
    3606                 msg_print("Score file unavailable."); 
    3607         } 
     3516        /* Display the scores */ 
     3517        if (character_generated) 
     3518                predict_score(); 
    36083519        else 
    3609         { 
    3610                 /* Save Screen */ 
    3611                 screen_save(); 
     3520                display_scores_aux(0, MAX_HISCORES, -1, NULL); 
    36123521 
    3613                 /* Clear screen */ 
    3614                 Term_clear(); 
     3522        screen_load(); 
    36153523 
    3616                 /* Display the scores */ 
    3617                 if (character_generated) 
    3618                         predict_score(); 
    3619                 else 
    3620                         display_scores_aux(0, MAX_HISCORES, -1, NULL); 
    3621  
    3622                 /* Shut the high score file */ 
    3623                 (void)fd_close(highscore_fd); 
    3624  
    3625                 /* Forget the high score fd */ 
    3626                 highscore_fd = -1; 
    3627  
    3628                 /* Load screen */ 
    3629                 screen_load(); 
    3630  
    3631                 /* Hack - Flush it */ 
    3632                 Term_fresh(); 
    3633         } 
     3524        /* Hack - Flush it */ 
     3525        Term_fresh(); 
    36343526} 
    36353527 
    36363528 
     
    38723764 */ 
    38733765void close_game(void) 
    38743766{ 
    3875         char buf[1024]; 
    3876  
    3877  
    38783767        /* Handle stuff */ 
    38793768        handle_stuff(); 
    38803769 
     
    38933782        character_icky++; 
    38943783 
    38953784 
    3896         /* Build the filename */ 
    3897         path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); 
    3898  
    3899         /* Grab permissions */ 
    3900         safe_setuid_grab(); 
    3901  
    3902         /* Open the high score file, for reading/writing */ 
    3903         highscore_fd = fd_open(buf, O_RDWR); 
    3904  
    3905         /* Drop permissions */ 
    3906         safe_setuid_drop(); 
    3907  
    39083785        /* Handle death */ 
    39093786        if (p_ptr->is_dead) 
    39103787        { 
     
    39183795                /* Save the game */ 
    39193796                do_cmd_save_game(); 
    39203797 
    3921                 if(Term->mapped_flag) { 
     3798                if (Term->mapped_flag) 
     3799                { 
    39223800                        /* Prompt for scores XXX XXX XXX */ 
    39233801                        prt("Press Return (or Escape).", 0, 40); 
    39243802 
     
    39283806        } 
    39293807 
    39303808 
    3931         /* Shut the high score file */ 
    3932         fd_close(highscore_fd); 
    3933  
    3934         /* Forget the high score fd */ 
    3935         highscore_fd = -1; 
    3936  
    3937  
    39383809        /* Hack -- Decrease "icky" depth */ 
    39393810        character_icky--; 
    39403811 
     
    39893860 
    39903861 
    39913862 
    3992 static void write_html_escape_char(FILE *htm, char c) 
     3863static void write_html_escape_char(ang_file *fp, char c) 
    39933864{ 
    39943865        switch (c) 
    39953866        { 
    39963867                case '<': 
    3997                         fprintf(htm, "&lt;"); 
     3868                        file_putf(fp, "&lt;"); 
    39983869                        break; 
    39993870                case '>': 
    4000                         fprintf(htm, "&gt;"); 
     3871                        file_putf(fp, "&gt;"); 
    40013872                        break; 
    40023873                case '&': 
    4003                         fprintf(htm, "&amp;"); 
     3874                        file_putf(fp, "&amp;"); 
    40043875                        break; 
    40053876                default: 
    4006                         fprintf(htm, "%c", c); 
     3877                        file_putf(fp, "%c", c); 
    40073878                        break; 
    40083879        } 
    40093880} 
     
    40273898                                        : "[/COLOR][COLOR=\"#%02X%02X%02X\"]"; 
    40283899        const char *close_color_fmt = mode ==  0 ? "</font>" : "[/COLOR]"; 
    40293900 
    4030         FILE *htm; 
    4031  
     3901        ang_file *fp; 
    40323902        char buf[1024]; 
    40333903 
    4034         /* Build the filename */ 
     3904 
    40353905        path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name); 
     3906        fp = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
    40363907 
    4037         /* File type is "TEXT" */ 
    4038         FILE_TYPE(FILE_TYPE_TEXT); 
    4039  
    4040         /* Append to the file */ 
    4041         htm = my_fopen(buf, "w"); 
    4042  
    40433908        /* Oops */ 
    4044         if (!htm) 
     3909        if (!fp) 
    40453910        { 
    40463911                plog_fmt("Cannot write the '%s' file!", buf); 
    40473912                return; 
     
    40503915        /* Retrieve current screen size */ 
    40513916        Term_get_size(&wid, &hgt); 
    40523917 
    4053         if(mode == 0) 
     3918        if (mode == 0) 
    40543919        { 
    4055                 fprintf(htm, "<!DOCTYPE html><html><head>\n"); 
    4056                 fprintf(htm, "  <meta='generator' content='%s %s'>\n", 
     3920                file_putf(fp, "<!DOCTYPE html><html><head>\n"); 
     3921                file_putf(fp, "  <meta='generator' content='%s %s'>\n", 
    40573922                        VERSION_NAME, VERSION_STRING); 
    4058                 fprintf(htm, "  <title>%s</title>\n", name); 
    4059                 fprintf(htm, "</head>\n\n"); 
    4060                 fprintf(htm, "<body style='color: #fff; background: #000;'>\n"); 
    4061                 fprintf(htm, "<pre>\n"); 
     3923                file_putf(fp, "  <title>%s</title>\n", name); 
     3924                file_putf(fp, "</head>\n\n"); 
     3925                file_putf(fp, "<body style='color: #fff; background: #000;'>\n"); 
     3926                file_putf(fp, "<pre>\n"); 
    40623927        } 
    40633928        else  
    40643929        { 
    4065                 fprintf(htm, "[CODE][TT][BC=black][COLOR=white]\n"); 
     3930                file_putf(fp, "[CODE][TT][BC=black][COLOR=white]\n"); 
    40663931        } 
    40673932 
    40683933        /* Dump the screen */ 
     
    40793944                                /* From the default white to another color */ 
    40803945                                if (oa == TERM_WHITE) 
    40813946                                { 
    4082                                         fprintf(htm, new_color_fmt, 
     3947                                        file_putf(fp, new_color_fmt, 
    40833948                                                angband_color_table[a][1], 
    40843949                                                angband_color_table[a][2], 
    40853950                                                angband_color_table[a][3]); 
    40863951                                } 
     3952 
    40873953                                /* From another color to the default white */ 
    40883954                                else if (a == TERM_WHITE) 
    40893955                                { 
    4090                                         fprintf(htm, close_color_fmt); 
     3956                                        file_putf(fp, close_color_fmt); 
    40913957                                } 
     3958 
    40923959                                /* Change colors */ 
    40933960                                else 
    40943961                                { 
    4095                                         fprintf(htm, change_color_fmt, 
     3962                                        file_putf(fp, change_color_fmt, 
    40963963                                                angband_color_table[a][1], 
    40973964                                                angband_color_table[a][2], 
    40983965                                                angband_color_table[a][3]); 
     
    41033970                        } 
    41043971 
    41053972                        /* Write the character and escape special HTML characters */ 
    4106                         if (mode == 0) write_html_escape_char(htm, c); 
    4107                         else fprintf(htm, "%c", c); 
     3973                        if (mode == 0) write_html_escape_char(fp, c); 
     3974                        else file_putf(fp, "%c", c); 
    41083975                } 
    41093976 
    41103977                /* End the row */ 
    4111                 fprintf(htm, "\n"); 
     3978                file_putf(fp, "\n"); 
    41123979        } 
    41133980 
    41143981        /* Close the last font-color tag if necessary */ 
    4115         if (oa != TERM_WHITE) fprintf(htm, close_color_fmt); 
     3982        if (oa != TERM_WHITE) file_putf(fp, close_color_fmt); 
    41163983 
    41173984        if (mode == 0) 
    41183985        { 
    4119                 fprintf(htm, "</pre>\n"); 
    4120                 fprintf(htm, "</body>\n"); 
    4121                 fprintf(htm, "</html>\n"); 
     3986                file_putf(fp, "</pre>\n"); 
     3987                file_putf(fp, "</body>\n"); 
     3988                file_putf(fp, "</html>\n"); 
    41223989        } 
    41233990        else  
    41243991        { 
    4125                 fprintf(htm, "[/COLOR][/BC][/TT][/CODE]\n"); 
     3992                file_putf(fp, "[/COLOR][/BC][/TT][/CODE]\n"); 
    41263993        } 
    41273994 
    41283995        /* Close it */ 
    4129         my_fclose(htm); 
     3996        file_close(fp); 
    41303997} 
  • init2.c

     
    7474{ 
    7575#ifdef PRIVATE_USER_PATH 
    7676        char buf[1024]; 
    77         char dirpath[1024]; 
    7877#endif /* PRIVATE_USER_PATH */ 
    7978 
    8079        /*** Free everything ***/ 
     
    112111 
    113112#ifdef PRIVATE_USER_PATH 
    114113 
    115         /* Get an absolute path from the filename, */ 
    116         path_parse(dirpath, sizeof(dirpath), PRIVATE_USER_PATH); 
    117  
    118114        /* Build the path to the user specific directory */ 
    119         path_build(buf, sizeof(buf), dirpath, VERSION_NAME); 
     115        path_build(buf, sizeof(buf), PRIVATE_USER_PATH, VERSION_NAME); 
    120116        ANGBAND_DIR_USER = string_make(buf); 
    121117 
    122118#else /* PRIVATE_USER_PATH */ 
     
    171167 
    172168 
    173169        /* Get an absolute path from the filename */ 
    174         path_parse(dirpath, sizeof(dirpath), PRIVATE_USER_PATH); 
     170        path_build(dirpath, sizeof(dirpath), PRIVATE_USER_PATH, ""); 
    175171 
    176172        /* Create the ~/.angband/ directory */ 
    177173        mkdir(dirpath, 0700); 
     
    276272/* 
    277273 * Initialize a "*_info" array, by parsing a binary "image" file 
    278274 */ 
    279 static errr init_info_raw(int fd, header *head) 
     275static bool init_info_raw(const char *fname, header *head) 
    280276{ 
    281277        header test; 
     278        ang_file *fh = file_open(fname, MODE_READ, -1); 
    282279 
     280        if (!fh) return FALSE; 
    283281 
    284282        /* Read and verify the header */ 
    285         if (fd_read(fd, (char*)(&test), sizeof(header)) || 
     283        if (!file_read(fh, (char *)(&test), sizeof(header)) || 
    286284            (test.v_major != head->v_major) || 
    287285            (test.v_minor != head->v_minor) || 
    288286            (test.v_patch != head->v_patch) || 
     
    292290            (test.head_size != head->head_size) || 
    293291            (test.info_size != head->info_size)) 
    294292        { 
    295                 /* Error */ 
    296                 return (-1); 
     293                file_close(fh); 
     294                return FALSE; 
    297295        } 
    298296 
    299297 
     
    303301 
    304302        /* Allocate and read the "*_info" array */ 
    305303        head->info_ptr = C_RNEW(head->info_size, char); 
    306         fd_read(fd, head->info_ptr, head->info_size); 
     304        file_read(fh, head->info_ptr, head->info_size); 
    307305 
    308306        if (head->name_size) 
    309307        { 
    310308                /* Allocate and read the "*_name" array */ 
    311309                head->name_ptr = C_RNEW(head->name_size, char); 
    312                 fd_read(fd, head->name_ptr, head->name_size); 
     310                file_read(fh, head->name_ptr, head->name_size); 
    313311        } 
    314312 
    315313        if (head->text_size) 
    316314        { 
    317315                /* Allocate and read the "*_text" array */ 
    318316                head->text_ptr = C_RNEW(head->text_size, char); 
    319                 fd_read(fd, head->text_ptr, head->text_size); 
     317                file_read(fh, head->text_ptr, head->text_size); 
    320318        } 
    321319 
    322         /* Success */ 
    323         return (0); 
     320        file_close(fh); 
     321        return TRUE; 
    324322} 
    325323 
    326324 
     
    385383 */ 
    386384static errr init_info(cptr filename, header *head) 
    387385{ 
    388         int fd; 
     386        ang_file *fh; 
    389387 
    390388        errr err = 1; 
    391389 
    392         FILE *fp; 
     390        char raw_file[1024]; 
     391        char txt_file[1024]; 
    393392 
    394 #ifdef ALLOW_TEMPLATES_OUTPUT 
    395         FILE *fpout; 
    396 #endif /* ALLOW_TEMPLATES_OUTPUT */ 
    397  
    398         /* General buffer */ 
    399393        char buf[1024]; 
    400394 
    401395 
    402 #ifdef ALLOW_TEMPLATES 
     396        /* Build the filenames */ 
     397        path_build(raw_file, sizeof(raw_file), ANGBAND_DIR_DATA, format("%s.raw", filename)); 
     398        path_build(txt_file, sizeof(txt_file), ANGBAND_DIR_EDIT, format("%s.txt", filename)); 
    403399 
    404         /*** Load the binary image file ***/ 
    405400 
    406         /* Build the filename */ 
    407         path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, format("%s.raw", filename)); 
     401#ifdef ALLOW_TEMPLATES 
    408402 
    409         /* Attempt to open the "raw" file */ 
    410         fd = fd_open(buf, O_RDONLY); 
    411  
    412         /* Process existing "raw" file */ 
    413         if (fd >= 0) 
     403        /* If the raw file's more recent than the text file, load it */ 
     404        if (file_newer(raw_file, txt_file) && 
     405            init_info_raw(raw_file, head)) 
    414406        { 
    415 #ifdef CHECK_MODIFICATION_TIME 
     407                return 0; 
     408        } 
    416409 
    417                 err = check_modification_date(fd, format("%s.txt", filename)); 
    418410 
    419 #endif /* CHECK_MODIFICATION_TIME */ 
     411        /*** Make the fake arrays ***/ 
    420412 
    421                 /* Attempt to parse the "raw" file */ 
    422                 if (!err) 
    423                         err = init_info_raw(fd, head); 
     413        /* Allocate the "*_info" array */ 
     414        head->info_ptr = C_ZNEW(head->info_size, char); 
    424415 
    425                 /* Close it */ 
    426                 fd_close(fd); 
     416        /* MegaHack -- make "fake" arrays */ 
     417        if (z_info) 
     418        { 
     419                head->name_ptr = C_ZNEW(z_info->fake_name_size, char); 
     420                head->text_ptr = C_ZNEW(z_info->fake_text_size, char); 
    427421        } 
    428422 
    429         /* Do we have to parse the *.txt file? */ 
    430         if (err) 
    431         { 
    432                 /*** Make the fake arrays ***/ 
    433423 
    434                 /* Allocate the "*_info" array */ 
    435                 head->info_ptr = C_ZNEW(head->info_size, char); 
     424        /*** Load the ascii template file ***/ 
    436425 
    437                 /* MegaHack -- make "fake" arrays */ 
    438                 if (z_info) 
    439                 { 
    440                         head->name_ptr = C_ZNEW(z_info->fake_name_size, char); 
    441                         head->text_ptr = C_ZNEW(z_info->fake_text_size, char); 
    442                 } 
     426        /* Open the file */ 
     427        fh = file_open(txt_file, MODE_READ, -1); 
     428        if (!fh) quit(format("Cannot open '%s.txt' file.", filename)); 
    443429 
     430        /* Parse the file */ 
     431        err = init_info_txt(fh, buf, head, head->parse_info_txt); 
    444432 
    445                 /*** Load the ascii template file ***/ 
     433        file_close(fh); 
    446434 
    447                 /* Build the filename */ 
    448                 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, format("%s.txt", filename)); 
     435        /* Errors */ 
     436        if (err) display_parse_error(filename, err, buf); 
    449437 
    450                 /* Open the file */ 
    451                 fp = my_fopen(buf, "r"); 
     438        /* Post processing the data */ 
     439        if (head->eval_info_power) eval_info(head->eval_info_power, head); 
    452440 
    453                 /* Parse it */ 
    454                 if (!fp) quit(format("Cannot open '%s.txt' file.", filename)); 
    455  
    456                 /* Parse the file */ 
    457                 err = init_info_txt(fp, buf, head, head->parse_info_txt); 
    458  
    459                 /* Close it */ 
    460                 my_fclose(fp); 
    461  
    462                 /* Errors */ 
    463                 if (err) display_parse_error(filename, err, buf); 
    464  
    465                 /* Post processing the data */ 
    466                 if (head->eval_info_power) eval_info(head->eval_info_power, head); 
    467  
    468441#ifdef ALLOW_TEMPLATES_OUTPUT 
    469442 
    470                 /*** Output a 'parsable' ascii template file ***/ 
    471                 if ((head->emit_info_txt_index) || (head->emit_info_txt_always)) 
    472                 { 
    473                         /* Build the filename */ 
    474                         path_build(buf, 1024, ANGBAND_DIR_EDIT, format("%s.txt", filename)); 
     443        /*** Output a 'parsable' ascii template file ***/ 
     444        if ((head->emit_info_txt_index) || (head->emit_info_txt_always)) 
     445        { 
     446                char user_file[1024]; 
     447                ang_file *fout; 
    475448 
    476                         /* Open the file */ 
    477                         fp = my_fopen(buf, "r"); 
     449                /* Open the original */ 
     450                fh = file_open(txt_file, MODE_READ, -1); 
     451                if (!fh) quit(format("Cannot open '%s.txt' file for re-parsing.", filename)); 
    478452 
    479                         /* Parse it */ 
    480                         if (!fp) quit(format("Cannot open '%s.txt' file for re-parsing.", filename)); 
     453                /* Open for output */ 
     454                path_build(user_file, 1024, ANGBAND_DIR_USER, format("%s.txt", filename)); 
     455                fout = file_open(user_file, MODE_WRITE, FTYPE_TEXT); 
     456                if (!fout) quit(format("Cannot open '%s.txt' file for output.", filename)); 
    481457 
    482                         /* Build the filename */ 
    483                         path_build(buf, 1024, ANGBAND_DIR_USER, format("%s.txt", filename)); 
     458                /* Parse and output the files */ 
     459                err = emit_info_txt(fout, fh, user_file, head, head->emit_info_txt_index, head->emit_info_txt_always); 
    484460 
    485                         /* Open the file */ 
    486                         fpout = my_fopen(buf, "w"); 
     461                /* Close both files */ 
     462                file_close(fh); 
     463                file_close(fout); 
     464        } 
    487465 
    488                         /* Parse it */ 
    489                         if (!fpout) quit(format("Cannot open '%s.txt' file for output.", filename)); 
    490  
    491                         /* Parse and output the files */ 
    492                         err = emit_info_txt(fpout, fp, buf, head, head->emit_info_txt_index, head->emit_info_txt_always); 
    493  
    494                         /* Close both files */ 
    495                         my_fclose(fpout); 
    496                         my_fclose(fp); 
    497                 } 
    498  
    499466#endif 
    500467 
    501468 
    502                 /*** Dump the binary image file ***/ 
     469        /*** Dump the binary image file ***/ 
    503470 
    504                 /* File type is "DATA" */ 
    505                 FILE_TYPE(FILE_TYPE_DATA); 
     471        safe_setuid_grab(); 
     472        fh = file_open(raw_file, MODE_WRITE, FTYPE_RAW); 
     473        safe_setuid_drop(); 
    506474 
    507                 /* Build the filename */ 
    508                 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, format("%s.raw", filename)); 
     475        /* Failure */ 
     476        if (!fh) 
     477        { 
     478                plog_fmt("Cannot write the '%s' file!", raw_file); 
     479                return (0); 
     480        } 
    509481 
     482        /* Dump it */ 
     483        file_write(fh, (const char *) head, head->head_size); 
    510484 
    511                 /* Attempt to open the file */ 
    512                 fd = fd_open(buf, O_RDONLY); 
     485        /* Dump the "*_info" array */ 
     486        if (head->info_size > 0) 
     487                file_write(fh, head->info_ptr, head->info_size); 
    513488 
    514                 /* Failure */ 
    515                 if (fd < 0) 
    516                 { 
    517                         int mode = 0644; 
     489        /* Dump the "*_name" array */ 
     490        if (head->name_size > 0) 
     491                file_write(fh, head->name_ptr, head->name_size); 
    518492 
    519                         /* Grab permissions */ 
    520                         safe_setuid_grab(); 
     493        /* Dump the "*_text" array */ 
     494        if (head->text_size > 0) 
     495                file_write(fh, head->text_ptr, head->text_size); 
    521496 
    522                         /* Create a new file */ 
    523                         fd = fd_make(buf, mode); 
     497        /* Close */ 
     498        file_close(fh); 
    524499 
    525                         /* Drop permissions */ 
    526                         safe_setuid_drop(); 
    527500 
    528                         /* Failure */ 
    529                         if (fd < 0) 
    530                         { 
    531                                 /* Complain */ 
    532                                 plog_fmt("Cannot create the '%s' file!", buf); 
     501        /*** Kill the fake arrays ***/ 
    533502 
    534                                 /* Continue */ 
    535                                 return (0); 
    536                         } 
    537                 } 
     503        /* Free the "*_info" array */ 
     504        FREE(head->info_ptr); 
    538505 
    539                 /* Close it */ 
    540                 fd_close(fd); 
     506        /* MegaHack -- Free the "fake" arrays */ 
     507        if (z_info) 
     508        { 
     509                FREE(head->name_ptr); 
     510                FREE(head->text_ptr); 
     511        } 
    541512 
    542                 /* Grab permissions */ 
    543                 safe_setuid_grab(); 
    544513 
    545                 /* Attempt to create the raw file */ 
    546                 fd = fd_open(buf, O_WRONLY); 
    547  
    548                 /* Drop permissions */ 
    549                 safe_setuid_drop(); 
    550  
    551                 /* Failure */ 
    552                 if (fd < 0) 
    553                 { 
    554                         /* Complain */ 
    555                         plog_fmt("Cannot write the '%s' file!", buf); 
    556  
    557                         /* Continue */ 
    558                         return (0); 
    559                 } 
    560  
    561                 /* Dump to the file */ 
    562                 if (fd >= 0) 
    563                 { 
    564                         /* Dump it */ 
    565                         fd_write(fd, (cptr)head, head->head_size); 
    566  
    567                         /* Dump the "*_info" array */ 
    568                         if (head->info_size > 0) 
    569                                 fd_write(fd, head->info_ptr, head->info_size); 
    570  
    571                         /* Dump the "*_name" array */ 
    572                         if (head->name_size > 0) 
    573                                 fd_write(fd, head->name_ptr, head->name_size); 
    574  
    575                         /* Dump the "*_text" array */ 
    576                         if (head->text_size > 0) 
    577                                 fd_write(fd, head->text_ptr, head->text_size); 
    578  
    579                         /* Close */ 
    580                         fd_close(fd); 
    581                 } 
    582  
    583  
    584                 /*** Kill the fake arrays ***/ 
    585  
    586                 /* Free the "*_info" array */ 
    587                 FREE(head->info_ptr); 
    588  
    589                 /* MegaHack -- Free the "fake" arrays */ 
    590                 if (z_info) 
    591                 { 
    592                         FREE(head->name_ptr); 
    593                         FREE(head->text_ptr); 
    594                 } 
    595  
    596  
    597514#endif /* ALLOW_TEMPLATES */ 
    598515 
    599516 
    600                 /*** Load the binary image file ***/ 
     517        /*** Load the binary image file ***/ 
    601518 
    602                 /* Build the filename */ 
    603                 path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, format("%s.raw", filename)); 
     519        if (!init_info_raw(raw_file, head)) 
     520                quit(format("Cannot load '%s.raw' file.", filename)); 
    604521 
    605                 /* Attempt to open the "raw" file */ 
    606                 fd = fd_open(buf, O_RDONLY); 
    607522 
    608                 /* Process existing "raw" file */ 
    609                 if (fd < 0) quit(format("Cannot load '%s.raw' file.", filename)); 
    610  
    611                 /* Attempt to parse the "raw" file */ 
    612                 err = init_info_raw(fd, head); 
    613  
    614                 /* Close it */ 
    615                 fd_close(fd); 
    616  
    617                 /* Error */ 
    618                 if (err) quit(format("Cannot parse '%s.raw' file.", filename)); 
    619  
    620 #ifdef ALLOW_TEMPLATES 
    621         } 
    622 #endif /* ALLOW_TEMPLATES */ 
    623  
    624523        /* Success */ 
    625524        return (0); 
    626525} 
     
    15281427 */ 
    15291428void init_angband(void) 
    15301429{ 
    1531         int fd; 
     1430        ang_file *fp; 
    15321431 
    1533         int mode = 0644; 
    1534  
    1535         FILE *fp; 
    1536  
    15371432        char buf[1024]; 
    15381433 
    15391434 
    15401435        /*** Verify the "news" file ***/ 
    15411436 
    1542         /* Build the filename */ 
    15431437        path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, "news.txt"); 
    1544  
    1545         /* Attempt to open the file */ 
    1546         fd = fd_open(buf, O_RDONLY); 
    1547  
    1548         /* Failure */ 
    1549         if (fd < 0) 
     1438        if (!file_exists(buf)) 
    15501439        { 
    15511440                char why[1024]; 
    15521441 
    1553                 /* Message */ 
    1554                 strnfmt(why, sizeof(why), "Cannot access the '%s' file!", buf); 
    1555  
    15561442                /* Crash and burn */ 
     1443                strnfmt(why, sizeof(why), "Cannot access the '%s' file!", buf); 
    15571444                init_angband_aux(why); 
    15581445        } 
    15591446 
    1560         /* Close it */ 
    1561         fd_close(fd); 
    15621447 
    1563  
    15641448        /*** Display the "news" file ***/ 
    15651449 
    1566         /* Clear screen */ 
    15671450        Term_clear(); 
    15681451 
    1569         /* Build the filename */ 
     1452        /* Open the News file */ 
    15701453        path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, "news.txt"); 
     1454        fp = file_open(buf, MODE_READ, -1); 
    15711455 
    1572         /* Open the News file */ 
    1573         fp = my_fopen(buf, "r"); 
    1574  
    15751456        /* Dump */ 
    15761457        if (fp) 
    15771458        { 
    15781459                int i = 0; 
    15791460 
    15801461                /* Dump the file to the screen */ 
    1581                 while (0 == my_fgets(fp, buf, sizeof(buf))) 
    1582                 { 
    1583                         /* Display and advance */ 
     1462                while (file_getl(fp, buf, sizeof(buf))) 
    15841463                        Term_putstr(0, i++, -1, TERM_WHITE, buf); 
    1585                 } 
    15861464 
    1587                 /* Close */ 
    1588                 my_fclose(fp); 
     1465                file_close(fp); 
    15891466        } 
    15901467 
    15911468        /* Flush it */ 
    15921469        Term_fresh(); 
    15931470 
    15941471 
    1595         /*** Verify (or create) the "high score" file ***/ 
    15961472 
    1597         /* Build the filename */ 
    1598         path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); 
    1599  
    1600         /* Attempt to open the high score file */ 
    1601         fd = fd_open(buf, O_RDONLY); 
    1602  
    1603         /* Failure */ 
    1604         if (fd < 0) 
    1605         { 
    1606                 /* File type is "DATA" */ 
    1607                 FILE_TYPE(FILE_TYPE_DATA); 
    1608  
    1609                 /* Grab permissions */ 
    1610                 safe_setuid_grab(); 
    1611  
    1612                 /* Create a new high score file */ 
    1613                 fd = fd_make(buf, mode); 
    1614  
    1615                 /* Drop permissions */ 
    1616                 safe_setuid_drop(); 
    1617  
    1618                 /* Failure */ 
    1619                 if (fd < 0) 
    1620                 { 
    1621                         char why[1024]; 
    1622  
    1623                         /* Message */ 
    1624                         strnfmt(why, sizeof(why), "Cannot create the '%s' file!", buf); 
    1625  
    1626                         /* Crash and burn */ 
    1627                         init_angband_aux(why); 
    1628                 } 
    1629         } 
    1630  
    1631         /* Close it */ 
    1632         fd_close(fd); 
    1633  
    1634  
    16351473        /* Initialize the menus */ 
    1636         /* This must occur before preference files are read */ 
     1474        /* This must occur before preference files are read(?) */ 
    16371475        init_cmd4_c(); 
    16381476         
    16391477        /*** Initialize some arrays ***/ 
  • variable.c

     
    129129 
    130130 
    131131/* 
    132  * Player info 
    133  */ 
    134 int player_uid; 
    135 int player_egid; 
    136  
    137  
    138 /* 
    139132 * Buffer to hold the current savefile name 
    140133 */ 
    141134char savefile[1024]; 
     
    753746/* 
    754747 * Hack - the destination file for text_out_to_file. 
    755748 */ 
    756 FILE *text_out_file = NULL; 
     749ang_file *text_out_file = NULL; 
    757750 
    758751 
    759752/* 
  • main-x11.c

     
    21172117 
    21182118static void save_prefs(void) 
    21192119{ 
    2120         FILE *fff; 
     2120        ang_file *fff; 
    21212121        int i; 
    21222122 
    21232123        /* Open the settings file */ 
    2124         fff = my_fopen(settings, "w"); 
    2125  
    2126         /* Oops */ 
     2124        fff = file_open(settings, MODE_WRITE, FTYPE_TEXT); 
    21272125        if (!fff) return; 
    21282126 
    21292127        /* Header */ 
    2130         fprintf(fff, "# %s X11 settings\n\n", VERSION_NAME); 
     2128        file_putf(fff, "# %s X11 settings\n\n", VERSION_NAME); 
    21312129 
    21322130        /* Number of term windows to open */ 
    2133         fprintf(fff, "TERM_WINS=%d\n\n", term_windows_open); 
     2131        file_putf(fff, "TERM_WINS=%d\n\n", term_windows_open); 
    21342132 
    21352133        /* Save window prefs */ 
    21362134        for (i = 0; i < MAX_TERM_DATA; i++) 
     
    21402138                if (!td->t.mapped_flag) continue; 
    21412139 
    21422140                /* Header */ 
    2143                 fprintf(fff, "# Term %d\n", i); 
     2141                file_putf(fff, "# Term %d\n", i); 
    21442142 
    21452143                /* 
    21462144                 * This doesn't seem to work under various WMs 
     
    21532151                 */ 
    21542152 
    21552153                /* Window specific location (x) */ 
    2156                 fprintf(fff, "AT_X_%d=%d\n", i, td->win->x_save); 
     2154                file_putf(fff, "AT_X_%d=%d\n", i, td->win->x_save); 
    21572155 
    21582156                /* Window specific location (y) */ 
    2159                 fprintf(fff, "AT_Y_%d=%d\n", i, td->win->y_save); 
     2157                file_putf(fff, "AT_Y_%d=%d\n", i, td->win->y_save); 
    21602158 
    21612159                /* Window specific cols */ 
    2162                 fprintf(fff, "COLS_%d=%d\n", i, td->t.wid); 
     2160                file_putf(fff, "COLS_%d=%d\n", i, td->t.wid); 
    21632161 
    21642162                /* Window specific rows */ 
    2165                 fprintf(fff, "ROWS_%d=%d\n", i, td->t.hgt); 
     2163                file_putf(fff, "ROWS_%d=%d\n", i, td->t.hgt); 
    21662164 
    21672165                /* Window specific inner border offset (ox) */ 
    2168                 fprintf(fff, "IBOX_%d=%d\n", i, td->win->ox); 
     2166                file_putf(fff, "IBOX_%d=%d\n", i, td->win->ox); 
    21692167 
    21702168                /* Window specific inner border offset (oy) */ 
    2171                 fprintf(fff, "IBOY_%d=%d\n", i, td->win->oy); 
     2169                file_putf(fff, "IBOY_%d=%d\n", i, td->win->oy); 
    21722170 
    21732171                /* Window specific font name */ 
    2174                 fprintf(fff, "FONT_%d=%s\n", i, td->fnt->name); 
     2172                file_putf(fff, "FONT_%d=%s\n", i, td->fnt->name); 
    21752173 
    21762174                /* Window specific tile width */ 
    2177                 fprintf(fff, "TILE_WIDTH_%d=%d\n", i, td->tile_wid); 
     2175                file_putf(fff, "TILE_WIDTH_%d=%d\n", i, td->tile_wid); 
    21782176 
    21792177                /* Window specific tile height */ 
    2180                 fprintf(fff, "TILE_HEIGHT_%d=%d\n", i, td->tile_hgt); 
     2178                file_putf(fff, "TILE_HEIGHT_%d=%d\n", i, td->tile_hgt); 
    21812179 
    21822180                /* Footer */ 
    2183                 fprintf(fff, "\n"); 
     2181                file_putf(fff, "\n"); 
    21842182        } 
    21852183 
    21862184        /* Close */ 
    2187         (void)my_fclose(fff); 
     2185        file_close(fff); 
    21882186} 
    21892187 
    21902188 
     
    22212219 
    22222220        XSizeHints *sh; 
    22232221 
    2224         FILE *fff; 
     2222        ang_file *fff; 
    22252223 
    22262224        char buf[1024]; 
    22272225        char cmd[40]; 
     
    22362234        path_build(settings, sizeof(settings), ANGBAND_DIR_USER, "x11-settings.prf"); 
    22372235 
    22382236        /* Open the file */ 
    2239         fff = my_fopen(settings, "r"); 
     2237        fff = file_open(settings, MODE_READ, -1); 
    22402238 
    22412239        /* File exists */ 
    22422240        if (fff) 
    22432241        { 
    22442242                /* Process the file */ 
    2245                 while (0 == my_fgets(fff, buf, sizeof(buf))) 
     2243                while (file_getl(fff, buf, sizeof(buf))) 
    22462244                { 
    22472245                        /* Count lines */ 
    22482246                        line++; 
     
    23582356                } 
    23592357 
    23602358                /* Close */ 
    2361                 my_fclose(fff); 
     2359                file_close(fff); 
    23622360        } 
    23632361 
    23642362        /* 
     
    26172615 
    26182616        int num_term = 1; 
    26192617 
    2620         FILE *fff; 
     2618        ang_file *fff; 
    26212619 
    26222620        char buf[1024]; 
    26232621        cptr str; 
     
    26462644        (void)path_build(settings, sizeof(settings), ANGBAND_DIR_USER, "x11-settings.prf"); 
    26472645 
    26482646        /* Open the file */ 
    2649         fff = my_fopen(settings, "r"); 
     2647        fff = file_open(settings, MODE_READ, -1); 
    26502648 
    26512649        /* File exists */ 
    26522650        if (fff) 
    26532651        { 
    26542652                /* Process the file */ 
    2655                 while (0 == my_fgets(fff, buf, sizeof(buf))) 
     2653                while (file_getl(fff, buf, sizeof(buf))) 
    26562654                { 
    26572655                        /* Count lines */ 
    26582656                        line++; 
     
    26772675                } 
    26782676 
    26792677                /* Close */ 
    2680                 (void)my_fclose(fff); 
     2678                (void)file_close(fff); 
    26812679        } 
    26822680 
    26832681        /* Parse args */ 
     
    28492847        { 
    28502848                /* Try the file */ 
    28512849                path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, bitmap_file); 
    2852                 if (!my_fexists(filename)) 
     2850                if (!file_exists(filename)) 
    28532851                { 
    28542852                        use_graphics = GRAPHICS_NONE; 
    28552853                        use_transparency = FALSE; 
  • load.c

     
    4343/* 
    4444 * Local "savefile" pointer 
    4545 */ 
    46 static FILE     *fff; 
     46static ang_file *fff; 
    4747 
    4848/* 
    4949 * Hack -- old "encryption" byte 
     
    204204        byte c, v; 
    205205 
    206206        /* Get a character, decode the value */ 
    207         c = getc(fff) & 0xFF; 
     207        file_readc(fff, &c); 
     208        c &= 0xFF; 
    208209        v = c ^ xor_byte; 
    209210        xor_byte = c; 
    210211 
     
    22092210{ 
    22102211        errr err; 
    22112212 
    2212         /* Grab permissions */ 
     2213        /* Open savefile */ 
    22132214        safe_setuid_grab(); 
    2214  
    2215         /* The savefile is a binary file */ 
    2216         fff = my_fopen(savefile, "rb"); 
    2217  
    2218         /* Drop permissions */ 
     2215        fff = file_open(savefile, MODE_READ, -1); 
    22192216        safe_setuid_drop(); 
    22202217 
    22212218        /* Paranoia */ 
     
    22242221        /* Call the sub-function */ 
    22252222        err = rd_savefile_new_aux(); 
    22262223 
    2227         /* Check for errors */ 
    2228         if (ferror(fff)) err = -1; 
    2229  
    22302224        /* Close the file */ 
    2231         my_fclose(fff); 
     2225        file_close(fff); 
    22322226 
    22332227        /* Result */ 
    22342228        return (err); 
     
    22512245 */ 
    22522246bool load_player(bool *character_loaded, bool *reusing_savefile) 
    22532247{ 
    2254         int fd = -1; 
     2248        ang_file *fh; 
     2249        cptr what = "generic"; 
    22552250 
    22562251        errr err = 0; 
    22572252 
    2258         byte vvv[4]; 
    22592253 
    2260         cptr what = "generic"; 
    2261  
    2262  
    22632254        /* Paranoia */ 
    22642255        turn = 0; 
    22652256        p_ptr->is_dead = FALSE; 
     
    22702261        /* Allow empty savefile name */ 
    22712262        if (!savefile[0]) return (TRUE); 
    22722263 
    2273         /* Grab permissions */ 
    2274         safe_setuid_grab(); 
    2275  
    2276         /* Open the savefile */ 
    2277         fd = fd_open(savefile, O_RDONLY); 
    2278  
    2279         /* Drop permissions */ 
    2280         safe_setuid_drop(); 
    2281  
    22822264        /* No file */ 
    2283         if (fd < 0) 
     2265        if (!file_exists(savefile)) 
    22842266        { 
    22852267                /* Give a message */ 
    22862268                msg_print("Savefile does not exist."); 
     
    22902272                return (TRUE); 
    22912273        } 
    22922274 
    2293         /* Close the file */ 
    2294         fd_close(fd); 
     2275        /* Open savefile */ 
     2276        safe_setuid_grab(); 
     2277        fh = file_open(savefile, MODE_READ, -1); 
     2278        safe_setuid_drop(); 
    22952279 
    2296  
    2297         /* Okay */ 
    2298         if (!err) 
     2280        /* No file */ 
     2281        if (!fh) 
    22992282        { 
    2300                 /* Grab permissions */ 
    2301                 safe_setuid_grab(); 
    2302  
    2303                 /* Open the savefile */ 
    2304                 fd = fd_open(savefile, O_RDONLY); 
    2305  
    2306                 /* Drop permissions */ 
    2307                 safe_setuid_drop(); 
    2308  
    2309                 /* No file */ 
    2310                 if (fd < 0) err = -1; 
    2311  
    2312                 /* Message (below) */ 
    2313                 if (err) what = "Cannot open savefile"; 
     2283                err = -1; 
     2284                what = "Cannot open savefile"; 
    23142285        } 
    23152286 
    23162287        /* Process file */ 
    23172288        if (!err) 
    23182289        { 
    2319                 /* Read the first four bytes */ 
    2320                 if (fd_read(fd, (char*)(vvv), sizeof(vvv))) err = -1; 
     2290                /* Extract version */ 
     2291                err = file_readc(fh, &sf_major) ? 0 : -1; 
     2292                if (!err) err = file_readc(fh, &sf_minor) ? 0 : -1; 
     2293                if (!err) err = file_readc(fh, &sf_patch) ? 0 : -1; 
     2294                if (!err) err = file_readc(fh, &sf_extra) ? 0 : -1; 
    23212295 
    2322                 /* What */ 
    2323                 if (err) what = "Cannot read savefile"; 
    2324  
    2325                 /* Close the file */ 
    2326                 fd_close(fd); 
     2296                if (err) 
     2297                { 
     2298                        what = "Cannot read savefile"; 
     2299                        file_close(fh); 
     2300                } 
    23272301        } 
    23282302 
    23292303        /* Process file */ 
    23302304        if (!err) 
    23312305        { 
    2332                 /* Extract version */ 
    2333                 sf_major = vvv[0]; 
    2334                 sf_minor = vvv[1]; 
    2335                 sf_patch = vvv[2]; 
    2336                 sf_extra = vvv[3]; 
    2337  
    23382306                /* Clear screen */ 
    23392307                Term_clear(); 
    23402308 
  • tests/z-file.c

     
     1/* Simple test rig */ 
     2/* 2-clause BSD licenced */ 
     3 
     4#include <stdio.h> 
     5 
     6#include "../z-file.h" 
     7 
     8 
     9typedef struct 
     10{ 
     11        unsigned num_tests; 
     12        unsigned num_tests_failed; 
     13} test_stats; 
     14 
     15typedef int (*test_func)(void); 
     16 
     17void test_run(test_stats *stats, const char *name, test_func tester) 
     18{ 
     19        stats->num_tests++; 
     20        printf("running test %s... ", name); 
     21 
     22        if ((*tester)() == 0) 
     23        { 
     24                stats->num_tests_failed++; 
     25                printf("FAIL\n"); 
     26        } 
     27        else 
     28        { 
     29                printf("successful\n"); 
     30        } 
     31} 
     32 
     33void test_summarise(test_stats *stats) 
     34{ 
     35        printf("%d tests\n", stats->num_tests); 
     36        printf("%d failed\n", stats->num_tests_failed); 
     37} 
     38 
     39int test_success(test_stats *stats) 
     40{ 
     41        return (stats->num_tests_failed) ? 1 : 0; 
     42} 
     43 
     44#define TEST_RUN(stat, test)            test_run(stat, #test, test_##test) 
     45 
     46#define TEST(x)         static int test_##x(void) { 
     47#define TEST_END        return 1; } 
     48 
     49#define FAIL            return 0; 
     50 
     51 
     52/*** z-file tests ***/ 
     53 
     54static const char *test_fname = "./test"; 
     55 
     56TEST(file_open) 
     57{ 
     58        ang_file *f; 
     59 
     60        /* Try opening a new file */ 
     61        f = file_open(test_fname, MODE_WRITE, FTYPE_TEXT); 
     62        if (!f) FAIL; 
     63 
     64        /* Try closing that file */ 
     65        if (!file_close(f)) FAIL; 
     66} 
     67TEST_END 
     68 
     69TEST(file_exists) 
     70{ 
     71        /* Test for the existence of the file "test" */ 
     72        if (!file_exists(test_fname)) FAIL; 
     73} 
     74TEST_END 
     75 
     76TEST(file_lock) 
     77{ 
     78        /* Not sure what to do here -- spawn off another process? */ 
     79        void file_lock(ang_file *f); 
     80        void file_unlock(ang_file *f); 
     81} 
     82TEST_END 
     83 
     84TEST(file_rws) 
     85{ 
     86        ang_file *f; 
     87        char buffer[1024]; 
     88        char comparison_buffer[1024]; 
     89        size_t i; 
     90        u32b seek_positions[] = { 5, 18, 500, 95, 1023 }; 
     91        bool success; 
     92 
     93        /* Set up buffer */ 
     94        for (i = 0; i < sizeof(buffer); i++) 
     95                buffer[i] = (char) i * 3; 
     96 
     97        printf("opening, "); 
     98        f = file_open(test_fname, MODE_WRITE, FTYPE_TEXT); 
     99        if (!f) FAIL; 
     100 
     101        printf("writing, "); 
     102        success = file_write(f, buffer, sizeof(buffer)); 
     103        file_close(f); 
     104        if (!success) FAIL; 
     105 
     106        printf("reopening, "); 
     107        f = file_open(test_fname, MODE_READ, -1); 
     108        if (!f) FAIL; 
     109 
     110        /* Make sure the contents match up */    
     111        printf("reading, "); 
     112        file_read(f, comparison_buffer, sizeof(buffer)); 
     113        for (i = 0; i < sizeof(buffer); i++) 
     114        { 
     115                if (buffer[i] != comparison_buffer[i]) 
     116                        FAIL; 
     117        } 
     118 
     119        /* Seek, and make sure they still match up */ 
     120        printf("seeking "); 
     121        for (i = 0; i < N_ELEMENTS(seek_positions); i++) 
     122        { 
     123                u32b pos = seek_positions[i]; 
     124                byte b; 
     125 
     126                printf("%d", i); 
     127                if (!file_seek(f, pos)) 
     128                { 
     129                        file_close(f); 
     130                        FAIL; 
     131                } 
     132 
     133                printf("A"); 
     134                if (!file_readc(f, &b)) 
     135                { 
     136                        file_close(f); 
     137                        FAIL; 
     138                } 
     139 
     140                printf("B "); 
     141                if ((char)b != buffer[pos]) 
     142                { 
     143                        printf("was %d, should be %d", (char)b, (char)buffer[pos]); 
     144                        file_close(f); 
     145                        FAIL; 
     146                } 
     147        }        
     148} 
     149TEST_END 
     150 
     151TEST(file_chario) 
     152{ 
     153        size_t i; 
     154        ang_file *f; 
     155 
     156        /* Try opening a new file */ 
     157        printf("opening, "); 
     158        f = file_open(test_fname, MODE_WRITE, FTYPE_TEXT); 
     159        if (!f) FAIL; 
     160 
     161        for (i = 0; i < 25; i++) 
     162        { 
     163                if (!file_writec(f, (byte)i)) 
     164                { 
     165                        file_close(f); 
     166                        FAIL; 
     167                } 
     168        } 
     169        file_close(f); 
     170         
     171        /* Re-open for reading */ 
     172        printf("reopening, "); 
     173        f = file_open(test_fname, MODE_READ, FTYPE_TEXT); 
     174        if (!f) FAIL; 
     175 
     176        for (i = 0; i < 25; i++) 
     177        { 
     178                byte ch; 
     179 
     180                if (!file_readc(f, &ch)) 
     181                { 
     182                        file_close(f); 
     183                        FAIL; 
     184                } 
     185 
     186                if ((char)ch != i) 
     187                { 
     188                        file_close(f); 
     189                        FAIL; 
     190                } 
     191        } 
     192} 
     193TEST_END 
     194 
     195TEST(file_lineio) 
     196{ 
     197        ang_file *f; 
     198        size_t i; 
     199        const char *lineendings[] = { "\n", "\r", "\r\n" }; 
     200        const char *text[] = 
     201        { 
     202                "'Twas brillig, and the slithy toves", 
     203                "  Did gyre and gimble in the wabe", 
     204                "All mimsy were the borogoves", 
     205                "  And the mome raths outgrabe", 
     206                "", 
     207                "Beware the Jabberwock, my son!", 
     208                "  The jaws that bite, the claws that catch!", 
     209                "Beware the Jubjub bird, and shun", 
     210                "  The frumious Bandersnatch!", 
     211        }; 
     212 
     213        /* Try opening a new file */ 
     214        printf("opening, "); 
     215        f = file_open(test_fname, MODE_WRITE, FTYPE_TEXT); 
     216        if (!f) FAIL; 
     217 
     218        /* Put the text, line by line */ 
     219        printf("writing, "); 
     220        for (i = 0; i < N_ELEMENTS(text); i++) 
     221        { 
     222                if (!file_put(f, text[i])) 
     223                { 
     224                        file_close(f); 
     225                        FAIL; 
     226                } 
     227 
     228                if (!file_put(f, lineendings[i % N_ELEMENTS(lineendings)])) 
     229                { 
     230                        file_close(f); 
     231                        FAIL; 
     232                } 
     233        } 
     234        file_close(f); 
     235         
     236        /* Re-open for reading */ 
     237        printf("reopening, "); 
     238        f = file_open(test_fname, MODE_READ, FTYPE_TEXT); 
     239        if (!f) FAIL; 
     240 
     241        printf("reading, "); 
     242        for (i = 0; i < N_ELEMENTS(text); i++) 
     243        { 
     244                char buf[1024]; 
     245                printf("%d", i); 
     246                if (!file_getl(f, buf, sizeof(buf))) 
     247                { 
     248                        file_close(f); 
     249                        FAIL; 
     250                } 
     251                printf("B "); 
     252                if (strcmp(buf, text[i])) 
     253                { 
     254                        printf("%s %s", buf, text[i]); 
     255                        file_close(f); 
     256                        FAIL; 
     257                } 
     258        } 
     259 
     260        file_close(f); 
     261} 
     262TEST_END 
     263 
     264TEST(file_move) 
     265{ 
     266        printf("move, "); 
     267        if (!file_move(test_fname, "test2")) FAIL; 
     268        printf("check, "); 
     269        if (!file_exists("test2")) FAIL; 
     270        printf("move, "); 
     271        if (!file_move("test2", test_fname)) FAIL; 
     272        printf("check, "); 
     273        if (!file_exists(test_fname)) FAIL; 
     274} 
     275TEST_END 
     276 
     277TEST(file_newer) 
     278{ 
     279        if (!file_exists("z-file.c")) 
     280        { 
     281                printf("need z-file.c "); 
     282                FAIL; 
     283        } 
     284 
     285        if (!file_exists(test_fname)) 
     286        { 
     287                printf("need %s ", test_fname); 
     288                FAIL; 
     289        } 
     290 
     291        printf("testing existent files 1 "); 
     292        if (file_newer("z-file.c", test_fname)) FAIL; 
     293        printf("2 "); 
     294        if (!file_newer(test_fname, "z-file.c")) FAIL; 
     295 
     296        printf("testing nonexistent files 1 "); 
     297        if (file_newer("nonexistent", "z-file.c")) FAIL; 
     298        printf("2 "); 
     299        if (!file_newer("z-file.c", "nonexistent")) FAIL; 
     300} 
     301TEST_END 
     302 
     303TEST(file_delete) 
     304{ 
     305        if (!file_delete(test_fname)) FAIL; 
     306        if (file_exists(test_fname)) FAIL; 
     307} 
     308TEST_END 
     309 
     310 
     311TEST(path_build) 
     312{ 
     313        char buf[1024]; 
     314 
     315        path_build(buf, sizeof(buf), "some" PATH_SEP "path", "extra"); 
     316        if (strcmp(buf, "some" PATH_SEP "path" PATH_SEP "extra")) FAIL; 
     317 
     318        path_build(buf, sizeof(buf), "", "leaf"); 
     319        if (strcmp(buf, "leaf")) FAIL; 
     320 
     321        path_build(buf, sizeof(buf), "base", ""); 
     322        if (strcmp(buf, "base")) FAIL; 
     323 
     324        path_build(buf, sizeof(buf), "somepath", PATH_SEP "absolutepath"); 
     325        if (strcmp(buf, PATH_SEP "absolutepath")) FAIL; 
     326 
     327        /*** SET_UID only ***/ 
     328 
     329        path_build(buf, sizeof(buf), "~", ""); 
     330        if (!strcmp(buf, "~")) FAIL; 
     331 
     332        path_build(buf, sizeof(buf), "~" PATH_SEP "dull", ""); 
     333        if (!strcmp(buf, "~/dull")) FAIL; 
     334        if (!suffix(buf, PATH_SEP "dull")) FAIL; 
     335 
     336        path_build(buf, sizeof(buf), "~ajps", ""); 
     337        if (!strcmp(buf, "~ajps")) FAIL; 
     338 
     339        path_build(buf, sizeof(buf), "somepath", "~"); 
     340        if (!strcmp(buf, "somepath")) FAIL; 
     341} 
     342TEST_END 
     343 
     344 
     345int main(void) 
     346{ 
     347        test_stats test = { 0, 0 }; 
     348 
     349        TEST_RUN(&test, file_open); 
     350        TEST_RUN(&test, file_exists); 
     351        TEST_RUN(&test, file_lock); 
     352        TEST_RUN(&test, file_rws); 
     353        TEST_RUN(&test, file_chario); 
     354        TEST_RUN(&test, file_lineio); 
     355        TEST_RUN(&test, file_move); 
     356        TEST_RUN(&test, file_newer); 
     357        TEST_RUN(&test, file_delete); 
     358 
     359        TEST_RUN(&test, path_build); 
     360 
     361        test_summarise(&test); 
     362 
     363        return test_success(&test) ? 0 : 1; 
     364} 
  • tests/z-file.mk

     
     1EXE = z-file 
     2 
     3CC = gcc 
     4CFLAGS = -Wall -O2 -Wno-unused-parameter -fprofile-arcs -ftest-coverage 
     5LDFLAGS = -fprofile-arcs -ftest-coverage 
     6 
     7OBJS = z-file.o ../z-file.o ../z-virt.o ../z-util.o ../z-form.o  
     8 
     9$(EXE): $(OBJS) 
     10        $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXE) $(OBJS) $(LIBS) 
     11 
     12clean: 
     13        -rm -f *.o $(EXE) 
     14 
     15%.o: %.c 
     16        $(CC) $(CFLAGS) -o $@ -c $< 
     17 
     18z-file.o: ../z-file.o ../z-form.o 
     19../z-file.o: ../z-virt.o ../z-util.o ../z-form.o 
  • wizard1.c

     
    1818/* 
    1919 * The spoiler file being created 
    2020 */ 
    21 static FILE *fff = NULL; 
     21static ang_file *fh = NULL; 
    2222 
    2323 
    2424/* 
     
    2626 */ 
    2727static void spoiler_out_n_chars(int n, char c) 
    2828{ 
    29         while (--n >= 0) fputc(c, fff); 
     29        while (--n >= 0) file_writec(fh, c); 
    3030} 
    3131 
    3232/* 
     
    230230 
    231231        cptr format = "%-51s  %7s%6s%4s%9s\n"; 
    232232 
    233         /* Build the filename */ 
     233        /* Open the file */ 
    234234        path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); 
     235        fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
    235236 
    236         /* File type is "TEXT" */ 
    237         FILE_TYPE(FILE_TYPE_TEXT); 
    238  
    239         /* Open the file */ 
    240         fff = my_fopen(buf, "w"); 
    241  
    242237        /* Oops */ 
    243         if (!fff) 
     238        if (!fh) 
    244239        { 
    245240                msg_print("Cannot create spoiler file."); 
    246241                return; 
     
    248243 
    249244 
    250245        /* Header */ 
    251         fprintf(fff, "Spoiler File -- Basic Items (%s)\n\n\n", VERSION_STRING); 
     246        file_putf(fh, "Spoiler File -- Basic Items (%s)\n\n\n", VERSION_STRING); 
    252247 
    253248        /* More Header */ 
    254         fprintf(fff, format, "Description", "Dam/AC", "Wgt", "Lev", "Cost"); 
    255         fprintf(fff, format, "----------------------------------------", 
     249        file_putf(fh, format, "Description", "Dam/AC", "Wgt", "Lev", "Cost"); 
     250        file_putf(fh, format, "----------------------------------------", 
    256251                "------", "---", "---", "----"); 
    257252 
    258253        /* List the groups */ 
     
    297292                                kind_info(buf, sizeof(buf), dam, sizeof(dam), wgt, sizeof(wgt), &e, &v, who[s]); 
    298293 
    299294                                /* Dump it */ 
    300                                 fprintf(fff, "  %-51s%7s%6s%4d%9ld\n", 
     295                                file_putf(fh, "  %-51s%7s%6s%4d%9ld\n", 
    301296                                        buf, dam, wgt, e, (long)(v)); 
    302297                        } 
    303298 
     
    308303                        if (!group_item[i].tval) break; 
    309304 
    310305                        /* Start a new set */ 
    311                         fprintf(fff, "\n\n%s\n\n", group_item[i].name); 
     306                        file_putf(fh, "\n\n%s\n\n", group_item[i].name); 
    312307                } 
    313308 
    314309                /* Get legal item types */ 
     
    329324 
    330325 
    331326        /* Check for errors */ 
    332         if (ferror(fff) || my_fclose(fff)) 
     327        if (!file_close(fh)) 
    333328        { 
    334329                msg_print("Cannot close spoiler file."); 
    335330                return; 
     
    436431 
    437432        /* Build the filename */ 
    438433        path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); 
     434        fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
    439435 
    440         /* File type is "TEXT" */ 
    441         FILE_TYPE(FILE_TYPE_TEXT); 
    442  
    443         /* Open the file */ 
    444         fff = my_fopen(buf, "w"); 
    445  
    446436        /* Oops */ 
    447         if (!fff) 
     437        if (!fh) 
    448438        { 
    449439                msg_print("Cannot create spoiler file."); 
    450440                return; 
     
    452442 
    453443        /* Dump to the spoiler file */ 
    454444        text_out_hook = text_out_to_file; 
    455         text_out_file = fff; 
     445        text_out_file = fh; 
    456446 
    457447        /* Set object_info_out() hook */ 
    458448        object_info_out_flags = object_flags; 
     
    513503        } 
    514504 
    515505        /* Check for errors */ 
    516         if (ferror(fff) || my_fclose(fff)) 
     506        if (!file_close(fh)) 
    517507        { 
    518508                msg_print("Cannot close spoiler file."); 
    519509                return; 
     
    550540 
    551541        /* Build the filename */ 
    552542        path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); 
     543        fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
    553544 
    554         /* File type is "TEXT" */ 
    555         FILE_TYPE(FILE_TYPE_TEXT); 
    556  
    557         /* Open the file */ 
    558         fff = my_fopen(buf, "w"); 
    559  
    560545        /* Oops */ 
    561         if (!fff) 
     546        if (!fh) 
    562547        { 
    563548                msg_print("Cannot create spoiler file."); 
    564549                return; 
    565550        } 
    566551 
    567552        /* Dump the header */ 
    568         fprintf(fff, "Monster Spoilers for %s Version %s\n", 
     553        file_putf(fh, "Monster Spoilers for %s Version %s\n", 
    569554                VERSION_NAME, VERSION_STRING); 
    570         fprintf(fff, "------------------------------------------\n\n"); 
     555        file_putf(fh, "------------------------------------------\n\n"); 
    571556 
    572557        /* Dump the header */ 
    573         fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s  %11.11s\n", 
     558        file_putf(fh, "%-40.40s%4s%4s%6s%8s%4s  %11.11s\n", 
    574559                "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info"); 
    575         fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s  %11.11s\n", 
     560        file_putf(fh, "%-40.40s%4s%4s%6s%8s%4s  %11.11s\n", 
    576561                "----", "---", "---", "---", "--", "--", "-----------"); 
    577562 
    578563        /* Allocate the "who" array */ 
     
    642627                strnfmt(exp, sizeof(exp), "%s '%c'", attr_to_text(r_ptr->d_attr), r_ptr->d_char); 
    643628 
    644629                /* Dump the info */ 
    645                 fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s  %11.11s\n", 
     630                file_putf(fh, "%-40.40s%4s%4s%6s%8s%4s  %11.11s\n", 
    646631                        nam, lev, rar, spd, hp, ac, exp); 
    647632        } 
    648633 
    649634        /* End it */ 
    650         fprintf(fff, "\n"); 
     635        file_putf(fh, "\n"); 
    651636 
    652637        /* Free the "who" array */ 
    653638        FREE(who); 
    654639 
    655640 
    656641        /* Check for errors */ 
    657         if (ferror(fff) || my_fclose(fff)) 
     642        if (!file_close(fh)) 
    658643        { 
    659644                msg_print("Cannot close spoiler file."); 
    660645                return; 
     
    684669        int count = 0; 
    685670 
    686671 
    687         /* Build the filename */ 
     672        /* Open the file */ 
    688673        path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); 
     674        fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); 
    689675 
    690         /* File type is "TEXT" */ 
    691         FILE_TYPE(FILE_TYPE_TEXT); 
    692  
    693         /* Open the file */ 
    694         fff = my_fopen(buf, "w"); 
    695  
    696676        /* Oops */ 
    697         if (!fff) 
     677        if (!fh) 
    698678        { 
    699679                msg_print("Cannot create spoiler file."); 
    700680                return; 
     
    702682 
    703683        /* Dump to the spoiler file */ 
    704684        text_out_hook = text_out_to_file; 
    705         text_out_file = fff; 
     685        text_out_file = fh; 
    706686 
    707687        /* Dump the header */ 
    708688        strnfmt(buf, sizeof(buf), "Monster Spoilers for %s Version %s\n", 
     
    812792        FREE(who); 
    813793 
    814794        /* Check for errors */ 
    815         if (ferror(fff) || my_fclose(fff)) 
     795        if (!file_close(fh)) 
    816796        { 
    817797                msg_print("Cannot close spoiler file."); 
    818798                return; 
  • save.c

     
    1818 * Some "local" parameters, used to help write savefiles 
    1919 */ 
    2020 
    21 static FILE     *fff;           /* Current save "file" */ 
     21static ang_file *fff;           /* Current save "file" */ 
    2222 
    2323static byte     xor_byte;       /* Simple encryption */ 
    2424 
     
    3535{ 
    3636        /* Encode the value, write a character */ 
    3737        xor_byte ^= v; 
    38         (void)putc((int)xor_byte, fff); 
     38        file_writec(fff, xor_byte); 
    3939 
    4040        /* Maintain the checksum info */ 
    4141        v_stamp += v; 
     
    807807/* 
    808808 * Actually write a save-file 
    809809 */ 
    810 static bool wr_savefile_new(void) 
     810static void wr_savefile_new(void) 
    811811{ 
    812812        int i; 
    813813 
     
    10021002 
    10031003        /* Write the "encoded checksum" */ 
    10041004        wr_u32b(x_stamp); 
    1005  
    1006  
    1007         /* Error in save */ 
    1008         if (ferror(fff) || (fflush(fff) == EOF)) return FALSE; 
    1009  
    1010         /* Successful save */ 
    1011         return TRUE; 
    10121005} 
    10131006 
    10141007 
     
    10171010 */ 
    10181011static bool save_player_aux(cptr name) 
    10191012{ 
    1020         bool ok = FALSE; 
     1013        bool ok = TRUE; 
    10211014 
    1022         int fd; 
    10231015 
    1024         int mode = 0644; 
    1025  
    1026  
    10271016        /* No file yet */ 
    10281017        fff = NULL; 
    10291018 
    10301019 
    1031         /* File type is "SAVE" */ 
    1032         FILE_TYPE(FILE_TYPE_SAVE); 
    1033  
    1034  
    1035         /* Grab permissions */ 
     1020        /* Open the savefile */ 
    10361021        safe_setuid_grab(); 
    1037  
    1038         /* Create the savefile */ 
    1039         fd = fd_make(name, mode); 
    1040  
    1041         /* Drop permissions */ 
     1022        fff = file_open(name, MODE_WRITE, FTYPE_SAVE); 
    10421023        safe_setuid_drop(); 
    10431024 
    1044         /* File is okay */ 
    1045         if (fd >= 0) 
     1025        /* Successful open */ 
     1026        if (fff) 
    10461027        { 
    1047                 /* Close the "fd" */ 
    1048                 fd_close(fd); 
     1028                /* Write the savefile */ 
     1029                wr_savefile_new(); 
    10491030 
    1050                 /* Grab permissions */ 
    1051                 safe_setuid_grab(); 
     1031                /* Attempt to close it */ 
     1032                if (!file_close(fff)) ok = FALSE; 
     1033        } 
    10521034 
    1053                 /* Open the savefile */ 
    1054                 fff = my_fopen(name, "wb"); 
    1055  
    1056                 /* Drop permissions */ 
    1057                 safe_setuid_drop(); 
    1058  
    1059                 /* Successful open */ 
    1060                 if (fff) 
    1061                 { 
    1062                         /* Write the savefile */ 
    1063                         if (wr_savefile_new()) ok = TRUE; 
    1064  
    1065                         /* Attempt to close it */ 
    1066                         if (my_fclose(fff)) ok = FALSE; 
    1067                 } 
    1068  
    1069                 /* Grab permissions */ 
     1035        /* Grab permissions */ 
     1036        if (!ok) 
     1037        { 
    10701038                safe_setuid_grab(); 
    1071  
    1072                 /* Remove "broken" files */ 
    1073                 if (!ok) fd_kill(name); 
    1074  
    1075                 /* Drop permissions */ 
     1039                file_delete(name); 
    10761040                safe_setuid_drop(); 
    10771041        } 
    10781042 
     1043        if (ok) 
     1044                character_saved = TRUE; 
    10791045 
    1080         /* Failure */ 
    1081         if (!ok) return (FALSE); 
    1082  
    1083         /* Successful save */ 
    1084         character_saved = TRUE; 
    1085  
    1086         /* Success */ 
    1087         return (TRUE); 
     1046        return ok; 
    10881047} 
    10891048 
    10901049 
     
    10941053 */ 
    10951054bool save_player(void) 
    10961055{ 
    1097         int result = FALSE; 
     1056        int ok = TRUE; 
     1057        char new_savefile[1024]; 
     1058        char old_savefile[1024]; 
    10981059 
    1099         char safe[1024]; 
    1100  
    1101  
    11021060        /* New savefile */ 
    1103         my_strcpy(safe, savefile, sizeof(safe)); 
    1104         my_strcat(safe, ".new", sizeof(safe)); 
     1061        strnfmt(new_savefile, sizeof(new_savefile), "%s.new", savefile); 
     1062        strnfmt(old_savefile, sizeof(old_savefile), "%s.old", savefile); 
    11051063 
    1106         /* Grab permissions */ 
     1064        /* Make sure that these savefiles doesn't already exist */ 
    11071065        safe_setuid_grab(); 
    1108  
    1109         /* Remove it */ 
    1110         fd_kill(safe); 
    1111  
    1112         /* Drop permissions */ 
     1066        file_delete(new_savefile); 
     1067        file_delete(old_savefile); 
    11131068        safe_setuid_drop(); 
    11141069 
    11151070        /* Attempt to save the player */ 
    1116         if (save_player_aux(safe)) 
     1071        if (save_player_aux(new_savefile)) 
    11171072        { 
    1118                 char temp[1024]; 
    1119  
    1120                 /* Old savefile */ 
    1121                 my_strcpy(temp, savefile, sizeof(temp)); 
    1122                 my_strcat(temp, ".old", sizeof(temp)); 
    1123  
    1124                 /* Grab permissions */ 
    11251073                safe_setuid_grab(); 
    11261074 
    1127                 /* Remove it */ 
    1128                 fd_kill(temp); 
     1075                file_move(savefile, old_savefile); 
     1076                file_move(new_savefile, savefile); 
     1077                file_delete(old_savefile); 
    11291078 
    1130                 /* Preserve old savefile */ 
    1131                 fd_move(savefile, temp); 
    1132  
    1133                 /* Activate new savefile */ 
    1134                 fd_move(safe, savefile); 
    1135  
    1136                 /* Remove preserved savefile */ 
    1137                 fd_kill(temp); 
    1138  
    1139                 /* Drop permissions */ 
    11401079                safe_setuid_drop(); 
    1141  
    1142                 /* Success */ 
    1143                 result = TRUE; 
    11441080        } 
    11451081 
    1146  
    1147         /* Return the result */ 
    1148         return (result); 
     1082        return ok; 
    11491083} 
  • init1.c

     
    528528/* 
    529529 * Initialize an "*_info" array, by parsing an ascii "template" file 
    530530 */ 
    531 errr init_info_txt(FILE *fp, char *buf, header *head, 
     531errr init_info_txt(ang_file *fp, char *buf, header *head, 
    532532                   parse_info_txt_func parse_info_txt_line) 
    533533{ 
    534534        errr err; 
     
    548548        head->text_size = 0; 
    549549 
    550550        /* Parse */ 
    551         while (0 == my_fgets(fp, buf, 1024)) 
     551        while (file_getl(fp, buf, 1024)) 
    552552        { 
    553553                /* Advance the line number */ 
    554554                error_line++; 
  • externs.h

     
    132132extern s16b rating; 
    133133extern bool good_item_flag; 
    134134extern bool closing_flag; 
    135 extern int player_uid; 
    136 extern int player_egid; 
    137135extern char savefile[1024]; 
    138136extern s16b macro__num; 
    139137extern char **macro__pat; 
     
    238236extern bool (*get_mon_num_hook)(int r_idx); 
    239237extern bool (*get_obj_num_hook)(int k_idx); 
    240238extern void (*object_info_out_flags)(const object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3); 
    241 extern FILE *text_out_file; 
     239extern ang_file *text_out_file; 
    242240extern void (*text_out_hook)(byte a, cptr str); 
    243241extern int text_out_wrap; 
    244242extern int text_out_indent; 
     
    725723 * Hack -- conditional (or "bizarre") externs 
    726724 */ 
    727725 
    728 #ifdef RISCOS 
    729 /* main-ros.c */ 
    730 extern char *riscosify_name(cptr path); 
    731 #endif /* RISCOS */ 
    732  
    733 #if defined(MAC_MPW) || defined(MACH_O_CARBON) 
    734 /* main-mac.c, or its derivatives */ 
    735 extern u32b _fcreator; 
    736 extern u32b _ftype; 
    737 # if defined(MAC_MPW) && defined(CARBON) 
    738 extern void convert_pathname(char *path); 
    739 # endif 
    740 # if defined(MACH_O_CARBON) 
    741 extern void fsetfileinfo(cptr path, u32b fcreator, u32b ftype); 
    742 # endif 
    743 #endif 
    744  
    745726#ifdef ALLOW_DEBUG 
    746727/* wizard2.c */ 
    747728extern void do_cmd_debug(void);