Справочник по консольным командам Toybox для Android 12


  Ver.0.8.4     Ver.0.8.9     Pending  

Путь: Toys/Other, команды версии: Ver.4     Ver.9


xxd

Комментарии в файле xxd.c :

usage: xxd [-c n] [-g n] [-i] [-l n] [-o n] [-p] [-r] [-s n] [file]

Hexdump файла в стандартный вывод. Если файла нет в списке, скопируйте из стандартного ввода. Имя файла "-" является синонимом стандартного ввода.
  • -c n Показать n байтов в строке (по умолчанию 16)
  • -g n Группировать байты, добавляя ' ' через каждые n байтов (по умолчанию 2)
  • -i Выходной включаемый файл (шестнадцатеричные байты CSV, плюс верхний/нижний колонтитул C, если не стандартный ввод)
  • -l n Ограничение в n байтов перед остановкой ( по умолчанию нет ограничений)
  • -o n Добавить n для отображения смещения
  • -p Обычный шестнадцатеричный дамп (30 байт/строка, без группировки. С -c 0 без переноса/группы)
  • -r Обратная операция: превратить шестнадцатеричный дамп в двоичный файл
  • -s n Перейти к смещению n

  • usage: xxd [-c n] [-g n] [-i] [-l n] [-o n] [-p] [-r] [-s n] [file]

    Hexdump a file to stdout. If no file is listed, copy from stdin. Filename "-" is a synonym for stdin.
  • -c n Show n bytes per line (default 16)
  • -g n Group bytes by adding a ' ' every n bytes (default 2)
  • -i Output include file (CSV hex bytes, plus C header/footer if not stdin)
  • -l n Limit of n bytes before stopping (default is no limit)
  • -o n Add n to display offset
  • -p Plain hexdump (30 bytes/line, no grouping. With -c 0 no wrap/group)
  • -r Reverse operation: turn a hexdump into a binary file
  • -s n Skip to offset n

  • Исходный текст в файле xxd.c

    #define FOR_xxd
    #include "toys.h"
    
    GLOBALS(
      long s, g, o, l, c;
    )
    
    static void do_xxd(int fd, char *name)
    {
      long long pos = 0;
      long long limit = TT.l;
      int i, len, space, c = TT.c ? : sizeof(toybuf);
    
      if (FLAG(s)) {
        xlseek(fd, TT.s, SEEK_SET);
        pos = TT.s;
        if (limit) limit += TT.s;
      }
    
      while (0<(len = readall(fd, toybuf,
                              (limit && limit-pos<c)?limit-pos:c)))
      {
        if (!FLAG(p)) printf("%08llx: ", TT.o + pos);
        pos += len;
        space = 2*TT.c;
        space += TT.g ? (TT.c+TT.g-1)/TT.g+1 : 2;
    
        for (i=0; i<len;) {
          space -= printf("%02x", toybuf[i++]);
          if (TT.g && !(i%TT.g)) {
            putchar(' ');
            space--;
          }
        }
    
        if (!FLAG(p)) {
          printf("%*s", space, "");
          for (i = 0; i<len; i++)
            putchar((toybuf[i]>=' ' && toybuf[i]<='~') ? toybuf[i] : '.');
        }
        if (TT.c || !FLAG(p)) putchar('\n');
      }
      if (!TT.c && FLAG(p)) putchar('\n');
      if (len<0) perror_exit("read");
    }
    
    static void do_xxd_include(int fd, char *name)
    {
      int c = 1, i, len;
    
      // The original xxd outputs a header/footer if given a filename (not stdin).
      // We don't, which means that unlike the original we can implement -ri.
      while ((len = read(fd, toybuf, sizeof(toybuf))) > 0) {
        for (i = 0; i < len; ++i) {
          printf("%s%#.02x", c > 1 ? ", " : "  ", toybuf[i]);
          if (c++ == TT.c) {
            xprintf(",\n");
            c = 1;
          }
        }
      }
      if (len < 0) perror_msg_raw(name);
      if (c > 1) xputc('\n');
    }
    
    static int dehex(char ch)
    {
      if (ch >= '0' && ch <= '9') return ch - '0';
      if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
      if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
      return (ch == '\n') ? -2 : -1;
    }
    
    static void do_xxd_reverse(int fd, char *name)
    {
      FILE *fp = xfdopen(xdup(fd), "r");
      long long pos, current_pos = 0;
      int tmp;
    
      // -ri is a very easy special case.
      if (FLAG(i)) while (fscanf(fp, " 0x%02x,", &tmp) == 1) xputc(tmp);
      else while (!feof(fp)) {
        int col = 0;
    
        // Each line of a regular hexdump starts with an offset/address.
        // Each line of a plain hexdump just goes straight into the bytes.
        if (!FLAG(p) && fscanf(fp, "%llx: ", &pos) == 1) {
          if (pos != current_pos && fseek(stdout, pos, SEEK_SET)) {
            // TODO: just write out zeros if non-seekable?
            perror_exit("%s: seek failed", name);
          }
        }
    
        // A plain hexdump can have as many bytes per line as you like,
        // but a non-plain hexdump assumes garbage after it's seen the
        // specified number of bytes.
        while (FLAG(p) || !TT.c || col < TT.c) {
          int n1, n2;
    
          // If we're at EOF or EOL or we read some non-hex...
          if ((n1 = n2 = dehex(fgetc(fp))) < 0 || (n2 = dehex(fgetc(fp))) < 0) {
            // If we're at EOL, start on that line.
            if (n1 == -2 || n2 == -2) continue;
            // Otherwise, skip to the next line.
            break;
          }
    
          fputc((n1 << 4) | (n2 & 0xf), stdout);
          col++;
          current_pos++;
    
          // Is there any grouping going on? Ignore a single space.
          tmp = fgetc(fp);
          if (tmp != ' ') ungetc(tmp, fp);
        }
    
        // Skip anything else on this line (such as the ASCII dump).
        while ((tmp = fgetc(fp)) != EOF && tmp != '\n');
      }
    
      if (ferror(fp)) perror_msg_raw(name);
      fclose(fp);
    }
    
    void xxd_main(void)
    {
      // Plain style is 30 bytes/line, no grouping.
      if (!FLAG(c)) TT.c = FLAG(p) ? 30 : FLAG(i) ? 12 : 16;
      if (FLAG(p) && !FLAG(g)) TT.g = TT.c;
    
      loopfiles(toys.optargs,
        FLAG(r) ? do_xxd_reverse : (FLAG(i) ? do_xxd_include : do_xxd));
    }