From: SMTP%"DSJ@WKUVX1.WKU.EDU" 21-DEC-1993 10:53:45.15 To: EVERHART CC: Subj: OCTOBER93.FILOWN X-FileServer: Digital Systems Journal File Server Date: Tue, 21 Dec 1993 09:55:07 CDT Sender: DSJ-Mgr@WKUVX1.WKU.EDU Errors-To: DSJ-Mgr@WKUVX1.WKU.EDU Warnings-To: <> From: DSJ-Mgr@WKUVX1.WKU.EDU Reply-To: DSJ@WKUVX1.WKU.EDU Subject: OCTOBER93.FILOWN To: EVERHART@arisia.gce.com $ ! $ ! File : EXTRACT_HEADER.COM $ ! $ ! Procedure to extract a macro definition from a library and convert $ ! it to a VAX C header file. $ ! $ ! Written by Dennis Leiterman $ ! 12-Mar-1993 $ ! $ INPUT_LOOP: $ if (p1 .eqs. "") then inquire p1 "Enter module to be extracted " $ if (p1 .eqs. "") then goto input_loop $ if (p2 .eqs. "") then p2 := "lib" $ set on $ on error then goto exit $ library/extract=$'p1'/output='p1'/macro sys$library:'p2'.mlb $ set noon $ open/read in_file 'p1'.mar $ open/write out_file 'p1'.h $ write out_file "#ifndef ___''p1'__LOADED" $ write out_file "#define ___''p1'__LOADED 1" $ write out_file "" $ write out_file "/*" $ write out_file "This file has been created using the macro definitions" $ write out_file "located in ''p2'.mlb. All the $EQU statements have been" $ write out_file "changed to #define statements and the extension is changed" $ write out_file "to a .h" $ write out_file "*/" $ loop: $ read/end_of_file=done/error=done in_file in_buff $ if (f$extract(0, 4, in_buff) .eqs. "$EQU") then - write out_file "#define ''f$extract(4,80,in_buff)'" $ goto loop $ DONE: $ write out_file "" $ write out_file "#endif /* ''p1' loaded */" $ close in_file $ close out_file $ delete 'p1'.mar; $ EXIT: $ exit /* Program to read the INDEXF.SYS and check ownership of file headers -vs- the directory where they reside Written by Dennis Leiterman 2-Mar-1993 History: */ /* Standard definitions */ #include #include /* RMS definitions */ #include /* File information block definitions */ #include /* File Identification definitions */ #include /* QIO definitions */ #include /* System Service messages */ #include /* Taken from LIB.MLB */ #include /* Taken from LIB.MLB */ #define RECORD_SIZE FH2$C_LEVEL2 /* Record size of indexf */ #define BLOCK_SIZE 128 /* Block size */ #define MAX_HEADERS 100000 /* Maximum number of headers */ main(int argc, char **argv) { struct fibdef fib; struct { int fib_len, fib_address; } fib_desc; struct { short status; int count; short filler; } iosb; struct { unsigned char valid; /* Valid byte */ unsigned int owner; /* Owner identifier */ struct fiddef fid; /* File FID */ struct fiddef backlink; /* Directory FID */ } header_array[MAX_HEADERS]; struct dsc$descriptor_s filename_desc; struct dsc$descriptor_s device_desc; struct dsc$descriptor_s file_owner_desc; struct dsc$descriptor_s directory_owner_desc; /* System declarations */ int sys$assign(), sys$dassgn(), sys$qiow(), lib$int_over(), lib$fid_to_name(), sys$idtoasc(); /* Program declarations */ unsigned char *header_ptr; unsigned char block_buffer[RECORD_SIZE * BLOCK_SIZE]; char command_file[80], /* Name of command file */ log_file[80], /* Name of the log file */ file_owner[40], /* For sys$idtoasc */ directory_owner[40], /* Owner of directory */ device_name[80], /* Device to check */ filename[132]; /* Store file name from */ /* lib$fid_to_name() */ int validate_header(); /* Check header function */ unsigned int long_buff, /* Long int general variable */ vbn, /* Virtual block number */ header_count = 0, /* Total headers found */ status, /* General purpose status */ file_index; /* File index number */ unsigned short function_code, /* Function code for QIO */ filename_length, /* Length returned */ file_owner_length, /* Length from sys$idtoasc */ directory_owner_length, /* Directory length */ device_channel; /* Disk channel */ register i; /* General purpose index */ void supply_help(void); /* Give some help */ FILE *command_file_ptr; /* Command file to change ownership */ FILE *log_file_ptr; /* Log file */ /* See if a device is supplied on the command line */ if (argc != 2) { printf("RIN-E-NODEV, No device supplied\n"); supply_help(); exit(1); } /* End of device check */ strcpy(&device_name, argv[1]); /* Make a command and log file using the device name */ for (i=0; i <= strlen(device_name) && device_name[i] != ':'; i++) command_file[i] = log_file[i] = device_name[i]; command_file[i] = '\0'; log_file[i] = '\0'; strcat(command_file, "_misowned.com"); strcat(log_file, "_misowned.log"); if ((command_file_ptr = fopen(command_file, "w")) == NULL) { perror("open"); exit(); } if ((log_file_ptr = fopen(log_file, "w")) == NULL) { perror("open"); exit(); } fprintf(command_file_ptr, "$ set noon \n"); /* Make a descriptor for the device name */ device_desc.dsc$w_length = strlen(device_name); device_desc.dsc$a_pointer = &device_name; device_desc.dsc$b_class = DSC$K_CLASS_S; device_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* Make a descriptor for the file name */ filename_desc.dsc$w_length = sizeof(filename); filename_desc.dsc$a_pointer = &filename; filename_desc.dsc$b_class = DSC$K_CLASS_S; filename_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* Make a descriptor for the file owner name */ file_owner_desc.dsc$w_length = sizeof(file_owner); file_owner_desc.dsc$a_pointer = &file_owner; file_owner_desc.dsc$b_class = DSC$K_CLASS_S; file_owner_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* Make a descriptor for the directory owner name */ directory_owner_desc.dsc$w_length = sizeof(directory_owner); directory_owner_desc.dsc$a_pointer = &directory_owner; directory_owner_desc.dsc$b_class = DSC$K_CLASS_S; directory_owner_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* First assign a channel to the device */ status = sys$assign(&device_desc, &device_channel, 0, 0); if ((status &1) != 1) exit(status); /* Zero out the fib data structure */ memset(&fib, 0, sizeof(fib)); /* Access the INDEXF.SYS file */ fib.fib$r_fid_overlay.fib$w_fid[0] = FID$C_INDEXF; fib.fib$r_fid_overlay.fib$w_fid[1] = FID$C_INDEXF; fib.fib$r_fid_overlay.fib$w_fid[2] = 0; fib_desc.fib_len = FIB$K_LENGTH; fib_desc.fib_address = &fib; function_code = IO$_ACCESS | IO$M_ACCESS; status = sys$qiow(0, /* Event flag */ device_channel, /* Channel */ function_code, /* Function Code */ &iosb, /* I/O Status */ 0, 0, /* No AST */ &fib_desc, /* FIB */ 0, 0, 0, 0, 0); if ((status & 1) != 1) exit(status); if ((iosb.status & 1) != 1) exit(iosb.status); /* Now read in the home block */ function_code = IO$_READVBLK; status = sys$qiow(0, /* Event flag */ device_channel, /* Channel */ function_code, /* Function Code */ &iosb, /* I/O Status */ 0, 0, /* No AST */ &block_buffer, /* Stuff data here */ RECORD_SIZE, /* Size of buffer */ 2, /* Virtual block */ 0, 0, 0); if ((status &1) != 1) exit(status); if ((iosb.status & 1) != 1) exit(iosb.status); /* Find out where the data starts */ vbn = block_buffer[HM2$W_IBMAPVBN] + block_buffer[HM2$W_IBMAPSIZE]; /* Start reading headers */ for ( ;iosb.status != SS$_ENDOFFILE; vbn += BLOCK_SIZE) { function_code = IO$_READVBLK; status = sys$qiow(0, /* Event flag */ device_channel, /* Channel */ function_code, /* Function Code */ &iosb, /* I/O Status */ 0, 0, /* No AST */ &block_buffer, /* Stuff data here */ sizeof(block_buffer), /* Size of buffer */ vbn, /* Virtual block */ 0, 0, 0); if ((status &1) != 1) exit(status); if (iosb.status != SS$_ENDOFFILE) { if ((iosb.status & 1) != 1) exit(iosb.status); } /* Validate header */ for (header_ptr = block_buffer, i = 1; i <= (iosb.count / RECORD_SIZE); i++, header_ptr += RECORD_SIZE, header_count++) {ff> file_index = 0; /* See if it is a valid header */ if (validate_header(header_ptr)) { memcpy(&file_index, header_ptr + FH2$W_FID_NUM, 2); file_index += (*(header_ptr + FH2$B_FID_NMX) * 65536); /* See if it is a directory file, if so store it but make the valid byte 2 instead of 1 */ memcpy(&long_buff, (header_ptr + FH2$L_FILECHAR), 4); if (long_buff & FH2$M_DIRECTORY) header_array[file_index].valid = 2; else header_array[file_index].valid = 1; /* Valid file header */ memcpy(&header_array[file_index].owner, header_ptr + FH2$L_FILEOWNER, 4); memcpy(&header_array[file_index].fid.fid$w_num, header_ptr + FH2$W_FID, 6); memcpy(&header_array[file_index].backlink.fid$w_num, header_ptr + FH2$W_BACKLINK, 6); } /* End of valid header tasks */ else header_array[file_index].valid = 0; /* Not a valid header */ } /* End of IF loop for header_array store tasks */ } /* End of IF loop */ /* When we come here, we have stored all the valid file and directory headers in our array. Now lets check the owner of the file with the owner of the backlink pointer. If they don't match, flag them. With the count of valid headers found, check if the header array is valid, an entry exists for all possible headers in the INDEXF.SYS file. If the header was valid, we marked it as; 1 = file header, 2 = directory header. If this is a valid file header check the owner ship of the file against the owner of the backlink, which is the FID of the directory file where the file resides. If they don't match, use the owner UIC to find an entry in the rights database and find out in ascii who owns the file and the directory where is resides. Print out this info to the log file and print it out to the command file to correct ownership. */ for (i = 1; i <= header_count; i++) { if (header_array[i].valid == 1) { /* 1 = file 2 = directory */ if (header_array[i].backlink.fid$w_num == 0) continue; if (header_array[i].owner != header_array[header_array[i].backlink.fid$w_num].owner) { status = lib$fid_to_name(&device_desc, &header_array[i].fid.fid$w_num, &filename_desc, &filename_length, 0, 0); filename[filename_length] = '\0'; if (filename_length == 0) continue; /* Didn't find file name */ status = sys$idtoasc(header_array[i].owner, &file_owner_length, &file_owner_desc, 0, 0, 0); if (status != SS$_NOSUCHID) { if ((status &1) != 1) exit(status); file_owner[file_owner_length] = '\0'; } else strcpy(&file_owner, ""); status = sys$idtoasc(header_array[header_array[i].backlink.fid$w_num].owner, &directory_owner_length, &directory_owner_desc, 0, 0, 0); if (status != SS$_NOSUCHID) { if ((status &1) != 1) exit(status); directory_owner[directory_owner_length] = '\0'; } else strcpy(&directory_owner, ""); fprintf (log_file_ptr, "%s owned by %s directory owned by %s\n", filename, file_owner, directory_owner); fprintf(command_file_ptr, "$ set file %s /owner=parent\n", filename); } /* End misowned file check */ } /* End valid file IF */ } /* End of FOR loop */ /* Were done, deaccess the file */ function_code = IO$_DEACCESS; status = sys$qiow(0, /* Event flag */ device_channel, /* Channel */ function_code, /* Function Code */ &iosb, /* I/O Status */ 0, 0, /* No AST */ &fib_desc, /* FIB */ 0, 0, 0, 0, 0); if ((status & 1) != 1) exit(status); if ((iosb.status & 1) != 1) exit(iosb.status); status = sys$dassgn(device_channel); if ((status & 1) != 1) exit(status); } /* End of program */ /* Function to supply help */ void supply_help(void) { printf("\n"); printf("This program will find any files in a directory that are\n"); printf("not owned by the UIC or identifier of that directory.\n\n"); printf("To use this program, install it as a foriegn command;\n\n"); printf("$ FIND_MISOWNED := $device[directory]FIND_MISOWNED\n\n"); printf("Then type in;\n\n"); printf("$ FIND_MISOWNED device_name\n\n"); printf("This program will produce a log file and a command file\n"); printf("Check the log file for what files the program found and who\n"); printf("owns them, you can use the command file to correct the ownership.\n"); return; } /* Validate Header function, these steps were taken from the VMS File Systems Internal book by Kirby McCoy. Written by Dennis Leiterman 25-Feb-1993 */ /* Standard definitions */ #include /* RMS definitions */ #include /* Taken from LIB.MLB */ int validate_header(unsigned char *header_char_ptr) { unsigned short *header_word_ptr; unsigned int long_buff, /* Long int general buffer */ status, /* General purpose return check */ int_over_disable = 0, /* Turn off integer overflow */ int_over_save; /* Store whatever is was */ unsigned short short_buff, /* Short int general buffer */ checksum; /* Used to calculate header checksum */ register i; /* General purpose index */ header_word_ptr = header_char_ptr; /* Lets see if the file has been deleted, no sense going any further if it is. */ memcpy(&long_buff, (header_char_ptr + FH2$L_FILECHAR), 4); if (long_buff & FH2$M_MARKDEL) return 0; memcpy(&short_buff, (header_char_ptr + FH2$W_FID_NUM), 2); if ( (short_buff == 0) && (*(header_char_ptr + FH2$B_FID_NMX) == 0) && (*(header_char_ptr + FH2$B_FID_RVN) == 0) ) return 0; if ( *(header_word_ptr + 255) == 0) return 0; /* Verify that the offset to the data area (FH2$B_IDOFFSET) is past the FH2$L_HIGHWATER offset. FH2$B_IDOFFSET is the word offset to the data area. */ if (header_word_ptr + *(header_char_ptr + FH2$B_IDOFFSET) < *(header_char_ptr + FH2$L_HIGHWATER)) return 0; /* Next check is making sure all the offsets are greater then the one before. */ if (*(header_char_ptr + FH2$B_IDOFFSET) > *(header_char_ptr + FH2$B_MPOFFSET)) return 0; if (*(header_char_ptr + FH2$B_MPOFFSET) > *(header_char_ptr + FH2$B_ACOFFSET)) return 0; if (*(header_char_ptr + FH2$B_ACOFFSET) > *(header_char_ptr + FH2$B_RSOFFSET)) return 0; /* Now check some other values. */ if ((*(header_char_ptr + FH2$W_STRUCLEV + 1) != 2) && (*(header_char_ptr + FH2$W_STRUCLEV) < 1)) return 0; if ( *(header_char_ptr + FH2$B_MAP_INUSE) > ( *(header_char_ptr + FH2$B_ACOFFSET) - *(header_char_ptr + FH2$B_MPOFFSET)) ) return 0; /* Verify header with simple word checksum, 255 words added together with no regard to overflow must match the 256th word of the header. */ int_over_save = lib$int_over(&int_over_disable); /* Turn it off */ for (i=0, checksum=0; i < 255; i++) checksum += *(header_word_ptr + i); lib$int_over(&int_over_save); /* Restore it */ if (checksum != *(header_word_ptr + i)) return 0; /* Bad checksum, return */ return 1; /* Everything checked out, return success */ } /* End function VALIDATE_HEADER */