您尚未登录。

楼主 #1 2018-02-01 09:51:09

bugfix
会员
注册时间: 2017-11-22
已发帖子: 125
积分: 125

找到一个在内存中untar文件的方法,不敢独享,原理现在没看懂,但是基本也能用了。

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>

struct tar {
  char name[100];   char _unused[24];
  char size[12];    char _padding[376];
} *tar;

int is_file_in_tar(struct tar *tar, char *name, char **start, int *length )
{
    for( ; tar->name[0]; tar+=1+(*length+511)/512 )
    {
        sscanf(tar->size, "%o", length);
        if( !strcmp(tar->name,name) ){ *start = (char*)(tar+1); return 1; }
    }

    return 0;
}

int main()
{
    int fd=open("/mnt/hgfs/F/gif.tar", O_RDONLY );
    tar=mmap(NULL, 9348608, PROT_READ, MAP_PRIVATE, fd, 0);

    char *start; int length;

    char name[32];

    for(int i=0;i<25;i++)
    {
        snprintf(name, sizeof(name), "gif/xoApQkbkFnCkrao-%d.bmp", i);
        if( is_file_in_tar(tar,name,&start,&length) )
        {
            printf("%s.%d.%x\n", name, length, start);
        }
    }
}

编译指令:

gcc -o test test.c --std c99

运行结果:

bugfix@ubuntu:/$ ./test
gif/xoApQkbkFnCkrao-0.bmp.332986.4cd36400
gif/xoApQkbkFnCkrao-1.bmp.332986.4cd87c00
gif/xoApQkbkFnCkrao-2.bmp.332986.4d108400
gif/xoApQkbkFnCkrao-3.bmp.332986.4d3e5c00
gif/xoApQkbkFnCkrao-4.bmp.332986.4d437400
gif/xoApQkbkFnCkrao-5.bmp.332986.4d488c00
gif/xoApQkbkFnCkrao-6.bmp.332986.4d4da400
gif/xoApQkbkFnCkrao-7.bmp.332986.4d52bc00
gif/xoApQkbkFnCkrao-8.bmp.332986.4d57d400
gif/xoApQkbkFnCkrao-9.bmp.332986.4d5cec00
gif/xoApQkbkFnCkrao-10.bmp.332986.4cdd9400
gif/xoApQkbkFnCkrao-11.bmp.332986.4ce2ac00
gif/xoApQkbkFnCkrao-12.bmp.332986.4ce7c400
gif/xoApQkbkFnCkrao-13.bmp.332986.4cecdc00
gif/xoApQkbkFnCkrao-14.bmp.332986.4cf1f400
gif/xoApQkbkFnCkrao-15.bmp.332986.4cf70c00
gif/xoApQkbkFnCkrao-16.bmp.332986.4cfc2400
gif/xoApQkbkFnCkrao-17.bmp.332986.4d013c00
gif/xoApQkbkFnCkrao-18.bmp.332986.4d065400
gif/xoApQkbkFnCkrao-19.bmp.332986.4d0b6c00
gif/xoApQkbkFnCkrao-20.bmp.332986.4d159c00
gif/xoApQkbkFnCkrao-21.bmp.332986.4d1ab400
gif/xoApQkbkFnCkrao-22.bmp.332986.4d1fcc00
gif/xoApQkbkFnCkrao-23.bmp.332986.4d24e400
gif/xoApQkbkFnCkrao-24.bmp.332986.4d29fc00

参考链接:how-to-untar-file-in-memory-c-programming

离线

楼主 #2 2018-02-01 11:00:17

bugfix
会员
注册时间: 2017-11-22
已发帖子: 125
积分: 125

Re: 找到一个在内存中untar文件的方法,不敢独享,原理现在没看懂,但是基本也能用了。

正准备把上面这段代码移到 u-boot 上去, 发现sscanf链接错误, 看来u-boot不能用标准C库了,得自己去实现一个,谷歌去找找。

离线

楼主 #3 2018-02-01 11:02:40

bugfix
会员
注册时间: 2017-11-22
已发帖子: 125
积分: 125

Re: 找到一个在内存中untar文件的方法,不敢独享,原理现在没看懂,但是基本也能用了。

终于找到一个 http://blog.csdn.net/jiangdou88/article/details/46865797
加到 lib/vsprintf.c 可以用上,
然后继续搜了一下, 应该是从Linux里面拷过来的: lib/vsprintf.c

离线

楼主 #4 2018-02-01 11:04:13

bugfix
会员
注册时间: 2017-11-22
已发帖子: 125
积分: 125

Re: 找到一个在内存中untar文件的方法,不敢独享,原理现在没看懂,但是基本也能用了。

#define USHRT_MAX     ((u16)(~0U))
#define SHRT_MAX     ((s16)(USHRT_MAX>>1))


/**
* simple_strtoll - convert a string to a signed long long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
long long simple_strtoll(const char *cp, char **endp, unsigned int base)
{
     if (*cp == '-')
          return -simple_strtoull(cp + 1, endp, base);

     return simple_strtoull(cp, endp, base);
}

/* Convert a character to lower case */
__inline__ static char
_tolower (char c)
{
  if ((c >= 'A') && (c <= 'Z'))
    {
      c = (c - 'A') + 'a';
    }
  return c;
}

/**
* vsscanf - Unformat a buffer into a list of arguments
* @buf:     input buffer
* @fmt:     format of buffer
* @args:     arguments
*/
int vsscanf(const char *buf, const char *fmt, va_list args)
{
     const char *str = buf;
     char *next;
     char digit;
     int num = 0;
     u8 qualifier;
     u8 base;
     s16 field_width;
     char is_sign;

     while (*fmt && *str) {
          /* skip any white space in format */
          /* white space in format matchs any amount of
          * white space, including none, in the input.
          */
          if (isspace(*fmt)) {
               fmt = skip_spaces(++fmt);
               str = skip_spaces(str);
          }

          /* anything that is not a conversion must match exactly */
          if (*fmt != '%' && *fmt) {
               if (*fmt++ != *str++)
                    break;
               continue;
          }

          if (!*fmt)
               break;
          ++fmt;

          /* skip this conversion.
          * advance both strings to next white space
          */
          if (*fmt == '*') {
               while (!isspace(*fmt) && *fmt != '%' && *fmt)
                    fmt++;
               while (!isspace(*str) && *str)
                    str++;
               continue;
          }

          /* get field width */
          field_width = -1;
          if (isdigit(*fmt))
               field_width = skip_atoi(&fmt);

          /* get conversion qualifier */
          qualifier = -1;
          if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
              _tolower(*fmt) == 'z') {
               qualifier = *fmt++;
               if (unlikely(qualifier == *fmt)) {
                    if (qualifier == 'h') {
                         qualifier = 'H';
                         fmt++;
                    } else if (qualifier == 'l') {
                         qualifier = 'L';
                         fmt++;
                    }
               }
          }

          if (!*fmt || !*str)
               break;

          base = 10;
          is_sign = 0;

          switch (*fmt++) {
          case 'c':
          {
               char *s = (char *)va_arg(args, char*);
               if (field_width == -1)
                    field_width = 1;
               do {
                    *s++ = *str++;
               } while (--field_width > 0 && *str);
               num++;
          }
          continue;
          case 's':
          {
               char *s = (char *)va_arg(args, char *);
               if (field_width == -1)
                    field_width = SHRT_MAX;
               /* first, skip leading white space in buffer */
               str = skip_spaces(str);

               /* now copy until next white space */
               while (*str && !isspace(*str) && field_width--)
                    *s++ = *str++;
               *s = '\0';
               num++;
          }
          continue;
          case 'n':
               /* return number of characters read so far */
          {
               int *i = (int *)va_arg(args, int*);
               *i = str - buf;
          }
          continue;
          case 'o':
               base = 8;
               break;
          case 'x':
          case 'X':
               base = 16;
               break;
          case 'i':
               base = 0;
          case 'd':
               is_sign = 1;
          case 'u':
               break;
          case '%':
               /* looking for '%' in str */
               if (*str++ != '%')
                    return num;
               continue;
          default:
               /* invalid format; stop here */
               return num;
          }

          /* have some sort of integer conversion.
          * first, skip white space in buffer.
          */
          str = skip_spaces(str);

          digit = *str;
          if (is_sign && digit == '-')
               digit = *(str + 1);

          if (!digit
              || (base == 16 && !isxdigit(digit))
              || (base == 10 && !isdigit(digit))
              || (base == 8 && (!isdigit(digit) || digit > '7'))
              || (base == 0 && !isdigit(digit)))
               break;

          switch (qualifier) {
          case 'H':     /* that's 'hh' in format */
               if (is_sign) {
                    signed char *s = (signed char *)va_arg(args, signed char *);
                    *s = (signed char)simple_strtol(str, &next, base);
               } else {
                    unsigned char *s = (unsigned char *)va_arg(args, unsigned char *);
                    *s = (unsigned char)simple_strtoul(str, &next, base);
               }
               break;
          case 'h':
               if (is_sign) {
                    short *s = (short *)va_arg(args, short *);
                    *s = (short)simple_strtol(str, &next, base);
               } else {
                    unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
                    *s = (unsigned short)simple_strtoul(str, &next, base);
               }
               break;
          case 'l':
               if (is_sign) {
                    long *l = (long *)va_arg(args, long *);
                    *l = simple_strtol(str, &next, base);
               } else {
                    unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
                    *l = simple_strtoul(str, &next, base);
               }
               break;
          case 'L':
               if (is_sign) {
                    long long *l = (long long *)va_arg(args, long long *);
                    *l = simple_strtoll(str, &next, base);
               } else {
                    unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
                    *l = simple_strtoull(str, &next, base);
               }
               break;
          case 'Z':
          case 'z':
          {
               size_t *s = (size_t *)va_arg(args, size_t *);
               *s = (size_t)simple_strtoul(str, &next, base);
          }
          break;
          default:
               if (is_sign) {
                    int *i = (int *)va_arg(args, int *);
                    *i = (int)simple_strtol(str, &next, base);
               } else {
                    unsigned int *i = (unsigned int *)va_arg(args, unsigned int*);
                    *i = (unsigned int)simple_strtoul(str, &next, base);
               }
               break;
          }
          num++;

          if (!next)
               break;
          str = next;
     }

     /*
     * Now we've come all the way through so either the input string or the
     * format ended. In the former case, there can be a %n at the current
     * position in the format that needs to be filled.
     */
     if (*fmt == '%' && *(fmt + 1) == 'n') {
          int *p = (int *)va_arg(args, int *);
          *p = str - buf;
     }

     return num;
}
/**
* sscanf - Unformat a buffer into a list of arguments
* @buf:     input buffer
* @fmt:     formatting of buffer
* @...:     resulting arguments
*/
int sscanf(const char *buf, const char *fmt, ...)
{
     va_list args;
     int i;

     va_start(args, fmt);
     i = vsscanf(buf, fmt, args);
     va_end(args);

     return i;
}

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn