diff --git a/.gitignore b/.gitignore index 0711b11e..0b657d33 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ GTAGS TAGS tags *~ +compile_commands.json +.cache/ diff --git a/configure.ac b/configure.ac index faf4a937..b5593eac 100644 --- a/configure.ac +++ b/configure.ac @@ -461,7 +461,11 @@ dnl Update flags dnl Sets CFLAGS to force optimization and debugging options, which isn't quite kosher dnl AM_CPPFLAGS="-D_GNU_SOURCE -I\$(top_srcdir)/src -DLTFS_CONFIG_FILE='\"${sysconfdir}/ltfs.conf\"' -DLTFS_BASE_DIR='\"${prefix}\"'" -AM_CFLAGS="-Wall -Wsign-compare -fsigned-char ${FUSE_MODULE_CFLAGS} ${UUID_MODULE_CFLAGS} ${LIBXML2_MODULE_CFLAGS} ${ICU_MODULE_CFLAGS} ${SNMP_ENABLE} ${SNMP_MODULE_CFLAGS}" +dnl -Wno-unused-parameter: callback signatures (FUSE operations, plugin ops) +dnl must keep parameters they do not use. +dnl -Wno-missing-field-initializers: designated initializers of operation and +dnl option tables intentionally leave the remaining members zeroed. +AM_CFLAGS="-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wsign-compare -fsigned-char ${FUSE_MODULE_CFLAGS} ${UUID_MODULE_CFLAGS} ${LIBXML2_MODULE_CFLAGS} ${ICU_MODULE_CFLAGS} ${SNMP_ENABLE} ${SNMP_MODULE_CFLAGS}" if test "x$use_fast" = "xyes" then diff --git a/src/libltfs/arch/arch_info.c b/src/libltfs/arch/arch_info.c index dec5f225..ca932544 100644 --- a/src/libltfs/arch/arch_info.c +++ b/src/libltfs/arch/arch_info.c @@ -72,7 +72,9 @@ void show_runtime_system_info(void) ltfsmsg(LTFS_WARN, 17086W); } else { memset(kernel_version, 0, sizeof(kernel_version)); - read(fd, kernel_version, sizeof(kernel_version)); + /* Leave room for the terminator and the arch suffix appended below */ + if (read(fd, kernel_version, sizeof(kernel_version) - 16) < 0) + strcpy(kernel_version, "(unknown)"); if((tmp = strchr(kernel_version, '\n')) != NULL) *tmp = '\0'; @@ -118,7 +120,8 @@ void show_runtime_system_info(void) } else { if (fstat(fd, &stat_rel) != -1 && S_ISREG(stat_rel.st_mode)) { memset(destribution, 0, sizeof(destribution)); - read(fd, destribution, sizeof(destribution)); + if (read(fd, destribution, sizeof(destribution) - 1) < 0) + strcpy(destribution, "(unknown)"); if((tmp = strchr(destribution, '\n')) != NULL) *tmp = '\0'; ltfsmsg(LTFS_INFO, 17089I, destribution); diff --git a/src/libltfs/fs.c b/src/libltfs/fs.c index 790438d5..5e047baf 100644 --- a/src/libltfs/fs.c +++ b/src/libltfs/fs.c @@ -426,7 +426,9 @@ uint64_t fs_allocate_uid(struct ltfs_index *idx) int fs_dentry_lookup(struct dentry *dentry, char **name) { char **dentry_names = NULL, *tmp_name = NULL; - int i, names, namelen = 0, ret = 0; + int ret = 0; + ssize_t i; + size_t names, namelen = 0; struct dentry *d, *parent; const char *lookup_name; @@ -447,7 +449,7 @@ int fs_dentry_lookup(struct dentry *dentry, char **name) d = dentry; parent = d->parent; - for (i=names-1; i>=0; --i) { + for (i = (ssize_t)names - 1; i >= 0; --i) { if (parent) acquireread_mrsw(&parent->contents_lock); @@ -483,9 +485,9 @@ int fs_dentry_lookup(struct dentry *dentry, char **name) goto out; } - for (namelen=0, i=0; i 0 && i < names-1) + if (i > 0 && i < (ssize_t)names-1) arch_strcat(tmp_name, tmp_len, "/"); } @@ -496,7 +498,7 @@ int fs_dentry_lookup(struct dentry *dentry, char **name) if (ret != 0 && tmp_name) free(tmp_name); if (dentry_names) { /* BEAM: constant condition - dentry_names has always non-zero value here. */ - while (--names >= 0) + while (names-- > 0) if (dentry_names[names]) free(dentry_names[names]); free(dentry_names); diff --git a/src/libltfs/ltfs_fsops.c b/src/libltfs/ltfs_fsops.c index 3b7f57d6..81adb9f5 100644 --- a/src/libltfs/ltfs_fsops.c +++ b/src/libltfs/ltfs_fsops.c @@ -2067,14 +2067,16 @@ int ltfs_fsops_target_absolute_path(const char* link, const char* target, char* len -= strlen(temp_buf); /* length of "/aaa" */ } else if (strcmp(token, "." )) { /* have directory name */ work_buf[len] = '/'; /* put '/ 'as "/aaa/" */ - arch_strncpy(work_buf+len+1, token, work_buf_len, strlen(token)); /* "/aaa/ccc\0" */ + memcpy(work_buf+len+1, token, strlen(token)); /* "/aaa/ccc\0" */ + work_buf[len+1+strlen(token)] = '\0'; len = strlen(work_buf); } token = next_token; } work_buf[len] = '/'; /* put '/ 'as "/aaa/ccc/" */ if(token){ - arch_strncpy(work_buf+len+1, token, work_buf_len, strlen(token)); /* "/aaa/ccc/target.txt\0" */ + memcpy(work_buf+len+1, token, strlen(token)); /* "/aaa/ccc/target.txt\0" */ + work_buf[len+1+strlen(token)] = '\0'; } if (size < strlen(work_buf) + 1) { free(work_buf); diff --git a/src/libltfs/ltfstrace.c b/src/libltfs/ltfstrace.c index 9bf3a1ed..4b20e883 100644 --- a/src/libltfs/ltfstrace.c +++ b/src/libltfs/ltfstrace.c @@ -222,6 +222,16 @@ struct ltfs_timespec start; struct timer_info timerinfo; bool trace_enable = true; +/* The trace dump is best-effort diagnostics; a write failure must not fail + * the operation that triggered the dump. glibc marks write() with + * warn_unused_result and a (void) cast does not silence it, so consume the + * result here and deliberately ignore it. */ +static void _dump_write(int fd, const void *buf, size_t count) +{ + ssize_t ignored = arch_write(fd, buf, count); + (void)ignored; +} + static int ltfs_request_trace_init(void) { int ret = 0; @@ -576,7 +586,7 @@ int ltfs_dump(char *fname, const char *work_dir) int ret = 0, num_args = 0, status; char *path, *pid; pid_t fork_pid; - const unsigned int max_arguments = 32; + enum { max_arguments = 32 }; const char *args[max_arguments]; if(!work_dir) @@ -694,37 +704,37 @@ int ltfs_trace_dump(char *fname, const char *work_dir) trc_header->header_size + req_header->header_size + fn_trc_header->header_size; /* Write headers */ - (void)arch_write(fd, trc_header, sizeof(struct trace_header)); - (void)arch_write(fd, req_header, sizeof(struct request_header)); + _dump_write(fd, trc_header, sizeof(struct trace_header)); + _dump_write(fd, req_header, sizeof(struct request_header)); /* Write request trace data */ ltfs_mutex_lock(&req_trace->req_trace_lock); - (void)arch_write(fd, req_trace->entries, REQ_TRACE_SIZE); + _dump_write(fd, req_trace->entries, REQ_TRACE_SIZE); ltfs_mutex_unlock(&req_trace->req_trace_lock); /* Write function trace header */ - (void)arch_write(fd, &fn_trc_header->header_size, sizeof(uint32_t)); - (void)arch_write(fd, &fn_trc_header->num_of_fn_trace, sizeof(uint32_t)); + _dump_write(fd, &fn_trc_header->header_size, sizeof(uint32_t)); + _dump_write(fd, &fn_trc_header->num_of_fn_trace, sizeof(uint32_t)); for (unsigned int i=0; ireq_t_desc[i], sizeof(struct function_trace_descriptor)); - (void)arch_write(fd, &fn_trc_header->crc, sizeof(uint32_t)); + _dump_write(fd, &fn_trc_header->req_t_desc[i], sizeof(struct function_trace_descriptor)); + _dump_write(fd, &fn_trc_header->crc, sizeof(uint32_t)); free(fn_trc_header->req_t_desc); fn_trc_header->req_t_desc = NULL; /* Write function trace data */ for (fsitem=fs_tr_list; fsitem != NULL; fsitem=fsitem->hh.next) { acquireread_mrsw(&fsitem->fn_entry->trace_lock); - (void)arch_write(fd, fsitem->fn_entry->entries, FS_FN_TRACE_SIZE); + _dump_write(fd, fsitem->fn_entry->entries, FS_FN_TRACE_SIZE); releaseread_mrsw(&fsitem->fn_entry->trace_lock); } for (admitem=admin_tr_list; admitem != NULL; admitem=admitem->hh.next) { acquireread_mrsw(&admitem->fn_entry->trace_lock); - (void)arch_write(fd, admitem->fn_entry->entries, ADMIN_FN_TRACE_SIZE); + _dump_write(fd, admitem->fn_entry->entries, ADMIN_FN_TRACE_SIZE); releaseread_mrsw(&admitem->fn_entry->trace_lock); } TAILQ_FOREACH (tailq_item, acomp, list) { acquireread_mrsw(&tailq_item->fn_entry->trace_lock); - (void)arch_write(fd, tailq_item->fn_entry->entries, ADMIN_FN_TRACE_SIZE); + _dump_write(fd, tailq_item->fn_entry->entries, ADMIN_FN_TRACE_SIZE); releaseread_mrsw(&tailq_item->fn_entry->trace_lock); } } diff --git a/src/libltfs/tape.c b/src/libltfs/tape.c index 255ca2a2..d5cc7ce5 100644 --- a/src/libltfs/tape.c +++ b/src/libltfs/tape.c @@ -1782,8 +1782,9 @@ int tape_set_cart_coherency(struct device_data *dev, const tape_partition_t part /* APPLICATION CLIENT SPECIFIC INFORMATION LENGTH */ coh_data[30] = 0; /* Size of APPLICATION CLIENT SPECIFIC INFORMATION (Byte 1) */ coh_data[31] = 43; /* Size of APPLICATION CLIENT SPECIFIC INFORMATION (Byte 0) */ - /* Size of the buffer to insert 'LTFS' needs to be size of 5 for the 4 letters and the null terminator*/ - arch_strncpy((char *)coh_data + 32,"LTFS", 5, 4); + /* Bytes 32-36 hold the "LTFS" signature; the reader checks all five + * bytes, so copy the terminator explicitly. */ + memcpy(coh_data + 32, "LTFS", 5); memcpy(coh_data + 37, coh->uuid, 37); /* Version field @@ -2978,7 +2979,7 @@ void parse_vol(char *str, int start_len, int end_len) */ int u_get_truncate_size(const char *name, int name_len, int max_size) { - int32_t size = 0, re_size; + int32_t size = 0, re_size = 0; UChar32 c; UErrorCode err = U_ZERO_ERROR; @@ -3001,6 +3002,17 @@ int u_get_truncate_size(const char *name, int name_len, int max_size) * @param Tape attribute * @return 0: success, negative : cannot set correct value to tape_attr */ +/* MAM attribute fields have fixed widths; truncation is intentional and + * parse_vol() pads and terminates afterwards. */ +static void mam_field_copy(char *dest, size_t field_size, const char *src) +{ + size_t n = strlen(src); + + if (n > field_size) + n = field_size; + memcpy(dest, src, n); +} + void set_tape_attribute(struct ltfs_volume *vol, struct tape_attr *t_attr) { int len_volname = 0; @@ -3016,16 +3028,16 @@ void set_tape_attribute(struct ltfs_volume *vol, struct tape_attr *t_attr) } /* APPLICATION VENDOR set */ - arch_strncpy_auto(t_attr->vender, LTFS_VENDOR_NAME, TC_MAM_APP_VENDER_SIZE); + mam_field_copy(t_attr->vender, TC_MAM_APP_VENDER_SIZE, LTFS_VENDOR_NAME); parse_vol(t_attr->vender, strlen(LTFS_VENDOR_NAME), TC_MAM_APP_VENDER_SIZE); /* APPLICATION NAME set */ - arch_strncpy_auto(t_attr->app_name, PACKAGE_NAME, TC_MAM_APP_NAME_SIZE); + mam_field_copy(t_attr->app_name, TC_MAM_APP_NAME_SIZE, PACKAGE_NAME); parse_vol(t_attr->app_name, strlen(PACKAGE_NAME), TC_MAM_APP_NAME_SIZE); /* APPLICATION VERSION set */ - arch_strncpy_auto(t_attr->app_ver, PACKAGE_VERSION, TC_MAM_APP_VERSION_SIZE); + mam_field_copy(t_attr->app_ver, TC_MAM_APP_VERSION_SIZE, PACKAGE_VERSION); parse_vol(t_attr->app_ver, strlen(PACKAGE_VERSION), TC_MAM_APP_VERSION_SIZE); /* USER MEDIUM LABEL set */ @@ -3039,7 +3051,7 @@ void set_tape_attribute(struct ltfs_volume *vol, struct tape_attr *t_attr) if (len_volname == -LTFS_ICU_ERROR) len_volname = TC_MAM_USER_MEDIUM_LABEL_SIZE - 1; } - arch_strncpy(t_attr->medium_label, vol->index->volume_name.name, sizeof(t_attr->medium_label), len_volname); + memcpy(t_attr->medium_label, vol->index->volume_name.name, len_volname); } /* TEXT LOCALIZATION IDENTIFIER set */ @@ -3049,7 +3061,7 @@ void set_tape_attribute(struct ltfs_volume *vol, struct tape_attr *t_attr) if ( vol->label->barcode[0] ) { if ( strlen(vol->label->barcode) > TC_MAM_BARCODE_SIZE) ltfsmsg(LTFS_WARN, 17203W, "BARCODE", vol->label->barcode, TC_MAM_BARCODE_SIZE); - arch_strncpy_auto(t_attr->barcode, vol->label->barcode, TC_MAM_BARCODE_SIZE); + mam_field_copy(t_attr->barcode, TC_MAM_BARCODE_SIZE, vol->label->barcode); parse_vol(t_attr->barcode, strlen(vol->label->barcode), TC_MAM_BARCODE_SIZE); } else { ltfsmsg(LTFS_WARN, 17230W); @@ -3057,7 +3069,7 @@ void set_tape_attribute(struct ltfs_volume *vol, struct tape_attr *t_attr) } /* APPLICATION FORMAT VERSION set */ - arch_strncpy_auto(t_attr->app_format_ver, LTFS_INDEX_VERSION_STR, TC_MAM_APP_FORMAT_VERSION_SIZE); + mam_field_copy(t_attr->app_format_ver, TC_MAM_APP_FORMAT_VERSION_SIZE, LTFS_INDEX_VERSION_STR); parse_vol(t_attr->app_format_ver, strlen(LTFS_INDEX_VERSION_STR), TC_MAM_APP_FORMAT_VERSION_SIZE); /* VOLUME LOCKED set */ diff --git a/src/libltfs/tape_ops.h b/src/libltfs/tape_ops.h index 34c7a128..f47c23f0 100644 --- a/src/libltfs/tape_ops.h +++ b/src/libltfs/tape_ops.h @@ -62,8 +62,19 @@ #include #include +#include #include +/* Bounded, always-terminated string copy for the fixed-width identifier + * fields below; truncation of longer sources is intentional. */ +static inline void ltfs_string_copy(char *dest, size_t dest_size, const char *src) +{ + size_t n = strnlen(src, dest_size - 1); + + memcpy(dest, src, n); + dest[n] = '\0'; +} + #define VENDOR_ID_LENGTH (8) #define PRODUCT_ID_LENGTH (16) #define PRODUCT_REV_LENGTH (4) diff --git a/src/libltfs/xml_writer.c b/src/libltfs/xml_writer.c index 21ee8e0c..3b18799f 100644 --- a/src/libltfs/xml_writer.c +++ b/src/libltfs/xml_writer.c @@ -82,13 +82,15 @@ int xml_format_time(struct ltfs_timespec t, char** out) return -1; } - timebuf = calloc(31, sizeof(char)); + /* 31 bytes fit a normalized time exactly; the extra room keeps the + * formatting safe for any field value. */ + timebuf = calloc(64, sizeof(char)); if (!timebuf) { ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); return -1; } - arch_sprintf(timebuf, (31*sizeof(char)), "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ", tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, t.tv_nsec); + snprintf(timebuf, 64, "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ", tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (long)t.tv_nsec); *out = timebuf; return noramized; diff --git a/src/libltfs/xml_writer_libltfs.c b/src/libltfs/xml_writer_libltfs.c index 094ec442..0c9cab1c 100644 --- a/src/libltfs/xml_writer_libltfs.c +++ b/src/libltfs/xml_writer_libltfs.c @@ -882,7 +882,8 @@ int xml_schema_to_tape(char *reason, struct ltfs_volume *vol) } /* Generate the Index. */ - asprintf(&creator, "%s - %s", vol->creator, reason); + if (asprintf(&creator, "%s - %s", vol->creator, reason) < 0) + creator = NULL; if (creator) { ret = _xml_write_schema(writer, creator, vol->index); if (ret < 0) { diff --git a/src/tape_drivers/generic/itdtimg/itdtimg_tc.c b/src/tape_drivers/generic/itdtimg/itdtimg_tc.c index 7a5d768f..6bec801a 100644 --- a/src/tape_drivers/generic/itdtimg/itdtimg_tc.c +++ b/src/tape_drivers/generic/itdtimg/itdtimg_tc.c @@ -947,7 +947,10 @@ int itdtimage_read_attribute(void *vstate, const tape_partition_t part, const ui return -EDEV_HARDWARE_ERROR; } - fread(buf, 1, data2ReadFromFile, state->img_file); + if (fread(buf, 1, data2ReadFromFile, state->img_file) != data2ReadFromFile) { + ltfsmsg(LTFS_ERR, 31002E, (long long)attrLength, state->filename, offset); + return -EDEV_HARDWARE_ERROR; + } return DEVICE_GOOD; } @@ -1370,9 +1373,10 @@ int itdtimage_get_device_list(struct tc_drive_info *buf, int count) if (buf && deventries < count) { snprintf(buf[deventries].name, TAPE_DEVNAME_LEN_MAX, "%s/%s", devdir, entry->d_name); - arch_strncpy_auto(buf[deventries].vendor, "DUMMY", TAPE_VENDOR_NAME_LEN_MAX); - arch_strncpy_auto(buf[deventries].model, "DUMMYDEV", TAPE_MODEL_NAME_LEN_MAX); - arch_strncpy_auto(buf[deventries].serial_number, &(entry->d_name[strlen(DRIVE_FILE_PREFIX)]), TAPE_SERIAL_LEN_MAX); + ltfs_string_copy(buf[deventries].vendor, TAPE_VENDOR_NAME_LEN_MAX + 1, "DUMMY"); + ltfs_string_copy(buf[deventries].model, TAPE_MODEL_NAME_LEN_MAX + 1, "DUMMYDEV"); + ltfs_string_copy(buf[deventries].serial_number, TAPE_SERIAL_LEN_MAX + 1, + &(entry->d_name[strlen(DRIVE_FILE_PREFIX)])); ltfsmsg(LTFS_DEBUG, 31030D, buf[deventries].name, buf[deventries].vendor, buf[deventries].model, buf[deventries].serial_number); } diff --git a/src/tape_drivers/linux/sg/sg_scsi_tape.c b/src/tape_drivers/linux/sg/sg_scsi_tape.c index 310c50ae..ad2a731a 100644 --- a/src/tape_drivers/linux/sg/sg_scsi_tape.c +++ b/src/tape_drivers/linux/sg/sg_scsi_tape.c @@ -464,9 +464,10 @@ int sg_get_drive_identifier(struct sg_tape *device, scsi_device_identifier *id_d return -EDEV_DEVICE_UNSUPPORTABLE; } - strncpy(id_data->vendor_id, (char*)(&(inquiry_buf[8])), VENDOR_ID_LENGTH); - strncpy(id_data->product_id, (char*)(&(inquiry_buf[16])), PRODUCT_ID_LENGTH); - strncpy(id_data->product_rev, (char*)(&(inquiry_buf[32])), PRODUCT_REV_LENGTH); + /* Fixed-width INQUIRY fields; the memset above provides the terminators */ + memcpy(id_data->vendor_id, &inquiry_buf[8], VENDOR_ID_LENGTH); + memcpy(id_data->product_id, &inquiry_buf[16], PRODUCT_ID_LENGTH); + memcpy(id_data->product_rev, &inquiry_buf[32], PRODUCT_REV_LENGTH); ret = _inquiry_low(device, 0x80, inquiry_buf, MAX_INQ_LEN); if( ret < 0 ) { @@ -474,7 +475,14 @@ int sg_get_drive_identifier(struct sg_tape *device, scsi_device_identifier *id_d return ret; } - strncpy(id_data->unit_serial, (char*)(&(inquiry_buf[4])), inquiry_buf[3]); + /* The serial length byte is device-controlled; clamp it to the field */ + { + size_t serial_len = inquiry_buf[3]; + + if (serial_len > UNIT_SERIAL_LENGTH) + serial_len = UNIT_SERIAL_LENGTH; + memcpy(id_data->unit_serial, &inquiry_buf[4], serial_len); + } return 0; } diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 19f2beb8..68a274da 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -532,7 +532,7 @@ static int _raw_open(struct sg_data *priv) return -EDEV_DEVICE_UNOPENABLE; /* Unexpected device is opened */ } } else - strncpy(priv->drive_serial, id_data.unit_serial, sizeof(priv->drive_serial) - 1); + ltfs_string_copy(priv->drive_serial, sizeof(priv->drive_serial), id_data.unit_serial); /* Get SCSI ID */ if (! ioctl(priv->dev.fd, SG_GET_SCSI_ID, &scsi_id)) { @@ -550,12 +550,14 @@ static int _raw_open(struct sg_data *priv) ltfsmsg(LTFS_INFO, 30214I, id_data.product_rev); ltfsmsg(LTFS_INFO, 30215I, priv->drive_serial); - strncpy(priv->info.name, priv->devname, TAPE_DEVNAME_LEN_MAX + 1); - strncpy(priv->info.vendor, id_data.vendor_id, TAPE_VENDOR_NAME_LEN_MAX + 1); - strncpy(priv->info.model, id_data.product_id, TAPE_MODEL_NAME_LEN_MAX + 1); - strncpy(priv->info.serial_number, id_data.unit_serial, TAPE_SERIAL_LEN_MAX + 1); - strncpy(priv->info.product_rev, id_data.product_rev, PRODUCT_REV_LENGTH + 1); - strncpy(priv->info.product_name, _generate_product_name(id_data.product_id), PRODUCT_NAME_LENGTH + 1); + /* ltfs_string_copy guarantees termination, which strncpy with a bound + * equal to the field size did not */ + ltfs_string_copy(priv->info.name, TAPE_DEVNAME_LEN_MAX + 1, priv->devname); + ltfs_string_copy(priv->info.vendor, TAPE_VENDOR_NAME_LEN_MAX + 1, id_data.vendor_id); + ltfs_string_copy(priv->info.model, TAPE_MODEL_NAME_LEN_MAX + 1, id_data.product_id); + ltfs_string_copy(priv->info.serial_number, TAPE_SERIAL_LEN_MAX + 1, id_data.unit_serial); + ltfs_string_copy(priv->info.product_rev, PRODUCT_REV_LENGTH + 1, id_data.product_rev); + ltfs_string_copy(priv->info.product_name, PRODUCT_NAME_LENGTH + 1, _generate_product_name(id_data.product_id)); return 0; } @@ -1646,9 +1648,10 @@ int sg_inquiry(void *device, struct tc_inq *inq) return ret; memset(inq, 0, sizeof(struct tc_inq)); - strncpy((char*)inq->vid, (char*)inq_page.data + 8, VENDOR_ID_LENGTH); - strncpy((char*)inq->pid, (char*)inq_page.data + 16, PRODUCT_ID_LENGTH); - strncpy((char*)inq->revision, (char*)inq_page.data + 32, PRODUCT_REV_LENGTH); + /* Fixed-width INQUIRY fields; the memset above provides the terminators */ + memcpy(inq->vid, inq_page.data + 8, VENDOR_ID_LENGTH); + memcpy(inq->pid, inq_page.data + 16, PRODUCT_ID_LENGTH); + memcpy(inq->revision, inq_page.data + 32, PRODUCT_REV_LENGTH); inq->devicetype = priv->drive_type; @@ -1657,7 +1660,7 @@ int sg_inquiry(void *device, struct tc_inq *inq) else vendor_length = 20; - strncpy((char*)inq->vendor, (char*)inq_page.data + 36, vendor_length); + memcpy(inq->vendor, inq_page.data + 36, vendor_length); inq->vendor[vendor_length] = '\0'; return ret; @@ -1710,7 +1713,7 @@ int sg_test_unit_ready(void *device) case -EDEV_NEED_INITIALIZE: case -EDEV_CONFIGURE_CHANGED: print_msg = false; - /* fall throuh */ + /* fall through */ case -EDEV_NO_MEDIUM: case -EDEV_BECOMING_READY: case -EDEV_MEDIUM_MAY_BE_CHANGED: @@ -4432,12 +4435,12 @@ int sg_get_device_list(struct tc_drive_info *buf, int count) } if (found < count && buf) { - strncpy(buf[found].name, devname, TAPE_DEVNAME_LEN_MAX + 1); - strncpy(buf[found].vendor, identifier.vendor_id, TAPE_VENDOR_NAME_LEN_MAX + 1); - strncpy(buf[found].model, identifier.product_id, TAPE_MODEL_NAME_LEN_MAX + 1); - strncpy(buf[found].serial_number, identifier.unit_serial, TAPE_SERIAL_LEN_MAX + 1); - strncpy(buf[found].product_rev, identifier.product_rev, PRODUCT_REV_LENGTH + 1); - strncpy(buf[found].product_name, _generate_product_name(identifier.product_id), PRODUCT_NAME_LENGTH + 1); + ltfs_string_copy(buf[found].name, TAPE_DEVNAME_LEN_MAX + 1, devname); + ltfs_string_copy(buf[found].vendor, TAPE_VENDOR_NAME_LEN_MAX + 1, identifier.vendor_id); + ltfs_string_copy(buf[found].model, TAPE_MODEL_NAME_LEN_MAX + 1, identifier.product_id); + ltfs_string_copy(buf[found].serial_number, TAPE_SERIAL_LEN_MAX + 1, identifier.unit_serial); + ltfs_string_copy(buf[found].product_rev, PRODUCT_REV_LENGTH + 1, identifier.product_rev); + ltfs_string_copy(buf[found].product_name, PRODUCT_NAME_LENGTH + 1, _generate_product_name(identifier.product_id)); if (! ioctl(dev.fd, SG_GET_SCSI_ID, &scsi_id)) { buf[found].host = scsi_id.host_no;