Last update: 06-Jun-2021
Author: R. Koucha
Translation of UTF-16LE into ASCII
Introduction

I had to write a small tool in C language to dump the metadata of the GPT partitions of an eMMC. The task is quite straightforward except that I had no idea about how to display the unicode UTF16-LE of the partition names until I discovered iconv.

Overview of iconv

iconv provides services to translate characters from one encoding to another. The list of known character set encodings is obtain with the -l option of the tool:

$ iconv -l
[...]
  US-ASCII, US, UTF-7, UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE,
  UTF-32LE, UTF7, UTF8, UTF16, UTF16BE, UTF16LE, UTF32, UTF32BE, UTF32LE,
  VISCII, WCHAR_T, WIN-SAMI-2, WINBALTRIM, WINDOWS-31J, WINDOWS-874,
  WINDOWS-936, WINDOWS-1250, WINDOWS-1251, WINDOWS-1252, WINDOWS-1253,
  WINDOWS-1254, WINDOWS-1255, WINDOWS-1256, WINDOWS-1257, WINDOWS-1258,
  WINSAMI2, WS2, YU

For C language programs, iconv comes with 3 functions:

Example program
#include <errno.h>
#include <stdio.h>
#include <iconv.h>
#include <stdlib.h>

static char *gpt_utf16le2ascii(char *utf16le_str, size_t sz) {

  iconv_t cd;
  int     rc;
  char   *p;
  size_t  sz_in, sz_out;
  char   *str_out, *str_in;
  size_t  conv_sz;

  // ASCII string is shorter than UTF16
  sz_out = sz;
  str_out = (char *)malloc(sz_out);
  if (!str_out) {
    fprintf(stderr, "malloc(%zu): %m (%d)\n", sz, errno);
    return 0;
  }

  cd = iconv_open("ASCII", "UTF-16LE");
  if (cd == (iconv_t)-1) {
    fprintf(stderr, "iconv_open(): %m (%d)\n", errno);
    free(str_out);
    return 0;
  }

  sz_in = sz;
  str_in = utf16le_str;
  p = str_out;
  conv_sz = iconv(cd, &utf16le_str, &sz_in, &p, &sz_out);
  if (conv_sz == (size_t)-1) {
    fprintf(stderr, "iconv(): %m (%d)\n", errno);
    free(str_out);
    iconv_close(cd);
    return 0;
  }

  str_out[sz-sz_out] = '\0';

  rc = iconv_close(cd);
  if (rc == -1) {
    fprintf(stderr, "iconv_open(): %m (%d)\n", errno);
    free(str_out);
    return 0;
  }

  return str_out;
}

int main(void) {

  char str1[] = { 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x20, 0x00,
                  0x69, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x55, 0x00,
                  0x54, 0x00, 0x46, 0x00, 0x2D, 0x00, 0x31, 0x00,
                  0x36, 0x00, 0x4C, 0x00, 0x45, 0x00 };
  char *str;

  str = gpt_utf16le2ascii(str1, sizeof(str1));
  if (str) {
    printf("'%s'\n", str);
    free(str);
  }

  return 0;
}

Build and execution:

$ gcc example.c 
$ ./a.out 
'ABC in UTF-16LE'
About the author

The author is an engineer in computer sciences located in France. He can be contacted here.