/* * * expunge -- program to expunge a meeting; i.e. really delete those * deleted transaction. This program is linked to a server * so it can use the privileged procedure of create_mtg, and * the like. * */ #include #include #include #include #include #include #include #include #include #include #include #include "mtg.h" #define NULL 0 #define MAX_TRNS 1000 #define min(a, b) (a < b ? a : b) static int tempf; static char *mtg_name = NULL, *location = NULL, *chairman = NULL, *trn_file = NULL; static char *backup_location = NULL; static char *future_location = NULL; static int found_eof = 0; static int error_occurred = 0; tfile unix_tfile (); char *malloc(); extern char rpc_caller[]; extern int has_privs; extern int errno; extern int no_nuke; main (argc, argv) int argc; char **argv; { int i,n,low,high; mtg_info old_mtg_info,new_mtg_info; trn_info old_trn_info; int result; dsc_acl *acl_list,*new_acl_list; dsc_acl_entry *ae; char *new_modes; tfile tf; char control_name[256]; int control_fd; #if defined(__APPLE__) && defined(__MACH__) add_error_table(&et_dsc_error_table); #else initialize_dsc_error_table(); #endif for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (argv[i][1]) { case 'c': if (++i < argc) chairman = argv[i]; continue; case 'n': if (++i < argc) mtg_name = argv[i]; continue; default: goto lusage; } if (location == NULL) location = argv[i]; else goto lusage; } if (location == NULL) goto lusage; /* required */ has_privs = TRUE; /* Tell discuss we're special */ strcpy (rpc_caller, "expunger"); /* First, we get the mtg info to make sure it exists */ get_mtg_info (location, &old_mtg_info, &result); if (result != 0) { fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result)); exit (1); } get_acl (location, &result, &acl_list); if (result != 0) { fprintf(stderr, "%s: %s while getting acl\n", location, error_message(result)); exit (1); } /* Create the new meeting */ backup_location = malloc (strlen(location)+5); /* be generous */ strcpy (backup_location, location); strcat (backup_location, "~"); future_location = malloc (strlen(location)+5); /* be generous */ strcpy (future_location, location); strcat (future_location, "#"); printf("Creating new meeting\n"); fflush(stdout); if (mtg_name == NULL) { mtg_name = old_mtg_info.long_name; } if (chairman == NULL) { chairman = old_mtg_info.chairman; } /* get acl's on old meeting, so we can make it new one */ get_acl (location, &result, &new_acl_list); if (result != 0) { fprintf(stderr, "%s: %s while getting acl\n", backup_location, error_message(result)); exit (1); } create_mtg_priv (backup_location, mtg_name, old_mtg_info.public_flag, old_mtg_info.date_created, chairman, new_acl_list, &result); if (result != 0) { fprintf (stderr, "%s: %s while creating new meeting\n", location, error_message(result)); exit (1); } /* now, do the actual expunging */ low = old_mtg_info.lowest; high = old_mtg_info.highest; create_temp (); expunge_range: for (i = low; i <= high; i++) { get_trn_info (location, i, &old_trn_info, &result); if (result != 0 && result != DELETED_TRN && result != EXPUNGED_TRN) { fprintf(stderr, "Error getting info for transaction [%04d]: %s\n", i, error_message(result)); error_occurred = TRUE; } else if (result != 0) { /* expunge it */ no_nuke = TRUE; printf("Expunging transaction [%04d]\n", i); expunge_trn (backup_location, i, &result); no_nuke = FALSE; if (result != 0) { fprintf(stderr, "Error expunging transaction [%04d]: %s\n", i, error_message(result)); error_occurred = TRUE; } } else if (result == 0) { ftruncate(tempf,0); lseek(tempf,0,SEEK_SET); tf = unix_tfile (tempf); get_trn (location, i, tf, &result); if (result != 0) { fprintf(stderr, "Error getting transaction [%04d]: %s\n", i, error_message(result)); error_occurred = TRUE; free(old_trn_info. author); free(old_trn_info.subject); continue; } tdestroy (tf); lseek(tempf,0,SEEK_SET); tf = unix_tfile (tempf); no_nuke = TRUE; add_trn_priv (backup_location, tf, old_trn_info.subject, old_trn_info.pref, old_trn_info.current, old_trn_info.author, old_trn_info.date_entered, &n, &result); no_nuke = FALSE; if (result != 0) { fprintf(stderr, "Error getting info for transaction %d: %s\n", i, error_message(result)); error_occurred = TRUE; } free(old_trn_info.author); free(old_trn_info.subject); } } /* Check if any new transactions have been added */ free(old_mtg_info.long_name); free(old_mtg_info.chairman); free(old_mtg_info.location); get_mtg_info(location, &old_mtg_info, &result); if (result != 0) { fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result)); error_occurred = TRUE; } else if (old_mtg_info.highest > high) { /* New transactions added */ low = high+1; high = old_mtg_info.highest; goto expunge_range; } strcpy(control_name, location); strcat(control_name, "/control"); if ((control_fd = open (control_name, O_RDWR, 0700)) < 0) { error_occurred = TRUE; } else { flock(control_fd, LOCK_EX); /* Hold meeting by the balls */ free(old_mtg_info.long_name); free(old_mtg_info.chairman); free(old_mtg_info.location); no_nuke = TRUE; get_mtg_info(location, &old_mtg_info, &result); if (result != 0) { fprintf(stderr, "%s: %s while getting mtg info\n", location, error_message(result)); error_occurred = TRUE; flock(control_fd,LOCK_UN); close(control_fd); } else if (old_mtg_info.highest > high) { /* New transactions added */ low = high + 1; high = old_mtg_info.highest; flock(control_fd,LOCK_UN); close(control_fd); goto expunge_range; } } /* When we get here, we have the old meeting locked. Now we do the move as atomically as we can */ if (!error_occurred) { if (rename(location, future_location) < 0) { perror("rename of old meeting failed"); exit (1); } if (rename(backup_location, location) < 0) { perror("rename of new meeting"); exit (1); } remove_mtg (future_location, &result); if (result != 0) { fprintf(stderr, "%s: %s while removing new meeting.\n", location, error_message(result)); exit (1); } } else exit (1); /* error occurred */ exit (0); lusage: fprintf(stderr, "usage: expunge mtg_location {-c chairman} {-n name}\n"); exit (1); } /* * * create_temp () -- Create temp file, and let it be tempf. * */ create_temp() { char filename [20]; strcpy (filename, "/tmp/rcXXXXXX"); mktemp (filename); tempf = open (filename, O_RDWR | O_CREAT, 0700); if (tempf < 0) { fprintf (stderr, "Cannot open temp file\n"); exit (1); } }