summaryrefslogtreecommitdiffstats
path: root/vfat.c
blob: 801156bf7722c3f58816b5cd719565252205af68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#ident "$Id$"
/* ----------------------------------------------------------------------- *
 *   
 *   Copyright 2003 H. Peter Anvin - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Bostom MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * vfat.h
 *
 * Construct VFAT long filename descriptors
 */

#include <iconv.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include "fat.h"
#include "minmax.h"

#define VFAT_MAX_LEN	64
#define VFAT_MAX_SLOTS  ((VFAT_MAX_LEN+12)/13)

extern const char *program;

static iconv_t iconv_utf16;

void vfat_setup(void)
{
  iconv_utf16 = iconv_open("UTF-16LE", "");
  if ( iconv_utf16 == (iconv_t)-1 ) {
    fprintf("%s: failed to iconv_open UTF-16LE: %s\n",
	    program, strerror(errno));
    exit(1);
  }
}

int vfat_make_long_name(struct fat_vfat_slot *slots,
			const char *str,
			uint8_t csum)
{
  uint16_t buffer[VFAT_MAX_LEN];
  uint16_t *xb;
  char *inb, *outb;
  int inbl, outbl, xl, nx;
  int seq = 1;

  inb = str;
  inbl = strlen(inb);
  outb = (char *)buffer;
  outbl = VFAT_MAX_LEN << 1;

  iconv(iconv_utf16, NULL, NULL, NULL, NULL); /* Reset input state */
  iconv(iconv_utf16, &inb, &inbl, &outb, &outbl);

  xl = VFAT_MAX_LEN - (outbl >> 1);
  xb = buffer;

  while ( xl ) {
    memset(slots, 0, sizeof(*slots));
    slots->id = seq++;
    slots->attribute = 0xef;	/* FIX */
    slots->alias_csum = csum;
    
    nx = min(xl,5);
    memcpy(slots->name0, xb, nx<<1);
    xl -= nx;

    nx = min(xl,6);
    memcpy(slots->name5, xb, nx<<1);
    xl -= nx;

    nx = min(xl,2);
    memcpy(slots->name11, xb, nx<<1);
    xl -= nx;

    slots++;
  }

  return seq-1;
}