5 #define _XOPEN_SOURCE 500
13 #include <sys/types.h>
16 #include <sys/statvfs.h>
22 #include <sys/queue.h>
27 #include "test_driver.h"
32 typedef struct cmd_tree_t {
36 struct queue_t *children;
45 struct cmd_t cmd_list[] = {
46 {"alloc", get_buffer, usage_get_buffer},
47 {"chdir", test_do_chdir, usage_chdir},
48 {"checkbuf", do_checkbuf, usage_checkbuf},
49 {"chmod", test_do_chmod, usage_chmod},
50 {"chown", test_do_chown, usage_chown},
51 {"clear", test_do_clear, usage_clear},
52 {"close", test_do_close, usage_close},
53 {"cmpstr", cmp_bufs, usage_cmpbufs},
54 {"creat", test_do_creat, usage_creat},
55 {"debug", test_do_setdebug, usage_setdebug},
56 {"dup", test_do_dup, usage_dup},
57 {"dup2", test_do_dup2, usage_dup2},
58 {"endian", get_endian, usage_endian},
59 {"exit", test_do_exit, usage_exit},
60 {"fcntl", test_do_fcntl, usage_fcntl},
61 {"fdatasync", test_do_fdatasync, usage_fdatasync},
62 {"fill", test_do_fillbuff, usage_do_fillbuff},
63 {"free", free_buffer, usage_free_buffer},
64 {"fstat", test_do_fstat, usage_fstat},
65 {"fstatvfs", test_do_fstatvfs, usage_fstatvfs},
66 {"fsync", test_do_fsync, usage_fsync},
67 {"ftruncate", test_do_ftruncate, usage_ftruncate},
68 {"getcwd", test_do_getcwd, usage_getcwd},
69 {"getdirentries", test_do_getdirentries, usage_getdirentries},
70 {"init", test_do_init, usage_init},
71 {"init_iovec", test_do_init_iovec, usage_init_iovec},
72 {"init_xtvec", test_do_init_xtvec, usage_init_xtvec},
73 {"ioctl", test_do_ioctl, usage_ioctl},
74 {"iodone", test_do_iodone, usage_iodone},
75 {"iowait", test_do_iowait, usage_iowait},
76 {"ipread", test_do_ipread, usage_ipread},
77 {"ipreadv", test_do_ipreadv, usage_ipreadv},
78 {"ipwrite", test_do_ipwrite, usage_ipwrite},
79 {"ipwritev", test_do_ipwritev, usage_ipwritev},
80 {"iread", test_do_iread, usage_iread},
81 {"ireadv", test_do_ireadv, usage_ireadv},
82 {"ireadx", test_do_ireadx, usage_ireadx},
83 {"iwrite", test_do_iwrite, usage_iwrite},
84 {"iwritev", test_do_iwritev, usage_iwritev},
85 {"iwritex", test_do_iwritex, usage_iwritex},
86 {"list", test_do_list, usage_list},
87 {"lseek", test_do_lseek, usage_lseek},
88 {"lstat", test_do_lstat, usage_lstat},
89 {"mkdir", test_do_mkdir, usage_mkdir},
90 {"mknod", test_do_mknod, usage_mknod},
91 {"mount", test_do_mount, usage_mount},
92 {"open", test_do_open, usage_open},
93 {"printbuf", test_do_printbuf, usage_do_printbuf},
94 {"printline", test_do_printline, usage_printline},
95 {"pread", test_do_pread, usage_pread},
96 {"preadv", test_do_preadv, usage_preadv},
97 {"pwritev", test_do_pwritev, usage_pwritev},
98 {"pwrite", test_do_pwrite, usage_pwrite},
99 {"quit", test_do_exit, usage_exit},
100 {"read", test_do_read, usage_read},
101 {"readv", test_do_readv, usage_readv},
102 {"readx", test_do_readx, usage_readx},
103 {"rmdir", test_do_rmdir, usage_rmdir},
104 {"setbuf", do_setbuf, usage_setbuf},
105 {"sizeof", get_sizeof, usage_sizeof},
106 /* {"setoutput", test_do_setoutput, usage_setoutput}, */
107 {"stat", test_do_stat, usage_stat},
108 {"statvfs", test_do_statvfs, usage_statvfs},
109 {"symlink", test_do_symlink, usage_symlink},
110 {"truncate", test_do_truncate, usage_truncate},
111 {"umask", test_do_umask, usage_umask},
112 {"umount", test_do_umount, usage_umount},
113 {"unlink", test_do_unlink, usage_unlink},
114 {"write", test_do_write, usage_write},
115 {"writev", test_do_writev, usage_writev},
116 {"writex", test_do_writex, usage_writex},
120 int run_cmd(cmd_tree *cmd_arg);
121 cmd_tree* build_tree(char **cmd, int *length, int total);
123 * ##################################################
124 * # Memory functions #
125 * # Intended to allow users to gain access to #
126 * # buffers of memory to be manipulated later #
127 * ##################################################
130 void * alloc_buff32(unsigned int size, int align)
136 if ((err = memalign(&buf, align, size)) != 0) {
144 DBG(3, fprintf(outfp, "Buf is at %p\n", (void *)buf));
145 buf_ptr = (long)buf + ((long)buf & align);
147 DBG(3, fprintf(outfp, "Buf is at %p\n", (void *)buf_ptr));
148 return (void *)buf_ptr;
151 void free_buf32(void * ptr)
156 long alloc_buff64(unsigned int size, int align)
162 if (memalign((void **)&buf, align, size))
168 ret_value = (long)buf + ((long)buf & align);
172 void free_buf64(long ptr)
179 * Hash function for variables. Shamelessly stolen
182 unsigned int dx_hack_hash (const char *name, int len)
184 unsigned int hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
187 unsigned int hash = hash1 + (hash0 ^ (*name++ * 7152373));
188 if (hash & 0x80000000) hash -= 0x7fffffff;
195 struct var_mapping *get_map(char *var_name)
198 struct var_mapping_list *curr;
201 if (var_name[0] == '$') {
202 /* It is a name--chop off the initial and get the mapping $ */
206 index = dx_hack_hash(var_name, strlen(var_name));
207 index %= MAX_VARS -1;
209 DBG(5, fprintf(outfp, "Got index of %d for %s\n", index, var_name));
212 while ((curr) && (curr->map.obj != -1) ) {
213 if ( (curr->map.name == NULL) || (strcmp(curr->map.name, var_name)) )
222 char *get_str(char *var_name)
224 /* See if it is a quoted string */
225 if (var_name[0] == '"') {
226 /* Chop off the beginning and end quotes and return the string */
227 int len = strlen(var_name);
228 var_name[len-1] = '\0';
236 get_or_part(char **str, int* did_alloc)
238 char *tmp_str = *str;
244 if (tmp_str[0] == '|') {
249 for (i=0; (unsigned int)i < strlen(tmp_str); i++) {
250 if (tmp_str[i] == '|') {
251 char *new_str = (char *)malloc(i+1);
252 memcpy(new_str, tmp_str, i);
269 int get_obj(char *var_name)
271 char** str = &var_name;
273 struct var_mapping *var_map;
275 int obj=0, got_obj=0;
277 DBG(5, fprintf(outfp, "Getting object for %s\n", var_name));
279 /* If var_name is a digit, we assume it is a literal */
280 if (isdigit(var_name[0]))
281 return atoi(var_name);
284 * Check for '|', indicates that one or more values are or'd
287 while ((str1 = get_or_part(str, &did_alloc)) != NULL) {
289 if (isdigit(str1[0])) {
290 if (str1[0] == '0') {
291 /* Assume octal format */
292 obj |= strtol(str1, NULL, 8);
296 var_map = get_map(str1);
315 var_map = get_map(var_name);
323 void store_result(char *var_name, int result)
325 int index = dx_hack_hash(var_name, strlen(var_name));
326 struct var_mapping_list *map_obj;
327 struct var_mapping_list *new_map;
328 index %= MAX_VARS -1 ;
330 if (map[index].map.obj >= 0) {
332 /* Got a collision --just chain it*/
333 new_map = malloc(sizeof(struct var_mapping_list));
335 map_obj = &map[index];
336 while (map_obj->next != NULL)
337 map_obj = map_obj->next;
339 map_obj->next = new_map;
341 new_map = &map[index];
343 new_map->map.name = malloc(strlen(var_name) + 1);
344 strcpy(new_map->map.name, var_name);
345 new_map->map.obj = result;
346 new_map->map.type = last_type;
347 new_map->next = NULL;
348 DBG(3, fprintf(outfp, "Stored %d in index %d hashed with %s\n",
349 result, index, var_name));
352 void free_obj(char *obj_name)
355 struct var_mapping_list *prev, *curr;
358 /* See if it is a variable name */
359 if (obj_name[0] == '$') {
360 /* It is a name--chop off the initial $ */
363 index = dx_hack_hash(obj_name, strlen(obj_name));
364 index %= MAX_VARS -1;
366 DBG(5, fprintf(outfp, "Got index of %d\n", index));
371 while ((curr) && (curr->map.obj != -1) ) {
372 if (strcmp(curr->map.name, obj_name)) {
379 /* Remove the object from the chain */
381 prev->next = curr->next;
384 free(curr->map.name);
391 * Given a long string, returns the string divided into
392 * whitespace seperated words in list. Returns the number
395 int parser(char *str, char** list)
397 int len, i=0, j=0, counter=-1;
403 DBG(5, fprintf(outfp, "str is %s len is %d\n", str, len));
406 if ((i==0) || ((str[i] == ' ') && (in_quotes == 0)) ) {
409 DBG(5, fprintf(outfp, "Got word %s\n", list[counter]));
412 while ((str[i] == ' ') && (in_quotes == 0))
415 new_str = list[counter] = malloc(MAX_WORD);
427 if ((str[i] == ' ') && (in_quotes==0)){
428 while (str[i+1] == ' ')
437 DBG(5, fprintf(outfp, "Got word %s\n", list[counter]));
442 int execute_cmd(char *cmd, char **args, int arg_count)
446 if (!strcmp(cmd, "help")) {
448 while(cmd_list[i].cmd != NULL) {
449 if (!strcmp(cmd_list[i].cmd, args[0])) {
450 (cmd_list[i].usage)();
461 while(cmd_list[i].cmd != NULL) {
462 if (!strcmp(cmd_list[i].cmd, cmd)) {
463 return (cmd_list[i].func)(arg_count, args);
467 DBG(2, fprintf(outfp, "Command %s was invalid\n", cmd));
471 int get_args(struct queue_t *child, char** list, int num_args, int argnum)
475 if (child->val != NULL) {
477 } else if (child->cmd != NULL) {
479 if (child->cmd->res_name != NULL)
480 argval = child->cmd->res_name;
483 int val = last_ret_val;
484 sprintf(tmpstr, "%x", val);
488 DBG(2, fprintf(outfp, "I am confused\n"));
492 list[argnum] = malloc(strlen(argval) + 1);
493 strcpy(list[argnum], argval);
496 if (argnum == num_args)
498 else if (child->next == NULL) {
499 DBG(2, fprintf(outfp, "Only on arg number %d out of %d, but ran out of children\n",
503 return get_args(child->next, list, num_args, argnum);
508 int run_cmd(cmd_tree *cmd_arg)
510 char cmdstr[MAX_COMMAND];
516 struct queue_t *child;
523 child = cmd_arg->children;
524 if ( (!strcmp("exit", cmd)) || (!strcmp("quit", cmd)) ||
525 (!strcmp("EXIT", cmd)) || (!strcmp("QUIT", cmd)) )
526 strcpy(cmdstr, "exit");
527 else if (!strcmp("ALLOC", cmd))
528 strcpy(cmdstr, "alloc");
529 else if (!strcmp("FREE", cmd))
530 strcpy(cmdstr, "free");
531 else if (!strcmp("HELP", cmd))
532 strcpy(cmdstr, "help");
533 else if (!strcmp("CALL", cmd)) {
534 if (cmd_arg->arg_count < 1) {
535 DBG(2, fprintf(outfp, "Need at least one command\n"));
539 cmd_arg->arg_count--;
540 if (child->val != NULL)
543 DBG(2, fprintf(outfp, "Need to specify command\n"));
547 DBG(3, fprintf(outfp, "Got cmd %s\n", child->val));
548 if (cmd_arg->arg_count != 0)
552 } else if (!strcmp("DEPOSIT", cmd))
553 strcpy(cmdstr, "fill");
554 else if (!strcmp("PRINT", cmd))
555 strcpy(cmdstr, "printbuf");
557 if (cmd_arg->res_name != NULL) {
559 * If the cmd is not a valid command, just store it
561 res = get_obj(cmd_arg->children->val);
564 /* Just store it as a string */
565 buf = (struct buf_t *)malloc(sizeof(struct buf_t));
566 buf->len = strlen(cmd);
567 buf->buf = (char *)malloc(buf->len+1);
568 strcpy(buf->buf, cmd_arg->children->val);
571 DBG(3, fprintf(outfp, "Stored %s in index %d\n", (char *)buf->buf, next));
575 store_result(cmd_arg->res_name, res);
582 if (cmd_arg->arg_count == 0)
585 args = (char **)malloc(sizeof(char *)*cmd_arg->arg_count);
586 get_args(child, args, cmd_arg->arg_count, 0);
589 DBG(3, fprintf(outfp, "CMD: %s\n ARGS: ",cmdptr));
590 for (i=0; i < cmd_arg->arg_count; i++)
591 DBG(3, fprintf(outfp, "%s ", args[i]));
592 DBG(3, fprintf(outfp, "\n"));
593 res = execute_cmd(cmdptr, args, cmd_arg->arg_count);
594 if (cmd_arg->res_name != NULL)
595 store_result(cmd_arg->res_name, last_ret_val);
601 int is_command(char *name)
603 if ( (strcmp(name, "CALL")) && (strcmp(name, "FILL")) &&
604 (strcmp(name, "ALLOC")) && (strcmp(name, "PRINT")) &&
605 (strcmp(name, "FREE")) && (strcmp(name, "exit")) &&
606 (strcmp(name, "HELP")) && (strcmp(name, "help")) &&
607 (strcmp(name, "quit")) && (strcmp(name, "EXIT")) &&
608 (strcmp(name, "QUIT")) && (strcmp(name, "DEPOSIT")) )
615 int get_type(char *arg0)
617 if ((arg0[0] == '(') || (is_command(arg0)) ){
625 int add_args(char **cmd, int length, int total, cmd_tree *tree)
628 struct queue_t *old, *new;
630 old = tree->children;
631 while ((old) && (old->next))
633 new = (struct queue_t *)malloc(sizeof(struct queue_t));
637 tree->children = new;
640 type = get_type(cmd[0]);
642 DBG(2, fprintf(outfp, "Don't understand %s\n", cmd[0]));
646 new->val = (char *)malloc(strlen(cmd[0])+1);
647 strcpy(new->val, cmd[0]);
652 if (cmd[0][0] == '(') {
657 new->cmd = build_tree(&cmd[1], &new_len, total);
658 if (new->cmd == NULL) { /* Invalid command */
659 return length; /* Pretend we used everything up */
661 total = (length - new_len);
662 DBG(4, fprintf(outfp, "Used %d bytes\n", total));
668 void free_tree(cmd_tree* tree)
673 if (tree->children) {
674 struct queue_t *child = tree->children;
675 struct queue_t *next;
679 free_tree(child->cmd);
687 free(tree->res_name);
695 cmd_tree* build_tree(char **cmd, int *length, int total)
697 int index = 0, used_args = 0;
699 if ((*length < 0) || (!cmd) || (*cmd == NULL))
703 DBG(4, fprintf(outfp, "length is %d\n", *length));
704 tree = (cmd_tree *)malloc(sizeof(cmd_tree));
705 tree->res_name = NULL;
706 tree->children = NULL;
707 if (cmd[index][0] == '$') {
708 tree->res_name = (char *)malloc(strlen(cmd[index])+1);
709 strcpy(tree->res_name, (char*)(cmd[index]+1));
711 if (cmd[index][0] == '=')
714 tree->res_name = NULL;
716 if (is_command(cmd[index]) == 0) {
717 if (tree->res_name == NULL) {
718 DBG(2, fprintf(outfp, "command %s is invalid \n", cmd[index]));
723 tree->val = (char *)malloc(strlen(cmd[index])+1);
724 strcpy(tree->val, cmd[index]);
734 /* Got to get the arguments */
735 while (*length > 0) {
737 if (cmd[index][0] == ')') {
739 DBG(4, fprintf(outfp, "and now len is %d\n", *length));
743 used_args = add_args(&cmd[index], *length, total, tree);
745 *length -= used_args;
753 char *getline(char *prompt)
758 line = malloc(MAX_LINE);
759 if ((do_prompt) && (infp == stdin))
763 /* If we get an end of file, just wait */
765 while (feof(infp) && (line[i] != '\n')) {
768 fseek(infp, 0, SEEK_CUR);
773 fread(&line[i], 1, 1, infp);
774 } while(line[i] != '\n');
778 /* fprintf(stderr, "Got word %s\n", line); */
779 DBG(5, fprintf(outfp, "Got word %s\n", line));
783 void my_perror(char *msg)
785 char *errmsg = strerror(errno);
787 DBG(2, fprintf(outfp, "%s: %s\n", msg, errmsg));
790 /* Static list of flag names */
791 struct var_mapping flags_map[] = {
792 {"O_RDONLY", O_RDONLY, UINT },
793 {"O_WRONLY", O_WRONLY, UINT },
794 {"O_RDWR", O_RDWR, UINT },
795 {"O_CREAT", O_CREAT, UINT },
796 {"O_EXCL", O_EXCL, UINT },
797 {"O_NOCTTY", O_NOCTTY, UINT },
798 {"O_TRUNC", O_TRUNC, UINT },
799 {"O_APPEND", O_APPEND, UINT },
800 {"O_SYNC", O_NONBLOCK, UINT },
801 {"O_NDELAY", O_NDELAY, UINT },
802 {"O_SYNC", O_SYNC, UINT },
803 {"O_FSYNC", O_FSYNC, UINT },
804 {"O_ASYNC", O_ASYNC, UINT },
805 {"SEEK_SET", SEEK_SET, UINT },
806 {"SEEK_CUR", SEEK_CUR, UINT },
807 {"SEEK_END", SEEK_END, UINT },
808 {"S_ISUID", S_ISUID, UINT },
809 {"S_ISGID", S_ISGID, UINT },
810 {"S_ISVTX", S_ISVTX, UINT },
811 {"S_IRWXU", S_IRWXU, UINT },
812 {"S_IRUSR", S_IRUSR, UINT },
813 {"S_IREAD", S_IREAD, UINT },
814 {"S_IWUSR", S_IWUSR, UINT },
815 {"S_IWRITE", S_IWRITE, UINT },
816 {"S_IXUSR", S_IXUSR, UINT },
817 {"S_IEXEC", S_IEXEC, UINT },
818 {"S_IRWXG", S_IRWXG, UINT },
819 {"S_IRGRP", S_IRGRP, UINT },
820 {"S_IWGRP", S_IWGRP, UINT },
821 {"S_IXGRP", S_IXGRP, UINT },
822 {"S_IRWXO", S_IRWXO, UINT },
823 {"S_IROTH", S_IROTH, UINT },
824 {"S_IWOTH", S_IWOTH, UINT },
825 {"S_IXOTH", S_IXOTH, UINT },
826 {"S_IFCHR", S_IFCHR, UINT },
827 {"S_IFMT", S_IFMT, UINT },
828 {"S_IFBLK", S_IFBLK, UINT },
829 {"S_IFREG", S_IFREG, UINT },
830 {"S_IFIFO", S_IFIFO, UINT },
831 {"S_IFLNK", S_IFLNK, UINT },
839 while (flags_map[index].obj != -1) {
840 store_result(flags_map[index].name, flags_map[index].obj);
845 int getquotedlen(char *str)
849 if (str[0] != '"' && str[0] != '\'')
852 for (i=1; str[i] != '\0' && str[i] != '"' && str[i] != '\''; i++);
857 int perform_op(int num1, int num2, char op)
887 int get_constant_val(char **str_ptr, int type)
891 char *str = *str_ptr;
893 int i, j, num1, num2, size;
895 printf("Getting constant val from %s\n", str);
898 size = getquotedlen(str);
899 buf = (struct buf_t *)malloc(sizeof(struct buf_t));
900 buf->buf = alloc_buff32(size, 8);
905 for (i=1; i < size; i++) {
911 DBG(3, fprintf(outfp, "Your buffer (%p) (%p) is at index %d\n",
912 (void *)buf, buf->buf, next));
916 last_ret_val = next-1;
928 if ((ch == '+') || (ch == '/') || (ch == '*') ||
929 (ch == '-') || (ch == '%')) {
930 if (str_ptr[2][0] == '$')
931 num2 = get_obj(str_ptr[2]);
933 num2 = atoi(str_ptr[2]);
934 num1 = perform_op(num1, num2, ch);
943 DBG(2, fprintf(outfp, "Can't understand type of %d\n", type));
950 int is_constant(char *str)
952 if ((str[0] == '"') || (str[0] == '\''))
956 if ( (str[0] == '$') ||
957 ( ((int)str[0] > 47) && ((int)str[0] < 57) ) )
963 int main(int argc, char *argv[])
965 int count, err, i, orig_count;
969 extern int _test_sysio_startup(void);
974 err = _test_sysio_startup();
982 /* Get the input/output streams */
983 for (i = 1; i < argc; i++) {
984 if (!strcmp(argv[i], "--input")) {
986 infp = fopen(argv[i], "r");
988 fprintf(outfp, "Unable to open file %s for reading\n", argv[i]);
991 } else if (!strcmp(argv[i], "--output")) {
993 outfp = fopen(argv[i], "w");
995 fprintf(stderr, "Unable to open file %s for writing\n", argv[i]);
998 } else if (!strcmp(argv[i], "--np")) {
1001 fprintf(stderr, "%s: Invalid arg\n", argv[i]);
1005 /* Initilize the mapping */
1006 for (i=0; i < MAX_VARS; i++)
1007 map[i].map.obj = -1;
1009 /* Debug defaults */
1015 /* sysio defaults */
1016 strcpy(root_driver, DEFAULT_DRIVER);
1017 strcpy(mntpath, "/");
1023 /* Set up line buffering */
1028 * This sets up some common flags so that the string
1029 * names can be used (for instance 0_RDWR, SEEK_SET, etc
1035 bzero(output, 4096);
1037 input = getline("> ");
1038 cmd = malloc(MAX_COMMAND * sizeof(char *));
1039 count = orig_count = parser(input, cmd);
1041 if ((!count) || (count > MAX_COMMAND)){
1042 fprintf(outfp, "%s: invalid command\n", input);
1045 if (cmd[0][0] == '$') {
1046 /* Need to store output of command in var name */
1048 DBG(4, fprintf(outfp, "name is %s\n", name));
1050 /* The '=' is not necessary, but available */
1051 if (!strcmp(cmd[1], "=")){
1056 if ((err=is_constant(cmd[i])) != 0) {
1057 store_result((char *)(&cmd[0][1]), get_constant_val(&cmd[i], err));
1062 tree = build_tree(&cmd[i], &count, 0);
1064 err = run_cmd(tree);
1065 store_result((char *)(&cmd[0][1]), last_ret_val);
1070 tree = build_tree(cmd, &count, 0);
1072 err = run_cmd(tree);
1074 /* Print out return code and any string from command */
1075 fprintf(outfp, "%#04x %s\n", err, output);
1078 /* fprintf(stderr, "%#04x %s\n", err, output); */
1079 for (i=0; i < count; i++)