/***************************************************************************/ /***************************************************************************/ /* */ /* (c) 1995-1999. The Regents of the University of California. All */ /* rights reserved. */ /* */ /* This work was produced at the University of California, Lawrence */ /* Livermore National Laboratory (UC LLNL) under contract no. */ /* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */ /* (DOE) and The Regents of the University of California (University) */ /* for the operation of UC LLNL. Copyright is reserved to the */ /* University for purposes of controlled dissemination, */ /* commercialization through formal licensing, or other disposition */ /* under terms of Contract 48; DOE policies, regulations and orders; */ /* and U.S. statutes. The rights of the Federal Government are */ /* reserved under Contract 48 subject to the restrictions agreed upon */ /* by the DOE and University. */ /* */ /* */ /* DISCLAIMER */ /* */ /* This software was prepared as an account of work sponsored by an */ /* agency of the United States Government. Neither the United States */ /* Government nor the University of California nor any of their */ /* employees, makes any warranty, express or implied, or assumes any */ /* liability or responsibility for the accuracy, completeness, or */ /* usefulness of any information, apparatus, product, or process */ /* disclosed, or represents that its specific commercial products, */ /* process, or service by trade name, trademark, manufacturer, or */ /* otherwise, does not necessarily constitute or imply its */ /* endorsement, recommendation, or favoring by the United States */ /* Government or the University of California. The views and opinions */ /* of the authors expressed herein do not necessarily state or reflect */ /* those of the United States Government or the University of */ /* California, and shall not be used for advertising or product */ /* endorsement purposes. */ /* */ /* Permission to use, copy, modify and distribute this software and its */ /* documentation for any non-commercial purpose, without fee, is */ /* hereby granted, provided that the above copyright notice and this */ /* permission notice appear in all copies of the software and */ /* supporting documentation, and that all UC LLNL identification in */ /* the user interface remain unchanged. The title to copyright LLNL */ /* XDIR shall at all times remain with The Regents of the University */ /* of California and users agree to preserve same. Users seeking the */ /* right to make derivative works with LLNL XDIR for commercial */ /* purposes may obtain a license from the Lawrence Livermore National */ /* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */ /* Livermore, CA 94550. */ /* */ /***************************************************************************/ /***************************************************************************/ #include #include #include #include "xdir.h" #include "list.h" #include "str.h" static struct { int recursive; /* Requires initialization */ int level; /* Requires initialization */ struct dirwin_st *dirwin; /* Requires initialization */ struct entry_link *head[MAXLEVELS]; /* Requires initialization */ int error; /* Requires initialization */ int asked_user; /* Requires initialization */ char *rel_path; char *full_path; } dc; static char *del_question = "You are attempting to delete a (possibly nonempty)\ndirectory, but the general preference DELETE MODE\nis set to NONRECURSIVE.\n\nDelete nonempty directories anyway?"; static char *msg1 = "Unable to redisplay directory.\n\nDirectory window might be out of date."; extern struct st_host_info hinfo[]; extern int beep_when_ops_done; extern Widget w_toplev; extern int diagnostics; extern int inquire_on_delete; extern XtAppContext app; extern int rdelete_mode; char *merge_paths(); char *links_to_path(); int cb_delete_entries(); char **path_to_links(); /* * cb_delete - Callback that deletes selected file(s). */ void cb_delete(widget, client_data, call_data) Widget widget; XtPointer client_data; XtPointer call_data; { struct dirwin_st *dirwin = (struct dirwin_st *)client_data; struct entry_link *head; struct entry_link *tail; int i; int retval; /* Start operation */ if (!start_op(True)) return; /* Clear error flag */ raise_okflag(); /* Ask the user if okay to delete? */ if (inquire_on_delete) { if (!verify_selection(dirwin, dirwin, "Do you really want to delete these entries?")) { end_op(); return; } } /* Make operation interruptable */ show_stop_button(dirwin); /* This might take some time */ use_busy_cursor(); /* Make sure connection is still good */ if (dirwin->host != LOCAL) { retval = check_connection(dirwin->host, dirwin); if (retval < 0) { restore_prev_cursor(); switch (retval) { case -6: record_abort("Delete Entries"); break; case -1: record_and_alert("Unable to delete entries.", dirwin->w_shell); } hide_stop_button(); end_op(); return; } } /* Form list of selected items to delete */ head = NULL; tail = NULL; for (i=0; inentries; i++) if (dirwin->entries[i].level == 0) postorder_selected_items(&dirwin->entries[i], &head, &tail); /* Set up deletion control block */ dc.recursive = rdelete_mode; dc.level = 0; dc.dirwin = dirwin; dc.head[0] = head; dc.error = False; dc.asked_user = False; /* Perform deletion */ show_mp_monitor(dirwin, "Now Deleting:"); XtAppAddWorkProc(app, (XtWorkProc)cb_delete_entries, NULL); } /* * cb_delete_entries - Work procedure for executing deletion request. * State information is kept in "dc", the * deletion control block data structure. */ cb_delete_entries() { static char *del_error_msg = "Unable to delete entry(s). Can't get directory list."; struct entry_link *ptr; struct sl_struct *list; int retval; int len; int i; int is_a_directory; char msg[MAXPATHLEN+40]; int already_handled_dir = False; char **rel_path_links; int nlinks; char **link_ptr; int indx; char **first_path_links; char **p; char *dir; dc.full_path = NULL; dc.rel_path = NULL; /* Did user push stop button? */ if (stop()) goto abort; /* Is there more to do? */ if (dc.head[dc.level] == NULL) { if (dc.level == 0) { if (dc.error) record_and_alert("At least one deletion failed.", dc.dirwin->w_shell); goto done; } else { dc.level--; already_handled_dir = True; } } /* Build relative path name */ first_path_links = path_to_links(hinfo[dc.dirwin->host].system, dc.head[0]->entry); nlinks = 0; link_ptr = first_path_links; while (*link_ptr++) nlinks++; nlinks += dc.level; rel_path_links = (char **)XtMalloc(sizeof(char *)*(nlinks+1)); indx = 0; p = first_path_links; while (*p) { rel_path_links[indx++] = XtNewString(*p); p++; } release_path_links(first_path_links); for (i=1; i<=dc.level; i++) rel_path_links[indx++] = XtNewString(dc.head[i]->entry); rel_path_links[nlinks] = NULL; dc.rel_path = links_to_path(hinfo[dc.dirwin->host].system, rel_path_links, nlinks); release_path_links(rel_path_links); /* Build full path name */ dc.full_path = merge_paths(hinfo[dc.dirwin->host].system, dc.dirwin->dirname, dc.rel_path); /* Handle recursion */ if (!already_handled_dir) { if (dc.recursive || !dc.asked_user) { /* Test for directory by trying to cd to it */ is_a_directory = False; if (dc.dirwin->host == LOCAL) { if (local_cd(dc.full_path, False) == 0) is_a_directory = True; } else switch (remote_cd(dc.dirwin->host, dc.full_path, False)) { case -6: goto abort; case -3: goto lost; case 0: is_a_directory = True; } if (is_a_directory) { if (!dc.recursive) { beep(); if (question_dialog(del_question, dc.dirwin->w_shell)) dc.recursive = True; dc.asked_user = True; } if (dc.recursive) { /* Get directory list */ switch (get_dirlist(dc.dirwin->host, dc.full_path, TABULAR, True, False, False, &list)) { case -6: goto abort; case -3: goto lost; case -1: record_and_alert(del_error_msg, dc.dirwin->w_shell); goto done; } /* Add directory list to new level */ dc.level++; if (dc.level == MAXLEVELS) { record_and_alert( "Deletion(s) aborted. Recursion too deep.", dc.dirwin->w_shell); goto done; } dc.head[dc.level] = NULL; for (i=list->nentries-1; i>=0; i--) { ptr = XtNew(struct entry_link); ptr->entry = XtNewString(list->entries[i]); ptr->next = dc.head[dc.level]; dc.head[dc.level] = ptr; } release_array_list(list); XtFree(dc.full_path); XtFree(dc.rel_path); return False; } } } } /* Delete next directory entry */ update_mp_monitor(dc.rel_path); if (dc.dirwin->host == LOCAL) retval = local_delete(dc.full_path); else { flush_cache_directory(dc.dirwin->host, dc.full_path); parse_path(hinfo[dc.dirwin->host].system, dc.full_path, &dir, NULL); flush_cache_directory(dc.dirwin->host, dir); XtFree(dir); len = strlen(dc.full_path); if ((hinfo[dc.dirwin->host].system == SYS_VMS) && (dc.full_path[len-1] == ']')) retval = remote_rmdir(dc.dirwin->host, dc.full_path); else if (hinfo[dc.dirwin->host].server == SERVER_MAC_FTPD || hinfo[dc.dirwin->host].server == SERVER_WINDOWS_WFTPD || hinfo[dc.dirwin->host].server == SERVER_NT) switch (remote_cd(dc.dirwin->host, dc.full_path, False)) { case -6: goto abort; case -3: goto lost; case 0: retval = remote_rmdir(dc.dirwin->host, dc.full_path); break; default: retval = remote_delete(dc.dirwin->host, dc.full_path); } else retval = remote_delete(dc.dirwin->host, dc.full_path); } switch (retval) { case -6: goto abort; case -3: goto lost; case -1: sprintf(msg, "Unable to delete %s.", dc.rel_path); record_warning(msg); dc.error = True; break; case 0: if (diagnostics >= NORMAL) { sprintf(msg, "*** Successfully deleted: %s\n", dc.rel_path); write_log(msg); } } XtFree(dc.full_path); XtFree(dc.rel_path); ptr = dc.head[dc.level]; dc.head[dc.level] = ptr->next; XtFree(ptr->entry); XtFree((char *)ptr); return False; abort: hide_mp_monitor(); record_abort("Delete Entries"); write_log("*** Deletion(s) aborted."); dirwin_out_of_date_alert(dc.dirwin); goto final; done: hide_mp_monitor(); retval = display_dir(dc.dirwin->host, dc.dirwin, dc.dirwin->dirname, True, False, dc.dirwin->cache_mode, False); switch (retval) { case -6: record_abort("Delete Entries"); write_log("*** Deletion(s) aborted."); dirwin_out_of_date_alert(dc.dirwin); break; case -3: restore_lost_connection(dc.dirwin->host, dc.dirwin); break; case -1: record_and_alert(msg1, dc.dirwin->w_shell); } goto final; lost: hide_mp_monitor(); restore_lost_connection(dc.dirwin->host, dc.dirwin); final: /* Clean up the deletion control block data structure */ XtFree(dc.rel_path); dc.rel_path = NULL; XtFree(dc.full_path); dc.full_path = NULL; for(i=0; i<=dc.level; i++) release_linked_list(&dc.head[i]); /* Miscellaneous cleanup */ clear_selected_entries(); update_dir_controls(); if (beep_when_ops_done) beep(); restore_prev_cursor(); /* Signal end of operation */ hide_stop_button(); end_op(); return True; }