From dbe20d453d5e93bd0f1188a8851c6cf4fd230b26 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sat, 11 Nov 2023 00:01:34 -0500 Subject: Extend path_append_ex to truncate compname, remove some strmemdupa remove some duplicated strings previously allocd off the stack just removing string duplications that are easily handled with truncation now available with path_append_ex() this also has an advantage of less stack used in worst case scenarios Change-Id: I3a43e33ef8a8c36599e4c6c036a0ccdd8ed0c883 --- firmware/common/dircache.c | 89 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 26 deletions(-) (limited to 'firmware/common/dircache.c') diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 41564194d0..c5062d47ed 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -2488,44 +2488,81 @@ struct get_path_sub_data static ssize_t get_path_sub(int idx, struct get_path_sub_data *data) { + +#ifdef HAVE_MULTIVOLUME +#define NAMEBUFLEN (MAX(VOL_MAX_LEN+1, MAX_TINYNAME+1)) +#else +#define NAMEBUFLEN (MAX_TINYNAME+1) +#endif + char namebuf[NAMEBUFLEN]; +#undef NAMEBUFLEN + if (idx == 0) return -1; /* entry is an orphan split from any root */ - ssize_t len; - char *cename; + char *cename = ""; + size_t cename_len = (-1u); + ssize_t len = 0; + int next_idx = idx; + int count = 1; /* +1 for the idx incoming */ + int remain; - if (idx > 0) + do /* go all the way up to the root */ { - struct dircache_entry *ce = get_entry(idx); + count++; + if (next_idx > (int)dircache.numentries) + return -1; /* ERROR! */ + next_idx = dircache_runinfo.pentry[next_idx].up; + } while (next_idx > 0); - data->serialhash = dc_hash_serialnum(ce->serialnum, data->serialhash); + if (next_idx < 0) /* root */ + { + data->serialhash = dc_hash_serialnum(get_idx_dcvolp(next_idx)->serialnum, + data->serialhash); +#ifdef HAVE_MULTIVOLUME + /* prepend the volume specifier */ + cename = namebuf; + get_volume_name(IF_MV_VOL(-next_idx - 1), cename); +#endif /* HAVE_MULTIVOLUME */ + } - /* go all the way up then move back down from the root */ - len = get_path_sub(ce->up, data) - 1; - if (len < 0) - return -2; + /* we have the volume name write it to the buffer */ + goto write_path_component; + /* if not MULTIVOLUME it will just be adding '/' */ - cename = alloca(DC_MAX_NAME + 1); - entry_name_copy(cename, ce); - } - else /* idx < 0 */ + while (next_idx > 0 && count > 0) { - len = 0; - cename = ""; + struct dircache_entry *ce = &dircache_runinfo.pentry[next_idx]; + if (remain <= 0) + { + data->serialhash = dc_hash_serialnum(ce->serialnum, data->serialhash); + if (LIKELY(!ce->tinyname)) + { + cename = get_name(ce->name); + cename_len = CE_NAMESIZE(ce->namelen); + } + else + { + cename = namebuf; + entry_name_copy(cename, ce); + cename_len = -1u; + } +write_path_component: + len += path_append_ex(data->buf + len, PA_SEP_HARD, -1u, cename, cename_len, + data->size > (size_t)len ? data->size - len : 0); - #ifdef HAVE_MULTIVOLUME - /* prepend the volume specifier */ - int volume = IF_MV_VOL(-idx - 1); - cename = alloca(VOL_MAX_LEN+1); - get_volume_name(volume, cename); - #endif /* HAVE_MULTIVOLUME */ + count--; + remain = count - 1; + next_idx = idx; + } + else + { + remain--; + next_idx = ce->up; + } - data->serialhash = dc_hash_serialnum(get_idx_dcvolp(idx)->serialnum, - data->serialhash); } - - return len + path_append(data->buf + len, PA_SEP_HARD, cename, - data->size > (size_t)len ? data->size - len : 0); + return len; } /** -- cgit v1.2.3