Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL utils.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2013-2015, Michael Ellerman, IBM Corp.
 */


#define _GNU_SOURCE /* For CPU_ZERO etc. */

#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <link.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <linux/limits.h>

#include "utils.h"

static char auxv[4096];

int read_file(const char *path, char *buf, size_t count, size_t *len)
{
 ssize_t rc;
 int fd;
 int err;
 char eof;

 fd = open(path, O_RDONLY);
 if (fd < 0)
  return -errno;

 rc = read(fd, buf, count);
 if (rc < 0) {
  err = -errno;
  goto out;
 }

 if (len)
  *len = rc;

 /* Overflow if there are still more bytes after filling the buffer */
 if (rc == count) {
  rc = read(fd, &eof, 1);
  if (rc != 0) {
   err = -EOVERFLOW;
   goto out;
  }
 }

 err = 0;

out:
 close(fd);
 errno = -err;
 return err;
}

int read_file_alloc(const char *path, char **buf, size_t *len)
{
 size_t read_offset = 0;
 size_t buffer_len = 0;
 char *buffer = NULL;
 int err;
 int fd;

 fd = open(path, O_RDONLY);
 if (fd < 0)
  return -errno;

 /*
 * We don't use stat & preallocate st_size because some non-files
 * report 0 file size. Instead just dynamically grow the buffer
 * as needed.
 */

 while (1) {
  ssize_t rc;

  if (read_offset >= buffer_len / 2) {
   char *next_buffer;

   buffer_len = buffer_len ? buffer_len * 2 : 4096;
   next_buffer = realloc(buffer, buffer_len);
   if (!next_buffer) {
    err = -errno;
    goto out;
   }
   buffer = next_buffer;
  }

  rc = read(fd, buffer + read_offset, buffer_len - read_offset);
  if (rc < 0) {
   err = -errno;
   goto out;
  }

  if (rc == 0)
   break;

  read_offset += rc;
 }

 *buf = buffer;
 if (len)
  *len = read_offset;

 err = 0;

out:
 close(fd);
 if (err)
  free(buffer);
 errno = -err;
 return err;
}

int write_file(const char *path, const char *buf, size_t count)
{
 int fd;
 int err;
 ssize_t rc;

 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 if (fd < 0)
  return -errno;

 rc = write(fd, buf, count);
 if (rc < 0) {
  err = -errno;
  goto out;
 }

 if (rc != count) {
  err = -EOVERFLOW;
  goto out;
 }

 err = 0;

out:
 close(fd);
 errno = -err;
 return err;
}

int read_auxv(char *buf, ssize_t buf_size)
{
 int err;

 err = read_file("/proc/self/auxv", buf, buf_size, NULL);
 if (err) {
  perror("Error reading /proc/self/auxv");
  return err;
 }

 return 0;
}

int read_debugfs_file(const char *subpath, char *buf, size_t count)
{
 char path[PATH_MAX] = "/sys/kernel/debug/";

 strncat(path, subpath, sizeof(path) - strlen(path) - 1);

 return read_file(path, buf, count, NULL);
}

int write_debugfs_file(const char *subpath, const char *buf, size_t count)
{
 char path[PATH_MAX] = "/sys/kernel/debug/";

 strncat(path, subpath, sizeof(path) - strlen(path) - 1);

 return write_file(path, buf, count);
}

static int validate_int_parse(const char *buffer, size_t count, char *end)
{
 int err = 0;

 /* Require at least one digit */
 if (end == buffer) {
  err = -EINVAL;
  goto out;
 }

 /* Require all remaining characters be whitespace-ish */
 for (; end < buffer + count; end++) {
  if (*end == '\0')
   break;

  if (*end != ' ' && *end != '\n') {
   err = -EINVAL;
   goto out;
  }
 }

out:
 errno = -err;
 return err;
}

static int parse_bounded_int(const char *buffer, size_t count, intmax_t *result,
        int base, intmax_t min, intmax_t max)
{
 int err;
 char *end;

 errno = 0;
 *result = strtoimax(buffer, &end, base);

 if (errno)
  return -errno;

 err = validate_int_parse(buffer, count, end);
 if (err)
  goto out;

 if (*result < min || *result > max)
  err = -EOVERFLOW;

out:
 errno = -err;
 return err;
}

static int parse_bounded_uint(const char *buffer, size_t count, uintmax_t *result,
         int base, uintmax_t max)
{
 int err = 0;
 char *end;

 errno = 0;
 *result = strtoumax(buffer, &end, base);

 if (errno)
  return -errno;

 err = validate_int_parse(buffer, count, end);
 if (err)
  goto out;

 if (*result > max)
  err = -EOVERFLOW;

out:
 errno = -err;
 return err;
}

int parse_intmax(const char *buffer, size_t count, intmax_t *result, int base)
{
 return parse_bounded_int(buffer, count, result, base, INTMAX_MIN, INTMAX_MAX);
}

int parse_uintmax(const char *buffer, size_t count, uintmax_t *result, int base)
{
 return parse_bounded_uint(buffer, count, result, base, UINTMAX_MAX);
}

int parse_int(const char *buffer, size_t count, int *result, int base)
{
 intmax_t parsed;
 int err = parse_bounded_int(buffer, count, &parsed, base, INT_MIN, INT_MAX);

 *result = parsed;
 return err;
}

int parse_uint(const char *buffer, size_t count, unsigned int *result, int base)
{
 uintmax_t parsed;
 int err = parse_bounded_uint(buffer, count, &parsed, base, UINT_MAX);

 *result = parsed;
 return err;
}

int parse_long(const char *buffer, size_t count, long *result, int base)
{
 intmax_t parsed;
 int err = parse_bounded_int(buffer, count, &parsed, base, LONG_MIN, LONG_MAX);

 *result = parsed;
 return err;
}

int parse_ulong(const char *buffer, size_t count, unsigned long *result, int base)
{
 uintmax_t parsed;
 int err = parse_bounded_uint(buffer, count, &parsed, base, ULONG_MAX);

 *result = parsed;
 return err;
}

int read_long(const char *path, long *result, int base)
{
 int err;
 char buffer[32] = {0};

 err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
 if (err)
  return err;

 return parse_long(buffer, sizeof(buffer), result, base);
}

int read_ulong(const char *path, unsigned long *result, int base)
{
 int err;
 char buffer[32] = {0};

 err = read_file(path, buffer, sizeof(buffer) - 1, NULL);
 if (err)
  return err;

 return parse_ulong(buffer, sizeof(buffer), result, base);
}

int write_long(const char *path, long result, int base)
{
 int err;
 int len;
 char buffer[32];

 /* Decimal only for now: no format specifier for signed hex values */
 if (base != 10) {
  err = -EINVAL;
  goto out;
 }

 len = snprintf(buffer, sizeof(buffer), "%ld", result);
 if (len < 0 || len >= sizeof(buffer)) {
  err = -EOVERFLOW;
  goto out;
 }

 err = write_file(path, buffer, len);

out:
 errno = -err;
 return err;
}

int write_ulong(const char *path, unsigned long result, int base)
{
 int err;
 int len;
 char buffer[32];
 char *fmt;

 switch (base) {
 case 10:
  fmt = "%lu";
  break;
 case 16:
  fmt = "%lx";
  break;
 default:
  err = -EINVAL;
  goto out;
 }

 len = snprintf(buffer, sizeof(buffer), fmt, result);
 if (len < 0 || len >= sizeof(buffer)) {
  err = -errno;
  goto out;
 }

 err = write_file(path, buffer, len);

out:
 errno = -err;
 return err;
}

void *find_auxv_entry(int type, char *auxv)
{
 ElfW(auxv_t) *p;

 p = (ElfW(auxv_t) *)auxv;

 while (p->a_type != AT_NULL) {
  if (p->a_type == type)
   return p;

  p++;
 }

 return NULL;
}

void *get_auxv_entry(int type)
{
 ElfW(auxv_t) *p;

 if (read_auxv(auxv, sizeof(auxv)))
  return NULL;

 p = find_auxv_entry(type, auxv);
 if (p)
  return (void *)p->a_un.a_val;

 return NULL;
}

int pick_online_cpu(void)
{
 int ncpus, cpu = -1;
 cpu_set_t *mask;
 size_t size;

 ncpus = get_nprocs_conf();
 size = CPU_ALLOC_SIZE(ncpus);
 mask = CPU_ALLOC(ncpus);
 if (!mask) {
  perror("malloc");
  return -1;
 }

 CPU_ZERO_S(size, mask);

 if (sched_getaffinity(0, size, mask)) {
  perror("sched_getaffinity");
  goto done;
 }

 /* We prefer a primary thread, but skip 0 */
 for (cpu = 8; cpu < ncpus; cpu += 8)
  if (CPU_ISSET_S(cpu, size, mask))
   goto done;

 /* Search for anything, but in reverse */
 for (cpu = ncpus - 1; cpu >= 0; cpu--)
  if (CPU_ISSET_S(cpu, size, mask))
   goto done;

 printf("No cpus in affinity mask?!\n");

done:
 CPU_FREE(mask);
 return cpu;
}

int bind_to_cpu(int cpu)
{
 cpu_set_t mask;
 int err;

 if (cpu == BIND_CPU_ANY) {
  cpu = pick_online_cpu();
  if (cpu < 0)
   return cpu;
 }

 printf("Binding to cpu %d\n", cpu);

 CPU_ZERO(&mask);
 CPU_SET(cpu, &mask);

 err = sched_setaffinity(0, sizeof(mask), &mask);
 if (err)
  return err;

 return cpu;
}

bool is_ppc64le(void)
{
 struct utsname uts;
 int rc;

 errno = 0;
 rc = uname(&uts);
 if (rc) {
  perror("uname");
  return false;
 }

 return strcmp(uts.machine, "ppc64le") == 0;
}

int read_sysfs_file(char *fpath, char *result, size_t result_size)
{
 char path[PATH_MAX] = "/sys/";

 strncat(path, fpath, PATH_MAX - strlen(path) - 1);

 return read_file(path, result, result_size, NULL);
}

int read_debugfs_int(const char *debugfs_file, int *result)
{
 int err;
 char value[16] = {0};

 err = read_debugfs_file(debugfs_file, value, sizeof(value) - 1);
 if (err)
  return err;

 return parse_int(value, sizeof(value), result, 10);
}

int write_debugfs_int(const char *debugfs_file, int result)
{
 char value[16];

 snprintf(value, 16, "%d", result);

 return write_debugfs_file(debugfs_file, value, strlen(value));
}

static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
  int cpu, int group_fd, unsigned long flags)
{
 return syscall(__NR_perf_event_open, hw_event, pid, cpu,
        group_fd, flags);
}

static void perf_event_attr_init(struct perf_event_attr *event_attr,
     unsigned int type,
     unsigned long config)
{
 memset(event_attr, 0, sizeof(*event_attr));

 event_attr->type = type;
 event_attr->size = sizeof(struct perf_event_attr);
 event_attr->config = config;
 event_attr->read_format = PERF_FORMAT_GROUP;
 event_attr->disabled = 1;
 event_attr->exclude_kernel = 1;
 event_attr->exclude_hv = 1;
 event_attr->exclude_guest = 1;
}

int perf_event_open_counter(unsigned int type,
       unsigned long config, int group_fd)
{
 int fd;
 struct perf_event_attr event_attr;

 perf_event_attr_init(&event_attr, type, config);

 fd = perf_event_open(&event_attr, 0, -1, group_fd, 0);

 if (fd < 0)
  perror("perf_event_open() failed");

 return fd;
}

int perf_event_enable(int fd)
{
 if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) {
  perror("error while enabling perf events");
  return -1;
 }

 return 0;
}

int perf_event_disable(int fd)
{
 if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) {
  perror("error disabling perf events");
  return -1;
 }

 return 0;
}

int perf_event_reset(int fd)
{
 if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) {
  perror("error resetting perf events");
  return -1;
 }

 return 0;
}

int using_hash_mmu(bool *using_hash)
{
 char line[128];
 FILE *f;
 int rc;

 f = fopen("/proc/cpuinfo""r");
 FAIL_IF(!f);

 rc = 0;
 while (fgets(line, sizeof(line), f) != NULL) {
  if (!strcmp(line, "MMU : Hash\n") ||
      !strcmp(line, "platform : Cell\n") ||
      !strcmp(line, "platform : PowerMac\n")) {
   *using_hash = true;
   goto out;
  }

  if (strcmp(line, "MMU : Radix\n") == 0) {
   *using_hash = false;
   goto out;
  }
 }

 rc = -1;
out:
 fclose(f);
 return rc;
}

struct sigaction push_signal_handler(int sig, void (*fn)(int, siginfo_t *, void *))
{
 struct sigaction sa;
 struct sigaction old_handler;

 sa.sa_sigaction = fn;
 sigemptyset(&sa.sa_mask);
 sa.sa_flags = SA_SIGINFO;
 FAIL_IF_EXIT_MSG(sigaction(sig, &sa, &old_handler),
    "failed to push signal handler");

 return old_handler;
}

struct sigaction pop_signal_handler(int sig, struct sigaction old_handler)
{
 struct sigaction popped;

 FAIL_IF_EXIT_MSG(sigaction(sig, &old_handler, &popped),
    "failed to pop signal handler");

 return popped;
}

Messung V0.5
C=99 H=86 G=92

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge