int do_action()

in common/recipes-core/fruid/files/fruid-util.c [803:1053]


int do_action(int argc, char * argv[], unsigned char action_flag) {
  int ret;
  int fd_tmpbin;
  int fd_newbin;
  int fru_size;
  char path[64] = {0};
  char name[64] = {0};
  char eeprom_path[64] = {0};
  char command[128] = {0};
  char *file_path;
  uint8_t status;
  uint8_t fru;
  uint8_t num_devs = 0;
  uint8_t dev_id = DEV_NONE;
  fruid_info_t fruid;
  FILE *fp;

  ret = pal_get_fru_id(argv[optind], &fru);
  if (ret < 0) {
    print_usage();
  }

  if (fru == FRU_ALL) {
    print_usage();
    return -1;
  }

  ret = pal_get_fruid_name(fru, name);
  if (ret < 0) {
    printf("pal_get_fruid_name failed for fru: %d\n", fru);
    return ret;
  }

  ret = pal_is_fru_prsnt(fru, &status);
  if (ret < 0) {
    printf("pal_is_fru_prsnt failed for fru: %d\n", fru);
    return ret;
  }

  if (status == 0) {
    printf("%s is not present!\n\n", name);
    return ret;
  }

  ret = pal_is_fru_ready(fru, &status);
  if ((ret < 0) || (status == 0)) {
    printf("%s is unavailable!\n\n", name);
    return ret;
  }

  if (argc == 5 || argc == 7) {
    pal_get_num_devs(fru, &num_devs);
    if (num_devs == 0) {
      print_usage();
    }
    ret = pal_get_dev_id(argv[optind+1], &dev_id);
    if (ret < 0) {
      print_usage();
    }
    if ( dev_id == DEV_NONE || dev_id == DEV_ALL ) {
      print_usage();
    }
    pal_get_dev_fruid_name(fru, dev_id,name);
    ret = pal_get_dev_fruid_path(fru, dev_id, path);
  } else {
    ret = pal_get_fruid_path(fru, path);
  }
  if (ret < 0) {
    return ret;
  }

  switch(action_flag) {
    case FLAG_DUMP:
      file_path = argv[optind-1];
      fd_tmpbin = open(path, O_RDONLY);
      if (fd_tmpbin == -1) {
        syslog(LOG_ERR, "Unable to open the %s file: %s", path, strerror(errno));
        return errno;
      }

      fd_newbin = open(file_path, O_WRONLY | O_CREAT, 0644);
      if (fd_newbin == -1) {
        syslog(LOG_ERR, "Unable to create %s file: %s", file_path, strerror(errno));
        return errno;
      }

      ret = copy_file(fd_newbin, fd_tmpbin, FRUID_SIZE);
      if (ret < 0) {
        syslog(LOG_ERR, "copy: write to %s file failed: %s",
            file_path, strerror(errno));
      }

      close(fd_newbin);
      close(fd_tmpbin);
      return ret;

    case FLAG_WRITE:
      file_path = argv[optind-1];
      // Check if the new eeprom binary file exits.
      // TODO: Add file size check before adding to the eeprom
      if (access(file_path, F_OK) == -1) {
        print_usage();
        syslog(LOG_ERR, "Unable to access the %s file: %s", file_path, strerror(errno));
        return -1;
      }
      // Verify the checksum of the new binary
      ret = fruid_parse(file_path, &fruid);
      if(ret != 0) {
        printf("New FRU data checksum is invalid\n");
        syslog(LOG_CRIT, "New FRU data checksum is invalid");
        return -1;
      }

      fd_tmpbin = open(path, O_WRONLY | O_CREAT, 0666);
      if (fd_tmpbin == -1) {
        printf("Unable to open the %s file: %s\n", path, strerror(errno));
        syslog(LOG_ERR, "Unable to open the %s file: %s", path, strerror(errno));
        return errno;
      }

      fd_newbin = open(file_path, O_RDONLY);
      if (fd_newbin == -1) {
        printf("Unable to open the %s file: %s\n", file_path, strerror(errno));
        syslog(LOG_ERR, "Unable to open the %s file: %s", file_path, strerror(errno));
        return errno;
      }

      fp = fopen(file_path, "rb");
      if ( NULL == fp ) {
        printf("Unable to get the %s fp %s\n", file_path, strerror(errno));
        syslog(LOG_ERR, "Unable to get the %s fp %s", file_path, strerror(errno));
        return errno;
      }

      //get the size of the new binary
      fseek(fp, 0L, SEEK_END);
      fru_size = ftell(fp);
      rewind(fp);
      fclose(fp);

      //check the size overflow or not
      fru_size = (fru_size > FRUID_SIZE)?FRUID_SIZE:fru_size;

      ret = pal_get_fruid_eeprom_path(fru, eeprom_path);
      if ((dev_id != DEV_NONE) && (ret < 0)) {
         ret = pal_get_dev_fruid_eeprom_path(fru, dev_id, eeprom_path, sizeof(eeprom_path));
      }
      if (ret < 0) {
        //Can not handle in common, so call pal libray for update
        if (num_devs) {
          if (dev_id == DEV_ALL)
            ret = -1;
          else if (dev_id == DEV_NONE)
            ret = pal_fruid_write(fru, file_path);
          else
            ret = pal_dev_fruid_write(fru, dev_id, file_path);
        } else {
          ret = pal_fruid_write(fru, file_path);
        }

        if (ret < 0) {
          printf("FRU:%d Write failed!\n", fru);
          syslog(LOG_WARNING, "[%s] Please check the fruid: %d dev_id: %d file_path: %s", __func__, fru, dev_id, file_path);
          close(fd_newbin);
          close(fd_tmpbin);
          return -1;
        }
      } else {
        if (access(eeprom_path, F_OK) == -1) {
          printf("Fail to access eeprom file file : %s for fru %d\n", eeprom_path, fru);
          syslog(LOG_ERR, "cannot access the eeprom file : %s for fru %d",
              eeprom_path, fru);
          close(fd_newbin);
          close(fd_tmpbin);
          return -1;
        }
        sprintf(command, "dd if=%s of=%s bs=%d count=1", file_path, eeprom_path, fru_size);
        if (system(command) != 0) {
          printf("Copy of %s to %s failed!\n", file_path, eeprom_path);
          syslog(LOG_ERR, "Copy of %s to %s failed!\n", file_path, eeprom_path);
          return -1;
        }

        ret = pal_compare_fru_data(eeprom_path, file_path, fru_size);
        if (ret < 0) {
          printf("Compare %s with %s failed!\n", file_path, eeprom_path);
          syslog(LOG_ERR, "[%s] FRU:%d Write Fail", __func__, fru);
          close(fd_newbin);
          close(fd_tmpbin);
          return -1;
        }
      }

      ret = copy_file(fd_tmpbin, fd_newbin, fru_size);
      if (ret < 0) {
        printf("Write to %s file failed: %s\n", path, strerror(errno));
        syslog(LOG_ERR, "copy: write to %s file failed: %s", path, strerror(errno));
      }

      close(fd_newbin);
      close(fd_tmpbin);
      return ret;

    case FLAG_MODIFY:
      file_path = argv[argc-1];
      if (optind != 4) { //fail to get field "--XXX"
        printf("Parameter \"%s\" is invalid!\n",  argv[argc-3]);
        printf("Fail to modify %s FRU\n", name);
        return -1;
      }
      if(access(file_path, F_OK) == -1) {  //copy current FRU bin file to specified bin file
        fd_tmpbin = open(path, O_RDONLY);
        if (fd_tmpbin == -1) {
          syslog(LOG_ERR, "Unable to open the %s file: %s", path, strerror(errno));
          return errno;
        }

        fd_newbin = open(file_path, O_WRONLY | O_CREAT, 0644);
        if (fd_newbin == -1) {
          syslog(LOG_ERR, "Unable to create %s file: %s", file_path, strerror(errno));
          return errno;
        }

        ret = copy_file(fd_newbin, fd_tmpbin, FRUID_SIZE);
        if (ret < 0) {
          syslog(LOG_ERR, "copy: write to %s file failed: %s",
              file_path, strerror(errno));
          return ret;
        }

        close(fd_newbin);
        close(fd_tmpbin);
      } else {
        memset(path, 0, sizeof(path));
        sprintf(path, "%s", file_path);
      }

      ret = fruid_modify(path, file_path, argv[optind-2], argv[optind-1]);
      if(ret < 0){
        printf("Fail to modify %s FRU\n", name);
        return ret;
      }
      ret = get_fruid_info(fru, file_path, name, DEFAULT_FORMAT,NULL);
      return ret;

    default:
        return -1;
  }

  return 0;
}