nbd_connect_command(3)

πŸ’… nbd_connect_command(3) β€” like, the libnbd manual, but make it make sense

okay so bestie, welcome to the LIBNBD corner of the man pages 🌸 this one's all about nbd_connect_command and honestly? it's kind of iconic. it forks a whole little subprocess and talks NBD to it over stdin/stdout. let's get into it 🫢


✨ NAME ✨

nbd_connect_command β€” connect to NBD server command πŸ’«


✨ SYNOPSIS ✨

#include <libnbd.h>

int nbd_connect_command (
      struct nbd_handle *h, char **argv
    );

✨ DESCRIPTION ✨

So the vibe is: you run the command as a subprocess and then connect to it over stdin/stdout. That's it, that's the whole thing πŸŽ€

This is specifically for NBD servers that can behave like inetd clients β€” think nbdkit(1) with the -s/--single flag, or nbd-server(1) with the port number set to 0. iykyk πŸ’…

🚨 not me forgetting to mention this: if you want to run qemu-nbd(1), use nbd_connect_systemd_socket_activation(3) instead. periodt.

🌈 Subprocess

libnbd will fork the argv command and hand the NBD socket over to it using file descriptors 0 and 1 (stdin/stdout). literally passing the aux cord 🎧

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚ program β”‚ libnbd  β”‚    β”‚   NBD server   β”‚
 β”‚         β”‚         β”‚    β”‚       (argv)   β”‚
 β”‚         β”‚ socket ╍╍╍╍╍╍╍╍▢ stdin/stdout β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

and when the NBD handle is closed? the server subprocess gets killed. no loose ends, she's thorough πŸ’€βœ¨


✨ RETURN VALUE ✨

If the call is successful the function returns 0. slay πŸ‘‘


✨ ERRORS ✨

On error -1 is returned 😭

Refer to "ERROR HANDLING" in libnbd(3) for how to get further details of the error.

Also, these parameters must not be NULL: h, argv. For more info check "Non-NULL parameters" in libnbd(3) β€” don't come for me, it's literally in the docs πŸ™ˆ


✨ NOTES ✨

πŸ¦‹ Blocking connect call

This call returns when the connection has been made. By default, this proceeds all the way to transmission phase, but nbd_set_opt_mode(3) can be used for manual control over option negotiation performed before transmission phase. main character energy tbqh ✨


✨ HANDLE STATE ✨

nbd_connect_command can be called when the handle is in the following state β€” vibe check time:

  • Handle created, before connecting β€” βœ… allowed
  • Connecting β€” ❌ error
  • Connecting & handshaking (opt_mode) β€” ❌ error
  • Connected to the server β€” ❌ error
  • Connection shut down β€” ❌ error
  • Handle dead β€” ❌ error

so basically: fresh handle only. she does not do second chances πŸ’…


✨ VERSION ✨

This function first appeared in libnbd 1.0 ⭐

If you need to test if this function is available at compile time check if the following macro is defined:

#define LIBNBD_HAVE_NBD_CONNECT_COMMAND 1

✨ EXAMPLE ✨

This example is also available as examples/connect-command.c in the libnbd source code. it's giving "full working demo" and we're obsessed πŸ“

/* This example shows how to run an NBD server
 * (nbdkit) as a subprocess of libnbd.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libnbd.h>

int
main (int argc, char *argv[])
{
  struct nbd_handle *nbd;
  char wbuf[512], rbuf[512];
  size_t i;

  /* Create the libnbd handle. */
  nbd = nbd_create ();
  if (nbd == NULL) {
    fprintf (stderr, "%s\n", nbd_get_error ());
    exit (EXIT_FAILURE);
  }

  /* Run nbdkit as a subprocess. */
  char *args[] = {
    "nbdkit",

    /* You must use β€˜-s’ (which tells nbdkit to serve
     * a single connection on stdin/stdout).
     */
    "-s",

    /* It is recommended to use β€˜--exit-with-parent’
     * to ensure nbdkit is always cleaned up even
     * if the main program crashes.
     */
    "--exit-with-parent",

    /* Use this to enable nbdkit debugging. */
    "-v",

    /* The nbdkit plugin name - this is a RAM disk. */
    "memory", "size=1M",

    /* Use NULL to terminate the arg list. */
    NULL
  };
  if (nbd_connect_command (nbd, args) == -1) {
    fprintf (stderr, "%s\n", nbd_get_error ());
    exit (EXIT_FAILURE);
  }

  /* Write some random data to the first sector. */
  for (i = 0; i < sizeof wbuf; ++i)
    wbuf[i] = i % 13;
  if (nbd_pwrite (nbd, wbuf, sizeof wbuf, 0, 0) == -1) {
    fprintf (stderr, "%s\n", nbd_get_error ());
    exit (EXIT_FAILURE);
  }

  /* Read the first sector back. */
  if (nbd_pread (nbd, rbuf, sizeof rbuf, 0, 0) == -1) {
    fprintf (stderr, "%s\n", nbd_get_error ());
    exit (EXIT_FAILURE);
  }

  /* Close the libnbd handle. */
  nbd_close (nbd);

  /* What was read must be exactly the same as what
   * was written.
   */
  if (memcmp (rbuf, wbuf, sizeof rbuf) != 0) {
    fprintf (stderr, "FAILED: "
             "read data did not match written data\n");
    exit (EXIT_FAILURE);
  }

  exit (EXIT_SUCCESS);
}

✨ SEE ALSO ✨

the whole friend group 🫢 go read these too:


✨ AUTHORS ✨

Eric Blake

Richard W.M. Jones

(legends, both of them πŸ‘‘πŸ‘‘)


Copyright Red Hat


✨ LICENSE ✨

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA


πŸ’œ and that's the whole page bestie, mwah πŸ’œ this little beauty is from libnbd-1.25.8 and dated 2026-10-13 β€” go forth and fork some subprocesses, you've got this πŸ§šβœ¨πŸŽ€

πŸ“¦ where this page comes from