METALINK_PARSE_UPDATE(3)

πŸ“¦ version 0.1.3, in epel 9, opensuse-leap 16.0

okay so welcome to the libmetalink manual, bestie β€” this is the page for METALINK_PARSE_UPDATE(3), and we're gonna make it make sense. 🫢


🌸 NAME 🌸

metalink_parse_update, metalink_parse_final, metalink_parser_context_new, metalink_parser_context_delete β€” parse a Metalink file and create a metalink_t object. literally the whole glow-up: feed it XML, get your object. ✨


✨ SYNOPSIS ✨

bestie, here's the include and the function signatures, copy-paste ready:

#include <metalink/metalink.h>

metalink_error_t metalink_parse_update(metalink_parser_context_t *ctx,
                                        const char *buf, size_t len);
metalink_error_t metalink_parse_final(metalink_parser_context_t *ctx,
                                        const char *buf, size_t len,
                                        metalink_t **res);

metalink_parser_context_t* metalink_parser_context_new();
void metalink_parser_context_delete(metalink_parser_context_t *ctx);

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so these functions are the push-interface girlies for parsing Metalink XML files. you feed the parser data as it comes, instead of handing it a whole file at once. 🫢

before you call metalink_parse_update() and metalink_parse_final(), a metalink_parse_context_t has to be created by metalink_parser_context_new().

every time you call metalink_parse_update(), len bytes of buf are processed. at the last piece of data, call metalink_parse_final() to get the metalink_t(3) structure as a result. giving 0 as len is permitted. no cap. πŸ’…

metalink_parse_final() calls metalink_parser_context_delete() internally to deallocate the memory for the passed metalink_parser_context_t. so you don't have to call metlaink_parser_context_delete() if you call metalink_parse_final(). otherwise, call metalink_parser_context_delete() to free the allocated resource.

bestie, if you're not calling metalink_parse_final(), you gotta call metalink_parser_context_delete() so the allocated resource doesn't just vibe in memory forever. πŸ’€

you don't have to allocate memory for the metalink_t(3) structure. metalink_parse_final() takes the pointer of the metalink_t(3) pointer and allocates memory for that pointer. main character energy fr. πŸ‘‘

the caller must free the memory allocated for the metalink_t(3) structure using metalink_delete(3) if it is no longer used. periodt.


πŸŽ€ RETURN VALUE πŸŽ€

metalink_parse_update() and metalink_parse_final() return 0 for success. when an error occurred, a non-zero value error code is returned. if an error occurred, metalink_parse_final() does not allocate memory for metalink_t. the error codes are described in metalink_error.h. πŸ’€

in case of success, metalink_parser_context_new() allocates memory for metalink_parser_context_t() and returns the pointer to it. in case of failure, metalink_parser_context_new() returns NULL.

metalink_parser_context_delete() returns no value. it's giving void. πŸ«₯


🌈 EXAMPLE 🌈

okay bestie, this is the full example. don't let the length scare you β€” it's iconic:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <metalink/metalink.h>

int main(int argc, char** argv)
{
  metalink_error_t r;
  metalink_t* metalink;
  metalink_file_t* file;
  metalink_checksum_t** checksums;
  metalink_parser_context_t* context;
  int fd;
  char buf[BUFSIZ];
  ssize_t length;

  context = metalink_parser_context_new();

  if(context == NULL) {
    fprintf(stderr,
            "ERROR: failed to create metalink_parser_context_t\n");
    exit(EXIT_FAILURE);
  }

  fd = open("sample.metalink", O_RDONLY);
  if(fd == -1) {
    fprintf(stderr, "ERROR: open():%s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }
  while((length = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)))) != 0){
    r = metalink_parse_update(context, buf, length);
    if(r != 0) {
      fprintf(stderr, "ERROR: code=%d\n", r);
      metalink_parser_context_delete(context);
      exit(EXIT_FAILURE);
    }
  }
  if(length == -1) {
    fprintf(stderr, "ERROR: read():%s\n", strerror(errno));
    metalink_parser_context_delete(context);
    exit(EXIT_FAILURE);
  }

  r = metalink_parse_final(context, NULL, 0, &metalink);

  if(r != 0) {
    fprintf(stderr, "ERROR: code=%d\n", r);
    exit(EXIT_FAILURE);
  }

  TEMP_FAILURE_RETRY(close(fd));

  file = metalink->files[0];
  printf("name: %s\n", file->name);
  printf("size: %lld\n", file->size);
  printf("os  : %s\n", file->os);

  if(file->checksums) {
    checksums = file->checksums;
    while(*checksums) {
      printf("hash: %s %s\n", (*checksums)->type, (*checksums)->hash);
      ++checksums;
    }
  }
  if(file->chunk_checksum) {
    size_t count = 0;
    metalink_piece_hash_t** piece_hashes;
    printf("chunk checksum: size=%d, type=%s\n",
           file->chunk_checksum->length,
           file->chunk_checksum->type);
    printf("first 5 piece hashes...\n");
    piece_hashes = file->chunk_checksum->piece_hashes;
    while(*piece_hashes && count < 5) {
      printf("piece=%d, hash=%s\n", (*piece_hashes)->piece,
                                     (*piece_hashes)->hash);
      ++piece_hashes;
      ++count;
    }
    printf("...\n");
  }
  if(file->resources) {
    size_t count = 0;
    metalink_resource_t** resources;
    printf("first 5 resources...\n");
    resources = file->resources;
    while(*resources && count < 5) {
      printf("type=%s, location=%s, preference=%d, url=%s\n",
             (*resources)->type, (*resources)->location,
             (*resources)->preference, (*resources)->url);
      ++resources;
      ++count;
    }
    printf("...\n");
  }

  /* delete metalink_t */
  metalink_delete(metalink);

  return EXIT_SUCCESS;
}

see? iconic. now go delete your metalink_t with metalink_delete(metalink);. slay. πŸ’–


πŸ‘‘ SEE ALSO πŸ‘‘


mwah πŸ’‹ β€” this page is from libmetalink 0.1.0, dated July 2012, and it's the METALINK_PARSE_UPDATE(3) manual. you ate, bestie. πŸŽ€πŸ’œ