"Fossies" - the Fresh Open Source Software Archive

Member "smbnetfs-0.6.3/src/charset.c" (3 Jan 2015, 3618 Bytes) of package /linux/misc/smbnetfs-0.6.3.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "charset.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.5.3b_vs_0.6.0.

    1 #include "config.h"
    2 #include <errno.h>
    3 #include <iconv.h>
    4 #include <string.h>
    5 #include "charset.h"
    6 
    7 static char charset_buf[CHARSET_BUF_SIZE];
    8 
    9 static char charset_hex_digit[] = "0123456789ABCDEF";
   10 static iconv_t  charset_local2samba = (iconv_t) (-1);
   11 static iconv_t  charset_samba2local = (iconv_t) (-1);
   12 
   13 
   14 int charset_init(const char *local, const char *samba){
   15     charset_local2samba = iconv_open(samba, local);
   16     if (charset_local2samba == (iconv_t) (-1)) return -1;
   17 
   18     charset_samba2local = iconv_open(local, samba);
   19     if (charset_samba2local == (iconv_t) (-1)){
   20     iconv_close(charset_local2samba);
   21     charset_local2samba = (iconv_t) (-1);
   22     return -1;
   23     }
   24     return 0;
   25 }
   26 
   27 static char * charset_samba_to_local(iconv_t cd,
   28                 const char *str, size_t str_len,
   29                 char *buf, size_t buf_len){
   30     size_t  i, r, len, out_len;
   31     char    *in, *out;
   32 
   33     if ((buf == NULL) || (buf_len == 0) || (cd == (iconv_t)(-1))) return NULL;
   34 
   35     len = 0;
   36     while(str_len > 0){
   37     in = (char*) str;
   38     out = buf + len;
   39     out_len = buf_len - len;
   40     if (out_len == 0) return NULL;
   41 
   42     for(i = 1; i <= str_len; i++){
   43         r = iconv(cd, &in, &i, &out, &out_len);
   44 
   45         /* conversion error */
   46         if (r == (size_t)(-1)){
   47         if (errno == E2BIG) return NULL;
   48         if (errno == EINVAL) continue;
   49         goto conversion_is_bad;
   50         }
   51 
   52         /* conversion is ok, but not reversable */
   53         if (r != 0) goto conversion_is_bad;
   54 
   55         /* conversion is ok */
   56         switch(buf[len]){
   57         case ':':
   58         case '@':
   59         case '%':
   60         case '/':
   61         case '\\':
   62             /* this characters is not allowed in names */
   63             goto conversion_is_bad;
   64 
   65         default:
   66             goto conversion_is_ok;
   67         };
   68     }
   69 
   70       conversion_is_bad:
   71     if (buf_len - len < 3) return NULL;
   72     buf[len++] = '%';
   73     buf[len++] = charset_hex_digit[(*str & 0xF0) >> 4];
   74     buf[len++] = charset_hex_digit[*str & 0x0F];
   75     str++; str_len--;
   76     continue;
   77 
   78       conversion_is_ok:
   79     str_len -= (in - str); str = in;
   80     len = out - buf;
   81     continue;
   82     }
   83     return buf;
   84 }
   85 
   86 static char * charset_local_to_samba(iconv_t cd,
   87                 const char *str, size_t str_len,
   88                 char *buf, size_t buf_len){
   89     size_t  i, r, len, out_len;
   90     char    *in, *out;
   91 
   92     if ((buf == NULL) || (buf_len == 0) || (cd == (iconv_t)(-1))) return NULL;
   93 
   94     len = 0;
   95     while(str_len > 0){
   96     in = (char*) str;
   97     out = buf + len;
   98     out_len = buf_len - len;
   99     if (out_len == 0) return NULL;
  100 
  101     for(i = 1; i <= str_len; i++){
  102         r = iconv(cd, &in, &i, &out, &out_len);
  103         if (r != (size_t)(-1)) goto conversion_is_ok;
  104         if (errno == E2BIG) return NULL;
  105         if (errno == EINVAL) continue;
  106         break;
  107     }
  108 
  109     /* conversion is bad */
  110     return NULL;
  111 
  112       conversion_is_ok:
  113     str_len -= (in - str); str = in;
  114     len = out - buf;
  115     continue;
  116     }
  117     return buf;
  118 }
  119 
  120 char * charset_local2smb_r(const char *src, char *dst, size_t dst_len){
  121     const char      *smb_prefix = "smb:/";
  122     const int       smb_prefix_len  = 5;
  123     char        *res;
  124 
  125     memset(dst, 0, dst_len);
  126     strcpy(dst, smb_prefix);
  127     res = charset_local_to_samba(
  128             charset_local2samba,
  129             src, strlen(src),
  130             dst + smb_prefix_len, dst_len - smb_prefix_len - 1);
  131     return (res != NULL) ? dst : NULL;
  132 }
  133 
  134 char * charset_smb2local_r(const char *src, char *dst, size_t dst_len){
  135     char *res;
  136 
  137     memset(dst, 0, dst_len);
  138     res = charset_samba_to_local(
  139             charset_samba2local,
  140             src, strlen(src),
  141             dst, dst_len - 1);
  142     return (res != NULL) ? dst : NULL;
  143 }
  144 
  145 char * charset_local2smb(const char *src){
  146     return charset_local2smb_r(src,
  147             charset_buf,
  148             sizeof(charset_buf));
  149 }
  150 
  151 char * charset_smb2local(const char *src){
  152     return charset_smb2local_r(src,
  153             charset_buf,
  154             sizeof(charset_buf));
  155 }