summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2022-11-14 11:32:34 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2022-11-14 23:56:16 -0500
commitf6c719d7ec71cc7771c46d3daa390924a3871ba3 (patch)
treee6209f23565db01809f75067247e667963092ff6
parentb25a9d8f99b75570d18ea64602de7fe48da612d6 (diff)
downloadrockbox-f6c719d7ec71cc7771c46d3daa390924a3871ba3.tar.gz
rockbox-f6c719d7ec71cc7771c46d3daa390924a3871ba3.zip
replace strlcpy with strmemccpy
replace applicable calls to strlcpy with calls to strmemccpy which null terminates on truncation in theory the strmemccpy calls should be slightly faster since they don't traverse the rest of the source string on truncation but I seriously doubt there is too much of that going on in the code base Change-Id: Ia0251514e36a6242bbf3f03c5e0df123aba60ed2
-rw-r--r--apps/bookmark.c4
-rw-r--r--apps/buffering.c1
-rw-r--r--apps/cuesheet.c22
-rw-r--r--apps/debug_menu.c7
-rw-r--r--apps/gui/folder_select.c6
-rw-r--r--apps/gui/option_select.c8
-rw-r--r--apps/gui/skin_engine/skin_backdrops.c2
-rw-r--r--apps/gui/skin_engine/skin_parser.c2
-rw-r--r--apps/gui/skin_engine/skin_tokens.c2
-rw-r--r--apps/gui/statusbar-skinned.c1
-rw-r--r--apps/hosted/android/keyboard.c2
-rw-r--r--apps/iap/iap-lingo4.c11
-rw-r--r--apps/menus/eq_menu.c2
-rw-r--r--apps/misc.c6
-rw-r--r--apps/onplay.c6
-rw-r--r--apps/open_plugin.c4
-rw-r--r--apps/playlist.c12
-rw-r--r--apps/playlist_catalog.c12
-rw-r--r--apps/playlist_viewer.c6
-rw-r--r--apps/radio/presets.c4
-rw-r--r--apps/radio/radioart.c2
-rw-r--r--apps/recorder/albumart.c4
-rw-r--r--apps/recorder/keyboard.c2
-rw-r--r--apps/recorder/pcm_record.c4
-rw-r--r--apps/root_menu.c2
-rw-r--r--apps/screens.c8
-rw-r--r--apps/settings.c35
-rw-r--r--apps/settings_list.c4
-rw-r--r--apps/shortcuts.c10
-rw-r--r--apps/tagcache.c8
-rw-r--r--apps/tagtree.c18
-rw-r--r--apps/talk.c27
-rw-r--r--apps/tree.c10
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/buflib.c4
-rw-r--r--firmware/common/dircache.c8
-rw-r--r--firmware/common/strlcpy.c64
-rw-r--r--firmware/common/strmemccpy.c38
-rw-r--r--firmware/drivers/lcd-bitmap-common.c2
-rw-r--r--firmware/font.c2
-rw-r--r--firmware/general.c4
-rw-r--r--firmware/include/string-extra.h1
-rw-r--r--firmware/include/strmemccpy.h32
43 files changed, 236 insertions, 174 deletions
diff --git a/apps/bookmark.c b/apps/bookmark.c
index d594c51320..0cc2807609 100644
--- a/apps/bookmark.c
+++ b/apps/bookmark.c
@@ -1075,7 +1075,7 @@ static bool parse_bookmark(const char *bookmark, const bool parse_filenames, con
1075 { 1075 {
1076 size_t len = (end == NULL) ? strlen(s) : (size_t) (end - s); 1076 size_t len = (end == NULL) ? strlen(s) : (size_t) (end - s);
1077 len = MIN(TEMP_BUF_SIZE - 1, len); 1077 len = MIN(TEMP_BUF_SIZE - 1, len);
1078 strlcpy(global_temp_buffer, s, len + 1); 1078 strmemccpy(global_temp_buffer, s, len + 1);
1079 1079
1080 if (end != NULL) 1080 if (end != NULL)
1081 { 1081 {
@@ -1089,7 +1089,7 @@ static bool parse_bookmark(const char *bookmark, const bool parse_filenames, con
1089 end++; 1089 end++;
1090 } 1090 }
1091 } 1091 }
1092 strlcpy(global_filename, end, MAX_PATH); 1092 strmemccpy(global_filename, end, MAX_PATH);
1093 } 1093 }
1094 } 1094 }
1095 1095
diff --git a/apps/buffering.c b/apps/buffering.c
index 8661a42ab8..9743c9c319 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -20,7 +20,6 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "config.h" 21#include "config.h"
22#include <string.h> 22#include <string.h>
23#include "strlcpy.h"
24#include "system.h" 23#include "system.h"
25#include "storage.h" 24#include "storage.h"
26#include "thread.h" 25#include "thread.h"
diff --git a/apps/cuesheet.c b/apps/cuesheet.c
index da14147262..561be6a677 100644
--- a/apps/cuesheet.c
+++ b/apps/cuesheet.c
@@ -58,7 +58,7 @@ static bool search_for_cuesheet(const char *path, struct cuesheet_file *cue_file
58 slash_cuepath = &cuepath[slash - path]; 58 slash_cuepath = &cuepath[slash - path];
59 dot = strrchr(slash_cuepath, '.'); 59 dot = strrchr(slash_cuepath, '.');
60 if (dot) 60 if (dot)
61 strlcpy(dot, ".cue", MAX_PATH - (dot-cuepath)); 61 strmemccpy(dot, ".cue", MAX_PATH - (dot-cuepath));
62 62
63 if (!dot || !file_exists(cuepath)) 63 if (!dot || !file_exists(cuepath))
64 { 64 {
@@ -72,14 +72,14 @@ static bool search_for_cuesheet(const char *path, struct cuesheet_file *cue_file
72skip: 72skip:
73 if ((len+4) >= MAX_PATH) 73 if ((len+4) >= MAX_PATH)
74 return false; 74 return false;
75 strlcpy(cuepath, path, MAX_PATH); 75 strmemccpy(cuepath, path, MAX_PATH);
76 strlcat(cuepath, ".cue", MAX_PATH); 76 strlcat(cuepath, ".cue", MAX_PATH);
77 if (!file_exists(cuepath)) 77 if (!file_exists(cuepath))
78 return false; 78 return false;
79 } 79 }
80 } 80 }
81 81
82 strlcpy(cue_file->path, cuepath, MAX_PATH); 82 strmemccpy(cue_file->path, cuepath, MAX_PATH);
83 return true; 83 return true;
84} 84}
85 85
@@ -91,7 +91,7 @@ bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cu
91 cue_file->pos = track_id3->embedded_cuesheet.pos; 91 cue_file->pos = track_id3->embedded_cuesheet.pos;
92 cue_file->size = track_id3->embedded_cuesheet.size; 92 cue_file->size = track_id3->embedded_cuesheet.size;
93 cue_file->encoding = track_id3->embedded_cuesheet.encoding; 93 cue_file->encoding = track_id3->embedded_cuesheet.encoding;
94 strlcpy(cue_file->path, track_id3->path, MAX_PATH); 94 strmemccpy(cue_file->path, track_id3->path, MAX_PATH);
95 return true; 95 return true;
96 } 96 }
97 97
@@ -363,7 +363,7 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
363 } 363 }
364 else 364 else
365 { 365 {
366 strlcpy(dest, string, count); 366 strmemccpy(dest, string, count);
367 } 367 }
368 } 368 }
369 } 369 }
@@ -386,7 +386,7 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
386 strcpy(cue->file, cue->path); 386 strcpy(cue->file, cue->path);
387 char *slash = strrchr(cue->file, '/'); 387 char *slash = strrchr(cue->file, '/');
388 if (!slash++) slash = cue->file; 388 if (!slash++) slash = cue->file;
389 strlcpy(slash, line, MAX_PATH - (slash - cue->file)); 389 strmemccpy(slash, line, MAX_PATH - (slash - cue->file));
390 } 390 }
391 391
392 /* If some songs don't have performer info, we copy the cuesheet performer */ 392 /* If some songs don't have performer info, we copy the cuesheet performer */
@@ -394,10 +394,10 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
394 for (i = 0; i < cue->track_count; i++) 394 for (i = 0; i < cue->track_count; i++)
395 { 395 {
396 if (*(cue->tracks[i].performer) == '\0') 396 if (*(cue->tracks[i].performer) == '\0')
397 strlcpy(cue->tracks[i].performer, cue->performer, MAX_NAME*3); 397 strmemccpy(cue->tracks[i].performer, cue->performer, MAX_NAME*3);
398 398
399 if (*(cue->tracks[i].songwriter) == '\0') 399 if (*(cue->tracks[i].songwriter) == '\0')
400 strlcpy(cue->tracks[i].songwriter, cue->songwriter, MAX_NAME*3); 400 strmemccpy(cue->tracks[i].songwriter, cue->songwriter, MAX_NAME*3);
401 } 401 }
402 402
403 return true; 403 return true;
@@ -441,7 +441,7 @@ static const char* list_get_name_cb(int selected_item,
441 struct cuesheet *cue = (struct cuesheet *)data; 441 struct cuesheet *cue = (struct cuesheet *)data;
442 442
443 if (selected_item & 1) 443 if (selected_item & 1)
444 strlcpy(buffer, cue->tracks[selected_item/2].title, buffer_len); 444 strmemccpy(buffer, cue->tracks[selected_item/2].title, buffer_len);
445 else 445 else
446 snprintf(buffer, buffer_len, "%02d. %s", selected_item/2+1, 446 snprintf(buffer, buffer_len, "%02d. %s", selected_item/2+1,
447 cue->tracks[selected_item/2].performer); 447 cue->tracks[selected_item/2].performer);
@@ -508,7 +508,7 @@ void browse_cuesheet(struct cuesheet *cue)
508 /* check that this cue is the same one that would be found by 508 /* check that this cue is the same one that would be found by
509 a search from playback */ 509 a search from playback */
510 char file[MAX_PATH]; 510 char file[MAX_PATH];
511 strlcpy(file, cue->file, MAX_PATH); 511 strmemccpy(file, cue->file, MAX_PATH);
512 512
513 if (!strcmp(cue->path, file) || /* if embedded */ 513 if (!strcmp(cue->path, file) || /* if embedded */
514 (search_for_cuesheet(file, &cue_file) && 514 (search_for_cuesheet(file, &cue_file) &&
@@ -535,7 +535,7 @@ bool display_cuesheet_content(char* filename)
535 if (!cue || bufsize < sizeof(struct cuesheet)) 535 if (!cue || bufsize < sizeof(struct cuesheet))
536 return false; 536 return false;
537 537
538 strlcpy(cue_file.path, filename, MAX_PATH); 538 strmemccpy(cue_file.path, filename, MAX_PATH);
539 cue_file.pos = 0; 539 cue_file.pos = 0;
540 cue_file.size = 0; 540 cue_file.size = 0;
541 541
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 0b0bc8fc2b..5ebaa3a3f4 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -23,7 +23,7 @@
23#include <stdlib.h> 23#include <stdlib.h>
24#include <stdio.h> 24#include <stdio.h>
25#include <stdbool.h> 25#include <stdbool.h>
26#include <string.h> 26#include <string-extra.h>
27#include "lcd.h" 27#include "lcd.h"
28#include "lang.h" 28#include "lang.h"
29#include "menu.h" 29#include "menu.h"
@@ -1274,7 +1274,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
1274 { 1274 {
1275 card_name[i] = card_extract_bits(card->cid, (103-8*i), 8); 1275 card_name[i] = card_extract_bits(card->cid, (103-8*i), 8);
1276 } 1276 }
1277 strlcpy(card_name, card_name, sizeof(card_name)); 1277 strmemccpy(card_name, card_name, sizeof(card_name));
1278 simplelist_addline( 1278 simplelist_addline(
1279 "%s Rev %d.%d", card_name, 1279 "%s Rev %d.%d", card_name,
1280 (int) card_extract_bits(card->cid, 63, 4), 1280 (int) card_extract_bits(card->cid, 63, 4),
@@ -1628,8 +1628,7 @@ static int ata_smart_attr_to_string(
1628 slen += len; 1628 slen += len;
1629 } 1629 }
1630 1630
1631 if (!memccpy (str+slen, buf, '\0', size-slen)) 1631 strmemccpy(str+slen, buf, size-slen);
1632 (str+slen)[size-slen - 1] = '\0';
1633 } 1632 }
1634 1633
1635 return 1; /* ok */ 1634 return 1; /* ok */
diff --git a/apps/gui/folder_select.c b/apps/gui/folder_select.c
index 50d25e7305..a76d77562b 100644
--- a/apps/gui/folder_select.c
+++ b/apps/gui/folder_select.c
@@ -185,7 +185,7 @@ static struct folder* load_folder(struct folder* parent, char *folder)
185 if (len >= sizeof(fullpath)) 185 if (len >= sizeof(fullpath))
186 goto fail; 186 goto fail;
187 } 187 }
188 strlcpy(&fullpath[len], folder, sizeof(fullpath) - len); 188 strmemccpy(&fullpath[len], folder, sizeof(fullpath) - len);
189 logf("load_folder: [%s]", fullpath); 189 logf("load_folder: [%s]", fullpath);
190 190
191 dir = opendir(fullpath); 191 dir = opendir(fullpath);
@@ -518,7 +518,7 @@ static int select_paths(struct folder* root, const char* filenames)
518 lastfnp = fnp; 518 lastfnp = fnp;
519 if (len <= 0 || len + 1 >= buflen) 519 if (len <= 0 || len + 1 >= buflen)
520 continue; 520 continue;
521 strlcpy(buf, sstr, len + 1); 521 strmemccpy(buf, sstr, len + 1);
522 struct child *item = find_from_filename(buf, root); 522 struct child *item = find_from_filename(buf, root);
523 if (item) 523 if (item)
524 item->state = SELECTED; 524 item->state = SELECTED;
@@ -563,7 +563,7 @@ static void save_folders_r(struct folder *root, char* dst, size_t maxlen, size_t
563 int dlen = strlen(dst); 563 int dlen = strlen(dst);
564 if (dlen + len >= maxlen) 564 if (dlen + len >= maxlen)
565 continue; 565 continue;
566 strlcpy(&dst[dlen], buffer_front, maxlen - dlen); 566 strmemccpy(&dst[dlen], buffer_front, maxlen - dlen);
567 } 567 }
568 else 568 else
569 { 569 {
diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c
index e154467428..4687367fba 100644
--- a/apps/gui/option_select.c
+++ b/apps/gui/option_select.c
@@ -68,8 +68,8 @@ const char *option_get_valuestring(const struct settings_list *setting,
68 if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) 68 if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING)
69 { 69 {
70 bool val = (bool)temp_var; 70 bool val = (bool)temp_var;
71 strlcpy(buffer, str(val? setting->bool_setting->lang_yes : 71 strmemccpy(buffer, str(val? setting->bool_setting->lang_yes :
72 setting->bool_setting->lang_no), buf_len); 72 setting->bool_setting->lang_no), buf_len);
73 } 73 }
74#if 0 /* probably dont need this one */ 74#if 0 /* probably dont need this one */
75 else if ((setting->flags & F_FILENAME) == F_FILENAME) 75 else if ((setting->flags & F_FILENAME) == F_FILENAME)
@@ -121,7 +121,7 @@ const char *option_get_valuestring(const struct settings_list *setting,
121 const struct choice_setting *info = setting->choice_setting; 121 const struct choice_setting *info = setting->choice_setting;
122 if (info->talks[(int)temp_var] < LANG_LAST_INDEX_IN_ARRAY) 122 if (info->talks[(int)temp_var] < LANG_LAST_INDEX_IN_ARRAY)
123 { 123 {
124 strlcpy(buffer, str(info->talks[(int)temp_var]), buf_len); 124 strmemccpy(buffer, str(info->talks[(int)temp_var]), buf_len);
125 } 125 }
126 else 126 else
127 { 127 {
@@ -133,7 +133,7 @@ const char *option_get_valuestring(const struct settings_list *setting,
133 { 133 {
134 int value = (int)temp_var; 134 int value = (int)temp_var;
135 char *val = P2STR(setting->choice_setting->desc[value]); 135 char *val = P2STR(setting->choice_setting->desc[value]);
136 strlcpy(buffer, val, buf_len); 136 strmemccpy(buffer, val, buf_len);
137 } 137 }
138 } 138 }
139 return str; 139 return str;
diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c
index 215667d585..8be40d1ce2 100644
--- a/apps/gui/skin_engine/skin_backdrops.c
+++ b/apps/gui/skin_engine/skin_backdrops.c
@@ -137,7 +137,7 @@ int skin_backdrop_assign(char* backdrop, char *bmpdir,
137 } 137 }
138 if (free >= 0) 138 if (free >= 0)
139 { 139 {
140 strlcpy(backdrops[free].name, filename, MAX_PATH); 140 strmemccpy(backdrops[free].name, filename, MAX_PATH);
141 backdrops[free].buffer = NULL; 141 backdrops[free].buffer = NULL;
142 backdrops[free].screen = screen; 142 backdrops[free].screen = screen;
143 backdrops[free].ref_count = 1; 143 backdrops[free].ref_count = 1;
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index 419e49810d..4e3b7e4d12 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -2548,7 +2548,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
2548 { 2548 {
2549 /* get the bitmap dir */ 2549 /* get the bitmap dir */
2550 char *dot = strrchr(buf, '.'); 2550 char *dot = strrchr(buf, '.');
2551 strlcpy(bmpdir, buf, dot - buf + 1); 2551 strmemccpy(bmpdir, buf, dot - buf + 1);
2552 } 2552 }
2553 else 2553 else
2554 { 2554 {
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c
index a1d0a4b840..6d9d489a17 100644
--- a/apps/gui/skin_engine/skin_tokens.c
+++ b/apps/gui/skin_engine/skin_tokens.c
@@ -114,7 +114,7 @@ char* get_dir(char* buf, int buf_size, const char* path, int level)
114 return NULL; 114 return NULL;
115 115
116 len = MIN(last_sep - sep, buf_size - 1); 116 len = MIN(last_sep - sep, buf_size - 1);
117 strlcpy(buf, sep + 1, len + 1); 117 strmemccpy(buf, sep + 1, len + 1);
118 return buf; 118 return buf;
119} 119}
120 120
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index 5d2b65846d..d6dddf5cd2 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -27,7 +27,6 @@
27#include "appevents.h" 27#include "appevents.h"
28#include "screens.h" 28#include "screens.h"
29#include "screen_access.h" 29#include "screen_access.h"
30#include "strlcpy.h"
31#include "skin_parser.h" 30#include "skin_parser.h"
32#include "skin_buffer.h" 31#include "skin_buffer.h"
33#include "skin_engine/skin_engine.h" 32#include "skin_engine/skin_engine.h"
diff --git a/apps/hosted/android/keyboard.c b/apps/hosted/android/keyboard.c
index eda951a7c9..b74f67e782 100644
--- a/apps/hosted/android/keyboard.c
+++ b/apps/hosted/android/keyboard.c
@@ -100,7 +100,7 @@ int kbd_input(char* text, int buflen, unsigned short *kbd)
100 if (accepted) 100 if (accepted)
101 { 101 {
102 utf8_string = e->GetStringUTFChars(env_ptr, new_string, 0); 102 utf8_string = e->GetStringUTFChars(env_ptr, new_string, 0);
103 strlcpy(text, utf8_string, buflen); 103 strmemccpy(text, utf8_string, buflen);
104 e->ReleaseStringUTFChars(env_ptr, new_string, utf8_string); 104 e->ReleaseStringUTFChars(env_ptr, new_string, utf8_string);
105 e->DeleteGlobalRef(env_ptr, new_string); 105 e->DeleteGlobalRef(env_ptr, new_string);
106 } 106 }
diff --git a/apps/iap/iap-lingo4.c b/apps/iap/iap-lingo4.c
index abb13eac02..77ddeabcb3 100644
--- a/apps/iap/iap-lingo4.c
+++ b/apps/iap/iap-lingo4.c
@@ -87,7 +87,7 @@ static void get_playlist_name(unsigned char *dest,
87 } 87 }
88 } 88 }
89 if (playlist_file != NULL) { 89 if (playlist_file != NULL) {
90 strlcpy(dest, playlist_file->d_name, max_length); 90 strmemccpy(dest, playlist_file->d_name, max_length);
91 } 91 }
92 closedir(dp); 92 closedir(dp);
93} 93}
@@ -1465,22 +1465,21 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
1465 switch(buf[3]) 1465 switch(buf[3])
1466 { 1466 {
1467 case 0x05: 1467 case 0x05:
1468 len = strlcpy((char *)&data[7], id3.title,64); 1468 strmemccpy((char *)&data[7], id3.title,64);
1469 break; 1469 break;
1470 case 0x02: 1470 case 0x02:
1471 len = strlcpy((char *)&data[7], id3.artist,64); 1471 strmemccpy((char *)&data[7], id3.artist,64);
1472 break; 1472 break;
1473 case 0x03: 1473 case 0x03:
1474 len = strlcpy((char *)&data[7], id3.album,64); 1474 strmemccpy((char *)&data[7], id3.album,64);
1475 break; 1475 break;
1476 case 0x04: 1476 case 0x04:
1477 case 0x06: 1477 case 0x06:
1478 len = strlcpy((char *)&data[7], "Not Supported",14); 1478 strmemccpy((char *)&data[7], "Not Supported",14);
1479 break; 1479 break;
1480 } 1480 }
1481 break; 1481 break;
1482 } 1482 }
1483 (void)len; /* Shut up, compiler */
1484 put_u32(&data[3], start_index+counter); 1483 put_u32(&data[3], start_index+counter);
1485 iap_send_pkt(data, 7 + strlen(data+7) + 1); 1484 iap_send_pkt(data, 7 + strlen(data+7) + 1);
1486 yield(); 1485 yield();
diff --git a/apps/menus/eq_menu.c b/apps/menus/eq_menu.c
index 2bf26e2b5a..a0b00644ec 100644
--- a/apps/menus/eq_menu.c
+++ b/apps/menus/eq_menu.c
@@ -287,7 +287,7 @@ static char *advancedmenu_item_get_name(int selected_item, void *data, char *buf
287 buffer[0] = 0; 287 buffer[0] = 0;
288 else { 288 else {
289 buffer[0] = '\t'; 289 buffer[0] = '\t';
290 strlcpy(&buffer[1], str(lang), len - 1); 290 strmemccpy(&buffer[1], str(lang), len - 1);
291 } 291 }
292 292
293 return buffer; 293 return buffer;
diff --git a/apps/misc.c b/apps/misc.c
index 0ad1e62902..338ef9be19 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -896,7 +896,7 @@ char *strip_extension(char* buffer, int buffer_size, const char *filename)
896 /* no match on filename beginning with '.' or beyond buffer_size */ 896 /* no match on filename beginning with '.' or beyond buffer_size */
897 if(dotpos > 1 && dotpos < buffer_size) 897 if(dotpos > 1 && dotpos < buffer_size)
898 buffer_size = dotpos; 898 buffer_size = dotpos;
899 strlcpy(buffer, filename, buffer_size); 899 strmemccpy(buffer, filename, buffer_size);
900 900
901 return buffer; 901 return buffer;
902} 902}
@@ -1335,12 +1335,12 @@ const char *format_time_auto(char *buffer, int buf_len, long value,
1335 1335
1336 if (!supress_unit) 1336 if (!supress_unit)
1337 { 1337 {
1338 strlcpy(buffer, unit_strings_core[units[max_idx]], buf_len); 1338 strmemccpy(buffer, unit_strings_core[units[max_idx]], buf_len);
1339 left_offset += strlcat(buffer, " ", buf_len); 1339 left_offset += strlcat(buffer, " ", buf_len);
1340 strlcat(buffer, &timebuf[offsets[base_idx]], buf_len); 1340 strlcat(buffer, &timebuf[offsets[base_idx]], buf_len);
1341 } 1341 }
1342 else 1342 else
1343 strlcpy(buffer, &timebuf[offsets[base_idx]], buf_len); 1343 strmemccpy(buffer, &timebuf[offsets[base_idx]], buf_len);
1344 1344
1345 strlcat(buffer, sign, buf_len); 1345 strlcat(buffer, sign, buf_len);
1346 } 1346 }
diff --git a/apps/onplay.c b/apps/onplay.c
index bb93d204e0..8d53e26fc5 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -1587,7 +1587,7 @@ MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES),
1587#if LCD_DEPTH > 1 1587#if LCD_DEPTH > 1
1588static bool set_backdrop(void) 1588static bool set_backdrop(void)
1589{ 1589{
1590 strlcpy(global_settings.backdrop_file, selected_file, 1590 strmemccpy(global_settings.backdrop_file, selected_file,
1591 sizeof(global_settings.backdrop_file)); 1591 sizeof(global_settings.backdrop_file));
1592 settings_save(); 1592 settings_save();
1593 skin_backdrop_load_setting(); 1593 skin_backdrop_load_setting();
@@ -1600,7 +1600,7 @@ MENUITEM_FUNCTION(set_backdrop_item, 0, ID2P(LANG_SET_AS_BACKDROP),
1600#ifdef HAVE_RECORDING 1600#ifdef HAVE_RECORDING
1601static bool set_recdir(void) 1601static bool set_recdir(void)
1602{ 1602{
1603 strlcpy(global_settings.rec_directory, selected_file, 1603 strmemccpy(global_settings.rec_directory, selected_file,
1604 sizeof(global_settings.rec_directory)); 1604 sizeof(global_settings.rec_directory));
1605 settings_save(); 1605 settings_save();
1606 return false; 1606 return false;
@@ -1937,7 +1937,7 @@ int onplay(char* file, int attr, int from, bool hotkey)
1937 selected_file = NULL; 1937 selected_file = NULL;
1938 else 1938 else
1939 { 1939 {
1940 strlcpy(selected_file_path, file, MAX_PATH); 1940 strmemccpy(selected_file_path, file, MAX_PATH);
1941 selected_file = selected_file_path; 1941 selected_file = selected_file_path;
1942 } 1942 }
1943 selected_file_attr = attr; 1943 selected_file_attr = attr;
diff --git a/apps/open_plugin.c b/apps/open_plugin.c
index fad528e215..67b6f6d318 100644
--- a/apps/open_plugin.c
+++ b/apps/open_plugin.c
@@ -270,11 +270,11 @@ uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *p
270 if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0) 270 if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0)
271 { 271 {
272 /* path */ 272 /* path */
273 strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ); 273 strmemccpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
274 274
275 if(!parameter) 275 if(!parameter)
276 parameter = ""; 276 parameter = "";
277 strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ); 277 strmemccpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
278 goto retnhash; 278 goto retnhash;
279 } 279 }
280 else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0) 280 else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0)
diff --git a/apps/playlist.c b/apps/playlist.c
index 888b53d282..ab5c59328a 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -1457,7 +1457,7 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
1457 } 1457 }
1458 } 1458 }
1459 1459
1460 strlcpy(dir_buf, playlist->filename, playlist->dirlen); 1460 strmemccpy(dir_buf, playlist->filename, playlist->dirlen);
1461 1461
1462 return format_track_path(buf, tmp_buf, buf_length, dir_buf); 1462 return format_track_path(buf, tmp_buf, buf_length, dir_buf);
1463 1463
@@ -1551,7 +1551,7 @@ static int get_next_dir(char *dir, bool is_forward)
1551 1551
1552 /* if the current file is within our base dir, use its dir instead */ 1552 /* if the current file is within our base dir, use its dir instead */
1553 if (base_len == 0 || !strncmp(playlist->filename, dir, base_len)) 1553 if (base_len == 0 || !strncmp(playlist->filename, dir, base_len))
1554 strlcpy(dir, playlist->filename, playlist->dirlen); 1554 strmemccpy(dir, playlist->filename, playlist->dirlen);
1555 1555
1556 /* use the tree browser dircache to load files */ 1556 /* use the tree browser dircache to load files */
1557 *(tc->dirfilter) = SHOW_ALL; 1557 *(tc->dirfilter) = SHOW_ALL;
@@ -2034,7 +2034,7 @@ void playlist_init(void)
2034 mutex_init(&created_playlist_mutex); 2034 mutex_init(&created_playlist_mutex);
2035 2035
2036 playlist->current = true; 2036 playlist->current = true;
2037 strlcpy(playlist->control_filename, PLAYLIST_CONTROL_FILE, 2037 strmemccpy(playlist->control_filename, PLAYLIST_CONTROL_FILE,
2038 sizeof(playlist->control_filename)); 2038 sizeof(playlist->control_filename));
2039 playlist->fd = -1; 2039 playlist->fd = -1;
2040 playlist->control_fd = -1; 2040 playlist->control_fd = -1;
@@ -2955,7 +2955,7 @@ int playlist_set_current(struct playlist_info* playlist)
2955 2955
2956 empty_playlist(&current_playlist, false); 2956 empty_playlist(&current_playlist, false);
2957 2957
2958 strlcpy(current_playlist.filename, playlist->filename, 2958 strmemccpy(current_playlist.filename, playlist->filename,
2959 sizeof(current_playlist.filename)); 2959 sizeof(current_playlist.filename));
2960 2960
2961 current_playlist.utf8 = playlist->utf8; 2961 current_playlist.utf8 = playlist->utf8;
@@ -3517,7 +3517,7 @@ char *playlist_name(const struct playlist_info* playlist, char *buf,
3517 if (!playlist) 3517 if (!playlist)
3518 playlist = &current_playlist; 3518 playlist = &current_playlist;
3519 3519
3520 strlcpy(buf, playlist->filename+playlist->dirlen, buf_size); 3520 strmemccpy(buf, playlist->filename+playlist->dirlen, buf_size);
3521 3521
3522 if (!buf[0]) 3522 if (!buf[0])
3523 return NULL; 3523 return NULL;
@@ -3537,7 +3537,7 @@ char *playlist_get_name(const struct playlist_info* playlist, char *buf,
3537 if (!playlist) 3537 if (!playlist)
3538 playlist = &current_playlist; 3538 playlist = &current_playlist;
3539 3539
3540 strlcpy(buf, playlist->filename, buf_size); 3540 strmemccpy(buf, playlist->filename, buf_size);
3541 3541
3542 if (!buf[0]) 3542 if (!buf[0])
3543 return NULL; 3543 return NULL;
diff --git a/apps/playlist_catalog.c b/apps/playlist_catalog.c
index 98a2bb4cdb..0813db11c6 100644
--- a/apps/playlist_catalog.c
+++ b/apps/playlist_catalog.c
@@ -128,8 +128,8 @@ void catalog_set_directory(const char* directory)
128 } 128 }
129 else 129 else
130 { 130 {
131 strlcpy(global_settings.playlist_catalog_dir, 131 strmemccpy(global_settings.playlist_catalog_dir,
132 directory, sizeof(global_settings.playlist_catalog_dir)); 132 directory, sizeof(global_settings.playlist_catalog_dir));
133 } 133 }
134 initialized = false; 134 initialized = false;
135 initialize_catalog(); 135 initialize_catalog();
@@ -164,8 +164,8 @@ restart:
164 164
165 if (browse.flags & BROWSE_SELECTED) 165 if (browse.flags & BROWSE_SELECTED)
166 { 166 {
167 strlcpy(most_recent_playlist, selected_playlist+playlist_dir_length+1, 167 strmemccpy(most_recent_playlist, selected_playlist+playlist_dir_length+1,
168 sizeof(most_recent_playlist)); 168 sizeof(most_recent_playlist));
169 169
170 if (view) 170 if (view)
171 { 171 {
@@ -180,7 +180,7 @@ restart:
180 else 180 else
181 { 181 {
182 result = 0; 182 result = 0;
183 strlcpy(playlist, selected_playlist, MAX_PATH); 183 strmemccpy(playlist, selected_playlist, MAX_PATH);
184 } 184 }
185 } 185 }
186 186
@@ -360,7 +360,7 @@ bool catalog_add_to_a_playlist(const char* sel, int sel_attr,
360 (name!=NULL && (sel_attr & ATTR_DIRECTORY))?name+1:""); 360 (name!=NULL && (sel_attr & ATTR_DIRECTORY))?name+1:"");
361 } 361 }
362 else 362 else
363 strlcpy(playlist, m3u8name, MAX_PATH); 363 strmemccpy(playlist, m3u8name, MAX_PATH);
364 364
365 if (kbd_input(playlist, MAX_PATH, NULL)) 365 if (kbd_input(playlist, MAX_PATH, NULL))
366 return false; 366 return false;
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index f1f8954113..6c80b373a9 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -517,8 +517,7 @@ static enum pv_onplay_result open_with(const struct playlist_entry *current_trac
517 char selected_track[MAX_PATH]; 517 char selected_track[MAX_PATH];
518 close_playlist_viewer(); 518 close_playlist_viewer();
519 519
520 if (!memccpy (selected_track, current_track->name, '\0', sizeof(selected_track))) 520 strmemccpy(selected_track, current_track->name, sizeof(selected_track));
521 selected_track[sizeof(selected_track) - 1] = '\0';
522 521
523 522
524 return (filetype_list_viewers(selected_track) == 523 return (filetype_list_viewers(selected_track) ==
@@ -532,8 +531,7 @@ static enum pv_onplay_result open_pictureflow(const struct playlist_entry *curre
532 char selected_track[MAX_PATH]; 531 char selected_track[MAX_PATH];
533 close_playlist_viewer(); 532 close_playlist_viewer();
534 533
535 if (!memccpy (selected_track, current_track->name, '\0', sizeof(selected_track))) 534 strmemccpy(selected_track, current_track->name, sizeof(selected_track));
536 selected_track[sizeof(selected_track) - 1] = '\0';
537 535
538 return (filetype_load_plugin((void *)"pictureflow", selected_track) == 536 return (filetype_load_plugin((void *)"pictureflow", selected_track) ==
539 PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED); 537 PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED);
diff --git a/apps/radio/presets.c b/apps/radio/presets.c
index 6966f7e591..1cd85637e8 100644
--- a/apps/radio/presets.c
+++ b/apps/radio/presets.c
@@ -225,7 +225,7 @@ void radio_load_presets(char *filename)
225 } 225 }
226 /* Temporary preset, loaded until player shuts down. */ 226 /* Temporary preset, loaded until player shuts down. */
227 else if(filename[0] == '/') 227 else if(filename[0] == '/')
228 strlcpy(filepreset, filename, sizeof(filepreset)); 228 strmemccpy(filepreset, filename, sizeof(filepreset));
229 /* Preset from default directory. */ 229 /* Preset from default directory. */
230 else 230 else
231 snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr", 231 snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
@@ -246,7 +246,7 @@ void radio_load_presets(char *filename)
246 { 246 {
247 struct fmstation * const fms = &presets[num_presets]; 247 struct fmstation * const fms = &presets[num_presets];
248 fms->frequency = f; 248 fms->frequency = f;
249 strlcpy(fms->name, name, MAX_FMPRESET_LEN+1); 249 strmemccpy(fms->name, name, MAX_FMPRESET_LEN+1);
250 num_presets++; 250 num_presets++;
251 } 251 }
252 } 252 }
diff --git a/apps/radio/radioart.c b/apps/radio/radioart.c
index 34efdea0da..230948c051 100644
--- a/apps/radio/radioart.c
+++ b/apps/radio/radioart.c
@@ -82,7 +82,7 @@ static int load_radioart_image(struct radioart *ra, const char* preset_name,
82#endif 82#endif
83 return -1; 83 return -1;
84 } 84 }
85 strlcpy(ra->name, preset_name, MAX_FMPRESET_LEN+1); 85 strmemccpy(ra->name, preset_name, MAX_FMPRESET_LEN+1);
86 ra->dim.height = dim->height; 86 ra->dim.height = dim->height;
87 ra->dim.width = dim->width; 87 ra->dim.width = dim->width;
88 ra->last_tick = current_tick; 88 ra->last_tick = current_tick;
diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c
index e94ffcfb80..8991a81848 100644
--- a/apps/recorder/albumart.c
+++ b/apps/recorder/albumart.c
@@ -67,7 +67,7 @@ static char* strip_filename(char* buf, int buf_size, const char* fullpath)
67 } 67 }
68 68
69 len = MIN(sep - fullpath + 1, buf_size - 1); 69 len = MIN(sep - fullpath + 1, buf_size - 1);
70 strlcpy(buf, fullpath, len + 1); 70 strmemccpy(buf, fullpath, len + 1);
71 return (sep + 1); 71 return (sep + 1);
72} 72}
73 73
@@ -266,7 +266,7 @@ bool search_albumart_files(const struct mp3entry *id3, const char *size_string,
266 if (!found) 266 if (!found)
267 return false; 267 return false;
268 268
269 strlcpy(buf, path, buflen); 269 strmemccpy(buf, path, buflen);
270 logf("Album art found: %s", path); 270 logf("Album art found: %s", path);
271 return true; 271 return true;
272} 272}
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c
index 45cccdcf8b..f64061d303 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -1063,7 +1063,7 @@ static void kbd_draw_edit_line(struct keyboard_parameters *pm,
1063 while (*utf8 && i < pm->max_chars_text) 1063 while (*utf8 && i < pm->max_chars_text)
1064 { 1064 {
1065 j = utf8seek(utf8, 1); 1065 j = utf8seek(utf8, 1);
1066 strlcpy(outline, utf8, j+1); 1066 strmemccpy(outline, utf8, j+1);
1067 sc->getstringsize(outline, &w, NULL); 1067 sc->getstringsize(outline, &w, NULL);
1068 sc->putsxy(text_margin + i*pm->text_w + (pm->text_w-w)/2, 1068 sc->putsxy(text_margin + i*pm->text_w + (pm->text_w-w)/2,
1069 y, outline); 1069 y, outline);
diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c
index d3d45d3e1c..f7f4c77928 100644
--- a/apps/recorder/pcm_record.c
+++ b/apps/recorder/pcm_record.c
@@ -1352,7 +1352,7 @@ static void mark_stream(const char *path, enum mark_stream_action action)
1352 1352
1353 file->hdr.type = CHUNK_T_STREAM_START; 1353 file->hdr.type = CHUNK_T_STREAM_START;
1354 file->hdr.size = count; 1354 file->hdr.size = count;
1355 strlcpy(file->path, path, MAX_PATH); 1355 strmemccpy(file->path, path, MAX_PATH);
1356 } 1356 }
1357} 1357}
1358 1358
@@ -1582,7 +1582,7 @@ static void on_record(const char *filename)
1582 1582
1583 /* Copy path and let caller go */ 1583 /* Copy path and let caller go */
1584 char path[MAX_PATH]; 1584 char path[MAX_PATH];
1585 strlcpy(path, filename, MAX_PATH); 1585 strmemccpy(path, filename, MAX_PATH);
1586 1586
1587 queue_reply(&audio_queue, 0); 1587 queue_reply(&audio_queue, 0);
1588 1588
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 227ed75ee3..ae3d1b39b0 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -107,7 +107,7 @@ static void rootmenu_track_changed_callback(unsigned short id, void* param)
107{ 107{
108 (void)id; 108 (void)id;
109 struct mp3entry *id3 = ((struct track_event *)param)->id3; 109 struct mp3entry *id3 = ((struct track_event *)param)->id3;
110 strlcpy(current_track_path, id3->path, MAX_PATH); 110 strmemccpy(current_track_path, id3->path, MAX_PATH);
111} 111}
112static int browser(void* param) 112static int browser(void* param)
113{ 113{
diff --git a/apps/screens.c b/apps/screens.c
index 9191922c31..db24e534c1 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -20,7 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23#include <string.h> 23#include <string-extra.h>
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include "backlight.h" 26#include "backlight.h"
@@ -562,8 +562,7 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
562 if (!id3->comment) 562 if (!id3->comment)
563 return NULL; 563 return NULL;
564 564
565 if (!memccpy (buffer, id3->comment, '\0', buffer_len)) 565 strmemccpy(buffer, id3->comment, buffer_len);
566 buffer[buffer_len - 1] = '\0';
567 566
568 val=buffer; 567 val=buffer;
569 if(say_it && val) 568 if(say_it && val)
@@ -612,8 +611,7 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
612 if (id3->codectype >= AFMT_NUM_CODECS) 611 if (id3->codectype >= AFMT_NUM_CODECS)
613 return NULL; 612 return NULL;
614 613
615 if (!memccpy (buffer, audio_formats[id3->codectype].label, '\0', buffer_len)) 614 strmemccpy(buffer, audio_formats[id3->codectype].label, buffer_len);
616 buffer[buffer_len - 1] = '\0';
617 615
618 val=buffer; 616 val=buffer;
619 if(say_it) 617 if(say_it)
diff --git a/apps/settings.c b/apps/settings.c
index edf4d2b13f..7c4dc4d124 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -35,8 +35,7 @@
35#include "backlight.h" 35#include "backlight.h"
36#include "audio.h" 36#include "audio.h"
37#include "talk.h" 37#include "talk.h"
38#include "strlcpy.h" 38#include "string-extra.h"
39#include "strcasestr.h"
40#include "rtc.h" 39#include "rtc.h"
41#include "power.h" 40#include "power.h"
42#include "ata_idle_notify.h" 41#include "ata_idle_notify.h"
@@ -251,7 +250,7 @@ bool cfg_string_to_int(int setting_id, int* out, const char* str)
251 } 250 }
252 else return false; 251 else return false;
253 } 252 }
254 strlcpy(temp, start, end-start+1); 253 strmemccpy(temp, start, end-start+1);
255 if (!strcmp(str, temp)) 254 if (!strcmp(str, temp))
256 { 255 {
257 *out = count; 256 *out = count;
@@ -343,18 +342,22 @@ bool settings_load_config(const char* file, bool apply)
343 size_t len = strlen(dir); 342 size_t len = strlen(dir);
344 if (!strncasecmp(value, dir, len)) 343 if (!strncasecmp(value, dir, len))
345 { 344 {
346 strlcpy(storage, &value[len], MAX_PATH); 345 strmemccpy(storage, &value[len], MAX_PATH);
347 } 346 }
348 else strlcpy(storage, value, MAX_PATH); 347 else
348 strmemccpy(storage, value, MAX_PATH);
349
349 } 350 }
350 else strlcpy(storage, value, MAX_PATH); 351 else
352 strmemccpy(storage, value, MAX_PATH);
353
351 if (settings[i].filename_setting->suffix) 354 if (settings[i].filename_setting->suffix)
352 { 355 {
353 char *s = strcasestr(storage,settings[i].filename_setting->suffix); 356 char *s = strcasestr(storage,settings[i].filename_setting->suffix);
354 if (s) *s = '\0'; 357 if (s) *s = '\0';
355 } 358 }
356 strlcpy((char*)settings[i].setting, storage, 359 strmemccpy((char*)settings[i].setting, storage,
357 settings[i].filename_setting->max_len); 360 settings[i].filename_setting->max_len);
358 break; 361 break;
359 } 362 }
360 } 363 }
@@ -393,11 +396,11 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
393 if (value[count] == val) 396 if (value[count] == val)
394 { 397 {
395 if (end == NULL) 398 if (end == NULL)
396 strlcpy(buf, start, buf_len); 399 strmemccpy(buf, start, buf_len);
397 else 400 else
398 { 401 {
399 int len = MIN(buf_len, (end-start) + 1); 402 int len = MIN(buf_len, (end-start) + 1);
400 strlcpy(buf, start, len); 403 strmemccpy(buf, start, len);
401 } 404 }
402 return true; 405 return true;
403 } 406 }
@@ -421,11 +424,11 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
421 } 424 }
422 end = strchr(start,','); 425 end = strchr(start,',');
423 if (end == NULL) 426 if (end == NULL)
424 strlcpy(buf, start, buf_len); 427 strmemccpy(buf, start, buf_len);
425 else 428 else
426 { 429 {
427 int len = MIN(buf_len, (end-start) + 1); 430 int len = MIN(buf_len, (end-start) + 1);
428 strlcpy(buf, start, len); 431 strmemccpy(buf, start, len);
429 } 432 }
430 return true; 433 return true;
431} 434}
@@ -491,7 +494,7 @@ bool cfg_to_string(int i/*setting_id*/, char* buf, int buf_len)
491 else 494 else
492 { 495 {
493 int len = MIN(buf_len, settings[i].filename_setting->max_len); 496 int len = MIN(buf_len, settings[i].filename_setting->max_len);
494 strlcpy(buf,(char*)settings[i].setting,len); 497 strmemccpy(buf,(char*)settings[i].setting,len);
495 } 498 }
496 break; 499 break;
497 } /* switch () */ 500 } /* switch () */
@@ -1071,8 +1074,8 @@ void reset_setting(const struct settings_list *setting, void *var)
1071 break; 1074 break;
1072 case F_T_CHARPTR: 1075 case F_T_CHARPTR:
1073 case F_T_UCHARPTR: 1076 case F_T_UCHARPTR:
1074 strlcpy((char*)var, setting->default_val.charptr, 1077 strmemccpy((char*)var, setting->default_val.charptr,
1075 setting->filename_setting->max_len); 1078 setting->filename_setting->max_len);
1076 break; 1079 break;
1077 } 1080 }
1078} 1081}
@@ -1265,6 +1268,6 @@ void set_file(const char* filename, char* setting, const int maxlen)
1265 if (len > maxlen) 1268 if (len > maxlen)
1266 return; 1269 return;
1267 1270
1268 strlcpy(setting, fptr, len); 1271 strmemccpy(setting, fptr, len);
1269 settings_save(); 1272 settings_save();
1270} 1273}
diff --git a/apps/settings_list.c b/apps/settings_list.c
index f54738163a..f733ee4f69 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -624,11 +624,11 @@ static char* qs_write_to_cfg(void* setting, char*buf, int buf_len)
624 int index = *(int*)setting; 624 int index = *(int*)setting;
625 if (index < 0 || index >= nb_settings) 625 if (index < 0 || index >= nb_settings)
626 { 626 {
627 strlcpy(buf, "-", buf_len); 627 strmemccpy(buf, "-", buf_len);
628 return buf; 628 return buf;
629 } 629 }
630 const struct settings_list *var = &settings[index]; 630 const struct settings_list *var = &settings[index];
631 strlcpy(buf, var->cfg_name, buf_len); 631 strmemccpy(buf, var->cfg_name, buf_len);
632 return buf; 632 return buf;
633} 633}
634static bool qs_is_changed(void* setting, void* defaultval) 634static bool qs_is_changed(void* setting, void* defaultval)
diff --git a/apps/shortcuts.c b/apps/shortcuts.c
index 1253e77a65..752ca977e6 100644
--- a/apps/shortcuts.c
+++ b/apps/shortcuts.c
@@ -284,7 +284,7 @@ void shortcuts_add(enum shortcut_type type, const char* value)
284 if (type == SHORTCUT_SETTING) 284 if (type == SHORTCUT_SETTING)
285 sc->u.setting = (void*)value; 285 sc->u.setting = (void*)value;
286 else 286 else
287 strlcpy(sc->u.path, value, MAX_PATH); 287 strmemccpy(sc->u.path, value, MAX_PATH);
288 288
289 if (first_idx_to_writeback < 0) 289 if (first_idx_to_writeback < 0)
290 first_idx_to_writeback = shortcut_count - 1; 290 first_idx_to_writeback = shortcut_count - 1;
@@ -325,7 +325,7 @@ static int readline_cb(int n, char *buf, void *parameters)
325 } 325 }
326 else if (nm_op == 1) /*name*/ 326 else if (nm_op == 1) /*name*/
327 { 327 {
328 strlcpy(sc->name, value, MAX_SHORTCUT_NAME); 328 strmemccpy(sc->name, value, MAX_SHORTCUT_NAME);
329 } 329 }
330 else if (nm_op == 2) /*data*/ 330 else if (nm_op == 2) /*data*/
331 { 331 {
@@ -339,7 +339,7 @@ static int readline_cb(int n, char *buf, void *parameters)
339 case SHORTCUT_FILE: 339 case SHORTCUT_FILE:
340 case SHORTCUT_DEBUGITEM: 340 case SHORTCUT_DEBUGITEM:
341 case SHORTCUT_PLAYLISTMENU: 341 case SHORTCUT_PLAYLISTMENU:
342 strlcpy(sc->u.path, value, MAX_PATH); 342 strmemccpy(sc->u.path, value, MAX_PATH);
343 break; 343 break;
344 case SHORTCUT_SETTING: 344 case SHORTCUT_SETTING:
345 sc->u.setting = find_setting_by_cfgname(value, NULL); 345 sc->u.setting = find_setting_by_cfgname(value, NULL);
@@ -374,7 +374,7 @@ static int readline_cb(int n, char *buf, void *parameters)
374 } 374 }
375 else if (nm_op == 4) /*talkclip*/ 375 else if (nm_op == 4) /*talkclip*/
376 { 376 {
377 strlcpy(sc->talk_clip, value, MAX_PATH); 377 strmemccpy(sc->talk_clip, value, MAX_PATH);
378 } 378 }
379 } 379 }
380 return 0; 380 return 0;
@@ -534,7 +534,7 @@ static int shortcut_menu_speak_item(int selected_item, void * data)
534 if (*filename != '\0') 534 if (*filename != '\0')
535 { 535 {
536 int dirlen = (filename - sc->u.path); 536 int dirlen = (filename - sc->u.path);
537 strlcpy(path, sc->u.path, dirlen + 1); 537 strmemccpy(path, sc->u.path, dirlen + 1);
538 dir = opendir(path); 538 dir = opendir(path);
539 if (dir) 539 if (dir)
540 { 540 {
diff --git a/apps/tagcache.c b/apps/tagcache.c
index c5c40b9d50..a6c4c875be 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -853,7 +853,7 @@ static bool retrieve(struct tagcache_search *tcs, IF_DIRCACHE(int idx_id,)
853 { 853 {
854 struct tagfile_entry *ep = 854 struct tagfile_entry *ep =
855 (struct tagfile_entry *)&tcramcache.hdr->tags[tag][seek]; 855 (struct tagfile_entry *)&tcramcache.hdr->tags[tag][seek];
856 strlcpy(buf, ep->tag_data, bufsz); 856 strmemccpy(buf, ep->tag_data, bufsz);
857 857
858 return true; 858 return true;
859 } 859 }
@@ -3469,7 +3469,7 @@ static bool write_tag(int fd, const char *tagstr, const char *datastr)
3469 } 3469 }
3470 3470
3471 str_setlen(buf, bufsz - 1); 3471 str_setlen(buf, bufsz - 1);
3472 strlcpy(&buf[i], "\" ", (bufsz - i - 1)); 3472 strmemccpy(&buf[i], "\" ", (bufsz - i - 1));
3473 3473
3474 write(fd, buf, i + 2); 3474 write(fd, buf, i + 2);
3475 3475
@@ -4737,7 +4737,7 @@ void do_tagcache_build(const char *path[])
4737 /* check_dir might add new roots */ 4737 /* check_dir might add new roots */
4738 for(this = &roots_ll[0]; this; this = this->next) 4738 for(this = &roots_ll[0]; this; this = this->next)
4739 { 4739 {
4740 strlcpy(curpath, this->path, sizeof(curpath)); 4740 strmemccpy(curpath, this->path, sizeof(curpath));
4741 ret = ret && check_dir(this->path, true); 4741 ret = ret && check_dir(this->path, true);
4742 } 4742 }
4743 free_search_roots(&roots_ll[0]); 4743 free_search_roots(&roots_ll[0]);
@@ -4792,7 +4792,7 @@ void tagcache_build(void)
4792{ 4792{
4793 char *vect[MAX_STATIC_ROOTS + 1]; /* +1 to ensure NULL sentinel */ 4793 char *vect[MAX_STATIC_ROOTS + 1]; /* +1 to ensure NULL sentinel */
4794 char str[sizeof(global_settings.tagcache_scan_paths)]; 4794 char str[sizeof(global_settings.tagcache_scan_paths)];
4795 strlcpy(str, global_settings.tagcache_scan_paths, sizeof(str)); 4795 strmemccpy(str, global_settings.tagcache_scan_paths, sizeof(str));
4796 4796
4797 int res = split_string(str, ':', vect, MAX_STATIC_ROOTS); 4797 int res = split_string(str, ':', vect, MAX_STATIC_ROOTS);
4798 vect[res] = NULL; 4798 vect[res] = NULL;
diff --git a/apps/tagtree.c b/apps/tagtree.c
index abb6cf5cb0..fc1ce26f40 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -779,7 +779,7 @@ static bool parse_search(struct menu_entry *entry, const char *str)
779 logf("tagtree failed to allocate %s", "menu"); 779 logf("tagtree failed to allocate %s", "menu");
780 return false; 780 return false;
781 } 781 }
782 strlcpy(menus[menu_count]->id, buf, MAX_MENU_ID_SIZE); 782 strmemccpy(menus[menu_count]->id, buf, MAX_MENU_ID_SIZE);
783 entry->link = menu_count; 783 entry->link = menu_count;
784 ++menu_count; 784 ++menu_count;
785 785
@@ -1118,7 +1118,7 @@ static int parse_line(int n, char *buf, void *parameters)
1118 } 1118 }
1119 menu = menus[menu_count]; 1119 menu = menus[menu_count];
1120 ++menu_count; 1120 ++menu_count;
1121 strlcpy(menu->id, data, MAX_MENU_ID_SIZE); 1121 strmemccpy(menu->id, data, MAX_MENU_ID_SIZE);
1122 } 1122 }
1123 1123
1124 if (get_token_str(menu->title, sizeof(menu->title)) < 0) 1124 if (get_token_str(menu->title, sizeof(menu->title)) < 0)
@@ -1898,8 +1898,8 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
1898 csi = &menu->items[seek]->si; 1898 csi = &menu->items[seek]->si;
1899 c->currextra = 0; 1899 c->currextra = 0;
1900 1900
1901 strlcpy(current_title[c->currextra], dptr->name, 1901 strmemccpy(current_title[c->currextra], dptr->name,
1902 sizeof(current_title[0])); 1902 sizeof(current_title[0]));
1903 1903
1904 /* Read input as necessary. */ 1904 /* Read input as necessary. */
1905 for (i = 0; i < csi->tagorder_count; i++) 1905 for (i = 0; i < csi->tagorder_count; i++)
@@ -1928,7 +1928,7 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
1928 if (source == source_current_path && id3) 1928 if (source == source_current_path && id3)
1929 { 1929 {
1930 char *e; 1930 char *e;
1931 strlcpy(searchstring, id3->path, SEARCHSTR_SIZE); 1931 strmemccpy(searchstring, id3->path, SEARCHSTR_SIZE);
1932 e = strrchr(searchstring, '/'); 1932 e = strrchr(searchstring, '/');
1933 if (e) 1933 if (e)
1934 *e = '\0'; 1934 *e = '\0';
@@ -1941,7 +1941,7 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
1941 char **src = (char**)((char*)id3 + offset); 1941 char **src = (char**)((char*)id3 + offset);
1942 if (*src) 1942 if (*src)
1943 { 1943 {
1944 strlcpy(searchstring, *src, SEARCHSTR_SIZE); 1944 strmemccpy(searchstring, *src, SEARCHSTR_SIZE);
1945 } 1945 }
1946 } 1946 }
1947 else 1947 else
@@ -1994,8 +1994,8 @@ int tagtree_enter(struct tree_context* c, bool is_visible)
1994 c->dirlevel--; 1994 c->dirlevel--;
1995 1995
1996 /* Update the statusbar title */ 1996 /* Update the statusbar title */
1997 strlcpy(current_title[c->currextra], dptr->name, 1997 strmemccpy(current_title[c->currextra], dptr->name,
1998 sizeof(current_title[0])); 1998 sizeof(current_title[0]));
1999 break; 1999 break;
2000 2000
2001 default: 2001 default:
@@ -2251,7 +2251,7 @@ char* tagtree_get_entry_name(struct tree_context *c, int id,
2251 struct tagentry *entry = tagtree_get_entry(c, id); 2251 struct tagentry *entry = tagtree_get_entry(c, id);
2252 if (!entry) 2252 if (!entry)
2253 return NULL; 2253 return NULL;
2254 strlcpy(buf, entry->name, bufsize); 2254 strmemccpy(buf, entry->name, bufsize);
2255 return buf; 2255 return buf;
2256} 2256}
2257 2257
diff --git a/apps/talk.c b/apps/talk.c
index 65933c6895..777c0f5a01 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -810,8 +810,8 @@ void talk_init(void)
810 talk_force_shutup(); /* In case we have something speaking! */ 810 talk_force_shutup(); /* In case we have something speaking! */
811 811
812 talk_initialized = true; 812 talk_initialized = true;
813 strlcpy((char *)last_lang, (char *)global_settings.lang_file, 813 strmemccpy((char *)last_lang, (char *)global_settings.lang_file,
814 MAX_FILENAME); 814 MAX_FILENAME);
815 815
816 /* reset some states */ 816 /* reset some states */
817 queue_write = queue_read = 0; /* reset the queue */ 817 queue_write = queue_read = 0; /* reset the queue */
@@ -1066,14 +1066,21 @@ static int talk_spell_basename(const char *path,
1066 } 1066 }
1067 char buf[MAX_PATH]; 1067 char buf[MAX_PATH];
1068 /* Spell only the path component after the last slash */ 1068 /* Spell only the path component after the last slash */
1069 strlcpy(buf, path, sizeof(buf)); 1069 char *end = strmemccpy(buf, path, sizeof(buf));
1070 if(strlen(buf) >1 && buf[strlen(buf)-1] == '/') 1070
1071 /* strip trailing slash */ 1071 if (!end)
1072 buf[strlen(buf)-1] = '\0'; 1072 return 0;
1073
1074 size_t len = end - buf - 1;
1075 if(len >1 && buf[len-1] == '/')
1076 buf[--len] = '\0'; /* strip trailing slash */
1077
1073 char *ptr = strrchr(buf, '/'); 1078 char *ptr = strrchr(buf, '/');
1074 if(ptr && strlen(buf) >1) 1079 if(ptr && len >1)
1075 ++ptr; 1080 ++ptr;
1076 else ptr = buf; 1081 else
1082 ptr = buf;
1083
1077 return talk_spell(ptr, enqueue); 1084 return talk_spell(ptr, enqueue);
1078} 1085}
1079 1086
@@ -1122,7 +1129,7 @@ int talk_fullpath(const char* path, bool enqueue)
1122 return talk_spell(path, true); 1129 return talk_spell(path, true);
1123 talk_id(VOICE_CHAR_SLASH, true); 1130 talk_id(VOICE_CHAR_SLASH, true);
1124 char buf[MAX_PATH]; 1131 char buf[MAX_PATH];
1125 strlcpy(buf, path, MAX_PATH); 1132 strmemccpy(buf, path, MAX_PATH);
1126 char *start = buf+1; /* start of current component */ 1133 char *start = buf+1; /* start of current component */
1127 char *ptr = strchr(start, '/'); /* end of current component */ 1134 char *ptr = strchr(start, '/'); /* end of current component */
1128 while(ptr) { /* There are more slashes ahead */ 1135 while(ptr) { /* There are more slashes ahead */
@@ -1636,7 +1643,7 @@ bool talk_get_debug_data(struct talk_debug_data *data)
1636 if (global_settings.lang_file[0] && global_settings.lang_file[0] != 0xff) 1643 if (global_settings.lang_file[0] && global_settings.lang_file[0] != 0xff)
1637 p_lang = (char *)global_settings.lang_file; 1644 p_lang = (char *)global_settings.lang_file;
1638 1645
1639 strlcpy(data->voicefile, p_lang, sizeof(data->voicefile)); 1646 strmemccpy(data->voicefile, p_lang, sizeof(data->voicefile));
1640 1647
1641 if (!has_voicefile || index_handle <= 0) 1648 if (!has_voicefile || index_handle <= 0)
1642 { 1649 {
diff --git a/apps/tree.c b/apps/tree.c
index 1939c7ee05..23a909281d 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -383,7 +383,7 @@ static int update_dir(void)
383 { 383 {
384 if (ft_load(&tc, NULL) < 0) 384 if (ft_load(&tc, NULL) < 0)
385 return -1; 385 return -1;
386 strlcpy(lastdir, tc.currdir, MAX_PATH); 386 strmemccpy(lastdir, tc.currdir, MAX_PATH);
387 changed = true; 387 changed = true;
388 } 388 }
389 } 389 }
@@ -573,7 +573,7 @@ void set_current_file(const char *path)
573 name = strrchr(path+1,'/'); 573 name = strrchr(path+1,'/');
574 if (name) 574 if (name)
575 { 575 {
576 strlcpy(tc.currdir, path, name - path + 1); 576 strmemccpy(tc.currdir, path, name - path + 1);
577 name++; 577 name++;
578 } 578 }
579 else 579 else
@@ -582,7 +582,7 @@ void set_current_file(const char *path)
582 name = path+1; 582 name = path+1;
583 } 583 }
584 584
585 strlcpy(lastfile, name, MAX_PATH); 585 strmemccpy(lastfile, name, MAX_PATH);
586 586
587 587
588 /* If we changed dir we must recalculate the dirlevel 588 /* If we changed dir we must recalculate the dirlevel
@@ -1007,7 +1007,7 @@ int rockbox_browse(struct browse_context *browse)
1007 tc.selected_item = 0; 1007 tc.selected_item = 0;
1008 tc.dirlevel = 0; 1008 tc.dirlevel = 0;
1009 1009
1010 strlcpy(tc.currdir, browse->root, sizeof(tc.currdir)); 1010 strmemccpy(tc.currdir, browse->root, sizeof(tc.currdir));
1011 } 1011 }
1012 1012
1013 start_wps = false; 1013 start_wps = false;
@@ -1030,7 +1030,7 @@ int rockbox_browse(struct browse_context *browse)
1030 if (dirfilter != SHOW_ID3DB) 1030 if (dirfilter != SHOW_ID3DB)
1031 tc.dirfilter = &global_settings.dirfilter; 1031 tc.dirfilter = &global_settings.dirfilter;
1032 tc.browse = browse; 1032 tc.browse = browse;
1033 strlcpy(current, browse->root, MAX_PATH); 1033 strmemccpy(current, browse->root, MAX_PATH);
1034 set_current_file(current); 1034 set_current_file(current);
1035 if (browse->flags&BROWSE_RUNFILE) 1035 if (browse->flags&BROWSE_RUNFILE)
1036 ret_val = ft_enter(&tc); 1036 ret_val = ft_enter(&tc);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 94a986c9f8..b13a5ac304 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -240,6 +240,7 @@ common/strcasestr.c
240common/strnatcmp.c 240common/strnatcmp.c
241common/strlcat.c 241common/strlcat.c
242common/strlcpy.c 242common/strlcpy.c
243common/strmemccpy.c
243common/structec.c 244common/structec.c
244common/timefuncs.c 245common/timefuncs.c
245common/unicode.c 246common/unicode.c
diff --git a/firmware/buflib.c b/firmware/buflib.c
index 3130bc960c..2ce9cc344c 100644
--- a/firmware/buflib.c
+++ b/firmware/buflib.c
@@ -30,7 +30,7 @@
30#include <stdio.h> /* for snprintf() */ 30#include <stdio.h> /* for snprintf() */
31#include <stddef.h> /* for ptrdiff_t */ 31#include <stddef.h> /* for ptrdiff_t */
32#include "buflib.h" 32#include "buflib.h"
33#include "string-extra.h" /* strlcpy() */ 33#include "string-extra.h" /* strmemccpy() */
34#include "debug.h" 34#include "debug.h"
35#include "panic.h" 35#include "panic.h"
36#include "crc32.h" 36#include "crc32.h"
@@ -974,7 +974,7 @@ buflib_alloc_maximum(struct buflib_context* ctx, const char* name, size_t *size,
974 if (*size <= 0) /* OOM */ 974 if (*size <= 0) /* OOM */
975 return -1; 975 return -1;
976 976
977 strlcpy(buf, name, sizeof(buf)); 977 strmemccpy(buf, name, sizeof(buf));
978 978
979 return buflib_alloc_ex(ctx, *size, buf, ops); 979 return buflib_alloc_ex(ctx, *size, buf, ops);
980} 980}
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 1d6371a6b5..5902f8b3fd 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -1707,8 +1707,8 @@ static int sab_process_dir(struct dircache_entry *ce)
1707 /* save current paths size */ 1707 /* save current paths size */
1708 int pathpos = strlen(sab_path); 1708 int pathpos = strlen(sab_path);
1709 /* append entry */ 1709 /* append entry */
1710 strlcpy(&sab_path[pathpos], "/", sizeof(sab_path) - pathpos); 1710 strmemccpy(&sab_path[pathpos], "/", sizeof(sab_path) - pathpos);
1711 strlcpy(&sab_path[pathpos+1], entry->d_name, sizeof(sab_path) - pathpos - 1); 1711 strmemccpy(&sab_path[pathpos+1], entry->d_name, sizeof(sab_path) - pathpos - 1);
1712 1712
1713 int rc = sab_process_dir(ce->down); 1713 int rc = sab_process_dir(ce->down);
1714 /* restore path */ 1714 /* restore path */
@@ -1735,7 +1735,7 @@ static int sab_process_dir(struct dircache_entry *ce)
1735static int sab_process_volume(IF_MV(int volume,) struct dircache_entry *ce) 1735static int sab_process_volume(IF_MV(int volume,) struct dircache_entry *ce)
1736{ 1736{
1737 memset(ce, 0, sizeof(struct dircache_entry)); 1737 memset(ce, 0, sizeof(struct dircache_entry));
1738 strlcpy(sab_path, "/", sizeof sab_path); 1738 strmemccpy(sab_path, "/", sizeof sab_path);
1739 return sab_process_dir(ce); 1739 return sab_process_dir(ce);
1740} 1740}
1741 1741
@@ -1755,7 +1755,7 @@ int dircache_readdir_r(struct dircache_dirscan *dir, struct DIRENT *result)
1755 1755
1756 dir->scanidx = ce - dircache_root; 1756 dir->scanidx = ce - dircache_root;
1757 1757
1758 strlcpy(result->d_name, ce->d_name, sizeof (result->d_name)); 1758 strmemccpy(result->d_name, ce->d_name, sizeof (result->d_name));
1759 result->info = ce->dirinfo; 1759 result->info = ce->dirinfo;
1760 1760
1761 return 1; 1761 return 1;
diff --git a/firmware/common/strlcpy.c b/firmware/common/strlcpy.c
index e320649140..bfdb6482a4 100644
--- a/firmware/common/strlcpy.c
+++ b/firmware/common/strlcpy.c
@@ -1,51 +1,39 @@
1/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ 1/***************************************************************************
2 2 * __________ __ ___.
3/* 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
5 * 9 *
6 * Permission to use, copy, modify, and distribute this software for any 10 * Copyright (C) 2022 William Wilgus
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 * 11 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * This program is free software; you can redistribute it and/or
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * modify it under the terms of the GNU General Public License
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * as published by the Free Software Foundation; either version 2
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * of the License, or (at your option) any later version.
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 *
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * KIND, either express or implied.
17 */ 19 *
20 ****************************************************************************/
18 21
19#include <string.h> 22#include <string.h>
23#include "strmemccpy.h"
20 24
21/* 25/*
22 * Copy src to string dst of size siz. At most siz-1 characters 26 * Copy src to string dst of size siz. At most siz-1 characters
23 * will be copied. Always NUL terminates (unless siz == 0). 27 * will be copied. Always NUL terminates (unless siz == 0).
24 * Returns strlen(src); if retval >= siz, truncation occurred. 28 * Returns strlen(src); if retval >= siz, truncation occurred.
25 */ 29 */
26size_t 30size_t strlcpy(char *dst, const char *src, size_t siz)
27strlcpy(char *dst, const char *src, size_t siz)
28{ 31{
29 char *d = dst; 32 /* Copy as many bytes as will fit */
30 const char *s = src; 33 char *d = strmemccpy(dst, src, siz);
31 size_t n = siz; 34 if (d)
32 35 return (d - dst - 1); /* count does not include NUL */
33 /* Copy as many bytes as will fit */
34 if (n != 0) {
35 while (--n != 0) {
36 if ((*d++ = *s++) == '\0')
37 break;
38 }
39 }
40 36
41 /* Not enough room in dst, add NUL and traverse rest of src */ 37 /* Not enough room in dst, add NUL and traverse rest of src */
42 if (n == 0) { 38 return(siz + strlen(src+siz)); /* count does not include NUL */
43 if (siz != 0)
44 *d = '\0'; /* NUL-terminate dst */
45 while (*s++)
46 ;
47 }
48
49 return(s - src - 1); /* count does not include NUL */
50} 39}
51
diff --git a/firmware/common/strmemccpy.c b/firmware/common/strmemccpy.c
new file mode 100644
index 0000000000..830907f55e
--- /dev/null
+++ b/firmware/common/strmemccpy.c
@@ -0,0 +1,38 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2022 William Wilgus
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21/* (firmware/common/strmemccpy.c) */
22#include "string-extra.h"
23
24/* copies src to a buffer of len bytes stopping after
25 * len or the first NULL (\0) in src
26 * NULL terminates except when len = 0
27 * If len was exceeded NULL is returned otherwise returns
28 * a pointer to the first byte following the NULL in dst.
29*/
30char * strmemccpy(char *dst, const char *src, size_t len)
31{
32 char * ret = (char *)memccpy(dst, src, '\0', len);
33 if (ret == NULL && len > 0)
34 {
35 dst[len - 1] = '\0';
36 }
37 return ret;
38}
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c
index 389d30917b..975c494b5a 100644
--- a/firmware/drivers/lcd-bitmap-common.c
+++ b/firmware/drivers/lcd-bitmap-common.c
@@ -699,7 +699,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
699 } 699 }
700 700
701 /* copy contents to the line buffer */ 701 /* copy contents to the line buffer */
702 strlcpy(s->linebuffer, string, sizeof(s->linebuffer)); 702 strmemccpy(s->linebuffer, string, sizeof(s->linebuffer));
703 /* scroll bidirectional or forward only depending on the string width */ 703 /* scroll bidirectional or forward only depending on the string width */
704 if ( LCDFN(scroll_info).bidir_limit ) { 704 if ( LCDFN(scroll_info).bidir_limit ) {
705 s->bidir = w < (vp->width) * 705 s->bidir = w < (vp->width) *
diff --git a/firmware/font.c b/firmware/font.c
index 97a15221fc..d7473346da 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -854,7 +854,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
854static void font_path_to_glyph_path( const char *font_path, char *glyph_path) 854static void font_path_to_glyph_path( const char *font_path, char *glyph_path)
855{ 855{
856 /* take full file name, cut extension, and add .glyphcache */ 856 /* take full file name, cut extension, and add .glyphcache */
857 strlcpy(glyph_path, font_path, MAX_PATH); 857 strmemccpy(glyph_path, font_path, MAX_PATH);
858 glyph_path[strlen(glyph_path)-4] = '\0'; 858 glyph_path[strlen(glyph_path)-4] = '\0';
859 strcat(glyph_path, ".gc"); 859 strcat(glyph_path, ".gc");
860} 860}
diff --git a/firmware/general.c b/firmware/general.c
index 8508b34b88..d421d722a8 100644
--- a/firmware/general.c
+++ b/firmware/general.c
@@ -107,7 +107,7 @@ char *create_numbered_filename(char *buffer, const char *path,
107 int suffixlen = strlen(suffix); 107 int suffixlen = strlen(suffix);
108 108
109 if (buffer != path) 109 if (buffer != path)
110 strlcpy(buffer, path, MAX_PATH); 110 strmemccpy(buffer, path, MAX_PATH);
111 111
112 pathlen = strlen(buffer); 112 pathlen = strlen(buffer);
113 113
@@ -181,7 +181,7 @@ char *create_datetime_filename(char *buffer, const char *path,
181 last_tm = *tm; 181 last_tm = *tm;
182 182
183 if (buffer != path) 183 if (buffer != path)
184 strlcpy(buffer, path, MAX_PATH); 184 strmemccpy(buffer, path, MAX_PATH);
185 185
186 pathlen = strlen(buffer); 186 pathlen = strlen(buffer);
187 snprintf(buffer + pathlen, MAX_PATH - pathlen, 187 snprintf(buffer + pathlen, MAX_PATH - pathlen,
diff --git a/firmware/include/string-extra.h b/firmware/include/string-extra.h
index 549a018dfc..a9b34661a7 100644
--- a/firmware/include/string-extra.h
+++ b/firmware/include/string-extra.h
@@ -25,6 +25,7 @@
25#include "strlcat.h" 25#include "strlcat.h"
26#include "strcasecmp.h" 26#include "strcasecmp.h"
27#include "strcasestr.h" 27#include "strcasestr.h"
28#include "strmemccpy.h"
28#include "strtok_r.h" 29#include "strtok_r.h"
29#include "memset16.h" 30#include "memset16.h"
30 31
diff --git a/firmware/include/strmemccpy.h b/firmware/include/strmemccpy.h
new file mode 100644
index 0000000000..c7004610dd
--- /dev/null
+++ b/firmware/include/strmemccpy.h
@@ -0,0 +1,32 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2022 William Wilgus
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#ifndef __STRMEMCCPY_H__
24#define __STRMEMCCPY_H__
25/* copies src to a buffer of len bytes stopping after
26 * len or the first NULL (\0) in src
27 * NULL terminates except when len = 0
28 * If len was exceeded NULL is returned otherwise returns
29 * a pointer to the first byte following the NULL in dst.
30*/
31char * strmemccpy(char *dst, const char *src, size_t len);
32#endif