First pinch of libisofs rewrite
This commit is contained in:
632
libisofs/util.c
632
libisofs/util.c
@ -1,136 +1,190 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
/* vim: set ts=8 sts=8 sw=8 noet : */
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
#include <ctype.h>
|
||||
/**
|
||||
* Utility functions for the Libisofs library.
|
||||
*/
|
||||
|
||||
#include <wchar.h>
|
||||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <langinfo.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
int valid_d_char(char c)
|
||||
int div_up(int n, int div)
|
||||
{
|
||||
return (n + div - 1) / div;
|
||||
}
|
||||
|
||||
int round_up(int n, int mul)
|
||||
{
|
||||
return div_up(n, mul) * mul;
|
||||
}
|
||||
|
||||
wchar_t *towcs(const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
wchar_t *ret = malloc(sizeof(wchar_t) * (len + 1));
|
||||
mbstate_t ps;
|
||||
size_t n;
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
n = mbsrtowcs(ret, &str, len, &ps);
|
||||
ret[len] = '\0';
|
||||
|
||||
if (n != len) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *wcstoascii(const wchar_t *wsrc)
|
||||
{
|
||||
if (!wsrc)
|
||||
return NULL;
|
||||
|
||||
iconv_t conv = iconv_open("ASCII", "WCHAR_T");
|
||||
size_t outbytes = wcslen(wsrc);
|
||||
size_t inbytes = outbytes * sizeof(wchar_t);
|
||||
char src_[inbytes + sizeof(wchar_t)];
|
||||
char *src = src_;
|
||||
char *ret_, *ret;
|
||||
size_t n;
|
||||
|
||||
if (conv == (iconv_t)-1)
|
||||
return NULL;
|
||||
|
||||
memcpy(src, wsrc, inbytes + sizeof(wchar_t));
|
||||
ret = malloc(outbytes+1);
|
||||
ret[outbytes] = '\0';
|
||||
ret_ = ret;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
free(ret_);
|
||||
return NULL;
|
||||
}
|
||||
return ret_;
|
||||
}
|
||||
|
||||
/* FIXME: C&P */
|
||||
uint16_t *wcstoucs(const wchar_t *wsrc)
|
||||
{
|
||||
if (!wsrc)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
|
||||
iconv_t conv = iconv_open("UCS-2BE", "WCHAR_T");
|
||||
size_t outbytes = wcslen(wsrc) * 2;
|
||||
size_t inbytes = outbytes * sizeof(wchar_t) / 2;
|
||||
char src_[inbytes + sizeof(wchar_t)];
|
||||
char *src = src_;
|
||||
char *ret_, *ret;
|
||||
size_t n;
|
||||
|
||||
if (conv == (iconv_t)-1)
|
||||
return calloc(2, 1);
|
||||
|
||||
memcpy(src, wsrc, inbytes + sizeof(wchar_t));
|
||||
ret = malloc(outbytes + sizeof(wchar_t));
|
||||
ret[outbytes] = 0;
|
||||
ret[outbytes+1] = 0;
|
||||
ret_ = ret;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
perror ("error in iconv conversion");
|
||||
free(ret_);
|
||||
return calloc(2, 1);
|
||||
}
|
||||
return (uint16_t*)ret_;
|
||||
}
|
||||
|
||||
static int valid_d_char(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||
}
|
||||
|
||||
int valid_a_char(char c)
|
||||
static int valid_a_char(char c)
|
||||
{
|
||||
return (c >= ' ' && c <= '"') || (c >= '%' && c <= '?') || (c >= 'A' &&
|
||||
c <= 'Z')
|
||||
|| (c == '_');
|
||||
return (c >= ' ' && c <= '"') || (c >= '%' && c <= '?')
|
||||
|| (c >= 'A' && c <= 'Z')
|
||||
|| (c == '_');
|
||||
}
|
||||
|
||||
int valid_j_char(char msb, char lsb)
|
||||
static int valid_j_char(uint16_t c)
|
||||
{
|
||||
return !(msb == '\0' &&
|
||||
(lsb < ' ' || lsb == '*' || lsb == '/' || lsb == ':' ||
|
||||
lsb == ';' || lsb == '?' || lsb == '\\'));
|
||||
return !(c < (uint16_t)' ' || c == (uint16_t)'*' || c == (uint16_t)'/'
|
||||
|| c == (uint16_t)':' || c == (uint16_t)';'
|
||||
|| c == (uint16_t)'?' || c == (uint16_t)'\\');
|
||||
}
|
||||
|
||||
int valid_p_char(char c)
|
||||
/* FIXME: where are these documented? */
|
||||
static int valid_p_char(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' &&
|
||||
c <= 'z')
|
||||
|| (c == '.') || (c == '_') || (c == '-');
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
|
||||
|| (c >= 'a' && c <= 'z')
|
||||
|| (c == '.') || (c == '_') || (c == '-');
|
||||
}
|
||||
|
||||
char *iso_d_str(const char *src, int size, int pad)
|
||||
static char *iso_dirid(const wchar_t *src, int size)
|
||||
{
|
||||
char *dest = strlen(src) > size ||
|
||||
pad ? malloc(size + 1) : malloc(strlen(src) + 1);
|
||||
int i;
|
||||
char *ret = wcstoascii(src);
|
||||
size_t len, i;
|
||||
|
||||
/* Try converting to upper-case before validating. */
|
||||
for (i = 0; i < size && src[i]; i++) {
|
||||
char c = toupper(src[i]);
|
||||
|
||||
dest[i] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
|
||||
/* Optionally pad with spaces and terminate with NULL. */
|
||||
if (pad)
|
||||
while (i < size)
|
||||
dest[i++] = ' ';
|
||||
dest[i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *iso_a_str(const char *src, int size)
|
||||
{
|
||||
char *dest = malloc(size + 1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size && src[i]; i++) {
|
||||
char c = toupper(src[i]);
|
||||
|
||||
dest[i] = valid_a_char(c) ? c : '_';
|
||||
}
|
||||
while (i < size)
|
||||
dest[i++] = ' ';
|
||||
dest[i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
uint16_t *iso_j_str(const char *src)
|
||||
{
|
||||
int size = strlen(src) * 2;
|
||||
uint16_t *dest = malloc(size + 2);
|
||||
char *cpy, *in, *out;
|
||||
size_t inleft, outleft;
|
||||
iconv_t cd;
|
||||
|
||||
/* If the conversion is unavailable, return NULL. Obviously,
|
||||
nl_langinfo(..) requires the locale to be set correctly. */
|
||||
cd = iconv_open("UCS-2BE", nl_langinfo(CODESET));
|
||||
if (cd == (iconv_t) - 1) {
|
||||
free(dest);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
len = strlen(ret);
|
||||
if (len > size) {
|
||||
ret[size] = '\0';
|
||||
len = size;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
char c = toupper(ret[i]);
|
||||
ret[i] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
|
||||
/* In, out, inleft and outleft will be updated by iconv, that's why we
|
||||
need separate variables. */
|
||||
cpy = strdup(src); /* iconv doesn't take const * chars, so we need our
|
||||
* own copy. */
|
||||
in = cpy;
|
||||
out = (char*)dest;
|
||||
inleft = strlen(cpy);
|
||||
outleft = size;
|
||||
iconv(cd, &in, &inleft, &out, &outleft);
|
||||
|
||||
/* Since we need to pad with NULLs, we can pad up to and including the
|
||||
terminating NULLs. */
|
||||
outleft += 2;
|
||||
while (outleft) {
|
||||
*out++ = '\0';
|
||||
outleft--;
|
||||
}
|
||||
iconv_close(cd);
|
||||
free(cpy);
|
||||
|
||||
return dest;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *iso_1_fileid(const char *src)
|
||||
char *iso_1_dirid(const wchar_t *src)
|
||||
{
|
||||
char *dest = malloc(15); /* 15 = 8 (name) + 1 (.) + 3 (ext) + 2
|
||||
(;1) + 1 (\0) */
|
||||
char *dot = strrchr(src, '.'); /* Position of the last dot in the
|
||||
return iso_dirid(src, 8);
|
||||
}
|
||||
|
||||
char *iso_2_dirid(const wchar_t *src)
|
||||
{
|
||||
return iso_dirid(src, 31);
|
||||
}
|
||||
|
||||
char *iso_1_fileid(const wchar_t *wsrc)
|
||||
{
|
||||
char *src = wcstoascii(wsrc);
|
||||
char *dest;
|
||||
char *dot; /* Position of the last dot in the
|
||||
filename, will be used to calculate
|
||||
lname and lext. */
|
||||
int lname, lext, pos, i;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
dest = malloc(15); /* 15 = 8 (name) + 1 (.) + 3 (ext) + 2
|
||||
(;1) + 1 (\0) */
|
||||
dot = strrchr(src, '.');
|
||||
|
||||
lext = dot ? strlen(dot + 1) : 0;
|
||||
lname = strlen(src) - lext - (dot ? 1 : 0);
|
||||
|
||||
/* If we can't build a filename, return NULL. */
|
||||
if (lname == 0 && lext == 0) {
|
||||
free(src);
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
@ -156,16 +210,24 @@ char *iso_1_fileid(const char *src)
|
||||
dest[pos] = '\0';
|
||||
dest = (char *)realloc(dest, pos + 1);
|
||||
|
||||
free(src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *iso_2_fileid(const char *src)
|
||||
char *iso_2_fileid(const wchar_t *wsrc)
|
||||
{
|
||||
char *dest = malloc(34); /* 34 = 30 (name + ext) + 1 (.) + 2
|
||||
(;1) + 1 (\0) */
|
||||
char *dot = strrchr(src, '.');
|
||||
char *src = wcstoascii(wsrc);
|
||||
char *dest;
|
||||
char *dot;
|
||||
int lname, lext, lnname, lnext, pos, i;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
dest = malloc(34); /* 34 = 30 (name + ext) + 1 (.) + 2
|
||||
(;1) + 1 (\0) */
|
||||
dot = strrchr(src, '.');
|
||||
|
||||
/* Since the maximum length can be divided freely over the name and
|
||||
extension, we need to calculate their new lengths (lnname and
|
||||
lnext). If the original filename is too long, we start by trimming
|
||||
@ -177,12 +239,13 @@ char *iso_2_fileid(const char *src)
|
||||
} else {
|
||||
lext = strlen(dot + 1);
|
||||
lname = strlen(src) - lext - 1;
|
||||
lnext = (strlen(src) > 31 &&
|
||||
lext > 3) ? (lname < 27 ? 30 - lname : 3) : lext;
|
||||
lnext = (strlen(src) > 31 && lext > 3)
|
||||
? (lname < 27 ? 30 - lname : 3) : lext;
|
||||
lnname = (strlen(src) > 31) ? 30 - lnext : lname;
|
||||
}
|
||||
|
||||
if (lnname == 0 && lnext == 0) {
|
||||
free(src);
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
@ -206,276 +269,43 @@ char *iso_2_fileid(const char *src)
|
||||
dest[pos] = '\0';
|
||||
dest = (char *)realloc(dest, pos + 1);
|
||||
|
||||
free(src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
uint16_t *iso_j_id(char *src)
|
||||
char *
|
||||
iso_p_fileid(const wchar_t *src)
|
||||
{
|
||||
char *dest = malloc(136); /* 136 = 128 (name + ext) + 2 (\0 .) +
|
||||
4 (\0 ; \0 1) + 2 (\0 \0) */
|
||||
char *dot = strrchr(src, '.');
|
||||
int lname, lext, lcname, lcext, lnname, lnext, pos, i;
|
||||
size_t inleft, outleft;
|
||||
char *cname, *cext, *in, *out;
|
||||
iconv_t cd;
|
||||
char *ret = wcstoascii(src);
|
||||
size_t i, len;
|
||||
|
||||
if (dot == NULL || dot == src || *(dot + 1) == '\0') {
|
||||
lname = strlen(src);
|
||||
lext = 0;
|
||||
} else {
|
||||
lext = strlen(dot + 1);
|
||||
lname = strlen(src) - lext - 1;
|
||||
}
|
||||
|
||||
if (lname == 0 && lext == 0) {
|
||||
free(dest);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cd = iconv_open("UCS-2BE", nl_langinfo(CODESET));
|
||||
if (cd == (iconv_t) - 1) {
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We need to convert the name and extension first, in order to
|
||||
calculate the number of characters they have. */
|
||||
cname = malloc(lname * 2);
|
||||
in = src;
|
||||
out = cname;
|
||||
inleft = lname;
|
||||
outleft = lname * 2;
|
||||
iconv(cd, &in, &inleft, &out, &outleft);
|
||||
lcname = (lname * 2) - outleft;
|
||||
iconv_close(cd);
|
||||
|
||||
if (lext) {
|
||||
cd = iconv_open("UCS-2BE", nl_langinfo(CODESET));
|
||||
if (cd == (iconv_t) - 1) {
|
||||
free(dest);
|
||||
free(cname);
|
||||
return NULL;
|
||||
len = strlen(ret);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!valid_p_char(ret[i])) {
|
||||
ret[i] = (uint16_t)'_';
|
||||
}
|
||||
cext = malloc(lext * 2);
|
||||
in = dot + 1;
|
||||
out = cext;
|
||||
inleft = lext;
|
||||
outleft = lext * 2;
|
||||
iconv(cd, &in, &inleft, &out, &outleft);
|
||||
lcext = (lext * 2) - outleft;
|
||||
iconv_close(cd);
|
||||
} else
|
||||
lcext = 0;
|
||||
|
||||
/* Again, divide the available characters over name and extension, but
|
||||
keep a minimum of three characters for the new extension. */
|
||||
lnext = (lcname + lcext > 128 &&
|
||||
lcext > 6) ? (lcname < 122 ? 128 - lcname : 6) : lcext;
|
||||
lnname = (lcname + lcext > 128) ? 128 - lnext : lcname;
|
||||
|
||||
pos = 0;
|
||||
/* Copy up to lnname bytes from the converted filename. */
|
||||
for (i = 0; i < lnname; i = i + 2)
|
||||
if (valid_j_char(cname[i], cname[i + 1])) {
|
||||
dest[pos++] = cname[i];
|
||||
dest[pos++] = cname[i + 1];
|
||||
} else {
|
||||
dest[pos++] = '\0';
|
||||
dest[pos++] = '_';
|
||||
}
|
||||
/* Dot is now a 16 bit separator. */
|
||||
dest[pos++] = '\0';
|
||||
dest[pos++] = '.';
|
||||
/* Copy up to lnext bytes from the converted extension, if any. */
|
||||
for (i = 0; i < lnext; i = i + 2)
|
||||
if (valid_j_char(cext[i], cext[i + 1])) {
|
||||
dest[pos++] = cext[i];
|
||||
dest[pos++] = cext[i + 1];
|
||||
} else {
|
||||
dest[pos++] = '\0';
|
||||
dest[pos++] = '_';
|
||||
}
|
||||
/* Again, 2 bytes per character. */
|
||||
dest[pos++] = '\0';
|
||||
dest[pos++] = ';';
|
||||
dest[pos++] = '\0';
|
||||
dest[pos++] = '1';
|
||||
dest[pos++] = '\0';
|
||||
dest[pos] = '\0';
|
||||
|
||||
dest = (char *)realloc(dest, pos + 1);
|
||||
free(cname);
|
||||
if (lext)
|
||||
free(cext);
|
||||
|
||||
/* Fill in the size in bytes (including the terminating NULLs) of the
|
||||
destination string. */
|
||||
return (uint16_t *) dest;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *iso_p_filename(const char *src)
|
||||
uint16_t *
|
||||
iso_j_id(const wchar_t *src)
|
||||
{
|
||||
char *dest = malloc(251); /* We can fit up to 250 characters in
|
||||
a Rock Ridge name entry. */
|
||||
char *dot = strrchr(src, '.');
|
||||
int lname, lext, lnname, lnext, pos, i;
|
||||
uint16_t *j_str = wcstoucs(src);
|
||||
size_t len = ucslen(j_str);
|
||||
size_t n;
|
||||
|
||||
if (dot == NULL || dot == src || *(dot + 1) == '\0') {
|
||||
lname = strlen(src);
|
||||
lnname = (lname > 250) ? 250 : lname;
|
||||
lext = lnext = 0;
|
||||
} else {
|
||||
lext = strlen(dot + 1);
|
||||
lname = strlen(src) - lext - 1;
|
||||
lnext = (strlen(src) > 250 &&
|
||||
lext > 3) ? (lname < 246 ? 249 - lname : 3) : lext;
|
||||
lnname = (strlen(src) > 250) ? 249 - lnext : lname;
|
||||
if (len > 128) {
|
||||
j_str[128] = '\0';
|
||||
len = 128;
|
||||
}
|
||||
|
||||
if (lnname == 0 && lnext == 0) {
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
for (i = 0; i < lnname; i++)
|
||||
dest[pos++] = valid_p_char(src[i]) ? src[i] : '_';
|
||||
if (lnext) {
|
||||
dest[pos++] = '.';
|
||||
for (i = 0; i < lnext; i++)
|
||||
dest[pos++] =
|
||||
valid_p_char(src[lname + 1 + i]) ?
|
||||
src[lname + 1 + i] : '_';
|
||||
}
|
||||
dest[pos] = '\0';
|
||||
dest = (char *)realloc(dest, pos + 1);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *iso_p_dirname(const char *src)
|
||||
{
|
||||
char *dest = strlen(src) > 250 ? malloc(251) : malloc(strlen(src) + 1);
|
||||
int i;
|
||||
|
||||
if (strlen(src) == 0) {
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 250 && src[i]; i++)
|
||||
dest[i] = valid_p_char(src[i]) ? src[i] : '_';
|
||||
dest[i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *iso_pathname(const char *dir, const char *file)
|
||||
{
|
||||
char *path = malloc(strlen(dir) + strlen(file) + 2);
|
||||
|
||||
strcpy(path, dir);
|
||||
path[strlen(dir)] = '/';
|
||||
strcpy(path + strlen(dir) + 1, file);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void iso_a_strcpy(unsigned char *dest, int size, const char *src)
|
||||
{
|
||||
int i = 0, d = 0;
|
||||
|
||||
if (src)
|
||||
for (; i < size && *src; ++i, ++src) {
|
||||
char s = toupper(*src);
|
||||
|
||||
if (valid_a_char(s))
|
||||
dest[d++] = s;
|
||||
else
|
||||
dest[d++] = '_';
|
||||
}
|
||||
for (; i < size; ++i) {
|
||||
/* pad with spaces */
|
||||
dest[d++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void iso_d_strcpy(unsigned char *dest, int size, const char *src)
|
||||
{
|
||||
int i = 0, d = 0;
|
||||
|
||||
if (src)
|
||||
for (; i < size && *src; ++i, ++src) {
|
||||
char s = toupper(*src);
|
||||
|
||||
if (valid_d_char(s))
|
||||
dest[d++] = s;
|
||||
else
|
||||
dest[d++] = '_';
|
||||
}
|
||||
for (; i < size; ++i) {
|
||||
/* pad with spaces */
|
||||
dest[d++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
char *iso_a_strndup(const char *src, int size)
|
||||
{
|
||||
int i, d;
|
||||
char *out;
|
||||
|
||||
out = malloc(size + 1);
|
||||
for (i = d = 0; i < size && *src; ++i, ++src) {
|
||||
char s = toupper(*src);
|
||||
|
||||
if (valid_a_char(s))
|
||||
out[d++] = s;
|
||||
else
|
||||
out[d++] = '_';
|
||||
}
|
||||
out[d++] = '\0';
|
||||
out = realloc(out, d); /* shrink the buffer to what we used */
|
||||
return out;
|
||||
}
|
||||
|
||||
char *iso_d_strndup(const char *src, int size)
|
||||
{
|
||||
int i, d;
|
||||
char *out;
|
||||
|
||||
out = malloc(size + 1);
|
||||
for (i = d = 0; i < size && *src; ++i, ++src) {
|
||||
char s = toupper(*src);
|
||||
|
||||
if (valid_d_char(s))
|
||||
out[d++] = s;
|
||||
else
|
||||
out[d++] = '_';
|
||||
}
|
||||
out[d++] = '\0';
|
||||
out = realloc(out, d); /* shrink the buffer to what we used */
|
||||
return out;
|
||||
}
|
||||
|
||||
char *iso_strconcat(char sep, const char *a, const char *b)
|
||||
{
|
||||
char *out;
|
||||
int la, lb;
|
||||
|
||||
la = strlen(a);
|
||||
lb = strlen(b);
|
||||
out = malloc(la + lb + 1 + (sep ? 1 : 0));
|
||||
memcpy(out, a, la);
|
||||
memcpy(out + la + (sep ? 1 : 0), b, lb);
|
||||
if (sep)
|
||||
out[la] = sep;
|
||||
out[la + lb + (sep ? 1 : 0)] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
char *iso_strdup(const char *src)
|
||||
{
|
||||
return src ? strdup(src) : NULL;
|
||||
for (n = 0; n < len; n++)
|
||||
if (!valid_j_char(j_str[n]))
|
||||
j_str[n] = '_';
|
||||
return j_str;
|
||||
}
|
||||
|
||||
void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
|
||||
@ -551,7 +381,6 @@ void iso_datetime_17(unsigned char *buf, time_t t)
|
||||
static int tzsetup = 0;
|
||||
static int tzoffset;
|
||||
struct tm tm;
|
||||
char c[5];
|
||||
|
||||
if (t == (time_t) - 1) {
|
||||
/* unspecified time */
|
||||
@ -570,27 +399,13 @@ void iso_datetime_17(unsigned char *buf, time_t t)
|
||||
|
||||
localtime_r(&t, &tm);
|
||||
|
||||
/* year */
|
||||
sprintf(c, "%04d", tm.tm_year + 1900);
|
||||
memcpy(&buf[0], c, 4);
|
||||
/* month */
|
||||
sprintf(c, "%02d", tm.tm_mon + 1);
|
||||
memcpy(&buf[4], c, 2);
|
||||
/* day */
|
||||
sprintf(c, "%02d", tm.tm_mday);
|
||||
memcpy(&buf[6], c, 2);
|
||||
/* hour */
|
||||
sprintf(c, "%02d", tm.tm_hour);
|
||||
memcpy(&buf[8], c, 2);
|
||||
/* minute */
|
||||
sprintf(c, "%02d", tm.tm_min);
|
||||
memcpy(&buf[10], c, 2);
|
||||
/* second */
|
||||
sprintf(c, "%02d", MIN(59, tm.tm_sec));
|
||||
memcpy(&buf[12], c, 2);
|
||||
/* hundreths */
|
||||
sprintf((char*)&buf[0], "%04d", tm.tm_year + 1900);
|
||||
sprintf((char*)&buf[4], "%02d", tm.tm_mon + 1);
|
||||
sprintf((char*)&buf[6], "%02d", tm.tm_mday);
|
||||
sprintf((char*)&buf[8], "%02d", tm.tm_hour);
|
||||
sprintf((char*)&buf[10], "%02d", tm.tm_min);
|
||||
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
|
||||
memcpy(&buf[14], "00", 2);
|
||||
/* timezone */
|
||||
buf[16] = tzoffset;
|
||||
}
|
||||
}
|
||||
@ -611,47 +426,6 @@ time_t iso_datetime_read_17(const uint8_t *buf)
|
||||
return mktime(&tm) - buf[16] * 60 * 60;
|
||||
}
|
||||
|
||||
void iso_split_filename(char *name, char **ext)
|
||||
{
|
||||
char *r;
|
||||
|
||||
r = strrchr(name, '.');
|
||||
if (r) {
|
||||
*r = '\0';
|
||||
*ext = r + 1;
|
||||
} else
|
||||
*ext = "";
|
||||
}
|
||||
|
||||
void iso_filecpy(unsigned char *buf, int size, const char *name, int version)
|
||||
{
|
||||
char v[6];
|
||||
int nl, vl;
|
||||
|
||||
assert(version >= 0);
|
||||
assert(version < 0x8000);
|
||||
|
||||
nl = strlen(name);
|
||||
|
||||
memcpy(buf, name, nl);
|
||||
|
||||
if (!version)
|
||||
assert(size >= strlen(name));
|
||||
else {
|
||||
sprintf(v, "%d", version);
|
||||
vl = strlen(v);
|
||||
assert(size >= nl + vl + 1);
|
||||
|
||||
buf[nl] = ';';
|
||||
memcpy(&buf[nl + 1], v, vl);
|
||||
|
||||
nl += vl + 1;
|
||||
}
|
||||
/* pad with spaces */
|
||||
if (nl < size)
|
||||
memset(&buf[nl], ' ', size - nl);
|
||||
}
|
||||
|
||||
size_t ucslen(const uint16_t *str)
|
||||
{
|
||||
int i;
|
||||
@ -661,20 +435,30 @@ size_t ucslen(const uint16_t *str)
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Although each character is 2 bytes, we actually compare byte-by-byte
|
||||
* (thats what the spec says).
|
||||
*/
|
||||
int ucscmp(const uint16_t *s1, const uint16_t *s2)
|
||||
{
|
||||
int i;
|
||||
const char *s = (const char*)s1;
|
||||
const char *t = (const char*)s2;
|
||||
size_t len1 = ucslen(s1);
|
||||
size_t len2 = ucslen(s2);
|
||||
size_t i, len = MIN(len1, len2) * 2;
|
||||
|
||||
for (i=0; 1; i++) {
|
||||
if (s1[i] < s2[i]) {
|
||||
for (i=0; i < len; i++) {
|
||||
if (s[i] < t[i]) {
|
||||
return -1;
|
||||
} else if (s1[i] > s2[i]) {
|
||||
} else if (s[i] > t[i]) {
|
||||
return 1;
|
||||
} else if (s1[i] == 0 && s2[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len1 < len2)
|
||||
return -1;
|
||||
else if (len1 > len2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user