#include #include #include #include #include #include #include "cli_val.h" #include "cli_objects.h" extern char *cli_operation_name; static void remove_rf(boolean do_umount) { char *command = NULL; touch(); if (do_umount) { command = malloc(strlen(get_mdirp()) + 20); sprintf(command, "sudo umount %s", get_mdirp()); system(command); } command = realloc(command, strlen(m_path.path) + 10); sprintf(command, "rm -rf %s", m_path.path); system(command); if (do_umount) { command = realloc(command, strlen(get_mdirp()) + strlen(get_cdirp()) + strlen(get_mdirp()) + 100); sprintf(command, "sudo mount -t $UNIONFS -o dirs=%s=rw:%s=ro" " $UNIONFS %s", get_cdirp(), get_adirp(), get_mdirp()); system(command); } free(command); } static boolean has_default(char **def, int size) { char *buf_ptr; FILE *fp = fopen(t_path.path, "r"); if (fp) { char buf[1025]; while (fgets(buf, 1024, fp)) { if (strncmp(buf, "default:", 8) == 0) { buf_ptr = index(buf,':'); if (buf_ptr == NULL) { break; } //iterate up to non-whitespace character buf_ptr++; while (buf_ptr < (buf + size)) { if (*buf_ptr == ' ') { buf_ptr++; } else { break; } } if (size < strlen(buf_ptr)-1) { bye("default buffer size is too small\n"); } memcpy(*def, buf_ptr, strlen(buf_ptr)-1); fclose(fp); return 0; } } fclose(fp); } return 1; } static void reset_default(const char *def_val) { if (def_val == NULL) return; //strip off quotes char tmp_val[1025]; char *ptr = index(def_val,'"'); if (ptr != NULL) { strcpy(tmp_val,ptr+1); ptr = rindex(tmp_val,'"'); if (ptr != NULL) { *ptr = '\0'; } else { strcpy(tmp_val,def_val); //go with original value. } } else { strcpy(tmp_val,def_val); } char filename[strlen(m_path.path) + 10]; touch(); sprintf(filename, "%s/node.val", m_path.path); FILE *fp = fopen(filename, "w"); if (fp == NULL) bye("can not open: %s", filename); fputs(tmp_val, fp); fclose(fp); sprintf(filename, "%s/def", m_path.path); touch_file(filename); } /*************************************************** set_validate: validate value against definition return TRUE if OK, FALSE otherwise ****************************************************/ boolean set_validate(vtw_def *defp, char *valp) { boolean res; int status; struct stat statbuf; pop_path(&t_path); /* it was tag or real value */ push_path(&t_path, DEF_NAME); if (lstat(t_path.path, &statbuf) < 0 || (statbuf.st_mode & S_IFMT) != S_IFREG) { fprintf(out_stream, "The specified configuration node is not valid\n"); bye("Can not set value (2), no definition for %s", m_path.path); } /* defniition present */ memset(defp, 0, sizeof(vtw_def)); if ((status = parse_def(defp, t_path.path, FALSE))) { bye("parse error: %d\n", status); } res = validate_value(defp, valp); pop_path(&t_path); return res; } int main(int argc, char **argv) { int ai; struct stat statbuf; vtw_def def; boolean last_tag=0; int status; FILE *fp; boolean res; char *cp, *delp, *endp; boolean do_umount; /* this is needed before calling certain glib functions */ g_type_init(); cli_operation_name = "Delete"; if (initialize_output() == -1) { bye("can't initialize output\n"); } if (argc < 2) { fprintf(out_stream, "Need to specify the config node to delete\n"); bye("nothing to delete\n"); } dump_log( argc, argv); do_umount = FALSE; init_edit(); /* extend both paths per arguments given */ /* last argument is new value */ for (ai = 1; ai < argc; ++ai) { push_path(&t_path, argv[ai]); push_path(&m_path, argv[ai]); if (lstat(t_path.path, &statbuf) >= 0) { if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { bye("INTERNAL:regular file %s in templates", t_path.path); } last_tag = FALSE; continue; } /*else */ pop_path(&t_path); push_path(&t_path, TAG_NAME); if (lstat(t_path.path, &statbuf) >= 0) { if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { bye("INTERNAL:regular file %s in templates", t_path.path); } last_tag = TRUE; continue; } /* no match */ break; } /* cases: multiple tag-value - not achild mutilple tag-value - not the last child multiple tag-value - last child single value modified signle value unmodified multiple non-tag value - the last value multiple non-tag value - not the last value regular child */ if (ai == argc) { /* full path found */ /* all cases except multiple non-tag value */ /* check for single value */ if (last_tag) { /* case of multiple tag-value was this a real child? was it the last child? */ struct dirent *dirp; DIR *dp; if (lstat(m_path.path, &statbuf) < 0) { fprintf(out_stream, "Nothing to delete\n"); bye("Nothing to delete at %s", m_path.path); } remove_rf(FALSE); pop_path(&m_path); if ((dp = opendir(m_path.path)) == NULL){ INTERNAL; } while ((dirp = readdir(dp)) != NULL) { /*do we have real child */ if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..") && strcmp(dirp->d_name, MOD_NAME) && /* XXX */ strncmp(dirp->d_name, ".wh.", 4) ) break; } if (dirp == NULL) { /* no real children left */ /* kill parent also */ remove_rf(FALSE); } exit(0); } /*not tag */ push_path(&t_path, DEF_NAME); if (lstat(t_path.path, &statbuf) >= 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) { /* defniition present */ memset(&def, 0, sizeof(vtw_def)); if ((status = parse_def(&def, t_path.path, FALSE))) { bye("parse error: %d\n", status); } if (!def.tag && !def.multi && def.def_type!= ERROR_TYPE) { /* signgle value */ /* is it modified == it is in C, but not OPAQUE */ switch_path(CPATH); if(lstat(m_path.path, &statbuf) >= 0) { push_path(&m_path, OPQ_NAME); if(lstat(m_path.path, &statbuf) < 0) { /* yes remove from C only */ pop_path(&m_path); remove_rf(TRUE); exit(0); } pop_path(&m_path); /*OPQ_NAME */ } switch_path(MPATH); } } /* else no defnition, remove it also */ char *def_val; def_val = malloc(1025); if (has_default(&def_val,1024) == 0) { reset_default(def_val); free(def_val); } else { remove_rf(FALSE); } // remove_rf(FALSE); exit(0); } if(ai < argc -1 || last_tag) { fprintf(out_stream, "The specified configuration node is not valid\n"); bye("There is no appropriate template for %s", m_path.path + strlen(get_mdirp())); } /*ai == argc -1, must be actual value */ pop_path(&m_path); /*it was value, not path segment */ push_path(&m_path, VAL_NAME); /* set value */ if (lstat(m_path.path, &statbuf) < 0) { fprintf(out_stream, "Nothing to delete\n"); bye("Nothing to delete at %s", m_path.path); } if ((statbuf.st_mode & S_IFMT) != S_IFREG) bye("Not a regular file %s", m_path.path); /* get definition to deal with potential multi */ pop_path(&t_path); /* it was tag or real value */ push_path(&t_path, DEF_NAME); if (lstat(t_path.path, &statbuf) < 0 || (statbuf.st_mode & S_IFMT) != S_IFREG) { fprintf(out_stream, "The specified configuration node is not valid\n"); bye("Can not delete value, no definition for %s", m_path.path); } /* defniition present */ memset(&def, 0, sizeof(vtw_def)); if ((status = parse_def(&def, t_path.path, FALSE))) { bye("parse error: %d\n", status); } if (def.multi) { /* delete from multivalue */ valstruct new_value, old_value; status = char2val(&def, argv[argc - 1], &new_value); if (status) exit(0); cp = NULL; pop_path(&m_path); /* get_value will push VAL_NAME */ status = get_value(&cp, &m_path); if (status != VTWERR_OK) bye("Cannot read old value %s\n", m_path.path); status = char2val(&def, cp, &old_value); if (status != VTWERR_OK) bye("Corrupted old value ---- \n%s\n-----\n", cp); res = val_cmp(&new_value, &old_value, IN_COND); if (!res) { fprintf(out_stream, "%s is not a configured value, %s\n", new_value.val,old_value.val); bye("Not in multivalue"); } touch(); if (old_value.cnt) { push_path(&m_path, VAL_NAME); fp = fopen(m_path.path, "w"); if (fp == NULL) bye("Can not open value file %s", m_path.path); if (is_in_cond_tik()) { for(delp=cp;delp && is_in_cond_tik(); dec_in_cond_tik()) { delp = strchr(delp, '\n'); if (!delp) INTERNAL; ++delp; /* over \n */ } /* write "left" of deleted */ fwrite(cp, 1, delp-cp, fp); }else delp = cp; /* find end of value */ endp = strchr(delp, '\n'); if (endp && *++endp) { /* write "right" of deleted */ fwrite(endp, 1, strlen(endp), fp); /* need the final '\n' */ fwrite("\n", 1, 1, fp); } fclose(fp); return 0; } /* it multi with only 1 value, remove */ remove_rf(FALSE); return 0; } /* let's do a new check here: -> if this is a leaf and there is a value look for a match of the value -> make sure to check existing configuration as well as uncommitted config */ if (ai+1 == argc) { //does this work up until the last value pop_path(&m_path); if(lstat(m_path.path, &statbuf) == 0) { //now compare last value with that in the node.def file to determine whether to accept this delete status = get_value(&cp, &m_path); if (status != VTWERR_OK) { bye("Cannot read old value %s\n", m_path.path); } if (!strcmp(cp,argv[argc - 1])) { /* Also need to handle the case where the value is not specified. */ char *def_val; def_val = malloc(1025); if (has_default(&def_val,1024) == 0) { reset_default(def_val); free(def_val); } else { remove_rf(FALSE); } return 0; } } } fprintf(out_stream, "The specified configuration node is not valid\n"); bye("There is no appropriate template for %s", m_path.path + strlen(get_mdirp())); return 1; }