[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: Not actually a network block device client yet.
From: Rob Landley <rob () landley ! net>
Date: 2010-08-31 5:54:39
Message-ID: 201008310054.40297.rob () landley ! net
[Download RAW message or body]
At the "It compiled, I wonder if it runs?" stage. Haven't got an NBD server
lying around to plug it into, but I thought I'd post it before going to bed.
(Not yet busyboxified, just sort of standalone. And still kind of ugly.)
FYI,
Rob
--
GPLv3: as worthy a successor as The Phantom Menace, as timely as Duke Nukem
Forever, and as welcome as New Coke.
["nbd-client.c" (text/x-csrc)]
/* nbd-client
Copyright 2010 Rob Landley <rob@landley.net> Licensed under GPLv2
Usage: nbd-client HOST PORT DEVICE
[-sSpn] [-b BLOCK_SIZE] [-t TIMEOUT] [-N name]
-s swap
-S sdp
-p persist
-n nofork
-d DEVICE
-c DEVICE
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#define NBD_SET_SOCK _IO(0xab, 0)
#define NBD_SET_BLKSIZE _IO(0xab, 1)
#define NBD_SET_SIZE _IO(0xab, 2)
#define NBD_DO_IT _IO(0xab, 3)
#define NBD_CLEAR_SOCK _IO(0xab, 4)
#define NBD_CLEAR_QUEUE _IO(0xab, 5)
#define NBD_PRINT_DEBUG _IO(0xab, 6)
#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7)
#define NBD_DISCONNECT _IO(0xab, 8)
#define NBD_SET_TIMEOUT _IO(0xab, 9)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#include <byteswap.h>
#define SWAP_BE32(x) __bswap_32(x)
#define SWAP_BE64(x) __bswap_64(x)
#else
#define SWAP_BE32(x) (x)
#define SWAP_BE64(x) (x)
#endif
int main(int argc, char *argv[])
{
int sock, nbd, flags;
unsigned long timeout = 0;
struct addrinfo *addr, *p;
char *host=argv[1], *port=argv[2], *device=argv[3];
uint64_t devsize;
char data[124];
// Parse command line stuff (just a stub now)
if (argc != 4) {
fprintf(stderr, "Usage: nbd-client HOST PORT DEVICE\n");
exit(1);
}
// Make sure the /dev/nbd exists.
if (0>(nbd = open(device, O_RDWR))) {
fprintf(stderr, "Can't open '%s'\n", device);
exit(1);
}
// Repeat until spanked
for (;;) {
int temp;
// Find and connect to server
if (getaddrinfo(host, port, NULL, &addr)) addr = 0;
for (p = addr; p; p = p->ai_next) {
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (-1 != connect(sock, p->ai_addr, p->ai_addrlen)) break;
}
freeaddrinfo(addr);
if (!p) {
fprintf(stderr, "Can't connect '%s' port '%s'\n", host, port);
exit(1);
}
temp = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &temp, sizeof(int));
// Log on to the server. (Todo: one big 8+8+8+4+124=152 read)
if (read(sock, data, 8) != 8 || memcmp(data, "NBDMAGIC", 8)
|| read(sock, &devsize, 8) != 8
|| SWAP_BE64(devsize) != 0x420281861253LL
|| read(sock, &devsize, 8) != 8 || read(sock, &flags, 4) != 4
|| read(sock, data, 124) != 124)
{
fprintf(stderr, "Login fail\n");
exit(1);
}
devsize = SWAP_BE64(devsize);
flags = SWAP_BE32(flags);
// Set 4k block size. Everything uses that these days.
ioctl(nbd, NBD_SET_BLKSIZE, 4096);
ioctl(nbd, NBD_SET_SIZE_BLOCKS, devsize/4096);
ioctl(nbd, NBD_CLEAR_SOCK);
// If the sucker was exported read only, respect that locally.
temp = (flags & 2) ? 1 : 0;
if (ioctl(nbd, BLKROSET, &temp)<1) {
fprintf(stderr, "Login fail\n");
exit(1);
}
if (timeout && ioctl(nbd, NBD_SET_TIMEOUT, timeout)<0) break;
if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) break;
// if (swap) mlockall(MCL_CURRENT|MCL_FUTURE);
// Open the device to force reread of the partition table.
if (!fork()) {
char *s = strrchr(device, '/');
sprintf(data, "/sys/block/%.32s/pid", s ? s+1 : device);
// Is it up yet?
for (;;) {
temp = open(data, O_RDONLY);
if (temp == -1) sleep(1);
else {
close(temp);
break;
}
}
close(open(device, O_RDONLY));
exit(0);
}
// Daemonize here.
// Process NBD requests until further notice.
if (ioctl(nbd, NBD_DO_IT)>=0 || errno==EBADR) break;
close(sock);
close(nbd);
}
// Flush queue and exit.
ioctl(nbd, NBD_CLEAR_QUEUE);
ioctl(nbd, NBD_CLEAR_SOCK);
exit(0);
}
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic