/* Arbitrary Attribute Interchange Protocol , AAIP version 0.2 Demonstration program for encoding and decoding EA and ACL. See http://libburnia-project.org/wiki/AAIP test/aaip_0_2_test.c - Main program for test binary Compile: cc -g -Wall -o test/aaip test/aaip_0_2.c test/aaip_0_2_test.c -lacl Usage: ./aaip name value Long parameters ./aaip -name"x100" -value"x100" >>> ACLs */ #include #include #include #include #include #include #include #include #include "aaip_0_2.h" #define Aaip_test_name_sizE 1024 #define Aaip_test_value_sizE 1024 static int print_result(unsigned char *result, size_t result_len, int flag) { int i; printf( " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); printf("\n"); printf("%4u : ", 0); for(i= 0; i < result_len; i++) { if(result[i] >= 32 && result[i] <= 126) printf("'%c' ", result[i]); else printf("%3u ", (unsigned int) ((unsigned char *) result)[i]); if((i % 10) == 9) printf("\n%4u : ", (unsigned int) (i + 1)); } printf("\n\n"); printf( " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); printf("\n"); return(1); } static int print_attrs(size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { size_t i, j; for(i= 0; i < num_attrs; i++) { printf("name='"); for(j= 0; names[i][j] != 0; j++) { if(names[i][j] >= 32 && names[i][j] <= 126 && names[i][j] != '\\' && names[i][j] != '\'') printf("%c", names[i][j]); else printf("\\%o", (unsigned int) ((unsigned char **) names)[i][j]); } printf("' (%d)\n", (int) j); printf("value='"); for(j= 0; j < value_lengths[i]; j++) { if(values[i][j] >= 32 && values[i][j] <= 126 && values[i][j] != '\\' && values[i][j] != '\'') printf("%c", values[i][j]); else printf("\\%3.3o", (unsigned int) ((unsigned char **) values)[i][j]); } printf("' (%d)\n\n", (int) j); } return(1); } static int do_touch(char *path, int flag) { FILE *fp; fp= fopen(path, "a"); if(fp == NULL) { fprintf(stderr, "fopen(\"%s\") failed: %d %s\n", path, errno, errno != 0 ? strerror(errno) : ""); return(0); } fclose(fp); return(1); } static int decode_acl(unsigned char *result, size_t result_len, char *out_path, int flag) { int ret; size_t consumed, text_fill; char *text= NULL; ret= aaip_decode_acl(result, result_len, &consumed, NULL, 0, &text_fill, 1); if(ret <= 0) { fprintf(stderr, "aaip_decode_acl(,1) failed: ret= %d\n", ret); ret= 0; goto ex; } text= calloc(text_fill, 1); ret= aaip_decode_acl(result, result_len, &consumed, text, text_fill, &text_fill, 0); if(ret <= 0) { fprintf(stderr, "aaip_decode_acl(,0) failed: ret= %d\n", ret); ret= 0; goto ex; } printf("--- ret= %d , text=\n%s--- end of text\n\n", ret, text); if(out_path == NULL) {ret= 1; goto ex;} ret= do_touch(out_path, 0); if(ret <= 0) goto ex; ret= aaip_set_acl_text(out_path, text, 0); if(ret <= 0) { fprintf(stderr, "aaip_set_acl_text() failed"); if(ret == -1) fprintf(stderr, ": %d %s\n", errno, errno != 0 ? strerror(errno) : ""); else fprintf(stderr, "\n"); ret= 0; goto ex; } ret= 1; ex: if(text != NULL) free(text); return(ret); } static int test_acl(char *in_path, char *out_path, int flag) { int ret; char *acl_text= NULL; unsigned char *result= NULL; size_t result_len; ret= aaip_get_acl_text(in_path, &acl_text, 0); if(ret <= 0) { fprintf(stderr, "aaip_get_acl_text() failed"); if(ret == -1) fprintf(stderr, ": %d %s\n", errno, errno != 0 ? strerror(errno) : ""); else fprintf(stderr, "\n"); ret= 6; goto ex; } printf("--- ACL:\n%s--- end of ACL\n\n", acl_text); ret= aaip_encode_acl(acl_text, &result_len, &result, 0); if(ret <= 0) { fprintf(stderr, "aaip_encode_acl(text) failed: ret= %d\n", ret); ret= 7; goto ex; } print_result(result, result_len, 0); ret= decode_acl(result, result_len, out_path, 0); if(ret <= 0) {ret= 8; goto ex;} free(result); result= NULL; ret= aaip_encode_acl(acl_text, &result_len, &result, 2); if(ret <= 0) { fprintf(stderr, "aaip_encode_acl(num) failed: ret= %d\n", ret); ret= 9; goto ex; } print_result(result, result_len, 0); ret= decode_acl(result, result_len, out_path, 0); if(ret <= 0) {ret= 10; goto ex;} ret= 0; ex:; aaip_get_acl_text("", &acl_text, 1 << 15); if(result != NULL) free(result); return(ret); } int synthetic_pairs(char *prog, int argc, char **argv, int flag) { int ret, l, mult= 0, k; size_t result_len, i; unsigned char *result= NULL; char **names= NULL, **values= NULL, *cpt, **param; size_t *value_lengths= NULL; struct aaip_state *aaip; size_t consumed= 0; char name[Aaip_test_name_sizE + 1]; size_t name_fill; char value[Aaip_test_value_sizE + 1]; size_t value_fill; size_t todo; int submit_data, is_done; unsigned char *rpt; unsigned int skipped, was_skipped= 0; aaip= (struct aaip_state *) calloc(aaip_sizeof_aaip_state(), 1); names= calloc(sizeof(char *), argc / 2); values= calloc(sizeof(char *), argc / 2); value_lengths= calloc(sizeof(size_t), argc / 2); for(i= 0; i < argc; i++) { if(i % 2) param= values + i / 2; else param= names + i / 2; (*param)= argv[i]; if(argv[i][0] == '-') { cpt= strchr(argv[i], 'x'); if(cpt != NULL) { l= cpt - argv[i] - 1; if(l > 0) sscanf(cpt + 1, "%d", &mult); if(l > 0 && mult > 0) { (*param)= calloc(1, l * mult + 1); if((*param) != NULL) { for(k= 0; k < mult; k++) memcpy((*param) + k * l, argv[i] + 1, l); (*param)[mult * l]= 0; } else (*param)= argv[i]; } } } if(i % 2) value_lengths[i / 2]= strlen(values[i / 2]); } ret= aaip_encode("AA", (unsigned int) (argc / 2), names, value_lengths, values, &result_len, &result, 0); if(ret <= 0) { fprintf(stderr, "%s : aaip_encode failed with ret= %d\n", prog, ret); return(2); } print_result(result, result_len, 0); aaip_init_aaip_state(aaip, "AA", 0); rpt= result; submit_data= 1; is_done= 0; while(!is_done) { if(submit_data) { todo= result_len - (rpt - result); if(todo > 2048) todo= 2048; if(todo == 0) { fprintf(stderr, "%s : Out of data while still prompted to submit\n", prog); return(5); } } else todo= 0; ret= aaip_decode_pair(aaip, rpt, todo, &consumed, name, Aaip_test_name_sizE, &name_fill, value, Aaip_test_value_sizE, &value_fill, 0); skipped= aaip_get_pairs_skipped(aaip, 0); if(skipped > was_skipped) { printf("- skipped %d pair%s -\n\n", skipped - was_skipped, skipped - was_skipped > 1 ? "s" : ""); was_skipped= skipped; } if(ret < 0) { fprintf(stderr, "%s : aaip_decode_pair failed with ret= %d\n", prog, ret); return(3); } rpt+= todo; if(ret == 0) { rpt-= todo; submit_data= 0; continue; } else if(ret == 1) { submit_data= 1; continue; } else if(ret == 2) { submit_data= 1; } else if(ret == 3) { submit_data= 0; } else if(ret == 4) { is_done= 1; } else if(ret == 5) { is_done= 1; break; } else { fprintf(stderr, "%s : Unknown return %d from aaip_decode_pair()\n", prog, ret); return(4); } name[name_fill]= 0; value[value_fill]= 0; if((name_fill < 1000 && value_fill < 1000)) { printf("name = '%s' (%lu)\n", name, (unsigned long) name_fill); printf("value= '%s' (%lu)\n", value, (unsigned long) value_fill); } else { printf("name = (%lu)\n", (unsigned long) name_fill); printf("value= (%lu)\n", (unsigned long) value_fill); } printf("\n"); } return(0); } /* @param flag bit0= use numeric qualifiers */ static int copy_all(char *in_path, char *out_path, int flag) { int ret; struct aaip_state *aaip= NULL; size_t in_num_attrs, *in_value_lengths= NULL; char **in_names= NULL, **in_values= NULL; int is_done= 0, first_round= 1; unsigned char *result= NULL, *rpt; size_t result_len, todo, consumed; size_t out_num_attrs, *out_value_lengths= NULL; char **out_names= NULL, **out_values= NULL; ret= aaip_get_attr_list(in_path, &in_num_attrs, &in_names, &in_value_lengths, &in_values, 1 | ((flag & 1) << 1)); if(ret <= 0) {ret= 11; goto ex;} print_attrs(in_num_attrs, in_names, in_value_lengths, in_values, 0); ret= aaip_encode("AA", (unsigned int) in_num_attrs, in_names, in_value_lengths, in_values, &result_len, &result, 0); if(ret == 0) {ret= 12; goto ex;} if(result_len <= 0) { fprintf(stderr, "No result\n"); ret= 13; goto ex; } print_result(result, result_len, 0); rpt= result; while(!is_done) { todo= result_len - (rpt - result); if(todo > 2048) todo= 2048; if(todo == 0) { fprintf(stderr, "Out of data while still prompted to submit\n"); ret= 14; goto ex; } /* Allow 1 million bytes of memory consumption, 100,000 attributes */ ret= aaip_decode_attrs(&aaip, "AA", (size_t) 1000000, (size_t) 100000, rpt, todo, &consumed, first_round); rpt+= consumed; first_round= 0; if(ret == 1) continue; if(ret == 2) break; fprintf(stderr, "aaip_decode_attrs() returns %d\n", ret); ret= 15; goto ex; } if(rpt - result != result_len) { fprintf(stderr, "aaip_decode_attrs() returns 2 but %d bytes are left\n", (int) (result_len - (rpt - result))); ret= 16; goto ex; } ret= aaip_get_decoded_attrs(&aaip, &out_num_attrs, &out_names, &out_value_lengths, &out_values, 0); if(ret != 1) { fprintf(stderr, "aaip_get_decoded_attrs() returns %d\n", ret); ret= 17; goto ex; } print_attrs(out_num_attrs, out_names, out_value_lengths, out_values, 0); ret= do_touch(out_path, 0); if(ret <= 0) {ret= 19; goto ex;} ret= aaip_set_attr_list(out_path, out_num_attrs, out_names, out_value_lengths, out_values, 1 | 2); if(ret != 1) { fprintf(stderr, "aaip_set_attr_list() returns %d\n", ret); ret= 18; goto ex; } ret= 0; ex:; if(in_names != NULL || in_value_lengths != NULL || in_values != NULL) aaip_get_attr_list(in_path, &in_num_attrs, &in_names, &in_value_lengths, &in_values, 1 << 15); if(out_names != NULL || out_value_lengths != NULL || out_values != NULL) aaip_get_decoded_attrs(&aaip, &out_num_attrs, &out_names, &out_value_lengths, &out_values, 15); aaip_decode_attrs(&aaip, "AA", (size_t) 0, (size_t) 0, NULL, (size_t) 0, &consumed, 1 << 15); return(ret); } int main(int argc, char **argv) { int ret; if(argc < 2) { usage: fprintf(stderr, "usage : %s options\n", argv[0]); fprintf(stderr, " -pairs [-]name[xNNN] [-]value[xNNN] [...]\n"); fprintf(stderr, " -copy_acl source_path target_path\n"); fprintf(stderr, " -copy source_path target_path\n"); exit(1); } if(strcmp(argv[1], "-pairs") == 0) { if(argc < 4 || (argc % 2) != 0) goto usage; ret= synthetic_pairs(argv[0], argc - 2, argv + 2, 0); } else if(strcmp(argv[1], "-copy_acl") == 0) { if(argc != 4) goto usage; ret= test_acl(argv[2], argv[3], 0); } else if(strcmp(argv[1], "-copy") == 0) { if(argc != 4) goto usage; ret= copy_all(argv[2], argv[3], 1); } else goto usage; exit(ret); }