X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fwrite_entry.c;h=8a49a2c0d7f4b005f740f0a03b456a72ddd7631d;hp=057b3c22a44782dd2593bcad485da579a57c4667;hb=90d42867e1296bc79021006a92032c76e59068b6;hpb=9e3a472c069d718e4f510e8477373618f80227ae diff --git a/ncurses/tinfo/write_entry.c b/ncurses/tinfo/write_entry.c index 057b3c22..8a49a2c0 100644 --- a/ncurses/tinfo/write_entry.c +++ b/ncurses/tinfo/write_entry.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2015,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,14 +39,7 @@ #include #include -#include - #include -#include - -#ifndef S_ISDIR -#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR) -#endif #if 1 #define TRACE_OUT(p) DEBUG(2, p) @@ -54,12 +47,13 @@ #define TRACE_OUT(p) /*nothing */ #endif -MODULE_ID("$Id: write_entry.c,v 1.74 2009/09/19 20:30:48 Daniel.Jacobowitz Exp $") +MODULE_ID("$Id: write_entry.c,v 1.98 2017/02/05 01:47:34 tom Exp $") static int total_written; +static int total_parts; +static int total_size; static int make_db_root(const char *); -static int write_object(TERMTYPE *, char *, unsigned *, unsigned); #if !USE_HASHED_DB static void @@ -76,8 +70,8 @@ write_file(char *filename, TERMTYPE *tp) } DEBUG(1, ("Created %s", filename)); - if (write_object(tp, buffer, &offset, limit) == ERR - || fwrite(buffer, sizeof(char), offset, fp) != offset) { + if (_nc_write_object(tp, buffer, &offset, limit) == ERR + || fwrite(buffer, sizeof(char), (size_t) offset, fp) != offset) { _nc_syserr_abort("error writing %s/%s", _nc_tic_dir(0), filename); } @@ -100,13 +94,13 @@ check_writeable(int code) char dir[sizeof(LEAF_FMT)]; char *s = 0; - if (code == 0 || (s = strchr(dirnames, code)) == 0) + if (code == 0 || (s = (strchr) (dirnames, code)) == 0) _nc_err_abort("Illegal terminfo subdirectory \"" LEAF_FMT "\"", code); if (verified[s - dirnames]) return; - sprintf(dir, LEAF_FMT, code); + _nc_SPRINTF(dir, _nc_SLIMIT(sizeof(dir)) LEAF_FMT, code); if (make_db_root(dir) < 0) { _nc_err_abort("%s/%s: permission denied", _nc_tic_dir(0), dir); } @@ -116,34 +110,35 @@ check_writeable(int code) #endif /* !USE_HASHED_DB */ static int -make_db_path(char *dst, const char *src, unsigned limit) +make_db_path(char *dst, const char *src, size_t limit) { int rc = -1; const char *top = _nc_tic_dir(0); if (src == top || _nc_is_abs_path(src)) { if (strlen(src) + 1 <= limit) { - (void) strcpy(dst, src); + _nc_STRCPY(dst, src, limit); rc = 0; } } else { if (strlen(top) + strlen(src) + 2 <= limit) { - (void) sprintf(dst, "%s/%s", top, src); + _nc_SPRINTF(dst, _nc_SLIMIT(limit) "%s/%s", top, src); rc = 0; } } #if USE_HASHED_DB if (rc == 0) { - if (_nc_is_dir_path(dst)) { - rc = -1; - } else { - unsigned have = strlen(dst); - if (have > 3 && strcmp(dst + have - 3, DBM_SUFFIX)) { - if (have + 3 <= limit) - strcat(dst, DBM_SUFFIX); - else - rc = -1; + static const char suffix[] = DBM_SUFFIX; + size_t have = strlen(dst); + size_t need = strlen(suffix); + if (have > need && strcmp(dst + (int) (have - need), suffix)) { + if (have + need <= limit) { + _nc_STRCAT(dst, suffix, limit); + } else { + rc = -1; } + } else if (_nc_is_dir_path(dst)) { + rc = -1; } } #endif @@ -163,10 +158,11 @@ make_db_root(const char *path) #if USE_HASHED_DB DB *capdbp; - if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL) + if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL) { rc = -1; - else if (_nc_db_close(capdbp) < 0) + } else if (_nc_db_close(capdbp) < 0) { rc = -1; + } #else struct stat statbuf; @@ -190,13 +186,16 @@ make_db_root(const char *path) * Set the write directory for compiled entries. */ NCURSES_EXPORT(void) -_nc_set_writedir(char *dir) +_nc_set_writedir(const char *dir) { const char *destination; char actual[PATH_MAX]; if (dir == 0 - && use_terminfo_vars()) +#ifndef USE_ROOT_ENVIRON + && use_terminfo_vars() +#endif + ) dir = getenv("TERMINFO"); if (dir != 0) @@ -278,16 +277,21 @@ _nc_write_entry(TERMTYPE *const tp) char name_list[MAX_TERMINFO_LENGTH]; char *first_name, *other_names; char *ptr; + char *term_names = tp->term_names; + size_t name_size = strlen(term_names); - assert(strlen(tp->term_names) != 0); - assert(strlen(tp->term_names) < sizeof(name_list)); + if (name_size == 0) { + _nc_syserr_abort("no terminal name found."); + } else if (name_size >= sizeof(name_list) - 1) { + _nc_syserr_abort("terminal name too long: %s", term_names); + } - (void) strcpy(name_list, tp->term_names); + _nc_STRCPY(name_list, term_names, sizeof(name_list)); DEBUG(7, ("Name list = '%s'", name_list)); first_name = name_list; - ptr = &name_list[strlen(name_list) - 1]; + ptr = &name_list[name_size - 1]; other_names = ptr + 1; while (ptr > name_list && *ptr != '|') @@ -313,7 +317,7 @@ _nc_write_entry(TERMTYPE *const tp) _nc_set_type(first_name); #if USE_HASHED_DB - if (write_object(tp, buffer + 1, &offset, limit - 1) != ERR) { + if (_nc_write_object(tp, buffer + 1, &offset, limit - 1) != ERR) { DB *capdb = _nc_db_open(_nc_tic_dir(0), TRUE); DBT key, data; @@ -321,8 +325,8 @@ _nc_write_entry(TERMTYPE *const tp) buffer[0] = 0; memset(&key, 0, sizeof(key)); - key.data = tp->term_names; - key.size = strlen(tp->term_names); + key.data = term_names; + key.size = name_size; memset(&data, 0, sizeof(data)); data.data = buffer; @@ -335,9 +339,13 @@ _nc_write_entry(TERMTYPE *const tp) key.data = name_list; key.size = strlen(name_list); - strcpy(buffer + 1, tp->term_names); - data.size = strlen(tp->term_names) + 1; + _nc_STRCPY(buffer + 1, + term_names, + sizeof(buffer) - 1); + data.size = name_size + 1; + total_size += data.size; + total_parts++; _nc_db_put(capdb, &key, &data); while (*other_names != '\0') { @@ -352,9 +360,10 @@ _nc_write_entry(TERMTYPE *const tp) key.data = ptr; key.size = strlen(ptr); + total_size += data.size; + total_parts++; _nc_db_put(capdb, &key, &data); } - _nc_db_close(capdb); } } #else /* !USE_HASHED_DB */ @@ -362,10 +371,11 @@ _nc_write_entry(TERMTYPE *const tp) start_time = 0; } - if (strlen(first_name) >= sizeof(filename) - 3) + if (strlen(first_name) >= sizeof(filename) - (2 + LEAF_LEN)) _nc_warning("terminal name too long."); - sprintf(filename, LEAF_FMT "/%s", first_name[0], first_name); + _nc_SPRINTF(filename, _nc_SLIMIT(sizeof(filename)) + LEAF_FMT "/%s", first_name[0], first_name); /* * Has this primary name been written since the first call to @@ -375,7 +385,22 @@ _nc_write_entry(TERMTYPE *const tp) if (start_time > 0 && stat(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { +#if HAVE_LINK && !USE_SYMLINKS + /* + * If the file has more than one link, the reason for the previous + * write could be that the current primary name used to be an alias for + * the previous entry. In that case, unlink the file so that we will + * not modify the previous entry as we write this one. + */ + if (statbuf.st_nlink > 1) { + _nc_warning("name redefined."); + unlink(filename); + } else { + _nc_warning("name multiply defined."); + } +#else _nc_warning("name multiply defined."); +#endif } check_writeable(first_name[0]); @@ -396,7 +421,7 @@ _nc_write_entry(TERMTYPE *const tp) if (*other_names != '\0') *(other_names++) = '\0'; - if (strlen(ptr) > sizeof(linkname) - 3) { + if (strlen(ptr) > sizeof(linkname) - (2 + LEAF_LEN)) { _nc_warning("terminal alias %s too long.", ptr); continue; } @@ -406,7 +431,8 @@ _nc_write_entry(TERMTYPE *const tp) } check_writeable(ptr[0]); - sprintf(linkname, LEAF_FMT "/%s", ptr[0], ptr); + _nc_SPRINTF(linkname, _nc_SLIMIT(sizeof(linkname)) + LEAF_FMT "/%s", ptr[0], ptr); if (strcmp(filename, linkname) == 0) { _nc_warning("self-synonym ignored"); @@ -418,13 +444,14 @@ _nc_write_entry(TERMTYPE *const tp) { int code; #if USE_SYMLINKS - if (first_name[0] == linkname[0]) - strncpy(symlinkname, first_name, sizeof(symlinkname) - 1); - else { - strcpy(symlinkname, "../"); - strncat(symlinkname, filename, sizeof(symlinkname) - 4); +#define MY_SIZE sizeof(symlinkname) - 1 + if (first_name[0] == linkname[0]) { + _nc_STRNCPY(symlinkname, first_name, MY_SIZE); + } else { + _nc_STRCPY(symlinkname, "../", sizeof(symlinkname)); + _nc_STRNCPY(symlinkname + 3, filename, MY_SIZE - 3); } - symlinkname[sizeof(symlinkname) - 1] = '\0'; + symlinkname[MY_SIZE] = '\0'; #endif /* USE_SYMLINKS */ #if HAVE_REMOVE code = remove(linkname); @@ -468,29 +495,29 @@ _nc_write_entry(TERMTYPE *const tp) #endif /* USE_HASHED_DB */ } -static unsigned +static size_t fake_write(char *dst, unsigned *offset, - unsigned limit, + size_t limit, char *src, - unsigned want, - unsigned size) + size_t want, + size_t size) { - unsigned have = (limit - *offset); + size_t have = (limit - *offset); want *= size; if (have > 0) { if (want > have) want = have; memcpy(dst + *offset, src, want); - *offset += want; + *offset += (unsigned) want; } else { want = 0; } return (want / size); } -#define Write(buf, size, count) fake_write(buffer, offset, limit, (char *) buf, count, size) +#define Write(buf, size, count) fake_write(buffer, offset, (size_t) limit, (char *) buf, (size_t) count, (size_t) size) #undef LITTLE_ENDIAN /* BSD/OS defines this as a feature macro */ #define HI(x) ((x) / 256) @@ -501,10 +528,10 @@ fake_write(char *dst, #define WRITE_STRING(str) (Write(str, sizeof(char), strlen(str) + 1) == strlen(str) + 1) static int -compute_offsets(char **Strings, unsigned strmax, short *offsets) +compute_offsets(char **Strings, size_t strmax, short *offsets) { int nextfree = 0; - unsigned i; + size_t i; for (i = 0; i < strmax; i++) { if (Strings[i] == ABSENT_STRING) { @@ -522,9 +549,9 @@ compute_offsets(char **Strings, unsigned strmax, short *offsets) } static void -convert_shorts(unsigned char *buf, short *Numbers, unsigned count) +convert_shorts(unsigned char *buf, short *Numbers, size_t count) { - unsigned i; + size_t i; for (i = 0; i < count; i++) { if (Numbers[i] == ABSENT_NUMERIC) { /* HI/LO won't work */ buf[2 * i] = buf[2 * i + 1] = 0377; @@ -533,7 +560,7 @@ convert_shorts(unsigned char *buf, short *Numbers, unsigned count) buf[2 * i + 1] = 0377; } else { LITTLE_ENDIAN(buf + 2 * i, Numbers[i]); - TRACE_OUT(("put Numbers[%d]=%d", i, Numbers[i])); + TRACE_OUT(("put Numbers[%u]=%d", (unsigned) i, Numbers[i])); } } } @@ -576,7 +603,7 @@ extended_Strings(TERMTYPE *tp) for (i = 0; i < tp->ext_Strings; ++i) { if (tp->Strings[STRCOUNT + i] != ABSENT_STRING) - result = (i + 1); + result = (unsigned short) (i + 1); } return result; } @@ -599,8 +626,8 @@ extended_object(TERMTYPE *tp) } #endif -static int -write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) +NCURSES_EXPORT(int) +_nc_write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) { char *namelist; size_t namelen, boolmax, nummax, strmax; @@ -705,7 +732,7 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) return (ERR); nextfree = compute_offsets(tp->Strings + STRCOUNT, - tp->ext_Strings, + (size_t) tp->ext_Strings, offsets); TRACE_OUT(("after extended string capabilities, nextfree=%d", nextfree)); @@ -713,7 +740,7 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) return (ERR); nextfree += compute_offsets(tp->ext_Names, - extcnt, + (size_t) extcnt, offsets + tp->ext_Strings); TRACE_OUT(("after extended capnames, nextfree=%d", nextfree)); strmax = tp->ext_Strings + extcnt; @@ -741,7 +768,7 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) TRACE_OUT(("WRITE %d numbers @%d", tp->ext_Numbers, *offset)); if (tp->ext_Numbers) { - convert_shorts(buf, tp->Numbers + NUMCOUNT, tp->ext_Numbers); + convert_shorts(buf, tp->Numbers + NUMCOUNT, (size_t) tp->ext_Numbers); if (Write(buf, 2, tp->ext_Numbers) != tp->ext_Numbers) return (ERR); } @@ -781,6 +808,8 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) #endif /* NCURSES_XNAMES */ total_written++; + total_parts++; + total_size = total_size + (int) (*offset + 1); return (OK); } @@ -790,5 +819,7 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) NCURSES_EXPORT(int) _nc_tic_written(void) { + TR(TRACE_DATABASE, ("_nc_tic_written %d entries, %d parts, %d size", + total_written, total_parts, total_size)); return total_written; }