コード例 #1
0
ファイル: fba2dump.c プロジェクト: hreinecke/s390-tools
/*
 * Dump all memory to DASD partition
 */
void dt_dump_mem(void)
{
    unsigned long blk, addr, page;

    ccw_program_init();
    blk = device.blk_start;
    page = get_zeroed_page();

    /* Write dump header */
    writeblock(blk, __pa(dump_hdr), m2b(DF_S390_HDR_SIZE), 0);
    blk += DF_S390_HDR_SIZE / BLK_SIZE;

    /* Write memory */
    for (addr = 0; addr < dump_hdr->mem_size; addr += b2m(BLK_PWRT)) {
        writeblock(blk, addr, BLK_PWRT, page);
        progress_print(addr);
        blk += BLK_PWRT;
    }
    progress_print(addr);

    /* Write end marker */
    df_s390_em_page_init(page);
    writeblock(blk, page, 1, 0);
    free_page(page);
}
コード例 #2
0
ファイル: vmclient.c プロジェクト: sugar84/voiceman_client
vm_result_t vm_text(vm_connection_t con, char* text)
{
  unsigned long k, i;
  char* t;
  assert(con != VOICEMAN_BAD_CONNECTION);
  if (con == VOICEMAN_BAD_CONNECTION)
    return VOICEMAN_ERROR;
  assert(text);
  if (!text)
    return VOICEMAN_ERROR;
  k = strlen(text);
  if (k == 0)
    return VOICEMAN_OK;
  t = (char*)malloc(k + 1);
  if (t == NULL)
    return VOICEMAN_ERROR;
  strcpy(t, text);
  for(i = 0;i < k;i++)/*all \n must be replaced with spaces;*/
    if (t[i] == '\n')
      t[i] = ' ';
  if (writeblock(con, "T:", 2) == -1)
    {
      free(t);
      return VOICEMAN_ERROR;
    }
  if (writebuf(con, t, k) == -1)
    {
      free(t);
      return VOICEMAN_ERROR;
    }
  free(t);
  if (writeblock(con, "\n", 1) == -1)
    return VOICEMAN_ERROR;
  return VOICEMAN_OK;
}
コード例 #3
0
ファイル: send_recv.c プロジェクト: schambersnh/school
/* writes a fixed-size header followed by variable length data
 *
 * fills in header with values from type, length and info
 * writes length bytes of variable length data from user_data
 *
 * returns 0 if all ok, else -1 on any error
 */
int
our_send_message(int fd, enum message_types type, unsigned int length, void *user_data)
{
	struct our_header header;
	
	/* print error to stderr if its an error message */
	if(type == ERROR_LINE)
		fprintf(stderr, "%s", (char*)user_data);


	header.message_type = htonl(type);
	header.var_length = htonl(length);

	/* write fixed-size header */
	if (writeblock(fd, &header, sizeof(header)) != sizeof(header)) {
		return -1;
	}

	if (length > 0 ) {
		if (writeblock(fd, user_data, length) != (signed)length) {
			return -1;
		}
	}
	return 0;
}	/* our_send_message */
コード例 #4
0
ファイル: tcpserver.c プロジェクト: chenxiaoyang1/SBPFS
int main(void) {
	int listenfd, connectfd, newfd;
	pthread_t thread; //id of thread
	struct sockaddr_in server; //server's address info
	struct sockaddr_in client; //client's
	int sin_size;

	writeblock(3263, 3, 3, "abc");
		writeblock(3363, 3, 4, "abcd");
		writeblock(3463, 3, 3, "abc");
		readblock(3263, 3, 3);
		readblock(3363, 3, 4);


	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("creating socket failed.");
		exit(1);
	}

	int opt = SO_REUSEADDR;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	bzero(&server, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(PORT);
	server.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(listenfd, (struct sockaddr *) &server, sizeof(struct sockaddr))
			== -1) {
		perror("bind error.\n");
		exit(1);
	}
	if (listen(listenfd, BACKLOG) == -1) {
		perror("listen() error \n");
		exit(1);
	}
	char* ip = "127.0.0.1";
	reportlist(ip, PORT);
	sin_size = sizeof(struct sockaddr_in);
	while (1) {
		if ((connectfd = accept(listenfd, (struct sockaddr *) &client,
				(socklen_t*) &sin_size)) == -1) {
			printf("accept() error \n");
		}
		newfd = connectfd;

		if (pthread_create(&thread, NULL, sbp_recv, &newfd) != 0) {
			printf("error: can't create more thread!\n");
		}
	}
	return 0;
}
コード例 #5
0
ファイル: bin2z80.c プロジェクト: 8l/FUZIX
static void write_z80(char *name)
{
	int fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644);
	if (fd == -1) {
		perror(name);
		exit(1);
	}
	header[8] = 0xF0;		/* set SP somewhere */
	header[9] = 0xFF;
	
	header[29] = 0x40 | 1;		/* IM1, Kempston joystick */
	header[30] = 54;
	header[32] = 0x03;		/* Run from C003 */
	header[33] = 0xC0;
	header[34] = 5;			/* 128K with Interface 1 */
	header[37] = 3;			/* Emulate LDIR and R details */
	header[61] = 0xFF;		/* low memory is ROM */
	header[62] = 0xFF;
	write(fd, header, 86);		/* Header */

	writeblock(fd, 0, bank0);
	writeblock(fd, 1, bank1);
	writeblock(fd, 2, bank5);
	writeblock(fd, 3, emptybank);
	writeblock(fd, 4, emptybank);
	writeblock(fd, 5, bank2);
	writeblock(fd, 6, emptybank);
	writeblock(fd, 7, bank7);
	close(fd);
}
コード例 #6
0
/** write_error_line
 * Sends an ERROR_LINE message to a client
 * 
 * Parameters:
 *     char *output - the string that shoud be sent in the ERROR_LINE message 
 *     struct Globals *gl - the "global" variables for this search
 */
void
write_error_line(char *output, struct Globals *gl){
	unsigned int *optionsmsg;
	
	optionsmsg = calloc(sizeof(int), 1);
	*optionsmsg = htonl((unsigned int)ERROR_LINE);
	writeblock(gl->fd, optionsmsg, 4);
	
	*optionsmsg = htonl((unsigned int)(strlen(output) + 1));
	writeblock(gl->fd, optionsmsg, 4);
	
	writeblock(gl->fd, output, (strlen(output) + 1));
	/*write_error_line*/
}
コード例 #7
0
ファイル: blockimg.c プロジェクト: 10114395/android-5.0.0_r5
static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) {
    RangeSinkState* rss = (RangeSinkState*) token;

    if (rss->p_remain <= 0) {
        fprintf(stderr, "range sink write overrun");
        exit(1);
    }

    ssize_t written = 0;
    while (size > 0) {
        size_t write_now = size;
        if (rss->p_remain < write_now) write_now = rss->p_remain;
        writeblock(rss->fd, data, write_now);
        data += write_now;
        size -= write_now;

        rss->p_remain -= write_now;
        written += write_now;

        if (rss->p_remain == 0) {
            // move to the next block
            ++rss->p_block;
            if (rss->p_block < rss->tgt->count) {
                rss->p_remain = (rss->tgt->pos[rss->p_block*2+1] - rss->tgt->pos[rss->p_block*2]) * BLOCKSIZE;
                check_lseek(rss->fd, (off64_t)rss->tgt->pos[rss->p_block*2] * BLOCKSIZE, SEEK_SET);
            } else {
                // we can't write any more; return how many bytes have
                // been written so far.
                return written;
            }
        }
    }

    return written;
}
コード例 #8
0
ファイル: vmclient.c プロジェクト: sugar84/voiceman_client
vm_result_t vm_letter(vm_connection_t con, char* letter)
{
  assert(con != VOICEMAN_BAD_CONNECTION);
  if (con == VOICEMAN_BAD_CONNECTION)
    return VOICEMAN_ERROR;
  assert(letter);
  if (!letter)
    return VOICEMAN_ERROR;
  if (writeblock(con, "L:", 2) == -1)
    return VOICEMAN_ERROR;
  if (writebuf(con, letter, strlen(letter)) == -1)
    return VOICEMAN_ERROR;
  if (writeblock(con, "\n", 1) == -1)
    return VOICEMAN_ERROR;
  return VOICEMAN_OK;
}
コード例 #9
0
ファイル: tcpserver.c プロジェクト: chenxiaoyang1/SBPFS
int ana_head(struct sbpfs_head* head, char* data) {
	char* ip;
	int port;
	char* headmethod;
	char* blocknumc;
	char* offsetc;
	char* lengthc;
	blocknumc = get_head_entry_value(head, "Arg0");
	offsetc = get_head_entry_value(head, "Arg1");
	lengthc = get_head_entry_value(head, "Arg2");
	u64_t blocknum = atoll(blocknumc);
	req_len = atoll(lengthc);
	u64_t req_offset = atoll(offsetc);
	if ((headmethod = get_head_entry_value(head, "method")) == NULL) {
		perror("fail to ananlyse! \n");
		return -1;
	} else if (strcmp(headmethod, "READ") == 0) {
		int succeed=readblock(blocknum, req_offset, req_len);
		sbphead = read_head(databuf, req_len,succeed);
		build_headr(&send_buf, &sbphead);
	} else if (strcmp(headmethod, "WRITE") == 0) {
		int succeed = writeblock(blocknum, req_offset, req_len, data);
		sbphead = write_head(databuf, req_len,succeed);
		build_headw(&send_buf, &sbphead);
		reportwrite(ip, blocknum, port, succeed);
	}
	return 0;
}
コード例 #10
0
ファイル: vmclient.c プロジェクト: sugar84/voiceman_client
vm_result_t vm_stop(vm_connection_t con)
{
  assert(con != VOICEMAN_BAD_CONNECTION);
  if (con == VOICEMAN_BAD_CONNECTION)
    return VOICEMAN_ERROR;
  if (writeblock(con, "S:\n", 3) == -1)
    return VOICEMAN_ERROR;
  return VOICEMAN_OK;
}
コード例 #11
0
ファイル: file_system.c プロジェクト: pscherer413/file_system
void write_super_block(disk_t disk){
	printf("Writing super block...");
	unsigned char *databuf = calloc(disk->block_size,sizeof(char) );
	//Info 0-3:SIZE 4:RDIR 5:FBM 6:DATA
	emplace_buf(databuf,disk->size,4,0);
	databuf[4] = ROOTBLOCK;
	databuf[5] = FREEBLOCK;
	databuf[6] = ceil(disk->size/disk->block_size)+1+FREEBLOCK;
	writeblock(disk,SUPERBLOCK,databuf);
	free(databuf);
	printf("\n");
}
コード例 #12
0
ファイル: vmclient.c プロジェクト: sugar84/voiceman_client
/*Writes buffer of any length producing subsequent calls to write fixed length blocks*/
static long writebuf(int fd, void* buf, unsigned long bufSize)
{
  char* b = (char*)buf;
  unsigned long c = 0;
  assert(buf);
  while(c < bufSize)
    {
      unsigned long requiredSize = bufSize > c + IO_BUF_SIZE?IO_BUF_SIZE:(unsigned long)(bufSize - c);
      unsigned long res = writeblock(fd, &b[c], requiredSize);
      if (res == -1)
	return -1;
      assert(res == (long)requiredSize);
      c += (unsigned long)res;
    } /*while();*/
  assert(c == bufSize);
  return (long)c;
}
コード例 #13
0
ファイル: cachetest.c プロジェクト: MohanDhar/cos318
/* read/write 100 blocks, randomly distributed */
void tester(int n)
{
    int i, blocknum;
    char block[BLOCKSIZE];

    for (i = 0; i < NTESTS; i++) {
        blocknum = randomblock();
        if (rand() % 2) {	/* if odd, simulate a write */
            *(int *)block = n * NBLOCKS + blocknum;
            writeblock(block, blocknum); /* write the new value */
            printf("Wrote block %2d in thread %d: %3d\n", blocknum, n, *(int *)block);
        }
        else {		/* if even, simulate a read */
            readblock(block, blocknum);
            printf("Read  block %2d in thread %d: %3d\n", blocknum, n, *(int *)block);
        }
    }
    sthread_exit(100 + n);
    // Not reached
}
コード例 #14
0
ファイル: file_system.c プロジェクト: pscherer413/file_system
void write_block_map(disk_t disk, int * bmap){
	//printf("Writing free block map...");
	//printf("\n");
	int i;
	char *disk_name;
	unsigned char *databuf;
	/* disk with n blocks requires a bitmap with n bits
	bitmap size is enough blocks to hold n bits, starts at block 2 */
	int *bitmap;


	databuf = calloc(disk->block_size,sizeof(char) );


	/*Initially every entry in bitmap is 0(unsused) 
	Chase: This is not true: the superblock, rootdir and bitmap blocks should all be filled with 1s. 
	To make this function work in more than one case it should just write the bmap given, 
	and the user can fill it with 0s and 1s to start*/
	//i = block number
	int bitmapindex = 0;
	for(i = 2; bitmapindex < disk->size;i+=1){
		int bufindex = 0;
		while(bufindex < disk->block_size && bitmapindex < disk->size){
			databuf[bufindex] = (bmap[bitmapindex] == 0)? '0' : '1';
			bufindex +=1;
			bitmapindex +=1;
		}
		if(bitmapindex == disk->size && bufindex < disk->block_size){
			databuf[bufindex] = '\0'; //terminate
			//printf("terminated\n");
		}
		//printf("wrote blockmap %s to %d\n",databuf,bitmapindex);
		writeblock(disk,i,databuf);
	}

	free(databuf);


}
コード例 #15
0
ファイル: output.c プロジェクト: daemqn/Atari_ST_Sources
int writeoutput(short hand,char *ps,short vof,short coll)
{
short lcount=0,offset=0,chof=0,cellw,dolen,junk2,ochof=0;
char *dp;
vst_font(ws.handle,(WORD)winfont);
vst_point(ws.handle,(WORD)winpoint,&junk2,&junk2,&junk2,&junk2);
dp=ps;
dolen=(short)strlen(dp);
while(offset<dolen){
flag=FALSE;
if(*(dp+lcount)==2){
if(lcount)ochof=ochof+writeblock(dp,lcount-1,ochof,vof,coll,hand);
ochof=ochof+chof;chof=0;cellw=0;
dp=dp+lcount+1;lcount=-1;flag=TRUE;
if(bold==1){bold=0;}else{bold=1;}
}
if(*(dp+lcount)==3 && !flag){
if(lcount)ochof=ochof+writeblock(dp,lcount-1,ochof,vof,coll,hand);
dp=dp+lcount+1;lcount=-1;flag=TRUE;
if(red==1){red=0;}else{red=1;}
}
if(*(dp+lcount)==15 && !flag){
if(lcount)ochof=ochof+writeblock(dp,lcount-1,ochof,vof,coll,hand);
dp=dp+lcount+1;lcount=-1;flag=TRUE;
if(reset==1){reset=0;}else{reset=1;}
}
if(*(dp+lcount)==22 && !flag){
if(lcount)ochof=ochof+writeblock(dp,lcount-1,ochof,vof,coll,hand);
dp=dp+lcount+1;lcount=-1;flag=TRUE;
if(reversed==1){reversed=0;}else{reversed=1;}
}
if(*(dp+lcount)==31 && !flag){
if(lcount)ochof=ochof+writeblock(dp,lcount-1,ochof,vof,coll,hand);
dp=dp+lcount+1;lcount=-1;flag=TRUE;
if(underlined==1){underlined=0;}else{underlined=1;}
}
offset++;
lcount++;
}
if(lcount)ochof=ochof+writeblock(dp,lcount-1,ochof,vof,coll,hand);
return 0;
}
コード例 #16
0
ファイル: setup.c プロジェクト: diegonc/console-xkb-support
/* Get ready to run on device with pathname DEV. */
int
setup (char *dev)
{
  struct stat st;
  int changedsb;
  size_t bmapsize;

  device_name = dev;

  if (stat (dev, &st) == -1)
    {
      error (0, errno, "%s", dev);
      return 0;
    }
  if (!S_ISCHR (st.st_mode) && !S_ISBLK (st.st_mode))
    {
      problem (1, "%s is not a character or block device", dev);
      if (! reply ("CONTINUE"))
	return 0;
    }
  if (preen == 0)
    printf ("** %s", dev);
  if (!nowrite)
    readfd = open (dev, O_RDWR);
  if (nowrite || readfd == -1)
    {
      readfd = open (dev, O_RDONLY);
      if (readfd == -1)
	{
	  error (0, errno, "%s", dev);
	  return 0;
	}
      writefd = -1;
      nowrite = 1;
      if (preen)
	warning (1, "NO WRITE ACCESS");
      printf (" (NO WRITE)");
    }
  else
    writefd = readfd;

  if (preen == 0)
    printf ("\n");

  lfdir = 0;

  /* We don't do the alternate superblock stuff here (yet). */
  readblock (SBLOCK, sblock, SBSIZE);
  changedsb = 0;

  if (sblock->fs_magic != FS_MAGIC)
    {
      warning (1, "BAD MAGIC NUMBER");
      return 0;
    }
  if (sblock->fs_ncg < 1)
    {
      warning (1, "NCG OUT OF RANGE");
      return 0;
    }
  if (sblock->fs_cpg < 1)
    {
      warning (1, "CPG OUT OF RANGE");
      return 0;
    }
  if (sblock->fs_ncg * sblock->fs_cpg < sblock->fs_ncyl
      || (sblock->fs_ncg - 1) * sblock->fs_cpg >= sblock->fs_ncyl)
    {
      warning (1, "NCYL INCONSISTENT WITH NCG AND CPG");
      return 0;
    }
  if (sblock->fs_sbsize > SBSIZE)
    {
      warning (1, "SBLOCK SIZE PREPONTEROUSLY LARGE");
      return 0;
    }
  if (sblock->fs_optim != FS_OPTTIME && sblock->fs_optim != FS_OPTSPACE)
    {
      problem (1, "UNDEFINED OPTIMIZATION IN SUPERBLOCK");
      if (reply ("SET TO DEFAULT"))
	{
	  sblock->fs_optim = FS_OPTTIME;
	  changedsb = 1;
	}
    }
  if (sblock->fs_minfree < 0 || sblock->fs_minfree > 99)
    {
      problem (0, "IMPOSSIBLE MINFREE=%ld IN SUPERBLOCK", sblock->fs_minfree);
      if (preen || reply ("SET TO DEFAULT"))
	{
	  sblock->fs_minfree = 10;
	  changedsb = 1;
	  pfix ("SET TO DEFAULT");
	}
    }
  if (sblock->fs_interleave < 1
      || sblock->fs_interleave > sblock->fs_nsect)
    {
      problem (0, "IMPOSSIBLE INTERLEAVE=%ld IN SUPERBLOCK",
	       sblock->fs_interleave);
      if (preen || reply ("SET TO DEFAULT"))
	{
	  sblock->fs_interleave = 1;
	  changedsb = 1;
	  pfix ("SET TO DEFAULT");
	}
    }
  if (sblock->fs_npsect < sblock->fs_nsect
      || sblock->fs_npsect > sblock->fs_nsect * 2)
    {
      problem (0, "IMPOSSIBLE NPSECT=%ld IN SUPERBLOCK", sblock->fs_npsect);
      if (preen || reply ("SET TO DEFAULT"))
	{
	  sblock->fs_npsect = sblock->fs_nsect;
	  changedsb = 1;
	  pfix ("SET TO DEFAULT");
	}
    }
  if (sblock->fs_inodefmt >= FS_44INODEFMT)
    newinofmt = 1;
  else
    {
      sblock->fs_qbmask = ~sblock->fs_bmask;
      sblock->fs_qfmask = ~sblock->fs_fmask;
      newinofmt = 0;
    }

  if (changedsb)
    writeblock (SBLOCK, sblock, SBSIZE);

  /* Constants */
  maxfsblock = sblock->fs_size;
  maxino = sblock->fs_ncg * sblock->fs_ipg;
  direct_symlink_extension = sblock->fs_maxsymlinklen > 0;

  /* Allocate and initialize maps */
  bmapsize = roundup (howmany (maxfsblock, NBBY), sizeof (short));
  blockmap = calloc (bmapsize, sizeof (char));
  inodestate = calloc (maxino + 1, sizeof (char));
  typemap = calloc (maxino + 1, sizeof (char));
  linkcount = calloc (maxino + 1, sizeof (nlink_t));
  linkfound = calloc (maxino + 1, sizeof (nlink_t));
  return 1;
}
コード例 #17
0
ファイル: wsmanage.c プロジェクト: m-lohmann/qnial
void
wsdump(FILE * f1)
{
  nialptr     startaddr,
              addr,
              highest,
              next;
  nialint     cnt;

#ifdef DEBUG
  if (!continueflag)         /* don't memchk if storing continue */
    memchk();
#endif

#ifdef CALLDLL
  /* This will clear all is_loaded flags for DLL , so that when this
     workspace is loaded later, the DLL will be reloaded */
  DLLclearflags();
#endif

  /* find the address of the highest free block */
  highest = freelisthdr,
  next = freelisthdr;
  while (next != TERMINATOR) {
    if (next > highest)
      highest = next;
    next = fwdlink(next);
  }

  /* store global giving workspace size */
  if (highest + blksize(highest) == memsize)
    wssize = highest;
  else
    wssize = memsize;        /* there is a used block at the end */

  /* set a version stamp for the workspace */

#ifdef DEBUG
  strcpy(wsstamp, systemname);
  strcat(wsstamp, nialversion);
  strcat(wsstamp, " (debug)");
#else
  strcpy(wsstamp, systemname);
  strcat(wsstamp, nialversion);
#endif

  /* write out global structure */
  testerr(writeblock(f1, (char *) &G, (long) sizeof G, false, 0L, 0));


  /* loop to write out allocated blocks */
  addr = membase;
  startaddr = addr;
  cnt = 0;
  while (addr < memsize) {
    if (allocated(addr)) {
      cnt += blksize(addr);
      addr += blksize(addr);
    }
    else {                   /* write out the block */
#ifdef DEBUG
      if (cnt == 0) {
        nprintf(OF_DEBUG, "second empty block in a row found in wsdump\n");
        showfl();
        nabort(NC_ABORT_F);
      }
#endif
/* nprintf(OF_DEBUG,"writing block startaddr %d cnt %d \n",startaddr,cnt); */

      testerr(writeblock(f1, (char *) &cnt, (long) sizeof cnt, false, 0L, 0));
      testerr(writeblock(f1, (char *) &startaddr, (long) sizeof addr, false, 0L, 0));
      testerr(writeblock(f1, (char *) &mem[startaddr], (long) bytespu * cnt, false, 0L, 0));

      /* prepare for next block after free space */

/* nprintf(OF_DEBUG,"skipping free block addr %d blksize %d\n",addr,blksize(addr)); */

      addr = addr + blksize(addr);
      startaddr = addr;
      cnt = 0;
    }
  }

  if (startaddr != memsize) 
  {/* there is a last block to write out */

    /* nprintf(OF_DEBUG,"writing last block startaddr %d cnt %d \n",startaddr,cnt); */

    testerr(writeblock(f1, (char *) &cnt, (long) sizeof cnt, false, 0L, 0));
    testerr(writeblock(f1, (char *) &startaddr, (long) sizeof addr, false, 0L, 0));
    testerr(writeblock(f1, (char *) &mem[startaddr], (long) bytespu * cnt, false, 0L, 0));
  }

  /* write final cnt == 0 to signal end of workspace */
  cnt = 0;
  testerr(writeblock(f1, (char *) &cnt, (long) sizeof cnt, false, 0L, 0));
  closefile(f1);
  return;

fail:  /* the testerr and testrderr macros branch here on an error */

  nprintf(OF_NORMAL_LOG, errmsgptr);
  nprintf(OF_NORMAL_LOG, "workspace failed to write correctly\n");
  closefile(f1);
  exit_cover(NC_WS_WRITE_ERR_W);
}
コード例 #18
0
ファイル: d_node.c プロジェクト: gtxx3600/SBPFS
void process_req(struct list_entry * ent) {
	char* head_data;
	int head_data_len;
	struct sbpfs_head head;
	if (ent->req == 1) {
		char* data = (char*) malloc(ent->length);
		if (data == NULL) {
			printf("malloc data failed\n");
			return;
		}
		int succeed = readblock(ent->block_num, ent->offset, ent->length, data);
		printf("succeed: %d\n", succeed);
		if (succeed < 0)
			send_err(ent->skt, "read_block", "cannot read block");
		else {
			head.data = NULL;
			head.title = REQUEST_OK;
			head.entry_num = 0;
			char data_length_s[32];
			sprintf(data_length_s, "%d", ent->length);
			mkent(head,CONTENT_LEN,data_length_s);
			if (make_head(&head_data, &head_data_len, &head) == -1) {
				printf("mkhead failed\n");
				free(head_data);
				free(data);
				return;
			}
			if (sbp_send(ent->skt, head_data, head_data_len) < 0) {
				printf("send head err failed\n");
				sbp_perror("a");
				perror("a");
				free(data);
				free(head_data);
				return;
			}
			if (sbp_send(ent->skt, data, ent->length) < 0) {
				printf("send data err failed\n");
				sbp_perror("a");
				perror("a");
				free(data);
				free(head_data);

				return;
			}
			free(data);
			free(head_data);
			return;
		}
	}
	if (ent->req == 2) {
		int succeed = writeblock(ent->block_num, ent->offset, ent->length,
				ent->data);
		printf("succeed in write : %d\n", succeed);
		if (succeed < 0) {
			send_err(ent->skt, "write_block", "cannot write block");
		} else {
			head.data = NULL;
			head.title = REQUEST_OK;
			head.entry_num = 0;
			mkent(head,CONTENT_LEN,"0");
		}
		if (make_head(&head_data, &head_data_len, &head) == -1) {
			printf("mkhead failed\n");
			free(head_data);
			return;
		}
		if (sbp_send(ent->skt, head_data, head_data_len) < 0) {
			printf("send head err failed\n");
			sbp_perror("a");
			perror("a");
			free(head_data);
			return;
		}
		char*ip = "59.78.15.46";
		//send_success(ip,ent->block_num);
	}
	if (ent->req == 3) {
		int succeed = writeblock(ent->block_num, ent->offset, ent->length,
				ent->data);
		printf("succeed in copy : %d\n", succeed);

	}
}
コード例 #19
0
static void extern_rec(value v)
{
 tailcall:
  if (Is_long(v)) {
    intnat n = Long_val(v);
    if (n >= 0 && n < 0x40) {
      Write(PREFIX_SMALL_INT + n);
    } else if (n >= -(1 << 7) && n < (1 << 7)) {
      writecode8(CODE_INT8, n);
    } else if (n >= -(1 << 15) && n < (1 << 15)) {
      writecode16(CODE_INT16, n);
#ifdef ARCH_SIXTYFOUR
    } else if (n < -((intnat)1 << 31) || n >= ((intnat)1 << 31)) {
      writecode64(CODE_INT64, n);
#endif
    } else
      writecode32(CODE_INT32, n);
    return;
  }
  if (Is_in_value_area(v)) {
    header_t hd = Hd_val(v);
    tag_t tag = Tag_hd(hd);
    mlsize_t sz = Wosize_hd(hd);

    if (tag == Forward_tag) {
      value f = Forward_val (v);
      if (Is_block (f)
          && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag
              || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag)){
        /* Do not short-circuit the pointer. */
      }else{
        v = f;
        goto tailcall;
      }
    }
    /* Atoms are treated specially for two reasons: they are not allocated
       in the externed block, and they are automatically shared. */
    if (sz == 0) {
      if (tag < 16) {
        Write(PREFIX_SMALL_BLOCK + tag);
      } else {
        writecode32(CODE_BLOCK32, hd);
      }
      return;
    }
    /* Check if already seen */
    if (Color_hd(hd) == Caml_blue) {
      uintnat d = obj_counter - (uintnat) Field(v, 0);
      if (d < 0x100) {
        writecode8(CODE_SHARED8, d);
      } else if (d < 0x10000) {
        writecode16(CODE_SHARED16, d);
      } else {
        writecode32(CODE_SHARED32, d);
      }
      return;
    }

    /* Output the contents of the object */
    switch(tag) {
    case String_tag: {
      mlsize_t len = caml_string_length(v);
      if (len < 0x20) {
        Write(PREFIX_SMALL_STRING + len);
      } else if (len < 0x100) {
        writecode8(CODE_STRING8, len);
      } else {
        writecode32(CODE_STRING32, len);
      }
      writeblock(String_val(v), len);
      size_32 += 1 + (len + 4) / 4;
      size_64 += 1 + (len + 8) / 8;
      extern_record_location(v);
      break;
    }
    case Double_tag: {
      if (sizeof(double) != 8)
        extern_invalid_argument("output_value: non-standard floats");
      Write(CODE_DOUBLE_NATIVE);
      writeblock_float8((double *) v, 1);
      size_32 += 1 + 2;
      size_64 += 1 + 1;
      extern_record_location(v);
      break;
    }
    case Double_array_tag: {
      mlsize_t nfloats;
      if (sizeof(double) != 8)
        extern_invalid_argument("output_value: non-standard floats");
      nfloats = Wosize_val(v) / Double_wosize;
      if (nfloats < 0x100) {
        writecode8(CODE_DOUBLE_ARRAY8_NATIVE, nfloats);
      } else {
        writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats);
      }
      writeblock_float8((double *) v, nfloats);
      size_32 += 1 + nfloats * 2;
      size_64 += 1 + nfloats;
      extern_record_location(v);
      break;
    }
    case Abstract_tag:
      extern_invalid_argument("output_value: abstract value (Abstract)");
      break;
    case Infix_tag:
      writecode32(CODE_INFIXPOINTER, Infix_offset_hd(hd));
      extern_rec(v - Infix_offset_hd(hd));
      break;
    case Custom_tag: {
      uintnat sz_32, sz_64;
      char * ident = Custom_ops_val(v)->identifier;
      void (*serialize)(value v, uintnat * wsize_32,
                        uintnat * wsize_64)
        = Custom_ops_val(v)->serialize;
      if (serialize == NULL)
        extern_invalid_argument("output_value: abstract value (Custom)");
      Write(CODE_CUSTOM);
      writeblock(ident, strlen(ident) + 1);
      Custom_ops_val(v)->serialize(v, &sz_32, &sz_64);
      size_32 += 2 + ((sz_32 + 3) >> 2);  /* header + ops + data */
      size_64 += 2 + ((sz_64 + 7) >> 3);
      extern_record_location(v);
      break;
    }
    default: {
      value field0;
      mlsize_t i;
      if (tag < 16 && sz < 8) {
        Write(PREFIX_SMALL_BLOCK + tag + (sz << 4));
#ifdef ARCH_SIXTYFOUR
      } else if (hd >= ((uintnat)1 << 32)) {
        writecode64(CODE_BLOCK64, Whitehd_hd (hd));
#endif
      } else {
        writecode32(CODE_BLOCK32, Whitehd_hd (hd));
      }
      size_32 += 1 + sz;
      size_64 += 1 + sz;
      field0 = Field(v, 0);
      extern_record_location(v);
      if (sz == 1) {
        v = field0;
      } else {
        extern_rec(field0);
        for (i = 1; i < sz - 1; i++) extern_rec(Field(v, i));
        v = Field(v, i);
      }
      goto tailcall;
    }
    }
  }
  else if ((char *) v >= caml_code_area_start &&
コード例 #20
0
ファイル: dosfns.c プロジェクト: krinkleneck/ForthDOS
UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err)
{
  sft FAR *s;
  WORD sys_idx;
  sfttbl FAR *sp;
  UCOUNT ReadCount;

  /* Test that the handle is valid                */
  if (hndl < 0)
  {
    *err = DE_INVLDHNDL;
    return 0;
  }

  /* Get the SFT block that contains the SFT      */
  if ((s = get_sft(hndl)) == (sft FAR *) - 1)
  {
    *err = DE_INVLDHNDL;
    return 0;
  }

  /* If this is not opened and it's not a write   */
  /* another error                                */
  if (s->sft_count == 0 ||
      (!(s->sft_mode & SFT_MWRITE) && !(s->sft_mode & SFT_MRDWR)))
  {
    *err = DE_ACCESS;
    return 0;
  }
  if (s->sft_flags & SFT_FSHARED)
  {
    ReadCount = Remote_RW(REM_WRITE, n, bp, s, err);
    if (err)
    {
      return ReadCount;
    }
    else
      return 0;
  }

  /* Do a device write if device                  */
  if (s->sft_flags & SFT_FDEVICE)
  {
    request rq;

    /* set to no EOF                        */
    s->sft_flags &= ~SFT_FEOF;

    /* if null just report full transfer    */
    if (s->sft_flags & SFT_FNUL)
    {
      *err = SUCCESS;
      return n;
    }

    /* Now handle raw and cooked modes      */
    if (s->sft_flags & SFT_FBINARY)
    {
      rq.r_length = sizeof(request);
      rq.r_command = C_OUTPUT;
      rq.r_count = n;
      rq.r_trans = (BYTE FAR *) bp;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
      {
        char_error(&rq, s->sft_dev);
      }
      else
      {
        if (s->sft_flags & SFT_FCONOUT)
        {
          WORD cnt = rq.r_count;
          while (cnt--)
          {
            switch (*bp++)
            {
              case CR:
                scr_pos = 0;
                break;
              case LF:
              case BELL:
                break;
              case BS:
                --scr_pos;
                break;
              default:
                ++scr_pos;
            }
          }
        }
        *err = SUCCESS;
        return rq.r_count;
      }
    }
    else
    {
      REG WORD c,
        cnt = n,
        spaces_left = 0,
        next_pos,
        xfer = 0;
      static BYTE space = ' ';

    start:
      if (cnt-- == 0)
        goto end;
      if (*bp == CTL_Z)
        goto end;
      if (s->sft_flags & SFT_FCONOUT)
      {
        switch (*bp)
        {
          case CR:
            next_pos = 0;
            break;
          case LF:
          case BELL:
            next_pos = scr_pos;
            break;
          case BS:
            next_pos = scr_pos ? scr_pos - 1 : 0;
            break;
          case HT:
            spaces_left = 8 - (scr_pos & 7);
            next_pos = scr_pos + spaces_left;
            goto output_space;
          default:
            next_pos = scr_pos + 1;
        }
      }
      rq.r_length = sizeof(request);
      rq.r_command = C_OUTPUT;
      rq.r_count = 1;
      rq.r_trans = bp;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
        char_error(&rq, s->sft_dev);
      goto post;
    output_space:
      rq.r_length = sizeof(request);
      rq.r_command = C_OUTPUT;
      rq.r_count = 1;
      rq.r_trans = &space;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
        char_error(&rq, s->sft_dev);
      --spaces_left;
    post:
      if (spaces_left)
        goto output_space;
      ++bp;
      ++xfer;
      if (s->sft_flags & SFT_FCONOUT)
        scr_pos = next_pos;
      if (break_ena && control_break())
      {
        handle_break();
        goto end;
      }
      goto start;
    end:
      *err = SUCCESS;
      return xfer;
    }
  }
  else
    /* a block write                           */
  {
    COUNT rc;

    ReadCount = writeblock(s->sft_status, bp, n, &rc);
    if (rc < SUCCESS)
    {
      *err = rc;
      return 0;
    }
    else
    {
      *err = SUCCESS;
      return ReadCount;
    }
  }
  *err = SUCCESS;
  return 0;
}
コード例 #21
0
ファイル: file_system.c プロジェクト: pscherer413/file_system
//max name size = 15
//will modify block_map
Inode* writeInode(disk_t disk, int block, int * gpointers,bool directory, char * nametemp){
	int * blkmap = read_block_map(disk);
	blkmap[block] = 1;
	write_block_map(disk,blkmap);
	
	int size = arrayLength(gpointers);
	int maxsize = (disk->block_size-20-(ceil(log10(disk->size))*2)/(ceil(log10(disk->size))+1));
	int * pointers = malloc(sizeof(int) * (size+1));
	int i,j;
	int strlength = length(nametemp);
	char * name = malloc(sizeof(char)*  16);
	for(i = 0; i < 15 && nametemp[i] != '\0';i+=1){
		name[i] = nametemp[i];
	}
	name[i] = '\0';
	int * wpointers = malloc(sizeof(int) * (size + 1));
	for(i = 0; i < size; i+=1){
		pointers[i] = gpointers[i];
		wpointers[i] = gpointers[i];
	}
	wpointers[i] = '\0';
	pointers[i] = '\0';
	char * potSize;
	if(size > (maxsize)){ //-4 for 3 \n and 1 \0 - 16 for name length
		int * newpointers = malloc(sizeof(int) * (maxsize+1));
		int * extrapointers = malloc(sizeof(int) * (size-maxsize+1));
		for(i = 0; i < maxsize;i+=1){
			newpointers[i] = pointers[i];
		}
		newpointers[i] = '\0';
		free(wpointers);
		wpointers = newpointers;
		for(j = 0; j <size-maxsize;j+=1){
			extrapointers[j] = pointers[i];
			i+=1;
		}
		
		extrapointers[j] = '\0';
		int newblk;
		
		for(i = 0; i < disk->size;i+=1){
			if(blkmap[i] == 0){
				newblk = i;
				break;
			}
		}
		freeInode(writeInode(disk,newblk,extrapointers,directory,name));
	}
	unsigned char *strings[6];
	potSize = int2str(size);
	strings[0] = (directory)? "0" : potSize;

	char * list = intArray2charArray(wpointers);
	char * pntrs = malloc(sizeof(char) * (length(list)+2));
	pntrs[0] = '\n';

	pntrs[1] = '\0';
	strcat(pntrs,list);
	strings[1] = pntrs;
	strings[2] = "\n";
	strings[3] = name;
	strings[4] = "\n";
	strings[5] = NULL;
	
	unsigned char *databuf = calloc(disk->block_size, sizeof(unsigned char) );
	copy2buf(databuf,strings,0);
	writeblock(disk,block,databuf);
	free(list);
	free(pntrs);
	free(databuf);
	//free(name);
	free(blkmap);
	free(potSize);
	free(wpointers);
	return createInode(size,pointers,directory,block,name);
}
コード例 #22
0
ファイル: postcomm.c プロジェクト: andreiw/polaris
static void
filter(void)
{
    static int	wflag = 0;	/* nonzero if we've written a block */
    int		fd_in = fileno(stdin);

/*
 *
 * Responsible for sending the next file to the printer.
 * Most of the hard stuff is done in getstatus() and readline().
 * All this routine really does is control what happens for the
 * different printer states. 
 *
 */


    logit("sending file\n");

    curfile++;

    while (readblock(fd_in))
	switch (getstatus(0))
	{
	    case WAITING:
		    writeblock();
		    wflag = 1;
		    break;

	    case BUSY:
	    case PRINTING:
	    case PRINTERERROR:
		    if (tostdout == FALSE)
		    {
			writeblock();
			wflag = 1;
		    }
		    else
			sleep(1);
		    break;

	    case UNKNOWN:
		    if (tostdout == FALSE)
		    {
			writeblock();
			wflag = 1;
		    }
		    break;

	    case NOSTATUS:
		    if (tostdout == FALSE)
		    {
			if (wflag)
			    writeblock();
		    }
		    else
			sleep(1);
		    break;

	    case IDLE:
		    if (wflag)
			error(FATAL, "printer is idle");
		    write(ttyo, "\n", 1);
		    break;

	    case ERROR:
		    fprintf(stderr, "%s", mesg);	/* for csw */
		    error(FATAL, "PostScript error");
		    break;

	    case FLUSHING:
		    error(FATAL, "PostScript error");
		    break;

	    case INITIALIZING:
		    error(FATAL, "printer booting");
		    break;

	    case DISCONNECT:
		    error(FATAL, "printer appears to be offline");
		    break;

	}   /* End switch */

}   /* End of print */
コード例 #23
0
static void extern_rec(value v)
{
  struct code_fragment * cf;
  struct extern_item * sp;
  sp = extern_stack;

  while(1) {
  if (Is_long(v)) {
    intnat n = Long_val(v);
    if (n >= 0 && n < 0x40) {
      Write(PREFIX_SMALL_INT + n);
    } else if (n >= -(1 << 7) && n < (1 << 7)) {
      writecode8(CODE_INT8, n);
    } else if (n >= -(1 << 15) && n < (1 << 15)) {
      writecode16(CODE_INT16, n);
#ifdef ARCH_SIXTYFOUR
    } else if (n < -((intnat)1 << 31) || n >= ((intnat)1 << 31)) {
      writecode64(CODE_INT64, n);
#endif
    } else
      writecode32(CODE_INT32, n);
    goto next_item;
  }
  if (Is_in_value_area(v)) {
    header_t hd = Hd_val(v);
    tag_t tag = Tag_hd(hd);
    mlsize_t sz = Wosize_hd(hd);

    if (tag == Forward_tag) {
      value f = Forward_val (v);
      if (Is_block (f)
          && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag
              || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag)){
        /* Do not short-circuit the pointer. */
      }else{
        v = f;
        continue;
      }
    }
    /* Atoms are treated specially for two reasons: they are not allocated
       in the externed block, and they are automatically shared. */
    if (sz == 0) {
      if (tag < 16) {
        Write(PREFIX_SMALL_BLOCK + tag);
      } else {
        writecode32(CODE_BLOCK32, hd);
      }
      goto next_item;
    }
    /* Check if already seen */
    if (Color_hd(hd) == Caml_blue) {
      uintnat d = obj_counter - (uintnat) Field(v, 0);
      if (d < 0x100) {
        writecode8(CODE_SHARED8, d);
      } else if (d < 0x10000) {
        writecode16(CODE_SHARED16, d);
      } else {
        writecode32(CODE_SHARED32, d);
      }
      goto next_item;
    }

    /* Output the contents of the object */
    switch(tag) {
    case String_tag: {
      mlsize_t len = caml_string_length(v);
      if (len < 0x20) {
        Write(PREFIX_SMALL_STRING + len);
      } else if (len < 0x100) {
        writecode8(CODE_STRING8, len);
      } else {
        writecode32(CODE_STRING32, len);
      }
      writeblock(String_val(v), len);
      size_32 += 1 + (len + 4) / 4;
      size_64 += 1 + (len + 8) / 8;
      extern_record_location(v);
      break;
    }
    case Double_tag: {
      if (sizeof(double) != 8)
        extern_invalid_argument("output_value: non-standard floats");
      Write(CODE_DOUBLE_NATIVE);
      writeblock_float8((double *) v, 1);
      size_32 += 1 + 2;
      size_64 += 1 + 1;
      extern_record_location(v);
      break;
    }
    case Double_array_tag: {
      mlsize_t nfloats;
      if (sizeof(double) != 8)
        extern_invalid_argument("output_value: non-standard floats");
      nfloats = Wosize_val(v) / Double_wosize;
      if (nfloats < 0x100) {
        writecode8(CODE_DOUBLE_ARRAY8_NATIVE, nfloats);
      } else {
        writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats);
      }
      writeblock_float8((double *) v, nfloats);
      size_32 += 1 + nfloats * 2;
      size_64 += 1 + nfloats;
      extern_record_location(v);
      break;
    }
    case Abstract_tag:
      extern_invalid_argument("output_value: abstract value (Abstract)");
      break;
    case Infix_tag:
      writecode32(CODE_INFIXPOINTER, Infix_offset_hd(hd));
      extern_rec(v - Infix_offset_hd(hd));
      break;
    case Custom_tag: {
      uintnat sz_32, sz_64;
      char * ident = Custom_ops_val(v)->identifier;
      void (*serialize)(value v, uintnat * wsize_32,
                        uintnat * wsize_64)
        = Custom_ops_val(v)->serialize;
      if (serialize == NULL)
        extern_invalid_argument("output_value: abstract value (Custom)");
      Write(CODE_CUSTOM);
      writeblock(ident, strlen(ident) + 1);
      Custom_ops_val(v)->serialize(v, &sz_32, &sz_64);
      size_32 += 2 + ((sz_32 + 3) >> 2);  /* header + ops + data */
      size_64 += 2 + ((sz_64 + 7) >> 3);
      extern_record_location(v);
      break;
    }
    default: {
      value field0;
      if (tag < 16 && sz < 8) {
        Write(PREFIX_SMALL_BLOCK + tag + (sz << 4));
#ifdef ARCH_SIXTYFOUR
      } else if (hd >= ((uintnat)1 << 32)) {
        writecode64(CODE_BLOCK64, Whitehd_hd (hd));
#endif
      } else {
        writecode32(CODE_BLOCK32, Whitehd_hd (hd));
      }
      size_32 += 1 + sz;
      size_64 += 1 + sz;
      field0 = Field(v, 0);
      extern_record_location(v);
      /* Remember that we still have to serialize fields 1 ... sz - 1 */
      if (sz > 1) {
        sp++;
        if (sp >= extern_stack_limit) sp = extern_resize_stack(sp);
        sp->v = &Field(v,1);
        sp->count = sz-1;
      }
      /* Continue serialization with the first field */
      v = field0;
      continue;
    }
    }
  }
  else if ((cf = extern_find_code((char *) v)) != NULL) {
    if (!extern_closures)
      extern_invalid_argument("output_value: functional value");
    writecode32(CODE_CODEPOINTER, (char *) v - cf->code_start);
    writeblock((char *) cf->digest, 16);
  } else {
    extern_invalid_argument("output_value: abstract value (outside heap)");
  }
  next_item:
    /* Pop one more item to marshal, if any */
    if (sp == extern_stack) {
        /* We are done.   Cleanup the stack and leave the function */
        extern_free_stack();
        return;
    }
    v = *((sp->v)++);
    if (--(sp->count) == 0) sp--;
  }
コード例 #24
0
ファイル: blockimg.c プロジェクト: 10114395/android-5.0.0_r5
Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[]) {
    Value* blockdev_filename;
    Value* transfer_list_value;
    char* transfer_list = NULL;
    Value* new_data_fn;
    Value* patch_data_fn;
    bool success = false;

    if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value,
                      &new_data_fn, &patch_data_fn) < 0) {
        return NULL;
    }

    if (blockdev_filename->type != VAL_STRING) {
        ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
        goto done;
    }
    if (transfer_list_value->type != VAL_BLOB) {
        ErrorAbort(state, "transfer_list argument to %s must be blob", name);
        goto done;
    }
    if (new_data_fn->type != VAL_STRING) {
        ErrorAbort(state, "new_data_fn argument to %s must be string", name);
        goto done;
    }
    if (patch_data_fn->type != VAL_STRING) {
        ErrorAbort(state, "patch_data_fn argument to %s must be string", name);
        goto done;
    }

    UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
    FILE* cmd_pipe = ui->cmd_pipe;

    ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;

    const ZipEntry* patch_entry = mzFindZipEntry(za, patch_data_fn->data);
    if (patch_entry == NULL) {
        ErrorAbort(state, "%s(): no file \"%s\" in package", name, patch_data_fn->data);
        goto done;
    }

    uint8_t* patch_start = ((UpdaterInfo*)(state->cookie))->package_zip_addr +
        mzGetZipEntryOffset(patch_entry);

    const ZipEntry* new_entry = mzFindZipEntry(za, new_data_fn->data);
    if (new_entry == NULL) {
        ErrorAbort(state, "%s(): no file \"%s\" in package", name, new_data_fn->data);
        goto done;
    }

    // The transfer list is a text file containing commands to
    // transfer data from one place to another on the target
    // partition.  We parse it and execute the commands in order:
    //
    //    zero [rangeset]
    //      - fill the indicated blocks with zeros
    //
    //    new [rangeset]
    //      - fill the blocks with data read from the new_data file
    //
    //    bsdiff patchstart patchlen [src rangeset] [tgt rangeset]
    //    imgdiff patchstart patchlen [src rangeset] [tgt rangeset]
    //      - read the source blocks, apply a patch, write result to
    //        target blocks.  bsdiff or imgdiff specifies the type of
    //        patch.
    //
    //    move [src rangeset] [tgt rangeset]
    //      - copy data from source blocks to target blocks (no patch
    //        needed; rangesets are the same size)
    //
    //    erase [rangeset]
    //      - mark the given blocks as empty
    //
    // The creator of the transfer list will guarantee that no block
    // is read (ie, used as the source for a patch or move) after it
    // has been written.
    //
    // Within one command the source and target ranges may overlap so
    // in general we need to read the entire source into memory before
    // writing anything to the target blocks.
    //
    // All the patch data is concatenated into one patch_data file in
    // the update package.  It must be stored uncompressed because we
    // memory-map it in directly from the archive.  (Since patches are
    // already compressed, we lose very little by not compressing
    // their concatenation.)

    pthread_t new_data_thread;
    NewThreadInfo nti;
    nti.za = za;
    nti.entry = new_entry;
    nti.rss = NULL;
    pthread_mutex_init(&nti.mu, NULL);
    pthread_cond_init(&nti.cv, NULL);

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&new_data_thread, &attr, unzip_new_data, &nti);

    int i, j;

    char* linesave;
    char* wordsave;

    int fd = open(blockdev_filename->data, O_RDWR);
    if (fd < 0) {
        ErrorAbort(state, "failed to open %s: %s", blockdev_filename->data, strerror(errno));
        goto done;
    }

    char* line;
    char* word;

    // The data in transfer_list_value is not necessarily
    // null-terminated, so we need to copy it to a new buffer and add
    // the null that strtok_r will need.
    transfer_list = malloc(transfer_list_value->size+1);
    if (transfer_list == NULL) {
        fprintf(stderr, "failed to allocate %zd bytes for transfer list\n",
                transfer_list_value->size+1);
        exit(1);
    }
    memcpy(transfer_list, transfer_list_value->data, transfer_list_value->size);
    transfer_list[transfer_list_value->size] = '\0';

    line = strtok_r(transfer_list, "\n", &linesave);

    // first line in transfer list is the version number; currently
    // there's only version 1.
    if (strcmp(line, "1") != 0) {
        ErrorAbort(state, "unexpected transfer list version [%s]\n", line);
        goto done;
    }

    // second line in transfer list is the total number of blocks we
    // expect to write.
    line = strtok_r(NULL, "\n", &linesave);
    int total_blocks = strtol(line, NULL, 0);
    // shouldn't happen, but avoid divide by zero.
    if (total_blocks == 0) ++total_blocks;
    int blocks_so_far = 0;

    uint8_t* buffer = NULL;
    size_t buffer_alloc = 0;

    // third and subsequent lines are all individual transfer commands.
    for (line = strtok_r(NULL, "\n", &linesave); line;
         line = strtok_r(NULL, "\n", &linesave)) {
        char* style;
        style = strtok_r(line, " ", &wordsave);

        if (strcmp("move", style) == 0) {
            word = strtok_r(NULL, " ", &wordsave);
            RangeSet* src = parse_range(word);
            word = strtok_r(NULL, " ", &wordsave);
            RangeSet* tgt = parse_range(word);

            printf("  moving %d blocks\n", src->size);

            allocate(src->size * BLOCKSIZE, &buffer, &buffer_alloc);
            size_t p = 0;
            for (i = 0; i < src->count; ++i) {
                check_lseek(fd, (off64_t)src->pos[i*2] * BLOCKSIZE, SEEK_SET);
                size_t sz = (src->pos[i*2+1] - src->pos[i*2]) * BLOCKSIZE;
                readblock(fd, buffer+p, sz);
                p += sz;
            }

            p = 0;
            for (i = 0; i < tgt->count; ++i) {
                check_lseek(fd, (off64_t)tgt->pos[i*2] * BLOCKSIZE, SEEK_SET);
                size_t sz = (tgt->pos[i*2+1] - tgt->pos[i*2]) * BLOCKSIZE;
                writeblock(fd, buffer+p, sz);
                p += sz;
            }

            blocks_so_far += tgt->size;
            fprintf(cmd_pipe, "set_progress %.4f\n", (double)blocks_so_far / total_blocks);
            fflush(cmd_pipe);

            free(src);
            free(tgt);

        } else if (strcmp("zero", style) == 0 ||
                   (DEBUG_ERASE && strcmp("erase", style) == 0)) {
            word = strtok_r(NULL, " ", &wordsave);
            RangeSet* tgt = parse_range(word);

            printf("  zeroing %d blocks\n", tgt->size);

            allocate(BLOCKSIZE, &buffer, &buffer_alloc);
            memset(buffer, 0, BLOCKSIZE);
            for (i = 0; i < tgt->count; ++i) {
                check_lseek(fd, (off64_t)tgt->pos[i*2] * BLOCKSIZE, SEEK_SET);
                for (j = tgt->pos[i*2]; j < tgt->pos[i*2+1]; ++j) {
                    writeblock(fd, buffer, BLOCKSIZE);
                }
            }

            if (style[0] == 'z') {   // "zero" but not "erase"
                blocks_so_far += tgt->size;
                fprintf(cmd_pipe, "set_progress %.4f\n", (double)blocks_so_far / total_blocks);
                fflush(cmd_pipe);
            }

            free(tgt);
        } else if (strcmp("new", style) == 0) {

            word = strtok_r(NULL, " ", &wordsave);
            RangeSet* tgt = parse_range(word);

            printf("  writing %d blocks of new data\n", tgt->size);

            RangeSinkState rss;
            rss.fd = fd;
            rss.tgt = tgt;
            rss.p_block = 0;
            rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
            check_lseek(fd, (off64_t)tgt->pos[0] * BLOCKSIZE, SEEK_SET);

            pthread_mutex_lock(&nti.mu);
            nti.rss = &rss;
            pthread_cond_broadcast(&nti.cv);
            while (nti.rss) {
                pthread_cond_wait(&nti.cv, &nti.mu);
            }
            pthread_mutex_unlock(&nti.mu);

            blocks_so_far += tgt->size;
            fprintf(cmd_pipe, "set_progress %.4f\n", (double)blocks_so_far / total_blocks);
            fflush(cmd_pipe);

            free(tgt);

        } else if (strcmp("bsdiff", style) == 0 ||
                   strcmp("imgdiff", style) == 0) {
            word = strtok_r(NULL, " ", &wordsave);
            size_t patch_offset = strtoul(word, NULL, 0);
            word = strtok_r(NULL, " ", &wordsave);
            size_t patch_len = strtoul(word, NULL, 0);

            word = strtok_r(NULL, " ", &wordsave);
            RangeSet* src = parse_range(word);
            word = strtok_r(NULL, " ", &wordsave);
            RangeSet* tgt = parse_range(word);

            printf("  patching %d blocks to %d\n", src->size, tgt->size);

            // Read the source into memory.
            allocate(src->size * BLOCKSIZE, &buffer, &buffer_alloc);
            size_t p = 0;
            for (i = 0; i < src->count; ++i) {
                check_lseek(fd, (off64_t)src->pos[i*2] * BLOCKSIZE, SEEK_SET);
                size_t sz = (src->pos[i*2+1] - src->pos[i*2]) * BLOCKSIZE;
                readblock(fd, buffer+p, sz);
                p += sz;
            }

            Value patch_value;
            patch_value.type = VAL_BLOB;
            patch_value.size = patch_len;
            patch_value.data = (char*)(patch_start + patch_offset);

            RangeSinkState rss;
            rss.fd = fd;
            rss.tgt = tgt;
            rss.p_block = 0;
            rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
            check_lseek(fd, (off64_t)tgt->pos[0] * BLOCKSIZE, SEEK_SET);

            if (style[0] == 'i') {      // imgdiff
                ApplyImagePatch(buffer, src->size * BLOCKSIZE,
                                &patch_value,
                                &RangeSinkWrite, &rss, NULL, NULL);
            } else {
                ApplyBSDiffPatch(buffer, src->size * BLOCKSIZE,
                                 &patch_value, 0,
                                 &RangeSinkWrite, &rss, NULL);
            }

            // We expect the output of the patcher to fill the tgt ranges exactly.
            if (rss.p_block != tgt->count || rss.p_remain != 0) {
                fprintf(stderr, "range sink underrun?\n");
            }

            blocks_so_far += tgt->size;
            fprintf(cmd_pipe, "set_progress %.4f\n", (double)blocks_so_far / total_blocks);
            fflush(cmd_pipe);

            free(src);
            free(tgt);
        } else if (!DEBUG_ERASE && strcmp("erase", style) == 0) {
            struct stat st;
            if (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode)) {
                word = strtok_r(NULL, " ", &wordsave);
                RangeSet* tgt = parse_range(word);

                printf("  erasing %d blocks\n", tgt->size);

                for (i = 0; i < tgt->count; ++i) {
                    uint64_t range[2];
                    // offset in bytes
                    range[0] = tgt->pos[i*2] * (uint64_t)BLOCKSIZE;
                    // len in bytes
                    range[1] = (tgt->pos[i*2+1] - tgt->pos[i*2]) * (uint64_t)BLOCKSIZE;

                    if (ioctl(fd, BLKDISCARD, &range) < 0) {
                        printf("    blkdiscard failed: %s\n", strerror(errno));
                    }
                }

                free(tgt);
            } else {
                printf("  ignoring erase (not block device)\n");
            }
        } else {
            fprintf(stderr, "unknown transfer style \"%s\"\n", style);
            exit(1);
        }
    }

    pthread_join(new_data_thread, NULL);
    success = true;

    free(buffer);
    printf("wrote %d blocks; expected %d\n", blocks_so_far, total_blocks);
    printf("max alloc needed was %zu\n", buffer_alloc);

  done:
    free(transfer_list);
    FreeValue(blockdev_filename);
    FreeValue(transfer_list_value);
    FreeValue(new_data_fn);
    FreeValue(patch_data_fn);
    return StringValue(success ? strdup("t") : strdup(""));
}