/* Program Name : FILERCPY.C */ /* Original Author : C. K. Hung */ /* Date : 22-MAY-1991 */ /* Program Description : */ /* : */ /* Revision History follows */ #include "global.h" #include "dx.h" #include "filer.h" #include "filercpy.h" #include "filerflt.h" #include "filerkpd.h" #include "filerque.h" #include "findfile.h" #include "inquire.h" #include #include #include #include #include /* **** INTERNAL FUNCTION PROTOTYPING *** */ static int filer_copy$2(char *, char *, char *); /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int filer_copy() { if (DX_CURRENT_DIRECTORY.filemode == multiple) filer_multiple_copy(); else filer_single_copy(); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int filer_multiple_copy() { char errmsg[MAXFILESPEC+1]; strcpy(errmsg, "Error copying file"); multi_get_userinput_and_exec( filer_copy$1, "Multiple Copy", "Copy to: ", "", errmsg); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int filer_single_copy() { char errmsg[MAXFILESPEC+1]; char fn[MAXFILESPEC+1]; if (!strcmp(DX_CURRENT_FILE->fn, "[-]")) { signal_err("Copy a parent directory file not allowed", bell); } else { find_full_path_name(DX_CURRENT_FILE->fn, fn, cntrl_info_block.cur_win); strcpy(errmsg, "Error copying file"); get_userinput_and_execute( filer_copy$1, "Copy File", "Copy to: ", "", errmsg, fn); } return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int filer_copy$1(to, from, errmsg) char *to; char *from; char *errmsg; { return filer_copy$2(from, to, errmsg); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ static int filer_copy$2(from, to, errmsg) char *from; char *to; char *errmsg; { struct filespec_list_tag *s; unsigned short int chan; unsigned short chan_o; /** I/O channel **/ /** File Characteristics Bits **/ unsigned long fch; /** Record Attributes Area **/ struct { unsigned char fat$b_rtype; unsigned char fat$b_rattrib; unsigned short int fat$w_rsize; struct { unsigned short int fat$w_hiblkh; unsigned short int fat$w_hiblkl; } fat$l_hiblk; struct { unsigned short int fat$w_efblkh; unsigned short int fat$w_efblkl; } fat$l_efblk; short int fat$w_ffbyte; unsigned char fat$b_bktsize; unsigned char fat$b_vfcsize; short int fat$w_maxrec; short int fat$w_defext; short int fat$w_gbc; short int spares1; int spares2; short int spares3; short int fat$w_versions; } raa; /** Statistics Block **/ struct sbkdef asb; /* ** struct representing a 64-bit binary value expressing ** the date and time **/ DATE_TIME edt, cdt; unsigned short int fpro; /** File Protection **/ /** Access Control Block **/ struct { unsigned short w_size; unsigned short w_type; char *l_addr; } acb[] = { { ATR$S_UCHAR, ATR$C_UCHAR, &fch }, { ATR$S_RECATTR, ATR$C_RECATTR, &raa }, { ATR$S_STATBLK, ATR$C_STATBLK, &asb }, { ATR$S_EXPDATE, ATR$C_EXPDATE, &edt }, { ATR$S_CREDATE, ATR$C_CREDATE, (char *)&cdt }, { ATR$S_FPRO, ATR$C_FPRO, (char *)&fpro }, { 0, 0, (char *)NULL } }; struct { unsigned short status; unsigned short bytcnt; int filler; } iosb; unsigned short bytes; unsigned long status; static struct fibdef fib; $DESCRIPTOR(fib_descriptor, (char *)&fib); char filespec[MAXFILESPEC+1]; unsigned short filespec_length; $DESCRIPTOR (filespec_descriptor, filespec); char buf[BUFSIZ]; int svb; struct FAB to_fab; struct NAM to_nam; char expand_name[NAM$C_MAXRSS]; char resultant_name[MAXFILESPEC+1]; $DESCRIPTOR (resultant_name_descriptor, resultant_name); unsigned short len; char devname[MAXVMSDEVICE+1]; $DESCRIPTOR(devname_descriptor, devname); char *cp; unsigned short from_fid[3]; short status_flag; int i; struct fil_dx_tag temp_entry; char errmsg1[256]; $DESCRIPTOR (errmsg1_descrip, errmsg1); /** Get directory fid and file name of the output file **/ to_fab = cc$rms_fab; to_nam = cc$rms_nam; to_fab.fab$l_fna = to; to_fab.fab$b_fns = strlen(to); to_fab.fab$l_nam = &to_nam; to_fab.fab$l_dna = from; to_fab.fab$b_dns = strlen(from); to_nam.nam$l_esa = &expand_name; to_nam.nam$b_ess = NAM$C_MAXRSS; if ((status = sys$parse(&to_fab, 0, 0)) != RMS$_NORMAL) { lib$sys_getmsg ( &status, &len, &errmsg1_descrip, 0, 0); errmsg1[len] = EOS; strcpy(errmsg, errmsg1); return DX__ERROR; } /** Get a channel for the output file **/ strncpy(devname, to_nam.nam$l_dev, to_nam.nam$b_dev); devname[to_nam.nam$b_dev] = EOS; if ((chan_o = get_chan(devname)) == 0) { sprintf(errmsg, "Establish a logical link with %s failed", to); return DX__ERROR; } /** Directory fid for the input file **/ __FIB(fib,fib$r_did_overlay,fib$w_did[0]) = DX_CURRENT_FILE->did[0]; __FIB(fib,fib$r_did_overlay,fib$w_did[1]) = DX_CURRENT_FILE->did[1]; __FIB(fib,fib$r_did_overlay,fib$w_did[2]) = DX_CURRENT_FILE->did[2]; /** SYS$QIO will not use device and directory name **/ if ((cp = strchr(from, ']')) == 0) { strcpy(filespec, from); } else { cp++; strcpy(filespec, cp); } LENGTH(filespec_descriptor) = strlen(filespec); /* ** Find the I/O channel for this file **/ for (s = DX_CURRENT_DIRECTORY.cur_filter.name_filespec_list; s != (struct filespec_list_tag *)NULL; s = s->next) { struct w_dids_tag *t; for (t = s->w_dids; t != (struct w_dids_tag *)NULL; t = t->next) { if (t->did[0] == DX_CURRENT_FILE->did[0] && t->did[1] == DX_CURRENT_FILE->did[1] && t->did[2] == DX_CURRENT_FILE->did[2]) { chan = t->chan; break; } } } __FIB(fib,fib$r_acctl_overlay,fib$l_acctl) = 0; LENGTH(fib_descriptor) = sizeof (struct fibdef); status = sys$qiow ( /** Read input file attributes **/ 0, chan, IO$_ACCESS+IO$M_ACCESS, &iosb, 0, 0, &fib_descriptor, &filespec_descriptor, 0, 0, acb, 0); if (!(status &1)) { /** No READ access **/ lib$sys_getmsg ( &status, &len, &errmsg1_descrip, 0, 0); errmsg1[len] = EOS; strcpy(errmsg, errmsg1); return DX__ERROR; } else if (!(iosb.status & 1)) { /** No READ access **/ lib$sys_getmsg ( &iosb.status, &len, &errmsg1_descrip, 0, 0); errmsg1[len] = EOS; strcpy(errmsg, errmsg1); return DX__ERROR; } else { /* ** Got input file attributes. ** Create a output file use the same attributes. **/ /** Save input file fid **/ for (i = 0; i <= 2; i++) from_fid[i] = __FIB(fib,fib$r_fid_overlay,fib$w_fid[i]); __FIB(fib,fib$r_did_overlay,fib$w_did[0]) = to_nam.nam$w_did[0]; __FIB(fib,fib$r_did_overlay,fib$w_did[1]) = to_nam.nam$w_did[1]; __FIB(fib,fib$r_did_overlay,fib$w_did[2]) = to_nam.nam$w_did[2]; memset (filespec, EOS, sizeof filespec); strncpy(filespec, to_nam.nam$l_name, to_nam.nam$b_name); strncat(filespec, to_nam.nam$l_type, to_nam.nam$b_type); if (strchr(to, ';') != 0) strncat(filespec, to_nam.nam$l_ver, to_nam.nam$b_ver); else strcat(filespec, ";0"); LENGTH(filespec_descriptor) = strlen(filespec); /** Update FIB information for output file **/ __FIB(fib,fib$r_acctl_overlay.fib$r_acctl_bits0,fib$v_write) = 1; __FIB(fib,fib$r_exctl_overlay.fib$r_exctl_bits,fib$v_extend) = 1; fib.fib$l_exsz = (asb.sbk$w_filesizh << 16)+asb.sbk$w_filesizl; sys$qiow ( /** Create the output file **/ 0, chan_o, IO$_CREATE+IO$M_CREATE+IO$M_ACCESS, &iosb, 0, 0, &fib_descriptor, &filespec_descriptor, &len, &resultant_name_descriptor, acb, 0); if (iosb.status != SS$_NORMAL) { /** File creation failed **/ for (i = 0; i <= 2; i++) __FIB(fib,fib$r_fid_overlay,fib$w_fid[i]) = from_fid[i]; check_OK(sys$qiow ( /** Close the input file **/ 0, chan, IO$_DEACCESS, &iosb, 0, 0, &fib_descriptor, 0, 0, 0, 0, 0)) sys$dassgn (chan_o); lib$sys_getmsg ( &iosb.status, &len, &errmsg1_descrip, 0, 0); errmsg1[len] = EOS; strcpy(errmsg, errmsg1); return DX__ERROR; } /* ** Copy to the output file by reading the virtual block(s) ** From the input file, stores it in a buffer, then writes it ** To the output file. **/ status_flag = 0; svb = 1; sys$qiow ( 0, chan, IO$_READVBLK, &iosb, 0, 0, buf, BUFSIZ, svb, 0, 0, 0); while (iosb.status == SS$_NORMAL) { bytes = iosb.bytcnt; sys$qiow ( 0, chan_o, IO$_WRITEVBLK, &iosb, 0, 0, buf, bytes, svb, 0, 0, 0); if (iosb.status != SS$_NORMAL) { /** WRITE A VIRTUAL BLOCK FAILED **/ status_flag++; sprintf(errmsg, "Error writing to %s", filespec); break; } svb++; sys$qiow ( 0, chan, IO$_READVBLK, &iosb, 0, 0, buf, BUFSIZ, svb, 0, 0, 0); } /* ** Close the output file. ** No error checking in case the output is SYS$OUTPUT. **/ sys$qiow ( 0, chan_o, IO$_DEACCESS, &iosb, 0, 0, &fib_descriptor, 0, 0, 0, 0, 0); sys$dassgn (chan_o); /** Directory fid for the input file **/ for (i = 0; i <= 2; i++) { __FIB(fib,fib$r_fid_overlay,fib$w_fid[i]) = from_fid[i]; } sys$qiow ( /** Close the input file **/ 0, chan, IO$_DEACCESS, &iosb, 0, 0, &fib_descriptor, 0, 0, 0, 0, 0); } if (status_flag) return DX__ERROR; /* ** Get output file attributes **/ strncpy(filespec, to_nam.nam$l_dev, to_nam.nam$b_dev+to_nam.nam$b_dir); filespec[to_nam.nam$b_dev+to_nam.nam$b_dir] = EOS; strcat(filespec, resultant_name); if (filestat(filespec, &temp_entry, errmsg) == DX__ERROR) { return DX__ERROR; } /* ** Update cache queue. ** In case of running out of memory, output error message ** but update current display(s) anyway. **/ if (update_filer_cache(temp_entry, add_to_filer_cache, errmsg) == DX__ERROR) { signal_err(errmsg, bell); } /** Add it to the FILER **/ if (add_to_filer(temp_entry, errmsg, cntrl_info_block.cur_win) == DX__ERROR) { return DX__ERROR; } /** Update other windows **/ for (i = 0; i < cntrl_info_block.windows; i++) { if (i != cntrl_info_block.cur_win) { check_OK(smg$set_physical_cursor ( &cntrl_info_block.pasteboard_id, &cntrl_info_block.pasteboard_rows, &1)) if (add_to_filer(temp_entry, errmsg, i) == DX__ERROR) { return DX__ERROR; } } } return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int add_to_filer( struct fil_dx_tag e, char *errmsg, unsigned short int win) { char dirname[NAM$C_MAXRSS]; char fn[NAM$C_MAXRSS]; struct filespec_list_tag *s; struct w_dids_tag *t; struct fil_dx_tag *p, *q; int row, col; int total_dids; char equ_name[MAXFILESPEC+1]; int total_devices; char dev_name[MAXFILESPEC+1]; unsigned short len; char str[MAXFILESPEC+1]; $DESCRIPTOR (str_descrip, str); int next_entry_row, next_entry_column; fn[0] = EOS; /* ** Find out the number of equivalent names of current directory **/ total_dids = 0; equ_name[0] = EOS; total_devices = 0; dev_name[0] = EOS; for (s = cntrl_info_block.dir_dx[win].cur_filter.name_filespec_list; s; s = s->next) { for (t = s->w_dids; t; t = t->next) { if (strcmp (t->equivalent_name, equ_name)) { total_dids++; strcpy (equ_name, t->equivalent_name); } len = strcspn (t->equivalent_name, "["); if (strncmp (t->equivalent_name, dev_name, len)) { total_devices++; strncpy (dev_name, t->equivalent_name, len); } if (t->did[0] == e.did[0] && t->did[1] == e.did[1] && t->did[2] == e.did[2]) { strcpy(fn, t->equivalent_name); } } } if (strlen(fn) == 0) { /** Directories not matched **/ return DX__NORMAL; } if (!strcmp(strrchr(e.fn, '.'), ".DIR;1")) { /** Insert a directory file **/ char *cp; char s[MAXFILESPEC+1]; strcpy(s, e.fn); cp = strrchr(s, '.'); *cp = ']'; /** Delete "DIR;1" **/ *++cp = EOS; if (total_dids <= 1) { sprintf(e.fn, "[.%s", s); } else { if (total_devices <= 1) { strcpy (e.fn, strchr (fn, '[')); } else { strcpy (e.fn, fn); } e.fn[strlen(e.fn)-1] = '.'; strcat (e.fn, s); } if (insert_filelist_entry( cntrl_info_block.dir_dx[win].dir_filelist, e, cntrl_info_block.dir_dx[win].sortby, cntrl_info_block.dir_dx[win].sortorder) == DX__NORMAL) { cntrl_info_block.dir_dx[win].tot_files++; cntrl_info_block.dir_dx[win].tot_blocks += e.filesize; cntrl_info_block.dir_dx[win].subdir++; } } else { /** Regular file **/ if (find_exclude_file( /** Update exclude list **/ &cntrl_info_block.dir_dx[win].exclude_filelist, cntrl_info_block.dir_dx[win].cur_filter, cntrl_info_block.dir_dx[win].sortby, cntrl_info_block.dir_dx[win].sortorder) == DX__ERROR) { strcpy( errmsg, "Insufficient memory to update the exclude file list"); return DX__ERROR; } strcat(fn, e.fn); /** Get full path name **/ if (!find_match_file(fn, win)) /** The new file is not in the list **/ { return DX__NORMAL; } /* ** Insert the new file to the list. Make sure it meets all ** the file selection criteria before insertion. **/ if (total_dids > 1) { if (total_devices <= 1) { strcpy(e.fn, strchr(fn, '[')); } else { strcpy(e.fn, fn); } } if (!filter_OK( e, cntrl_info_block.dir_dx[win].exclude_filelist, cntrl_info_block.dir_dx[win].cur_filter)) { return DX__NORMAL; } if (insert_filelist_entry( cntrl_info_block.dir_dx[win].non_dir_filelist, e, cntrl_info_block.dir_dx[win].sortby, cntrl_info_block.dir_dx[win].sortorder) == DX__NORMAL) { cntrl_info_block.dir_dx[win].tot_files++; cntrl_info_block.dir_dx[win].tot_blocks += e.filesize; } } /* ** Update current display. ** Find file location in current display. **/ for (p = cntrl_info_block.dir_dx[win].dir_filelist->forward; p != cntrl_info_block.dir_dx[win].non_dir_filelist; p = p->forward) { if (p == cntrl_info_block.dir_dx[win].dir_filelist) { p = cntrl_info_block.dir_dx[win].non_dir_filelist; } else { if (p->fid[0] == e.fid[0] && p->fid[1] == e.fid[1] && p->fid[2] == e.fid[2]) { break; } } } if (p == cntrl_info_block.dir_dx[win].non_dir_filelist) { return DX__NORMAL; } if (p->forward == cntrl_info_block.dir_dx[win].non_dir_filelist) { /** p is the last entry in non-directory file list **/ next_entry_row = next_entry_column = INT_MAX; } else if (p->forward == cntrl_info_block.dir_dx[win].dir_filelist) { /** p is the last entry in directory file list **/ next_entry_row = cntrl_info_block.dir_dx[win].non_dir_filelist->forward->beg_y; next_entry_column = cntrl_info_block.dir_dx[win].non_dir_filelist->forward->beg_x; } else { next_entry_row = p->forward->beg_y; next_entry_column = p->forward->beg_x; } /* ** Re-compute the position of the files in this directory **/ row = col = 1; compute_filer_begin_xy ( cntrl_info_block.dir_dx[win].dir_filelist, &row, &col, win); cntrl_info_block.dir_dx[win].non_dir_filelist->beg_y = cntrl_info_block.dir_dx[win].dir_filelist->backward->beg_y; cntrl_info_block.dir_dx[win].non_dir_filelist->beg_x = cntrl_info_block.dir_dx[win].dir_filelist->backward->beg_x; compute_filer_begin_xy ( cntrl_info_block.dir_dx[win].non_dir_filelist, &row, &col, win); /* ** Adjust FILER_DISPLAY rows **/ cntrl_info_block.dir_dx[win].filer_display.rows = max (cntrl_info_block.dir_dx[win].non_dir_filelist->backward->beg_y, cntrl_info_block.dir_dx[win].filer_display.view_rows); check_OK(smg$change_virtual_display ( &cntrl_info_block.dir_dx[win].filer_display.id, &cntrl_info_block.dir_dx[win].filer_display.rows, &cntrl_info_block.dir_dx[win].filer_display.width, 0, 0, 0)) /* ** Update screen with batch mode **/ check_OK(smg$begin_display_update ( &cntrl_info_block.dir_dx[win].filer_display.id)) if (cntrl_info_block.dir_dx[win].form == long_form) { if (p->beg_y < cntrl_info_block.dir_dx[win].filer_display.rows) { check_OK(smg$insert_line ( &cntrl_info_block.dir_dx[win].filer_display.id, &p->beg_y, 0, &SMG$M_DOWN, 0, 0, 0, 0)) } format_filer_entry(p, str, win); if (p->fn[ strlen(p->fn)-1 ] != ']') { LENGTH(str_descrip) = strlen(str); check_OK(smg$put_chars ( &cntrl_info_block.dir_dx[win].filer_display.id, &str_descrip, &p->beg_y, &p->beg_x, 0, 0, 0, 0)) } else { LENGTH(str_descrip) = 1; check_OK(smg$put_chars ( &cntrl_info_block.dir_dx[win].filer_display.id, &str_descrip, &p->beg_y, &1, 0, 0, 0, 0)) memcpy (str, str+1, strlen(str)); LENGTH(str_descrip) = 30; check_OK(smg$put_chars ( &cntrl_info_block.dir_dx[win].filer_display.id, &str_descrip, &p->beg_y, &2, 0, &SMG$M_BOLD, 0, 0)) memcpy (str, str+30, strlen(str)-30+1); LENGTH(str_descrip) = strlen(str); check_OK(smg$put_chars ( &cntrl_info_block.dir_dx[win].filer_display.id, &str_descrip, &p->beg_y, &32, 0, 0, 0, 0)) } } else { /** Short form **/ if (next_entry_row < p->beg_y || (next_entry_row == p->beg_y && next_entry_column < p->beg_x)) { check_OK(smg$erase_display ( &cntrl_info_block.dir_dx[win].filer_display.id, &next_entry_row, &next_entry_column, &cntrl_info_block.dir_dx[win].filer_display.rows, &cntrl_info_block.dir_dx[win].filer_display.width)) } else { check_OK(smg$erase_display ( &cntrl_info_block.dir_dx[win].filer_display.id, &p->beg_y, &p->beg_x, &cntrl_info_block.dir_dx[win].filer_display.rows, &cntrl_info_block.dir_dx[win].filer_display.width)) } for (q = p; q != cntrl_info_block.dir_dx[win].non_dir_filelist; q = q->forward) { if (q == cntrl_info_block.dir_dx[win].dir_filelist) { q = cntrl_info_block.dir_dx[win].non_dir_filelist; } else { format_filer_entry(q, str, win); LENGTH(str_descrip) = strlen(str); if (q->fn[ strlen(q->fn)-1 ] == ']') { check_OK(smg$put_chars ( &cntrl_info_block.dir_dx[win].filer_display.id, &str_descrip, &q->beg_y, &q->beg_x, 0, &SMG$M_BOLD, 0, 0)) } else { check_OK(smg$put_chars ( &cntrl_info_block.dir_dx[win].filer_display.id, &str_descrip, &q->beg_y, &q->beg_x, 0, 0, 0, 0)) } } } } change_filer_viewport(win); check_OK(smg$end_display_update ( &cntrl_info_block.dir_dx[win].filer_display.id)) put_filer_stat(win); return DX__NORMAL; }