Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset cc9f314 in mainline


Ignore:
Timestamp:
2012-03-27T13:13:06Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master
Children:
a9a6d8d
Parents:
9bdf1f2a
git-author:
Taylor Killian <> (2012-03-27 13:13:06)
git-committer:
Vojtech Horky <vojtechhorky@…> (2012-03-27 13:13:06)
Message:

Implement head and tail functionality in bdsh/cat (thx Taylor Killian)

This patch fixes a number of problems in the cat app. Most
importantly, it correctly displays characters at the end of the read
buffer, where previously multibyte characters were being rendered as
U_SPECIAL. It also implements the buffer size argument (-b) that the
—help mentions. The size of the buffer must be at least 4 though in
order to accommodate multibyte characters. Finally head (-H) and tail
(-t) were implemented as per —help.

Location:
uspace/app/bdsh/cmds/modules/cat
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/cmds/modules/cat/cat.c

    r9bdf1f2a rcc9f314  
    5252#define CAT_VERSION "0.0.1"
    5353#define CAT_DEFAULT_BUFLEN 1024
    54 
    55 static const char *cat_oops = "That option is not yet supported\n";
     54#define CAT_FULL_FILE 0
     55
    5656static const char *hexchars = "0123456789abcdef";
    5757
     
    163163}
    164164
    165 static unsigned int cat_file(const char *fname, size_t blen, bool hex)
     165static unsigned int cat_file(const char *fname, size_t blen, bool hex,
     166    off64_t head, off64_t tail, bool tail_first)
    166167{
    167168        int fd, bytes = 0, count = 0, reads = 0;
    168169        char *buff = NULL;
    169170        int i;
    170         size_t offset = 0;
     171        size_t offset = 0, copied_bytes = 0;
     172        off64_t file_size = 0, length = 0;
    171173
    172174        fd = open(fname, O_RDONLY);
     
    183185        }
    184186
     187        if (tail != CAT_FULL_FILE) {
     188                file_size = lseek(fd, 0, SEEK_END);
     189                if (head == CAT_FULL_FILE) {
     190                        head = file_size;
     191                        length = tail;
     192                } else if (tail_first) {
     193                        length = head;
     194                } else {
     195                        if (tail > head)
     196                                tail = head;
     197                        length = tail;
     198                }
     199
     200                if (tail_first) {
     201                        lseek(fd, (tail >= file_size) ? 0 : (file_size - tail), SEEK_SET);
     202                } else {
     203                        lseek(fd, ((head - tail) >= file_size) ? 0 : (head - tail), SEEK_SET);
     204                }
     205        } else
     206                length = head;
     207
    185208        do {
    186                 bytes = read(fd, buff, blen);
     209                bytes = read(fd, buff + copied_bytes, (
     210                        (length != CAT_FULL_FILE && length - (off64_t)count <= (off64_t)(blen - copied_bytes)) ?
     211                        (size_t)(length - count) :
     212                        (blen - copied_bytes) ) );
     213                bytes += copied_bytes;
     214                copied_bytes = 0;
     215
    187216                if (bytes > 0) {
    188                         count += bytes;
    189217                        buff[bytes] = '\0';
    190218                        offset = 0;
     
    193221                                        paged_char(hexchars[((uint8_t)buff[i])/16]);
    194222                                        paged_char(hexchars[((uint8_t)buff[i])%16]);
     223                                        paged_char(((count+i+1) & 0xf) == 0 ? '\n' : ' ');
    195224                                }
    196225                                else {
     
    199228                                                /* Reached end of string */
    200229                                                break;
     230                                        } else if (c == U_SPECIAL && offset + 2 >= (size_t)bytes) {
     231                                                /* If an extended character is cut off due to the size of the buffer,
     232                                                   we will copy it over to the next buffer so it can be read correctly. */
     233                                                copied_bytes = bytes - offset + 1;
     234                                                memcpy(buff, buff + offset - 1, copied_bytes);
     235                                                break;
    201236                                        }
    202237                                        paged_char(c);
     
    204239                               
    205240                        }
     241                        count += bytes;
    206242                        reads++;
    207243                }
    208         } while (bytes > 0 && !should_quit);
     244        } while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
    209245
    210246        close(fd);
     
    223259int cmd_cat(char **argv)
    224260{
    225         unsigned int argc, i, ret = 0, buffer = 0;
     261        unsigned int argc, i, ret = 0;
     262        size_t buffer = 0;
    226263        int c, opt_ind;
     264        aoff64_t head = CAT_FULL_FILE, tail = CAT_FULL_FILE;
    227265        bool hex = false;
    228266        bool more = false;
     267        bool tailFirst = false;
    229268        sysarg_t rows, cols;
    230269        int rc;
     
    254293                        return CMD_SUCCESS;
    255294                case 'H':
    256                         printf("%s", cat_oops);
    257                         return CMD_FAILURE;
     295                        if (!optarg || str_uint64_t(optarg, NULL, 10, false, &head) != EOK ) {
     296                                puts("Invalid head size\n");
     297                                return CMD_FAILURE;
     298                        }
     299                        break;
    258300                case 't':
    259                         printf("%s", cat_oops);
    260                         return CMD_FAILURE;
     301                        if (!optarg || str_uint64_t(optarg, NULL, 10, false, &tail) != EOK ) {
     302                                puts("Invalid tail size\n");
     303                                return CMD_FAILURE;
     304                        }
     305                        if (head == CAT_FULL_FILE)
     306                                tailFirst = true;
     307                        break;
    261308                case 'b':
    262                         printf("%s", cat_oops);
     309                        if (!optarg || str_size_t(optarg, NULL, 10, false, &buffer) != EOK ) {
     310                                puts("Invalid buffer size\n");
     311                                return CMD_FAILURE;
     312                        }
    263313                        break;
    264314                case 'm':
     
    279329        }
    280330
    281         if (buffer <= 0)
     331        if (buffer < 4)
    282332                buffer = CAT_DEFAULT_BUFLEN;
    283333       
     
    295345
    296346        for (i = optind; argv[i] != NULL && !should_quit; i++)
    297                 ret += cat_file(argv[i], buffer, hex);
     347                ret += cat_file(argv[i], buffer, hex, head, tail, tailFirst);
    298348
    299349        if (ret)
  • uspace/app/bdsh/cmds/modules/cat/cat.h

    r9bdf1f2a rcc9f314  
    44/* Prototypes for the cat command, excluding entry points */
    55
    6 static unsigned int cat_file(const char *, size_t, bool);
     6static unsigned int cat_file(const char *, size_t, bool, off64_t, off64_t, bool);
    77
    88#endif /* CAT_H */
Note: See TracChangeset for help on using the changeset viewer.