以正确的方式扩展结构

时间:2018-05-24 19:56:32

标签: c operating-system malloc realloc

我为自己的作业编写了一个程序,但是我犯了一个错误并设置为 由于该结构限制,该程序可以使用的用户数不变。我试着做一些realloc来扩展结构但它没有用,我得到了:

  

gcc:错误:O"SxW��D(/��A>A�0:没有这样的文件或目录

     

gcc:致命错误:没有输入文件

     

编译终止。

这是我的代码与相关行附近的待办事项,我将非常感谢一种方法,这将帮助我使代码与用户数量相关的不那么严格。谢谢!

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <memory.h>
#include <unistd.h>
#include <wait.h>

#define MAX_LENGTH 160
#define STDERR_FILDES 2
#define OPERATION_FAILED (-1)
#define BUFFER_SIZE 512
#define CONFIG_PLACE 1
#define CORRECT_ARGS_NUM 2
#define WRONG_ARGS_NUM_MSG "Wrong number of program arguments. Please enter 2 arguments."
#define SPACE_CHAR ' '
#define NEW_LINE_CHAR '\n'
#define NULL_CHAR '\0'
#define NULL_STR "\0"
#define SLASH_CHAR '/'
#define SLASH_STR "/"
#define CURR_DIR "."
#define PAR_DIR ".."
#define C_EXTENT "c"
#define EXT_DOT '.'
#define NUM_OF_USERS 5 //todo: here I define the rigid number of users.
#define ZERO_SCORE "0"
#define SON 0
#define NO_FILE "NO_C_FILE"
#define TIMEOUT "TIMEOUT"
#define COMP_ERR "COMPILATION_ERROR"
#define SIXTY_SCORE "60"
#define BAD_OUT "BAD_OUTPUT"
#define EIGHTY_SCORE "80"
#define SIM_OUT "SIMILAR_OUTPUT"
#define HUNDRED_SCORE "100"
#define GREAT_OUT "GREAT_JOB"
#define EQUAL 0
#define EXE_FILE_NAME "temp.out"
#define RUN_FILE_NAME "./temp.out"
#define COMP_FILE_NAME "./comp.out"
#define RES_FILE_NAME "res.txt"
#define OPER "gcc"
#define OPT_FLAG "-o"
#define RESULTS_FILE_REL_PATH "results.csv"
#define RESULTS_FILE_PERMISSIONS 0644
#define CSV_LINE_MAX_LEN 500
#define CSV_SEPARATOR ","
#define CSV_END_LINE "\n"
#define SECONDS_TO_SLEEP 5
#define WAIT_FOR_ANY_CHILD 0
#define IDENTICAL 3
#define SIMILAR 2
#define DIFFERENT 1

enum Bool
{
  false = 0,
  true = 1
};

typedef struct User {
  char name[MAX_LENGTH];
  char filePath[MAX_LENGTH];
  char dirPath[MAX_LENGTH];
  char score[MAX_LENGTH];
  char scoreInfo[MAX_LENGTH];
} User;

/**
 * Prints an error message using write function to file descriptor
 * number 2 (stderr), and exits with error status -1 (translates to 255).
 */
void sysCallFailureProcedure() {
  char errorMsg[] = "Error in system call\n";
  write(STDERR_FILDES, errorMsg, sizeof(errorMsg)-1);
  exit(OPERATION_FAILED);
}

/**
 * Get the file's extension.
 * @param filename The filename.
 * @return The file's extension.
 */
char *getFilenameExt(char *filename) {
  char *dot = strrchr(filename, EXT_DOT);
  if(!dot || dot == filename) return "";
  return dot + 1;
}

/**
 * Get the configurations from the configurations file.
 * @param configfilePath The configurations file.
 * @param mainDirPath The main directory path.
 * @param inputFilePath The input file path.
 * @param correctResFilePath The correct result file path.
 */
void getConfigFromFile(char* mainDirPath, char* inputFilePath, char* correctResFilePath, char* configfilePath){
  int configFileDes = open(configfilePath, O_RDONLY);
  if (configFileDes < 0){
    sysCallFailureProcedure();
  }
  int retVal;
  char  buff[BUFFER_SIZE];
  while ((retVal = read(configFileDes, buff, sizeof(buff))) > 0){
    int lineNumber = 1;
    int lineIdx = 0;
    int i=0;
    for (; i<retVal; i++) {
        if (lineNumber == 1){
          if (buff[i] == NEW_LINE_CHAR || buff[i] == SPACE_CHAR || buff[i] == NULL_CHAR) {
            lineNumber = 2;
            lineIdx = 0;
          } else {
            mainDirPath[lineIdx] = buff[i];
            lineIdx++;
          }
        }
        else if (lineNumber == 2){
          if (buff[i] == NEW_LINE_CHAR || buff[i] == SPACE_CHAR || buff[i] == NULL_CHAR) {
            lineNumber = 3;
            lineIdx = 0;
          } else {
            inputFilePath[lineIdx] = buff[i];
            lineIdx++;
          }
        }
        else if (lineNumber == 3){
          if (buff[i] != NEW_LINE_CHAR && buff[i] != SPACE_CHAR && buff[i] != NULL_CHAR) {
            correctResFilePath[lineIdx] = buff[i];
            lineIdx++;
          }
        }
    }
  }
  if (retVal < 0){
    sysCallFailureProcedure();
  }
  if (close(configFileDes) < 0){
    sysCallFailureProcedure();
  }
}

/**
 * Get the C file.
 * @param user The user.
 * @param userNum The user Num.
 * @param directory The directory.
 * @param filePath The file path.
 */
void getCFile(User* user, int userNum, char* directory,char* filePath){
  DIR* pDir = opendir(directory);
  if (pDir == NULL){
    sysCallFailureProcedure();
  }
  struct dirent* pDirent;
  while((pDirent = readdir(pDir))!=NULL) {
    if ((pDirent->d_type == DT_DIR) && (strcmp(pDirent->d_name, CURR_DIR) != 0)
        && (strcmp(pDirent->d_name, PAR_DIR) != 0)){
      char dir[MAX_LENGTH]={};
      strcpy(dir,directory);
      int length = strlen(dir);
      if (dir[length] != SLASH_CHAR) {
        strcat(dir, SLASH_STR);
      }
      strcat(dir, pDirent->d_name);
      getCFile(user, userNum, dir, filePath);
    } else if (pDirent->d_type == DT_REG) {
      char* extension = getFilenameExt(pDirent->d_name);
      if(strcmp(extension,C_EXTENT) == 0) {
        strcpy(filePath, pDirent->d_name);
        strcpy(user[userNum].dirPath, directory);
        break;
      }
    }
  }
}

/**
 * Process the main directory.
 * @param users The users.
 * @param userNum The user num.
 * @param mainDirPath The main directory path.
 */
void processMainDir(User* users, int* userNum, char* mainDirPath){
  DIR* pDir = opendir(mainDirPath);
  if (pDir == NULL){
    sysCallFailureProcedure();
  }
  struct dirent* pDirent;
  int usersSize = NUM_OF_USERS; // todo: remove if may...
  int userSize = sizeof(struct User);
  while ((pDirent = readdir(pDir))!=NULL) {
    if ((pDirent->d_type == DT_DIR) && (strcmp(pDirent->d_name, CURR_DIR) != 0)
        && (strcmp(pDirent->d_name, PAR_DIR) != 0)){
      strcpy(users[*userNum].name, pDirent->d_name);
      char path[MAX_LENGTH] = {};
      char dir[MAX_LENGTH]={};
      strcpy(dir, mainDirPath);
      int length = strlen(dir);
      if (dir[length] != SLASH_CHAR) {
        strcat(dir, SLASH_STR);
      }
      strcat(dir, pDirent->d_name);
      getCFile(users, *userNum, dir, path);
      strcpy(users[*userNum].filePath, path);
      (*userNum)++;
      if ((*userNum) >= usersSize){
        usersSize += NUM_OF_USERS;
        users = (User*) realloc(users, usersSize * userSize); // todo: check it out. it doesn't work!
        if (users == NULL){
          sysCallFailureProcedure();
        }
      }
    }
  }
  if (closedir(pDir) == OPERATION_FAILED){
    sysCallFailureProcedure();
  }
}

/*
 * Return true if there is an executable file.
 */
enum Bool isThereExecutable(){
  char workingDir[BUFFER_SIZE];
  DIR* pDir;
  struct dirent* pDirent;
  getcwd(workingDir, sizeof(workingDir));
  if ((pDir = opendir(workingDir)) == NULL){
    sysCallFailureProcedure();
  }
  while ((pDirent = readdir(pDir)) != NULL){
    if (strcmp(pDirent->d_name, EXE_FILE_NAME) == EQUAL){
      return true;
    }
  }
  return false;
}

/**
 * Fill up the results file.
 * @param resultsFilePath The path to the results file.
 * @param userNum The number of users.
 * @param users The users struct.
 */
void fillTheResultsFile(char* resultsFilePath, int userNum, User* users){
  int resultsFileDes = open(resultsFilePath, O_WRONLY | O_CREAT | O_TRUNC, RESULTS_FILE_PERMISSIONS);
  if (resultsFileDes < 0){
    sysCallFailureProcedure();
  }
  int i;
  for (i=0; i<userNum; i++) {
    char line[CSV_LINE_MAX_LEN] = {};
    strcpy(line, users[i].name);
    strcat(line, CSV_SEPARATOR);
    strcat(line, users[i].score);
    strcat(line, CSV_SEPARATOR);
    strcat(line, users[i].scoreInfo);
    if (i < userNum -1){
      strcat(line, CSV_END_LINE);
    }
    if (write(resultsFileDes, line, sizeof(line)-1) < 0){
      sysCallFailureProcedure();
    }
  }
  if (close(resultsFileDes) < 0){
    sysCallFailureProcedure();
  }
}

/**
 * Execute a file.
 * @param argv The file's args.
 */
void executeFile(char* argv[]){
  pid_t pId = fork();
  if (pId == SON) {
    int retVal = execvp(argv[0], &argv[0]);
    if (retVal == OPERATION_FAILED) {
      sysCallFailureProcedure();
    }
  }else{
    waitpid(pId, NULL, WCONTINUED);
  }
}

void executeProg(User* users, int userNum, char* inputFilePath, char* correctResFilePath){
  char* runArgs[] = {RUN_FILE_NAME, NULL};
  int status;
  pid_t pId = fork();
  if (pId == SON){
    int inputFileFileDes = open(inputFilePath, O_RDONLY);
    if (inputFileFileDes < 0){
      sysCallFailureProcedure();
    }
    int resFileFileDes = open(RES_FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC, RESULTS_FILE_PERMISSIONS);
    if (resFileFileDes < 0){
      sysCallFailureProcedure();
    }
    if (dup2(inputFileFileDes, STDIN_FILENO) < 0){
      sysCallFailureProcedure();
    }
    if (dup2(resFileFileDes, STDOUT_FILENO) < 0){
      sysCallFailureProcedure();
    }
    if (execvp(runArgs[0], &runArgs[0]) < 0){
      sysCallFailureProcedure();
    }
    if (close(inputFileFileDes) < 0){
      sysCallFailureProcedure();
    }
    if (close(resFileFileDes) < 0){
      sysCallFailureProcedure();
    }
  } else {
    sleep(SECONDS_TO_SLEEP);
    if (waitpid(pId, &status, WNOHANG) == 0){
      strcpy(users[userNum].scoreInfo, TIMEOUT);
      strcpy(users[userNum].score, ZERO_SCORE);
    } else {
      char* copmArguments[] = {COMP_FILE_NAME , RES_FILE_NAME, correctResFilePath, NULL};
      pid_t pId2 = fork();
      if (pId2 == SON){
        if (execvp(copmArguments[0], &copmArguments[0]) < 0){
          sysCallFailureProcedure();
        }
      } else{
        waitpid(pId2, &status, WAIT_FOR_ANY_CHILD);
        if (WIFEXITED(status)){
          int compRes = WEXITSTATUS(status);
          if (compRes == IDENTICAL){
            strcpy(users[userNum].scoreInfo, GREAT_OUT);
            strcpy(users[userNum].score, HUNDRED_SCORE);
          } else if (compRes == SIMILAR){
            strcpy(users[userNum].scoreInfo, SIM_OUT);
            strcpy(users[userNum].score, EIGHTY_SCORE);
          } else if (compRes == DIFFERENT){
            strcpy(users[userNum].scoreInfo, BAD_OUT);
            strcpy(users[userNum].score, SIXTY_SCORE);
          }
        }
        if (unlink(EXE_FILE_NAME) < 0){
          sysCallFailureProcedure();
        }
        if (unlink(RES_FILE_NAME) < 0){
          sysCallFailureProcedure();
        }
      }
    }
  }
}

/**
 * Get the scores and score info's.
 * @param inputFilePath The input file path.
 * @param correctResFilePath  The correct result file path.
 * @param users The users.
 * @param userNum The user num.
 */
void getScoresAndInfo(char* inputFilePath, char* correctResFilePath, User* users, int userNum){
  int i;
  for (i=0; i<userNum; i++) {
    if (strcmp(NULL_STR, users[i].filePath) == EQUAL){
      strcpy(users[i].scoreInfo, NO_FILE);
      strcpy(users[i].score, ZERO_SCORE);
    } else {
      char CompletePathToFile[MAX_LENGTH] = {};
      strcpy(CompletePathToFile, users[i].dirPath);
      strcat(CompletePathToFile, SLASH_STR);
      strcat(CompletePathToFile, users[i].filePath);
      char* executeArguments[] = {OPER, OPT_FLAG, EXE_FILE_NAME, CompletePathToFile, NULL};
      executeFile(executeArguments);
      if (!isThereExecutable()){
        strcpy(users[i].scoreInfo, COMP_ERR);
        strcpy(users[i].score, ZERO_SCORE);
      } else { 
        executeProg(users, i, inputFilePath, correctResFilePath);
      }
    }
  }
}

int main(int argc, char *argv[]) {
  if (argc != CORRECT_ARGS_NUM) {
    printf(WRONG_ARGS_NUM_MSG);
    exit(OPERATION_FAILED);
  }
  char mainDirPath[MAX_LENGTH] = {};
  char inputFilePath[MAX_LENGTH] = {};
  char correctResFilePath[MAX_LENGTH] = {};
  getConfigFromFile(mainDirPath, inputFilePath,correctResFilePath, argv[CONFIG_PLACE]);
  User* users = (User*)malloc(sizeof(User) * NUM_OF_USERS); // todo: here I malloc the users struct
  int idx = 0;
  if (users == NULL){
    sysCallFailureProcedure();
  }
  processMainDir(users, &idx, mainDirPath);
  getScoresAndInfo(inputFilePath, correctResFilePath, users, idx);
  fillTheResultsFile(RESULTS_FILE_REL_PATH, idx, users);
}

0 个答案:

没有答案