/* process the add file for the worktodo file <filename> */ int process_add_file(char *filename) { char add_filename[256]; char *dot; FILE *f_work, *f_add; char line[101]; if (add_file_disabled) return 1; // there was an error with this add file earlier strncpy (add_filename, filename, 245); // leave room if ".add.txt" will be appended add_filename[245]='\0'; dot = strrchr (add_filename, '.'); if (dot == NULL) { dot = add_filename + strlen(add_filename); // no dot? just append the extension } strcpy (dot, ".add"); if (!file_exists (add_filename)) { strcpy (dot, ".add.txt"); if (!file_exists (add_filename)) return 0; // no problem if there is no .add file } // here, add_filename contains an existing add file's name f_work = fopen_and_lock(filename, "a+"); if (f_work == NULL) return 1; f_add = fopen_and_lock(add_filename, "r"); if (f_add == NULL) { unlock_and_fclose(f_work); return 1; } printf("\nAdding \"%s\" to \"%s\".\n", add_filename, filename); while(fgets(line, 101, f_add) != NULL) { if (fputs(line, f_work) == EOF) { fprintf(stderr, "Error %d appending \"%s\" to \"%s\"\n", errno, add_filename, filename); add_file_disabled = 1; // Do not try again in order to avoid duplicating entries return 1; } } unlock_and_fclose(f_add); unlock_and_fclose(f_work); if (remove(add_filename)!= 0) { perror("Failed to delete add_file"); add_file_disabled = 1; // Do not try again in order to avoid duplicating entries } return add_file_disabled; }
int mms_mmbox_count(char *mmbox_root, char *user, unsigned long *msgcount, unsigned long *byte_count) { int tmpfd = -1; FILE *fp = NULL; char linbuf[1024]; int ret = -1; Octstr *home = user_mmbox_dir(mmbox_root,user); int ifd = -1; ifd = open_mmbox_index(octstr_get_cstr(home),1); if (ifd < 0) goto done; if ((tmpfd = dup(ifd)) < 0 || (fp = fdopen(tmpfd, "r")) == NULL) { error(0, "mmbox.count: %s Failed to dup descriptor for index " "file, fp = %p: error = %s\n", octstr_get_cstr(home), fp, strerror(errno)); goto done; } *msgcount = 0; *byte_count = 0; while (fgets(linbuf, sizeof linbuf, fp) != NULL) { int size = 0; sscanf(linbuf, "%*s %*s %d", &size); ++*msgcount; *byte_count = *byte_count + size; } ret = 0; done: if (fp) unlock_and_fclose(fp); else if (tmpfd) unlock_and_close(tmpfd); if (ifd > 0) unlock_and_close(ifd); return ret; }
List *mms_mmbox_search(char *mmbox_root, char *user, List *state, List *flag_cmds, int start, int limit, List *msgrefs) { int tmpfd = -1; FILE *fp = NULL; char linbuf[1024]; Octstr *home = user_mmbox_dir(mmbox_root,user); List *flags = NULL; List *dflist = NULL; int ifd = -1; int ct; ifd = open_mmbox_index(octstr_get_cstr(home),1); if (ifd < 0) goto done; if ((tmpfd = dup(ifd)) < 0 || (fp = fdopen(tmpfd, "r")) == NULL) { error(0, "mmbox.search_index: %s Failed to dup descriptor for index " "file, fp = %p: error = %s\n", octstr_get_cstr(home), fp, strerror(errno)); goto done; } flags = make_mm_flags(NULL, flag_cmds); ct = 1; dflist = gwlist_create(); while (fgets(linbuf, sizeof linbuf, fp) != NULL) { char idx[128], xstate[32]; List *xflags = NULL; int i, size; int match = (!state && (!msgrefs || gwlist_len(msgrefs) == 0) && (!xflags || gwlist_len(xflags) == 0)); sscanf(linbuf, "%s %s %d%n", idx, xstate, &size, &i); /* search: by id list if given, by states if given, by flags if given */ if (!match && state && gwlist_search(state, xstate, (gwlist_item_matches_t *)_x_octstr_str_compare) != NULL) match = 1; /* For the rest we only match if nothing else matched. Save time */ replace_slash(idx); if (!match && msgrefs && gwlist_search(msgrefs, idx, (gwlist_item_matches_t *)_x_octstr_str_compare) != NULL) match = 1; if (!match && flag_cmds && ((xflags = parse_string_list(linbuf + i)) != NULL && gwlist_search(xflags, flags, (gwlist_item_matches_t *)string_in_list) != NULL)) match = 1; if (match && ct >= start && gwlist_len(dflist) <= limit) { Octstr *x = octstr_create(idx); /* octstr_replace(x, octstr_imm("/"), octstr_imm("-")); */ gwlist_append(dflist, x); } ct++; if (xflags) gwlist_destroy(xflags, (gwlist_item_destructor_t *)octstr_destroy); } done: if (fp) unlock_and_fclose(fp); else if (tmpfd) unlock_and_close(tmpfd); if (ifd > 0) unlock_and_close(ifd); if (flags) gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy); if (home) octstr_destroy(home); return dflist; }
/* Format of Index file: * each message is described by a single line: * df state flag1 flag2 flag3 ... */ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd, Octstr *df, Octstr *state, List *flags, long msgsize) { char fbuf[256], linbuf[1024]; int tempfd; FILE *fp; /* Make a temp file. */ sprintf(fbuf, "%.128s/t%s.%ld.%ld", mmbox_dir, IDXFILE, time(NULL), random() % 1000); tempfd = open(fbuf, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); if (tempfd < 0 ) { error(0, "mmbox.update_index: Failed to open temp file %s: error = %s\n", fbuf, strerror(errno)); goto done; } else if (mm_lockfile(tempfd, fbuf, 0) != 0) { /* Lock it. */ error(0, "mmbox.update_index: Failed lock temp file %s: error = %s\n", fbuf, strerror(errno)); unlock_and_close(tempfd); tempfd = -1; goto done; } fp = fdopen(fd, "r"); if (!fp) { error(0, "mmbox.update_index: Failed fdopen on tempfd, file %s: error = %s\n", fbuf, strerror(errno)); unlock_and_close(tempfd); tempfd = -1; goto done; } while (fgets(linbuf, sizeof linbuf, fp) != NULL) { char idx[128], xstate[32]; Octstr *outs = NULL; int i; int size; sscanf(linbuf, "%s %s %d%n", idx, xstate, &size, &i); if (df && octstr_str_compare(df, idx) == 0) if (cmd == ITEM_DEL || cmd == ITEM_ADD) goto loop; /* Skip it. */ else { /* MOD. */ Octstr *p = linearise_string_list(flags, " "); outs = octstr_format("%S %S %d %S\n", df, state, msgsize, p); octstr_destroy(p); } else { /* Copy out as-is */ char *p = skip_space(linbuf + i); outs = octstr_format("%s %s %d %s%s", idx, xstate, size, p, (strchr(p, '\n') != NULL ? "" : "\n")); } loop: if (outs) { if (octstr_len(outs) > 0) octstr_write_to_socket(tempfd, outs); octstr_destroy(outs); } } if (cmd == ITEM_ADD) { /* Finally, for ADD, just add it. */ Octstr *s, *p = linearise_string_list(flags, " "); s = octstr_format("%S %S %d %S\n", df, state, msgsize, p); octstr_destroy(p); octstr_write_to_socket(tempfd, s); octstr_destroy(s); } fsync(tempfd); sprintf(linbuf, "%.128s/%s", mmbox_dir, IDXFILE); rename(fbuf, linbuf); unlock_and_fclose(fp); done: return tempfd; }
/************************************************************************************************************ * Function name : clear_assignment * * * * INPUT : char *filename * * unsigned int exponent * * int bit_min - from old assignment file * * int bit_max * * int bit_min_new - new bit_min,what was factored to--if 0,reached bit_max * * OUTPUT : * * * * 0 - OK * * 3 - clear_assignment : cannot open file <filename> * * 4 - clear_assignment : cannot open file "__worktodo__.tmp" * * 5 - clear_assignment : assignment not found * * 6 - clear_assignment : cannot rename temporary workfile to regular workfile * * * * If bit_min_new is zero then the specified assignment will be cleared. If bit_min_new is greater than * * zero the specified assignment will be modified * ************************************************************************************************************/ enum ASSIGNMENT_ERRORS clear_assignment(char *filename, unsigned int exponent, int bit_min, int bit_max, int bit_min_new) { int found = FALSE; FILE *f_in, *f_out; LINE_BUFFER line; // line buffer char *tail = NULL; // points to tail material in line, if non-null enum PARSE_WARNINGS value; unsigned int line_to_drop = UINT_MAX; unsigned int current_line; struct ASSIGNMENT assignment; // the found assignment.... f_in = fopen_and_lock(filename, "r"); if (NULL == f_in) return CANT_OPEN_WORKFILE; f_out = fopen_and_lock("__worktodo__.tmp", "w"); if (NULL == f_out) { unlock_and_fclose(f_in); return CANT_OPEN_TEMPFILE; } if ((bit_min_new > bit_min) && (bit_min_new < bit_max)) // modify only line_to_drop = UINT_MAX; else { current_line =0; while (END_OF_FILE != (value = parse_worktodo_line(f_in,&assignment,&line,&tail)) ) { current_line++; if (NO_WARNING == value) { if( (exponent == assignment.exponent) && (bit_min == assignment.bit_min) && (bit_max == assignment.bit_max)) // make final decision { if (line_to_drop > current_line) line_to_drop = current_line; break; } else { line_to_drop = current_line+1; // found different assignment, can drop no earlier than next line } } else if ((BLANK_LINE == value) && (UINT_MAX == line_to_drop)) line_to_drop = current_line+1; } } errno = 0; if (fseek(f_in,0L,SEEK_SET)) { unlock_and_fclose(f_in); f_in = fopen_and_lock(filename, "r"); if (NULL == f_in) { unlock_and_fclose(f_out); return CANT_OPEN_WORKFILE; } } found = FALSE; current_line = 0; while (END_OF_FILE != (value = parse_worktodo_line(f_in,&assignment,&line,&tail)) ) { current_line++; if ((NO_WARNING != value) || found) { if ((found) || (current_line < line_to_drop)) fprintf(f_out, "%s", line); } else // assignment on the line, so we may need to print it.. { found =( (exponent == assignment.exponent) && (bit_min == assignment.bit_min) && (bit_max == assignment.bit_max) ); if (!found) { fprintf(f_out,"%s",line); } else // we have the assignment... { if ((bit_min_new > bit_min) && (bit_min_new < bit_max)) { fprintf(f_out,"Factor=" ); if (strlen(assignment.assignment_key) != 0) fprintf(f_out,"%s,", assignment.assignment_key); fprintf(f_out,"%u,%u,%u",exponent, bit_min_new, bit_max); if (tail != NULL) fprintf(f_out,"%s",tail); } } } } // while..... unlock_and_fclose(f_out); unlock_and_fclose(f_in); if (!found) return ASSIGNMENT_NOT_FOUND; if(remove(filename) != 0) return CANT_RENAME; if(rename("__worktodo__.tmp", filename) != 0) return CANT_RENAME; return OK; }
/************************************************************************************************************ * Function name : get_next_assignment * * * * INPUT : char *filename * * unsigned int *exponent * * int *bit_min * * int *bit_max * * char *assignment_key[100]; * OUTPUT : * * * * 0 - OK * * 1 - get_next_assignment : cannot open file * * 2 - get_next_assignment : no valid assignment found * ************************************************************************************************************/ enum ASSIGNMENT_ERRORS get_next_assignment(char *filename, unsigned int *exponent, unsigned int *bit_min, unsigned int *bit_max, LINE_BUFFER *key, int verbosity) { FILE *f_in; enum PARSE_WARNINGS value; struct ASSIGNMENT assignment; char *tail; LINE_BUFFER line; unsigned int linecount=0; // first, make sure we have an up-to-date worktodo file process_add_file(filename); f_in = fopen_and_lock(filename, "r"); if(f_in == NULL) { printf("Can't open workfile %s\n", filename); return CANT_OPEN_FILE; // nothing to open... } for(;;) { linecount++; value = parse_worktodo_line(f_in,&assignment,&line,&tail); if ((BLANK_LINE == value) || (NONBLANK_LINE == value)) continue; if (NO_WARNING == value) { if (valid_assignment(assignment.exponent,assignment.bit_min, assignment.bit_max, verbosity)) break; value = INVALID_DATA; } if (END_OF_FILE == value) break; if(verbosity >= 1) { printf("WARNING: ignoring line %u in \"%s\"! Reason: ", linecount, filename); switch(value) { case LONG_LINE: printf("line is too long\n"); break; case NO_FACTOR_EQUAL: printf("doesn't begin with Factor=\n");break; case INVALID_FORMAT: printf("invalid format\n");break; case INVALID_DATA: printf("invalid data\n");break; default: printf("unknown error on >%s<",line); break; } } } unlock_and_fclose(f_in); if (NO_WARNING == value) { *exponent = assignment.exponent; *bit_min = assignment.bit_min; *bit_max = assignment.bit_max; if (key!=NULL)strcpy(*key,assignment.assignment_key); return OK; } else return VALID_ASSIGNMENT_NOT_FOUND; }