Ejemplo n.º 1
0
static void
send_stat_packet(int to_peer, int xfer_fd)
{
    struct stat st;
    if (fstat(xfer_fd, &st) == -1)
        die_errno("fstat");
    struct xfer_msg m = {
        .type = XFER_MSG_STAT,
        .u.stat.atime = st.st_atime,
        .u.stat.mtime = st.st_mtime,
#ifdef HAVE_STRUCT_STAT_ST_ATIM
        .u.stat.atime_ns = st.st_atim.tv_nsec,
#endif
#ifdef HAVE_STRUCT_STAT_ST_MTIM
        .u.stat.mtime_ns = st.st_mtim.tv_nsec,
#endif
        .u.stat.size = st.st_size,
        .u.stat.ugo_bits = st.st_mode & 0777,
    };

    send_xfer_msg(to_peer, &m);
}

struct xfer_ctx {
    int from_peer;
    int to_peer;
    const struct cmd_xfer_stub_info* info;
};

static uint32_t
recv_data_header(int from_peer)
{
    struct xfer_msg m = recv_xfer_msg(from_peer);
    if (m.type != XFER_MSG_DATA)
        die(ECOMM, "unexpected message type %u", (unsigned) m.type);
    return m.u.data.payload_size;
}

static void
send_data_header(int to_peer, uint32_t size)
{
    struct xfer_msg m = {
        .type = XFER_MSG_DATA,
        .u.data.payload_size = size,
    };

    send_xfer_msg(to_peer, &m);
}

static uint64_t
copy_loop_posix_recv(
    int from_peer,
    int dest_fd)
{
    SCOPED_RESLIST(rl);
    struct growable_buffer buf = { 0 };
    uint64_t total_written = 0;
    size_t chunksz;

    do {
        chunksz = recv_data_header(from_peer);
        dbg("data chunk header chunksz=%u", (unsigned) chunksz);
        resize_buffer(&buf, chunksz);
        if (read_all(from_peer, buf.buf, chunksz) != chunksz)
            die(ECOMM, "unexpected EOF");
        write_all(dest_fd, buf.buf, chunksz);
        if (SATADD(&total_written, total_written, chunksz))
            die(ECOMM, "file size too large");
    } while (chunksz > 0);

    return total_written;
}

static void
copy_loop_posix_send(
    int to_peer,
    int source_fd)
{
    SCOPED_RESLIST(rl);
    size_t bufsz = 32 * 1024;
    uint8_t* buf = xalloc(bufsz);
    size_t nr_read;

    assert(bufsz <= UINT32_MAX);

    do {
        nr_read = read_all(source_fd, buf, bufsz);
        send_data_header(to_peer, nr_read);
        write_all(to_peer, buf, nr_read);
    } while (nr_read > 0);
}
Ejemplo n.º 2
0
ssize_t PackedAudioPacket<T>::read_from_fd(int fd) {
    return read_all(fd, _data, size_bytes( ));
}
Ejemplo n.º 3
0
/**
 * main functiom - for colne or restore data
 */
int main(int argc, char **argv){ 

    char*		source;			/// source data
    int			dfr;		/// file descriptor for source and target
    int			r_size;		/// read and write size
    char*		buffer;		/// buffer data
    char*		buffer2;		/// buffer data
    unsigned long long	block_id, copied = 0;	/// block_id is every block in partition
    /// copied is copied block count
    off_t		offset = 0, sf = 0;	/// seek postition, lseek result
    int			start, stop;		/// start, range, stop number for progress bar
    char		bitmagic[8] = "BiTmAgIc";// only for check postition
    char		bitmagic_r[8];		/// read magic string from image
    int			cmp;			/// compare magic string
    char		*bitmap;		/// the point for bitmap data
    int			debug = 0;		/// debug or not
    unsigned long	crc = 0xffffffffL;	/// CRC32 check code for writint to image
    unsigned long	crc_ck = 0xffffffffL;	/// CRC32 check code for checking
    unsigned long	crc_ck2 = 0xffffffffL;	/// CRC32 check code for checking
    int			c_size;			/// CRC32 code size
    char*		crc_buffer;		/// buffer data for malloc crc code
    int			done = 0;
    int			s_count = 0;
    int			rescue_num = 0;
    int			tui = 0;		/// text user interface
    int			pui = 0;		/// progress mode(default text)
    int			raw = 0;
    char		image_hdr_magic[512];

    progress_bar	prog;			/// progress_bar structure defined in progress.h
    image_head		image_hdr;		/// image_head structure defined in partclone.h

    /**
     * get option and assign to opt structure
     * check parameter and read from argv
     */
    parse_option_chkimg(argc, argv, &opt);

    /**
     * if "-d / --debug" given
     * open debug file in "/var/log/partclone.log" for log message 
     */
    debug = opt.debug;
    open_log(opt.logfile);

    /**
     * using Text User Interface
     */
    if (opt.ncurses){
        pui = NCURSES;
        log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n");
    } else if (opt.dialog){
        pui = DIALOG;
        log_mesg(1, 0, 0, debug, "Using Dialog User Interface mode.\n");
    } else
        pui = TEXT;

    tui = open_pui(pui, opt.fresh);
    if ((opt.ncurses) && (tui == 0)){
        opt.ncurses = 0;
        log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n");
    } else if ((opt.dialog) && (tui == 1)){
        m_dialog.percent = 1;
    }

    /// print partclone info
    print_partclone_info(opt);

    /*
    if (geteuid() != 0)
        log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n"); 
    else
        log_mesg(1, 0, 0, debug, "UID is root.\n");
    */

    /**
     * open source and target 
     * clone mode, source is device and target is image file/stdout
     * restore mode, source is image file/stdin and target is device
     * dd mode, source is device and target is device !!not complete
     */
#ifdef _FILE_OFFSET_BITS
    log_mesg(1, 0, 0, debug, "enable _FILE_OFFSET_BITS %i\n", _FILE_OFFSET_BITS);
#endif
    dfr = open_source(opt.source, &opt);
    if (dfr == -1) {
        log_mesg(0, 1, 1, debug, "Erro EXIT.\n");
    }

    /**
     * get partition information like super block, image_head, bitmap
     * from device or image file.
     */


    log_mesg(1, 0, 0, debug, "Checking image hdr - get image_head from image file\n");

    restore_image_hdr(&dfr, &opt, &image_hdr);
    /// check the image magic
    if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0)
        log_mesg(0, 1, 1, debug, "The Image magic error. This file is NOT partclone Image\n");

    /// alloc a memory to restore bitmap
    bitmap = (char*)malloc(sizeof(char)*image_hdr.totalblock);
    if(bitmap == NULL){
        log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
    }

    log_mesg(2, 0, 0, debug, "initial main bitmap pointer %lli\n", bitmap);
    log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

    /// read and check bitmap from image file
    log_mesg(0, 0, 1, debug, "Calculating bitmap... ");
    log_mesg(0, 0, 1, debug, "Please wait... ");
    get_image_bitmap(&dfr, opt, image_hdr, bitmap);

    log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap);
    log_mesg(0, 0, 1, debug, "done!\n");

    log_mesg(1, 0, 0, debug, "print image_head\n");

    /// print option to log file
    if (debug)
        print_opt(opt);

    /// print image_head
    print_image_hdr_info(image_hdr, opt);

    /**
     * initial progress bar
     */
    start = 0;				/// start number of progress bar
    stop = image_hdr.usedblocks;	/// get the end of progress number, only used block
    log_mesg(1, 0, 0, debug, "Initial Progress bar\n");
    /// Initial progress bar
    progress_init(&prog, start, stop, image_hdr.block_size);
    copied = 1;				/// initial number is 1

    /**
     * start read and write data between device and image file
     */

    /**
     * read magic string from image file
     * and check it.
     */
    r_size = read_all(&dfr, bitmagic_r, 8, &opt); /// read a magic string
    cmp = memcmp(bitmagic, bitmagic_r, 8);
    if(cmp != 0)
        log_mesg(0, 1, 1, debug, "bitmagic error %i\n", cmp);

    /// start restore image file to partition
    for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ){

        r_size = 0;

        if((block_id + 1) == image_hdr.totalblock) 
            done = 1;

#ifdef _FILE_OFFSET_BITS
        if(copied == image_hdr.usedblocks) 
            done = 1;
#endif
        if (bitmap[block_id] == 1){ 
            /// The block is used
            log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id);
            log_mesg(1, 0, 0, debug, "bitmap=%i, ",bitmap[block_id]);

            offset = (off_t)(block_id * image_hdr.block_size);
            buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data
            if(buffer == NULL){
                log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
            }
            r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt);
            log_mesg(1, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size);
            if (r_size <0)
                log_mesg(0, 1, 1, debug, "read errno = %i \n", errno);

            /// read crc32 code and check it.
            crc_ck = crc32(crc_ck, buffer, r_size);
            crc_buffer = (char*)malloc(CRC_SIZE); ///alloc a memory to copy data
            if(crc_buffer == NULL){
                log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
            }
            c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt);
            if (c_size < CRC_SIZE)
                log_mesg(0, 1, 1, debug, "read CRC error, please check your image file. \n");
            memcpy(&crc, crc_buffer, CRC_SIZE);
            if (memcmp(&crc, &crc_ck, CRC_SIZE) != 0){
                log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), enlarge crc size and recheck again....\n ");
                /// check again
                buffer2 = (char*)malloc(image_hdr.block_size+CRC_SIZE); ///alloc a memory to copy data
                if(buffer2 == NULL){
                    log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
                }
                memcpy(buffer2, buffer, image_hdr.block_size);
                memcpy(buffer2+image_hdr.block_size, crc_buffer, CRC_SIZE);
                memcpy(buffer, buffer2+CRC_SIZE, image_hdr.block_size);

                crc_ck2 = crc32(crc_ck2, buffer, r_size);
                c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt);
                if (c_size < CRC_SIZE)
                    log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno));
                memcpy(&crc, crc_buffer, CRC_SIZE);
                if (memcmp(&crc, &crc_ck2, CRC_SIZE) != 0) {
                    log_mesg(0, 1, 1, debug, "CRC error again at %i...\n ", sf);
                } else {
                    crc_ck = crc_ck2;
                }
                free(buffer2);

            } else {
                crc_ck2 = crc_ck;
            }


            /// free buffer
            free(buffer);
            free(crc_buffer);


            copied++;					/// count copied block

            log_mesg(1, 0, 0, debug, "end\n");
        }

	update_pui(&prog, copied, done);
	if(done = 1)
	    break;
    } // end of for
    print_finish_info(opt);

    close (dfr);    /// close source
    free(bitmap);   /// free bitmp
    close_pui(pui);
    printf("Checked successfully.\n");
    if(opt.debug)
        close_log();
    return 0;	    /// finish
}
Ejemplo n.º 4
0
static gboolean
recv_message (GIOChannel  *channel,
	      GIOCondition cond,
	      gpointer    data)
{
  gint fd = g_io_channel_unix_get_fd (channel);
  gboolean retval = TRUE;

#ifdef VERBOSE
  g_print ("gio-test: ...from %d:%s%s%s%s\n", fd,
	   (cond & G_IO_ERR) ? " ERR" : "",
	   (cond & G_IO_HUP) ? " HUP" : "",
	   (cond & G_IO_IN)  ? " IN"  : "",
	   (cond & G_IO_PRI) ? " PRI" : "");
#endif

  if (cond & (G_IO_ERR | G_IO_HUP))
    {
      shutdown_source (data);
      retval = FALSE;
    }

  if (cond & G_IO_IN)
    {
      char buf[BUFSIZE];
      guint nbytes;
      guint nb;
      int i, j, seq;
      GIOError error;
      
      error = read_all (fd, channel, (gchar *) &seq, sizeof (seq), &nb);
      if (error == G_IO_ERROR_NONE)
	{
	  if (nb == 0)
	    {
#ifdef VERBOSE
	      g_print ("gio-test: ...from %d: EOF\n", fd);
#endif
	      shutdown_source (data);
	      return FALSE;
	    }
	  
	  g_assert (nb == sizeof (nbytes));

	  for (i = 0; i < nkiddies; i++)
	    if (seqtab[i].fd == fd)
	      {
		if (seq != seqtab[i].seq)
		  {
		    g_print ("gio-test: ...from %d: invalid sequence number %d, expected %d\n",
			     fd, seq, seqtab[i].seq);
		    g_assert_not_reached ();
		  }
		seqtab[i].seq++;
		break;
	      }

	  error = read_all (fd, channel, (gchar *) &nbytes, sizeof (nbytes), &nb);
	}

      if (error != G_IO_ERROR_NONE)
	return FALSE;
      
      if (nb == 0)
	{
#ifdef VERBOSE
	  g_print ("gio-test: ...from %d: EOF\n", fd);
#endif
	  shutdown_source (data);
	  return FALSE;
	}
      
      g_assert (nb == sizeof (nbytes));

      if (nbytes >= BUFSIZE)
	{
	  g_print ("gio-test: ...from %d: nbytes = %d (%#x)!\n", fd, nbytes, nbytes);
	  g_assert_not_reached ();
	}
      g_assert (nbytes >= 0 && nbytes < BUFSIZE);
#ifdef VERBOSE      
      g_print ("gio-test: ...from %d: %d bytes\n", fd, nbytes);
#endif      
      if (nbytes > 0)
	{
	  error = read_all (fd, channel, buf, nbytes, &nb);

	  if (error != G_IO_ERROR_NONE)
	    return FALSE;

	  if (nb == 0)
	    {
#ifdef VERBOSE
	      g_print ("gio-test: ...from %d: EOF\n", fd);
#endif
	      shutdown_source (data);
	      return FALSE;
	    }
      
	  for (j = 0; j < nbytes; j++)
	    if (buf[j] != ' ' + ((nbytes + j) % 95))
	      {
		g_print ("gio-test: ...from %d: buf[%d] == '%c', should be '%c'\n",
			 fd, j, buf[j], 'a' + ((nbytes + j) % 32));
		g_assert_not_reached ();
	      }
#ifdef VERBOSE
	  g_print ("gio-test: ...from %d: OK\n", fd);
#endif
	}
    }
  return retval;
}
Ejemplo n.º 5
0
/** Implement a cpuworker.  'data' is an fdarray as returned by socketpair.
 * Read and writes from fdarray[1].  Reads requests, writes answers.
 *
 *   Request format:
 *          Task type           [1 byte, always CPUWORKER_TASK_ONION]
 *          Opaque tag          TAG_LEN
 *          Onionskin challenge ONIONSKIN_CHALLENGE_LEN
 *   Response format:
 *          Success/failure     [1 byte, boolean.]
 *          Opaque tag          TAG_LEN
 *          Onionskin challenge ONIONSKIN_REPLY_LEN
 *          Negotiated keys     KEY_LEN*2+DIGEST_LEN*2
 *
 *  (Note: this _should_ be by addr/port, since we're concerned with specific
 * connections, not with routers (where we'd use identity).)
 */
static void
cpuworker_main(void *data)
{
  char question[ONIONSKIN_CHALLENGE_LEN];
  uint8_t question_type;
  tor_socket_t *fdarray = data;
  tor_socket_t fd;

  /* variables for onion processing */
  char keys[CPATH_KEY_MATERIAL_LEN];
  char reply_to_proxy[ONIONSKIN_REPLY_LEN];
  char buf[LEN_ONION_RESPONSE];
  char tag[TAG_LEN];
  crypto_pk_t *onion_key = NULL, *last_onion_key = NULL;

  fd = fdarray[1]; /* this side is ours */
#ifndef TOR_IS_MULTITHREADED
  tor_close_socket(fdarray[0]); /* this is the side of the socketpair the
                                 * parent uses */
  tor_free_all(1); /* so the child doesn't hold the parent's fd's open */
  handle_signals(0); /* ignore interrupts from the keyboard, etc */
#endif
  tor_free(data);

  dup_onion_keys(&onion_key, &last_onion_key);

  for (;;) {
    ssize_t r;

    if ((r = recv(fd, (void *)&question_type, 1, 0)) != 1) {
//      log_fn(LOG_ERR,"read type failed. Exiting.");
      if (r == 0) {
        log_info(LD_OR,
                 "CPU worker exiting because Tor process closed connection "
                 "(either rotated keys or died).");
      } else {
        log_info(LD_OR,
                 "CPU worker exiting because of error on connection to Tor "
                 "process.");
        log_info(LD_OR,"(Error on %d was %s)",
                 fd, tor_socket_strerror(tor_socket_errno(fd)));
      }
      goto end;
    }
    tor_assert(question_type == CPUWORKER_TASK_ONION);

    if (read_all(fd, tag, TAG_LEN, 1) != TAG_LEN) {
      log_err(LD_BUG,"read tag failed. Exiting.");
      goto end;
    }

    if (read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) !=
        ONIONSKIN_CHALLENGE_LEN) {
      log_err(LD_BUG,"read question failed. Exiting.");
      goto end;
    }

    if (question_type == CPUWORKER_TASK_ONION) {
      if (onion_skin_server_handshake(question, onion_key, last_onion_key,
          reply_to_proxy, keys, CPATH_KEY_MATERIAL_LEN) < 0) {
        /* failure */
        log_debug(LD_OR,"onion_skin_server_handshake failed.");
        *buf = 0; /* indicate failure in first byte */
        memcpy(buf+1,tag,TAG_LEN);
        /* send all zeros as answer */
        memset(buf+1+TAG_LEN, 0, LEN_ONION_RESPONSE-(1+TAG_LEN));
      } else {
        /* success */
        log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
        buf[0] = 1; /* 1 means success */
        memcpy(buf+1,tag,TAG_LEN);
        memcpy(buf+1+TAG_LEN,reply_to_proxy,ONIONSKIN_REPLY_LEN);
        memcpy(buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,keys,CPATH_KEY_MATERIAL_LEN);
      }
      if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) {
        log_err(LD_BUG,"writing response buf failed. Exiting.");
        goto end;
      }
      log_debug(LD_OR,"finished writing response.");
    }
  }
 end:
  if (onion_key)
    crypto_pk_free(onion_key);
  if (last_onion_key)
    crypto_pk_free(last_onion_key);
  tor_close_socket(fd);
  crypto_thread_cleanup();
  spawn_exit();
}
Ejemplo n.º 6
0
/**
 * main functiom - for colne or restore data
 */
int main(int argc, char **argv) {
#ifdef MEMTRACE
    setenv("MALLOC_TRACE", "partclone_mtrace.log", 1);
    mtrace();
#endif
    char*		source;			/// source data
    char*		target;			/// target data
    char*		buffer;			/// buffer data for malloc used
    char*		buffer2;			/// buffer data for malloc used
    int			dfr, dfw;		/// file descriptor for source and target
    int			r_size, w_size;		/// read and write size
    //unsigned long long	block_id, copied = 0;	/// block_id is every block in partition
    /// copied is copied block count
    off_t		offset = 0, sf = 0;	/// seek postition, lseek result
    int			start, stop;		/// start, range, stop number for progress bar
    unsigned long long	total_write = 0;	/// the copied size
    unsigned long long	needed_size = 0;	/// the copied size
    unsigned long long	needed_mem  = 0;	/// the copied size
    char		bitmagic[8] = "BiTmAgIc";// only for check postition
    char		bitmagic_r[8]="00000000";/// read magic string from image
    int			cmp;			/// compare magic string
    unsigned long	*bitmap;		/// the point for bitmap data
    int			debug = 0;		/// debug or not
    unsigned long	crc = 0xffffffffL;	/// CRC32 check code for writint to image
    unsigned long	crc_ck = 0xffffffffL;	/// CRC32 check code for checking
    unsigned long	crc_ck2 = 0xffffffffL;	/// CRC32 check code for checking
    int			c_size;			/// CRC32 code size
    int			n_crc_size = CRC_SIZE;
    char*		crc_buffer;		/// buffer data for malloc crc code
    //int			done = 0;
    int			s_count = 0;
    int			rescue_num = 0;
    unsigned long long			rescue_pos = 0;
    unsigned long long			main_pos = 0;
    int			tui = 0;		/// text user interface
    int			pui = 0;		/// progress mode(default text)
    int                 next=1,next_int=1,next_max_count=7,next_count=7,i;
    unsigned long long  next_block_id;
    char*               cache_buffer;
    int                 nx_current=0;
    char                bbuffer[4096];
    int flag;
    int pres;
    pthread_t prog_thread;
    void *p_result;

    char *bad_sectors_warning_msg =
        "*************************************************************************\n"
        "* WARNING: The disk has bad sector. This means physical damage on the   *\n"
        "* disk surface caused by deterioration, manufacturing faults or other   *\n"
        "* reason. The reliability of the disk may stay stable or degrade fast.  *\n"
        "* Use the --rescue option to efficiently save as much data as possible! *\n"
        "*************************************************************************\n";

    image_head		image_hdr;		/// image_head structure defined in partclone.h
    memset(&image_hdr, 0, sizeof(image_hdr));

    /**
     * get option and assign to opt structure
     * check parameter and read from argv
     */
    parse_options(argc, argv, &opt);

    /**
     * if "-d / --debug" given
     * open debug file in "/var/log/partclone.log" for log message
     */
    memset(&fs_opt, 0, sizeof(fs_cmd_opt));
    debug = opt.debug;
    fs_opt.debug = debug;
    fs_opt.ignore_fschk = opt.ignore_fschk;

    next_max_count = opt.max_block_cache-1;
    next_count = opt.max_block_cache-1;

    //if(opt.debug)
    open_log(opt.logfile);

    /**
     * using Text User Interface
     */
    if (opt.ncurses) {
        pui = NCURSES;
        log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n");
    } else
        pui = TEXT;

    tui = open_pui(pui, opt.fresh);
    if ((opt.ncurses) && (tui == 0)) {
        opt.ncurses = 0;
        log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n");
    }

    /// print partclone info
    print_partclone_info(opt);

    if (geteuid() != 0)
        log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n");
    else
        log_mesg(1, 0, 0, debug, "UID is root.\n");

    /// ignore crc check
    if(opt.ignore_crc)
        log_mesg(1, 0, 1, debug, "Ignore CRC error\n");

    /**
     * open source and target
     * clone mode, source is device and target is image file/stdout
     * restore mode, source is image file/stdin and target is device
     * dd mode, source is device and target is device !!not complete
     */
#ifdef _FILE_OFFSET_BITS
    log_mesg(1, 0, 0, debug, "enable _FILE_OFFSET_BITS %i\n", _FILE_OFFSET_BITS);
#endif
    source = opt.source;
    target = opt.target;
    dfr = open_source(source, &opt);
    if (dfr == -1) {
        log_mesg(0, 1, 1, debug, "Erro EXIT.\n");
    }

    dfw = open_target(target, &opt);
    if (dfw == -1) {
        log_mesg(0, 1, 1, debug, "Error Exit.\n");
    }

    /**
     * get partition information like super block, image_head, bitmap
     * from device or image file.
     */
    if (opt.clone) {

        log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n");
        log_mesg(0, 0, 1, debug, "Reading Super Block\n");

        /// get Super Block information from partition
        initial_image_hdr(source, &image_hdr);

        /// check memory size
        if (check_mem_size(image_hdr, opt, &needed_mem) == -1)
            log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem);

        strncpy(image_hdr.version, IMAGE_VERSION, VERSION_SIZE);

        /// alloc a memory to restore bitmap
        bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock));
        if(bitmap == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        log_mesg(2, 0, 0, debug, "initial main bitmap pointer %i\n", bitmap);
        log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

        /// read and check bitmap from partition
        log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... ");
        readbitmap(source, image_hdr, bitmap, pui);

        needed_size = (unsigned long long)(((image_hdr.block_size+sizeof(unsigned long))*image_hdr.usedblocks)+sizeof(image_hdr)+sizeof(char)*image_hdr.totalblock);
        if (opt.check)
            check_free_space(&dfw, needed_size);

        log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap);

        log_mesg(1, 0, 0, debug, "Writing super block and bitmap... ");
        // write image_head to image file
        w_size = write_all(&dfw, (char *)&image_hdr, sizeof(image_head), &opt);
        if(w_size == -1)
            log_mesg(0, 1, 1, debug, "write image_hdr to image error\n");

        // write bitmap information to image file
        for (i = 0; i < image_hdr.totalblock; i++) {
            if (pc_test_bit(i, bitmap)) {
                bbuffer[i % sizeof(bbuffer)] = 1;
            } else {
                bbuffer[i % sizeof(bbuffer)] = 0;
            }
            if (i % sizeof(bbuffer) == sizeof(bbuffer) - 1 || i == image_hdr.totalblock - 1) {
                w_size = write_all(&dfw, bbuffer, 1 + (i % sizeof(bbuffer)), &opt);
                if(w_size == -1)
                    log_mesg(0, 1, 1, debug, "write bitmap to image error\n");
            }
        }
        log_mesg(0, 0, 1, debug, "done!\n");
    } else if (opt.restore) {

        log_mesg(1, 0, 0, debug, "restore image hdr - get image_head from image file\n");
        log_mesg(1, 0, 1, debug, "Reading Super Block\n");
        /// get image information from image file
        restore_image_hdr(&dfr, &opt, &image_hdr);

        /// check memory size
        if (check_mem_size(image_hdr, opt, &needed_mem) == -1)
            log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem);

        /// alloc a memory to restore bitmap
        bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock));
        if(bitmap == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        /// check the image magic
        if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0)
            log_mesg(0, 1, 1, debug, "This is not partclone image.\n");

        /// check the file system
        //if (strcmp(image_hdr.fs, FS) != 0)
        //    log_mesg(0, 1, 1, debug, "%s can't restore from the image which filesystem is %s not %s\n", argv[0], image_hdr.fs, FS);

        log_mesg(2, 0, 0, debug, "initial main bitmap pointer %lli\n", bitmap);
        log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

        /// read and check bitmap from image file
        log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... ");
        get_image_bitmap(&dfr, opt, image_hdr, bitmap);

        /// check the dest partition size.
        if (opt.restore_row_file)
            check_free_space(&dfw, image_hdr.device_size);
        else if(opt.check)
            check_size(&dfw, image_hdr.device_size);

        log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap);
        log_mesg(0, 0, 1, debug, "done!\n");
    } else if (opt.dd) {
        log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n");
        log_mesg(1, 0, 1, debug, "Reading Super Block\n");

        /// get Super Block information from partition
        initial_image_hdr(source, &image_hdr);

        /// check memory size
        if (check_mem_size(image_hdr, opt, &needed_mem) == -1)
            log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem);

        strncpy(image_hdr.version, IMAGE_VERSION, VERSION_SIZE);

        /// alloc a memory to restore bitmap
        bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock));
        if(bitmap == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        log_mesg(2, 0, 0, debug, "initial main bitmap pointer %i\n", bitmap);
        log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

        /// read and check bitmap from partition
        log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... ");
        readbitmap(source, image_hdr, bitmap, pui);

        /// check the dest partition size.
        if(opt.check) {
            check_size(&dfw, image_hdr.device_size);
        }

        log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap);
        log_mesg(0, 0, 1, debug, "done!\n");
    } else if (opt.domain) {
        log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n");
        log_mesg(1, 0, 1, debug, "Reading Super Block\n");

        /// get Super Block information from partition
        initial_image_hdr(source, &image_hdr);

        /// check memory size
        if (check_mem_size(image_hdr, opt, &needed_mem) == -1)
            log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem);

        strncpy(image_hdr.version, IMAGE_VERSION, VERSION_SIZE);

        /// alloc a memory to restore bitmap
        bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock));
        if(bitmap == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        log_mesg(2, 0, 0, debug, "initial main bitmap pointer %i\n", bitmap);
        log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

        /// read and check bitmap from partition
        log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... ");
        readbitmap(source, image_hdr, bitmap, pui);

        log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap);
        log_mesg(0, 0, 1, debug, "done!\n");
    }

    log_mesg(1, 0, 0, debug, "print image_head\n");

    /// print option to log file
    if (debug)
        print_opt(opt);

    /// print image_head
    print_image_hdr_info(image_hdr, opt);

    /**
     * initial progress bar
     */
    //progress_bar	prog;		/// progress_bar structure defined in progress.h
    start = 0;				/// start number of progress bar
    stop = (image_hdr.usedblocks);	/// get the end of progress number, only used block
    log_mesg(1, 0, 0, debug, "Initial Progress bar\n");
    /// Initial progress bar
    if (opt.no_block_detail)
        flag = NO_BLOCK_DETAIL;
    else
        flag = IO;
    progress_init(&prog, start, stop, image_hdr.totalblock, flag, image_hdr.block_size);
    copied = 0;				/// initial number is 0

    /**
     * thread to print progress
     */
    pres = pthread_create(&prog_thread, NULL, thread_update_pui, NULL);

    /**
     * start read and write data between device and image file
     */
    if (opt.clone) {

        w_size = write_all(&dfw, bitmagic, 8, &opt); /// write a magic string

        /// read data from the first block and log the offset
        sf = lseek(dfr, 0, SEEK_SET);
        log_mesg(1, 0, 0, debug, "seek %lli for reading data string\n",sf);
        if (sf == (off_t)-1)
            log_mesg(0, 1, 1, debug, "seek set %lli\n", sf);

        buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data
        if(buffer == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        log_mesg(0, 0, 0, debug, "Total block %i\n", image_hdr.totalblock);


        /// start clone partition to image file
        log_mesg(1, 0, 0, debug, "start backup data...\n");
        for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ) {

            r_size = 0;
            w_size = 0;

            main_pos = lseek(dfr, 0, SEEK_CUR);
            log_mesg(3, 0, 0, debug, "man pos = %lli\n", main_pos);

            if (pc_test_bit(block_id, bitmap)) {
                /// if the block is used
                log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id);
                log_mesg(2, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap));

                offset = (off_t)(block_id * image_hdr.block_size);
#ifdef _FILE_OFFSET_BITS
                sf = lseek(dfr, offset, SEEK_SET);
                if (sf == -1)
                    log_mesg(0, 1, 1, debug, "source seek error = %lli, ",sf);
#endif
                /// read data from source to buffer
                memset(buffer, 0, image_hdr.block_size);
                rescue_pos = lseek(dfr, 0, SEEK_CUR);
                r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt);
                log_mesg(3, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size);
                if (r_size != (int)image_hdr.block_size) {

                    if ((r_size == -1) && (errno == EIO)) {
                        if (opt.rescue) {
                            r_size = 0;
                            for (rescue_num = 0; rescue_num < image_hdr.block_size; rescue_num += SECTOR_SIZE) {
                                rescue_sector(&dfr, rescue_pos + rescue_num, buffer + rescue_num, &opt);
                                r_size+=SECTOR_SIZE;
                            }
                        } else
                            log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg);

                    } else
                        log_mesg(0, 1, 1, debug, "read error: %s(%i) \n", strerror(errno), errno);
                }

                /// write buffer to target
                w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt);
                log_mesg(3, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size);
                if (w_size != (int)image_hdr.block_size)
                    log_mesg(0, 1, 1, debug, "write error %i \n", w_size);

                /// generate crc32 code and write it.
                crc_buffer = (char*)malloc(CRC_SIZE); ///alloc a memory to copy data
                if(crc_buffer == NULL) {
                    log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
                }
                crc = crc32(crc, buffer, w_size);
                memcpy(crc_buffer, &crc, CRC_SIZE);
                c_size = write_all(&dfw, crc_buffer, CRC_SIZE, &opt);

                /// free buffer
                free(crc_buffer);

                copied++;					/// count copied block
                total_write += (unsigned long long)(w_size);	/// count copied size
                log_mesg(3, 0, 0, debug, "total=%lli, ", total_write);

                /// read or write error
                if (r_size != w_size)
                    log_mesg(0, 1, 1, debug, "read(%i) and write(%i) different\n", r_size, w_size);
                log_mesg(2, 0, 0, debug, "end\n");
            } else {
#ifndef _FILE_OFFSET_BITS
                /// if the block is not used, I just skip it.
                log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id);
                sf = lseek(dfr, image_hdr.block_size, SEEK_CUR);
                log_mesg(2, 0, 0, debug, "skip seek=%lli, ",sf);
                if (sf == (off_t)-1)
                    log_mesg(0, 1, 1, debug, "clone seek error %lli errno=%i\n", (long long)offset, (int)errno);

                log_mesg(2, 0, 0, debug, "end\n");
#endif
            }
        } /// end of for
        free(buffer);
    } else if (opt.restore) {

        /**
         * read magic string from image file
         * and check it.
         */
        r_size = read_all(&dfr, bitmagic_r, 8, &opt); /// read a magic string
        cmp = memcmp(bitmagic, bitmagic_r, 8);
        if(cmp != 0)
            log_mesg(0, 1, 1, debug, "bitmagic error %i\n", cmp);

        /// seek to the first
        sf = lseek(dfw, 0, SEEK_SET);
        log_mesg(1, 0, 0, debug, "seek %lli for writing dtat string\n",sf);
        if (sf == (off_t)-1)
            log_mesg(0, 1, 1, debug, "seek set %lli\n", sf);

        cache_buffer = (char*)malloc(image_hdr.block_size * (next_max_count+1));
        if(cache_buffer == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data
        if(buffer == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        /// start restore image file to partition
        log_mesg(1, 0, 0, debug, "start restore data...\n");

        for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ) {

            r_size = 0;
            w_size = 0;


            if (pc_test_bit(block_id, bitmap)) {
                /// The block is used
                log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id);
                log_mesg(2, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap));

                memset(buffer, 0, image_hdr.block_size);
                r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt);
                log_mesg(3, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size);
                if (r_size <0)
                    log_mesg(0, 1, 1, debug, "read errno = %i \n", errno);

                /// read crc32 code and check it.
                crc_ck = crc32(crc_ck, buffer, r_size);
                crc_buffer = (char*)malloc(CRC_SIZE); ///alloc a memory to copy data
                if(crc_buffer == NULL) {
                    log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
                }
                c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt);
                if (c_size < CRC_SIZE)
                    log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno));

                memcpy(&crc, crc_buffer, CRC_SIZE);
                /*FIX: 64bit image can't ignore crc error*/
                if ((memcmp(&crc, &crc_ck, CRC_SIZE) != 0) && (!opt.ignore_crc)) {
                    log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), enlarge crc size and recheck again....\n ");
                    /// check again
                    buffer2 = (char*)malloc(image_hdr.block_size+CRC_SIZE); ///alloc a memory to copy data
                    if(buffer2 == NULL) {
                        log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
                    }
                    memcpy(buffer2, buffer, image_hdr.block_size);
                    memcpy(buffer2+image_hdr.block_size, crc_buffer, CRC_SIZE);
                    memcpy(buffer, buffer2+CRC_SIZE, image_hdr.block_size);

                    crc_ck2 = crc32(crc_ck2, buffer, r_size);
                    c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt);
                    if (c_size < CRC_SIZE)
                        log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno));
                    memcpy(&crc, crc_buffer, CRC_SIZE);
                    if ((memcmp(&crc, &crc_ck2, CRC_SIZE) != 0 )&& (!opt.ignore_crc)) {
                        log_mesg(0, 1, 1, debug, "CRC error again at %i...\n ", sf);
                    } else {
                        crc_ck = crc_ck2;
                    }
                    free(buffer2);
                } else {
                    crc_ck2 = crc_ck;
                }

                if(next != next_count) {
                    memset(cache_buffer, 0, image_hdr.block_size*next_max_count);
                    for (next_int = 1; next_int <= next_max_count; next_int++)
                    {
                        next_block_id = block_id+next_int;
                        if (pc_test_bit(next_block_id, bitmap)) {
                            next++;
                        } else {
                            next_count = next;
                            break;
                        }
                        next_count = next;
                    }
                    log_mesg(1, 0, 0, debug, "next = %i\n",next);
                }

                if ((next == next_count) &&(nx_current < next)) {
                    memcpy(cache_buffer+(image_hdr.block_size*nx_current), buffer, image_hdr.block_size);
                    w_size = 0;
                    nx_current++;
                }

                if ((next == next_count) && (nx_current == next)) {
#ifdef _FILE_OFFSET_BITS
                    offset = (off_t)((block_id-next+1) * image_hdr.block_size);
                    sf = lseek(dfw, offset, SEEK_SET);
                    if (sf == -1)
                        log_mesg(0, 1, 1, debug, "target seek error = %lli, ",sf);
#endif
                    /// write block from buffer to partition
                    w_size = write_all(&dfw, cache_buffer, (image_hdr.block_size*nx_current), &opt);
                    log_mesg(1, 0, 0, debug, "bs=%i and w=%i, ",(image_hdr.block_size*nx_current), w_size);
                    if (w_size != (int)image_hdr.block_size*nx_current)
                        log_mesg(0, 1, 1, debug, "write error %i \n", w_size);
                    next = 1;
                    next_count = next_max_count;
                    nx_current=0;
                }

                /// free buffer
                free(crc_buffer);
                copied++;					/// count copied block
                total_write += (unsigned long long) w_size;	/// count copied size

                /// read or write error
                //if ((r_size != w_size) || (r_size != image_hdr.block_size))
                //	log_mesg(0, 1, 1, debug, "read and write different\n");
                log_mesg(1, 0, 0, debug, "end\n");
            } else {
                /// for restore to row file, mount -o loop used.
                if ((block_id == (image_hdr.totalblock-1)) && (opt.restore_row_file)) {
                    write_last_block(&dfw, image_hdr.block_size, block_id, &opt);

                } else {
#ifndef _FILE_OFFSET_BITS
                    /// if the block is not used, I just skip it.
                    log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id);
                    sf = lseek(dfw, image_hdr.block_size, SEEK_CUR);
                    log_mesg(2, 0, 0, debug, "seek=%lli, ",sf);
                    if (sf == (off_t)-1)
                        log_mesg(0, 1, 1, debug, "seek error %lli errno=%i\n", (long long)offset, (int)errno);
                    log_mesg(2, 0, 0, debug, "end\n");
#endif
                }
            }
        } // end of for
        free(buffer);
    } else if (opt.dd) {
        sf = lseek(dfr, 0, SEEK_SET);
        log_mesg(1, 0, 0, debug, "seek %lli for reading data string\n",sf);
        if (sf == (off_t)-1)
            log_mesg(0, 1, 1, debug, "seek set %lli\n", sf);

        main_pos = lseek(dfr, 0, SEEK_CUR);
        log_mesg(1, 0, 0, debug, "man pos = %lli\n", main_pos);

        log_mesg(0, 0, 0, debug, "Total block %i\n", image_hdr.totalblock);

        buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data
        if(buffer == NULL) {
            log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
        }

        /// start clone partition to image file
        log_mesg(1, 0, 0, debug, "start backup data device-to-device...\n");
        for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ) {
            r_size = 0;
            w_size = 0;

            if (pc_test_bit(block_id, bitmap)) {
                /// if the block is used

                log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id);
                log_mesg(2, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap));
                offset = (off_t)(block_id * image_hdr.block_size);
#ifdef _FILE_OFFSET_BITS
                sf = lseek(dfr, offset, SEEK_SET);
                if (sf == -1)
                    log_mesg(0, 1, 1, debug, "source seek error = %lli, ",sf);
                sf = lseek(dfw, offset, SEEK_SET);
                if (sf == -1)
                    log_mesg(0, 1, 1, debug, "target seek error = %lli, ",sf);
#endif
                /// read data from source to buffer
                memset(buffer, 0, image_hdr.block_size);
                rescue_pos = lseek(dfr, 0, SEEK_CUR);
                r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt);
                log_mesg(3, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size);
                if (r_size != (int)image_hdr.block_size) {
                    if ((r_size == -1) && (errno == EIO)) {
                        if (opt.rescue) {
                            r_size = 0;
                            for (rescue_num = 0; rescue_num < image_hdr.block_size; rescue_num += SECTOR_SIZE) {
                                rescue_sector(&dfr, rescue_pos + rescue_num, buffer + rescue_num, &opt);
                                r_size+=SECTOR_SIZE;
                            }
                        } else
                            log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg);

                    } else
                        log_mesg(0, 1, 1, debug, "read error: %s(%i) \n", strerror(errno), errno);
                }

                /// write buffer to target
                w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt);
                log_mesg(3, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size);
                if (w_size != (int)image_hdr.block_size)
                    log_mesg(0, 1, 1, debug, "write error %i \n", w_size);

                copied++;                                       /// count copied block
                total_write += (unsigned long long)(w_size);    /// count copied size
                log_mesg(2, 0, 0, debug, "total=%lli, ", total_write);
                /// read or write error
                if (r_size != w_size)
                    log_mesg(0, 1, 1, debug, "read and write different\n");
                log_mesg(1, 0, 0, debug, "end\n");
            } else {
#ifndef _FILE_OFFSET_BITS
                /// if the block is not used, I just skip it.
                log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id);
                sf = lseek(dfr, image_hdr.block_size, SEEK_CUR);
                log_mesg(2, 0, 0, debug, "skip source seek=%lli, ",sf);
                sf = lseek(dfw, image_hdr.block_size, SEEK_CUR);
                log_mesg(2, 0, 0, debug, "skip target seek=%lli, ",sf);
                if (sf == (off_t)-1)
                    log_mesg(0, 1, 1, debug, "clone seek error %lli errno=%i\n", (long long)offset, (int)errno);
#endif
            }
        } /// end of for
        free(buffer);
    } else if (opt.domain) {
        log_mesg(0, 0, 0, debug, "Total block %i\n", image_hdr.totalblock);
        log_mesg(1, 0, 0, debug, "start writing domain log...\n");
        // write domain log comment and status line
        dprintf(dfw, "# Domain logfile created by %s v%s\n", EXECNAME, VERSION);
        dprintf(dfw, "# Source: %s\n", opt.source);
        dprintf(dfw, "# Offset: 0x%08llX\n", opt.offset_domain);
        dprintf(dfw, "# current_pos  current_status\n");
        dprintf(dfw, "0x%08llX     ?\n",
                opt.offset_domain + (image_hdr.totalblock * image_hdr.block_size));
        dprintf(dfw, "#      pos        size  status\n");
        // start logging the used/unused areas
        next_block_id = 0;
        cmp = pc_test_bit(0, bitmap);
        for( block_id = 0; block_id <= image_hdr.totalblock; block_id++ ) {
            if (block_id < image_hdr.totalblock) {
                nx_current = pc_test_bit(block_id, bitmap);
                if (nx_current == 1)
                    copied++;
            } else
                nx_current = -1;
            if (nx_current != cmp) {
                dprintf(dfw, "0x%08llX  0x%08llX  %c\n",
                        opt.offset_domain + (next_block_id * image_hdr.block_size),
                        (block_id - next_block_id) * image_hdr.block_size,
                        cmp ? '+' : '?');
                next_block_id = block_id;
                cmp = nx_current;
            }
            // don't bother updating progress
        } /// end of for
    }

    done = 1;
    pres = pthread_join(prog_thread, &p_result);
    update_pui(&prog, copied, block_id, done);
    sync_data(dfw, &opt);
    print_finish_info(opt);

    close (dfr);    /// close source
    close (dfw);    /// close target
    free(bitmap);   /// free bitmp
    close_pui(pui);
    printf("Cloned successfully.\n");
    if(opt.debug)
        close_log();
#ifdef MEMTRACE
    muntrace();
#endif
    return 0;	    /// finish
}
Ejemplo n.º 7
0
{
    SCOPED_RESLIST(rl_send_stub);

    struct child_start_info csi = {
        .flags = CHILD_MERGE_STDERR,
        .exename = "adb",
        .argv = argv_concat((const char*[]){"adb", NULL},
                            adb_args ?: empty_argv,
                            (const char*[]){"push", local, remote, NULL},
                            NULL),
    };
    struct child* adb = child_start(&csi);
    fdh_destroy(adb->fd[0]);

    char buf[512];
    size_t len = read_all(adb->fd[1]->fd, buf, sizeof (buf));
    fdh_destroy(adb->fd[1]);

    int status = child_wait(adb);
    if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
        if (len == sizeof (buf))
            --len;

        while (len > 0 && isspace(buf[len - 1]))
            --len;

        buf[len] = '\0';

        char* epos = buf;
        while (*epos != '\0' && isspace(*epos))
            ++epos;
Ejemplo n.º 8
0
static void
parse_arguments (int argc, char **argv, Arguments *arg)
{
  int c;

  /* defaults */

  arg->me = argv[0];
  arg->device = NULL;
  arg->forward_port = -1;
  arg->host_name = NULL;
  arg->host_port = DEFAULT_HOST_PORT;
  arg->proxy_name = NO_PROXY;
  arg->proxy_port = DEFAULT_PROXY_PORT;
  arg->proxy_buffer_size = NO_PROXY_BUFFER;
  arg->proxy_buffer_timeout = -1;
  arg->content_length = DEFAULT_CONTENT_LENGTH;
  arg->use_std = FALSE;
  arg->use_daemon = TRUE;
  arg->strict_content_length = FALSE;
  arg->keep_alive = DEFAULT_KEEP_ALIVE;
  arg->max_connection_age = DEFAULT_CONNECTION_MAX_TIME;
  arg->proxy_authorization = NULL;
  arg->user_agent = NULL;

  for (;;)
    {
      int option_index = 0;
      static struct option long_options[] =
      {
	{ "help", no_argument, 0, 'h' },
	{ "version", no_argument, 0, 'V' },
	{ "no-daemon", no_argument, 0, 'w' },
	{ "stdin-stdout", no_argument, 0, 's' },
#ifdef DEBUG_MODE
	{ "debug", required_argument, 0, 'D' },
	{ "logfile", required_argument, 0, 'l' },
#endif
	{ "proxy", required_argument, 0, 'P' },
	{ "device", required_argument, 0, 'd' },
	{ "timeout", required_argument, 0, 'T' },
	{ "keep-alive", required_argument, 0, 'k' },
	{ "user-agent", required_argument, 0, 'U' },
	{ "forward-port", required_argument, 0, 'F' },
	{ "content-length", required_argument, 0, 'c' },
	{ "strict-content-length", no_argument, 0, 'S' },
	{ "proxy-buffer-size", required_argument, 0, 'B' },
	{ "proxy-authorization", required_argument, 0, 'A' },
	{ "max-connection-age", required_argument, 0, 'M' },
	{ "proxy-authorization-file", required_argument, 0, 'z' },
	{ 0, 0, 0, 0 }
      };

      static const char *short_options = "A:B:c:d:F:hk:M:P:sST:U:Vwz:"
#ifdef DEBUG_MODE
	"D:l:"
#endif
	;

      c = getopt_long (argc, argv, short_options,
		       long_options, &option_index);
      if (c == -1)
	break;

      switch (c)
	{
	case 0:
	  fprintf (stderr, "option %s", long_options[option_index].name);
	  if (optarg)
	    fprintf (stderr, " with arg %s", optarg);
	  fprintf (stderr, "\n");
	  break;

	case 'A':
	  arg->proxy_authorization = optarg;
	  break;

	case 'B':
	  arg->proxy_buffer_size = atoi_with_postfix (optarg);
	  break;

	case 'c':
	  arg->content_length = atoi_with_postfix (optarg);
	  break;

	case 'd':
	  arg->device = optarg;
	  break;

#ifdef DEBUG_MODE
	case 'D':
	  if (optarg)
	    debug_level = atoi (optarg);
	  else
	    debug_level = 1;
	  break;

	case 'l':
	  debug_file = fopen (optarg, "w");
	  if (debug_file == NULL)
	    {
	      fprintf (stderr, "%s: couldn't open file %s for writing\n",
		       arg->me, optarg);
	      exit (1);
	    }
	  break;
#endif

	case 'F':
	  arg->forward_port = atoi (optarg);
	  break;

	case 'k':
	  arg->keep_alive = atoi (optarg);
	  break;

	case 'M':
	  arg->max_connection_age = atoi (optarg);
	  break;

	case 'h':
	  usage (stdout, arg->me);
	  exit (0);

	case 'P':
	  name_and_port (optarg, &arg->proxy_name, &arg->proxy_port);
	  if (arg->proxy_port == -1)
	    arg->proxy_port = DEFAULT_PROXY_PORT;
	  if (arg->proxy_buffer_timeout == -1)
	    arg->proxy_buffer_timeout = DEFAULT_PROXY_BUFFER_TIMEOUT;
	  break;

	case 's':
	  arg->use_std=TRUE;
	  arg->use_daemon=FALSE;
	  break;

	case 'S':
	  arg->strict_content_length = TRUE;
	  break;

	case 'T':
	  arg->proxy_buffer_timeout = atoi (optarg);
	  break;

	case 'U':
	  arg->user_agent = optarg;
	  break;

	case 'V':
	  printf ("htc (%s) %s\n", PACKAGE, VERSION);
	  exit (0);

	case 'w':
	  arg->use_daemon=FALSE;
	  break;

	case 'z':
	  {
	    struct stat s;
	    char *auth;
	    int f;

	    f = open (optarg, O_RDONLY);
	    if (f == -1)
	      {
		fprintf (stderr, "couldn't open %s: %s\n", optarg, strerror (errno));
		exit (1);
	      }

	    if (fstat (f, &s) == -1)
	      {
		fprintf (stderr, "error fstating %s: %s\n", optarg, strerror (errno));
		exit (1);
	      }

	    auth = malloc (s.st_size + 1);
	    if (auth == NULL)
	      {
		fprintf (stderr, "out of memory whilst allocating "
			"authentication string\n");
		exit (1);
	      }

	    if (read_all (f, auth, s.st_size) == -1)
	      {
		fprintf (stderr, "error reading %s: %s\n", optarg, strerror (errno));
		exit (1);
	      }

	    /*
	     * If file ends with a "\r\n" or "\n", chop them off.
	     */
	    if (s.st_size >= 1 && auth[s.st_size - 1] == '\n')
	      {
		s.st_size -=
		  (s.st_size >= 2 && auth[s.st_size - 2] == '\r') ? 2 : 1;
	      }

	    auth[s.st_size] = 0;
	    arg->proxy_authorization = auth;
	  }
	  break;

	case '?':
	  break;

	default:
	  fprintf (stderr, "?? getopt returned character code 0%o ??\n", c);
	}
    }

  if (optind == argc - 1)
    {
      name_and_port (argv[optind], &arg->host_name, &arg->host_port);
      if (arg->host_port == -1)
	arg->host_port = DEFAULT_HOST_PORT;
    }
  else
    {
      fprintf (stderr, "%s: the destination of the tunnel must be specified.\n"
	               "%s: try '%s --help' for help.\n",
	       arg->me, arg->me, arg->me);
      exit (1);
    }

  if (arg->device == NULL && arg->forward_port == -1 && !arg->use_std)
    {
      fprintf (stderr, "%s: one of --device, --forward-port or --stdin-stdout must be used.\n"
	               "%s: try '%s -help' for help.\n",
	       arg->me, arg->me, arg->me);
      exit (1);
    }

  if ((arg->device != NULL && arg->forward_port != -1) ||
      (arg->device != NULL && arg->use_std) ||
      (arg->forward_port != -1 && arg->use_std))
    {
      fprintf (stderr, "%s: only one of --device, --forward-port or --stdin-stdout can be used.\n"
	               "%s: try '%s --help' for help.\n",
	       arg->me, arg->me, arg->me);
      exit (1);
    }

  /* Removed test ((arg->device == NULL) == (arg->forward_port == -1))
   * by Sampo Niskanen - those have been tested already! */
  if (arg->host_name == NULL ||
      arg->host_port == -1 ||
      (arg->proxy_name != NO_PROXY && arg->proxy_port == -1))
    {
      usage (stderr, arg->me);
      exit (1);
    }

  if (debug_level == 0 && debug_file != NULL)
    {
      fprintf (stderr, "%s: --logfile can't be used without debugging\n",
	       arg->me);
      exit (1);
    }

  if (arg->proxy_name == NO_PROXY)
    {
      if (arg->proxy_buffer_size != NO_PROXY_BUFFER)
	{
	  fprintf (stderr, "%s: warning: --proxy-buffer-size can't be "
		   "used without --proxy\n", arg->me);
	  arg->proxy_buffer_size = NO_PROXY_BUFFER;
	}

      if (arg->proxy_buffer_timeout != -1)
	{
	  fprintf (stderr, "%s: warning: --proxy-buffer-timeout can't be "
		   "used without --proxy\n", arg->me);
	  arg->proxy_buffer_timeout = -1;
	}

      if (arg->proxy_authorization != NULL)
	{
	  fprintf (stderr, "%s: warning: --proxy-authorization can't be "
		   "used without --proxy\n", arg->me);
	  arg->proxy_authorization = NULL;
	}
    }
  else if (arg->proxy_buffer_size == NO_PROXY_BUFFER)
    arg->proxy_buffer_timeout = -1;
}
Ejemplo n.º 9
0
/**
 * main functiom - for colne or restore data
 */
int main(int argc, char **argv){ 

    char*		source;			/// source data
    char*		target;			/// target data
    char*		buffer;			/// buffer data for malloc used
    char*		buffer2;			/// buffer data for malloc used
    int			dfr, dfw;		/// file descriptor for source and target
    int			r_size, w_size;		/// read and write size
    //unsigned long long	block_id, copied = 0;	/// block_id is every block in partition
    /// copied is copied block count
    off_t		offset = 0, sf = 0;	/// seek postition, lseek result
    int			start, stop;		/// start, range, stop number for progress bar
    unsigned long long	total_write = 0;	/// the copied size 
    unsigned long long	needed_size = 0;	/// the copied size 
    unsigned long long	needed_mem  = 0;	/// the copied size 
    char		bitmagic[8] = "BiTmAgIc";// only for check postition
    char		bitmagic_r[8];		/// read magic string from image
    int			cmp;			/// compare magic string
    unsigned long	*bitmap;		/// the point for bitmap data
    int			debug = 0;		/// debug or not
    unsigned long	crc = 0xffffffffL;	/// CRC32 check code for writint to image
    unsigned long	crc_ck = 0xffffffffL;	/// CRC32 check code for checking
    unsigned long	crc_ck2 = 0xffffffffL;	/// CRC32 check code for checking
    int			c_size;			/// CRC32 code size
    //int			done = 0;
    int			s_count = 0;
    int			tui = 0;		/// text user interface
    int			pui = 0;		/// progress mode(default text)
    int			raw = 0;
    char		image_hdr_magic[512];
    int			next=1,next_int=1,next_max_count=7,next_count=7;
    unsigned long long	next_block_id;
    char*		cache_buffer;
    int			nx_current=0;
    int	flag;
    pthread_t prog_thread;
    int pres;
    void *p_result;
	
    //progress_bar	prog;			/// progress_bar structure defined in progress.h
    image_head		image_hdr;		/// image_head structure defined in partclone.h

    /**
     * get option and assign to opt structure
     * check parameter and read from argv
     */
    parse_options(argc, argv, &opt);

    /**
     * if "-d / --debug" given
     * open debug file in "/var/log/partclone.log" for log message 
     */
    debug = opt.debug;
    //if(opt.debug)
    open_log(opt.logfile);

    /**
     * using Text User Interface
     */
    if (opt.ncurses){
	pui = NCURSES;
	log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n");
    } else
	pui = TEXT;

    tui = open_pui(pui, opt.fresh);
    if ((opt.ncurses) && (tui == 0)){
	opt.ncurses = 0;
	log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n");
    }

    next_max_count = opt.max_block_cache-1;
    next_count = opt.max_block_cache-1;

    /// print partclone info
    print_partclone_info(opt);

    if (geteuid() != 0)
	log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n"); 
    else
	log_mesg(1, 0, 0, debug, "UID is root.\n");

    /// ignore crc check
    if(opt.ignore_crc)
	log_mesg(1, 0, 1, debug, "Ignore CRC error\n");

    /**
     * open source and target 
     * clone mode, source is device and target is image file/stdout
     * restore mode, source is image file/stdin and target is device
     * dd mode, source is device and target is device !!not complete
     */
#ifdef _FILE_OFFSET_BITS
    log_mesg(1, 0, 0, debug, "enable _FILE_OFFSET_BITS %i\n", _FILE_OFFSET_BITS);
#endif
    source = opt.source;
    target = opt.target;
    dfr = open_source(source, &opt);
    if (dfr == -1) {
	log_mesg(0, 1, 1, debug, "Erro EXIT.\n");
    }

    dfw = open_target(target, &opt);
    if (dfw == -1) {
	log_mesg(0, 1, 1, debug, "Error Exit.\n");
    }

    /**
     * get partition information like super block, image_head, bitmap
     * from device or image file.
     */

    if (opt.restore){

	log_mesg(1, 0, 0, debug, "restore image hdr - get image_head from image file\n");
	/// get first 512 byte
	r_size = read_all(&dfr, image_hdr_magic, 512, &opt);

	/// check the image magic
	if (memcmp(image_hdr_magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) == 0){
	    restore_image_hdr_sp(&dfr, &opt, &image_hdr, image_hdr_magic);

	    /// check memory size
	    if (check_mem_size(image_hdr, opt, &needed_mem) == -1)
		log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %llu bytes memory\n", needed_mem);

	    /// alloc a memory to restore bitmap
	    bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock));
	    if(bitmap == NULL){
		log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
	    }

	    /// check the file system
	    //if (strcmp(image_hdr.fs, FS) != 0)
	    //    log_mesg(0, 1, 1, debug, "%s can't restore from the image which filesystem is %s not %s\n", argv[0], image_hdr.fs, FS);

	    log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap);
	    log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

	    /// read and check bitmap from image file
	    log_mesg(0, 0, 1, debug, "Calculating bitmap... ");
	    log_mesg(0, 0, 1, debug, "Please wait... ");
	    get_image_bitmap(&dfr, opt, image_hdr, bitmap);

	    /// check the dest partition size.
	    if (opt.restore_raw_file)
		check_free_space(&dfw, image_hdr.device_size);
	    else if(opt.check)
		check_size(&dfw, image_hdr.device_size);

	    log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap);
	    log_mesg(0, 0, 1, debug, "done!\n");
	}else{
	    log_mesg(1, 0, 0, debug, "This is not partclone image.\n");
	    raw = 1;
	    //sf = lseek(dfr, 0, SEEK_SET);

	    log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n");

	    /// get Super Block information from partition
	    if (dfr != 0)
		initial_dd_hdr(dfr, &image_hdr);
	    else
		initial_dd_hdr(dfw, &image_hdr);

	    /// check the dest partition size.
	    if(opt.check){
		check_size(&dfw, image_hdr.device_size);
	    }
	}
    }

    log_mesg(1, 0, 0, debug, "print image_head\n");

    /// print option to log file
    if (debug)
	print_opt(opt);

    /// print image_head
    print_image_hdr_info(image_hdr, opt);

    /**
     * initial progress bar
     */
    start = 0;				/// start number of progress bar
    stop = (image_hdr.usedblocks+1);	/// get the end of progress number, only used block
    log_mesg(1, 0, 0, debug, "Initial Progress bar\n");
    /// Initial progress bar
    if (opt.no_block_detail)
	flag = NO_BLOCK_DETAIL;
    else
	flag = IO;
    progress_init(&prog, start, stop, image_hdr.totalblock, flag, image_hdr.block_size);
    copied = 0;				/// initial number is 0

    /**
     * thread to print progress
     */
    pres = pthread_create(&prog_thread, NULL, thread_update_pui, NULL);

    /**
     * start read and write data between device and image file
     */
    if ((opt.restore) && (!raw)) {

	/**
	 * read magic string from image file
	 * and check it.
	 */
	r_size = read_all(&dfr, bitmagic_r, 8, &opt); /// read a magic string
	cmp = memcmp(bitmagic, bitmagic_r, 8);
	if(cmp != 0)
	    log_mesg(0, 1, 1, debug, "bitmagic error %i\n", cmp);

	cache_buffer = (char*)malloc(image_hdr.block_size * (next_max_count+1));
	if(cache_buffer == NULL){
	    log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
	}
	buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data
	if(buffer == NULL){
	    log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
	}

	/// seek to the first
	sf = lseek(dfw, opt.offset, SEEK_SET);
	log_mesg(1, 0, 0, debug, "seek %lli for writing dtat string\n",sf);
	if (sf == (off_t)-1)
	    log_mesg(0, 1, 1, debug, "seek set %ji\n", (intmax_t)sf);
	/// start restore image file to partition
	for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ){

	    r_size = 0;
	    w_size = 0;

	    if (pc_test_bit(block_id, bitmap)){
		/// The block is used
		log_mesg(2, 0, 0, debug, "block_id=%llu, ",block_id);
		log_mesg(1, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap));

		memset(buffer, 0, image_hdr.block_size);
		r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt);
		log_mesg(1, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size);
		if (r_size <0)
		    log_mesg(0, 1, 1, debug, "read errno = %i \n", errno);

		/// read crc32 code and check it.
		crc_ck = crc32(crc_ck, buffer, r_size);
		char crc_buffer[CRC_SIZE];
		c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt);
		if (c_size < CRC_SIZE)
		    log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno));
		/*FIX: 64bit image can't ignore crc error*/
		if ((memcmp(crc_buffer, &crc_ck, CRC_SIZE) != 0) && (!opt.ignore_crc) ){
		    log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), enlarge crc size and recheck again....\n ");
		    /// check again
		    buffer2 = (char*)malloc(image_hdr.block_size+CRC_SIZE); ///alloc a memory to copy data
		    if(buffer2 == NULL){
			log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
		    }
		    memcpy(buffer2, buffer, image_hdr.block_size);
		    memcpy(buffer2+image_hdr.block_size, crc_buffer, CRC_SIZE);
		    memcpy(buffer, buffer2+CRC_SIZE, image_hdr.block_size);

		    crc_ck2 = crc32(crc_ck2, buffer, r_size);
		    c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt);
		    if (c_size < CRC_SIZE)
			log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno));
		    if ((memcmp(crc_buffer, &crc_ck2, CRC_SIZE) != 0) && (!opt.ignore_crc)){
			log_mesg(0, 1, 1, debug, "CRC error again at %ji...\n ", (intmax_t)sf);
		    } else {
			crc_ck = crc_ck2;
		    }
		    free(buffer2);

		} else {
		    crc_ck2 = crc_ck;
		}

		if(next != next_count){
		    memset(cache_buffer, 0, image_hdr.block_size*next_max_count);
		    for (next_int = 1; next_int <= next_max_count; next_int++)
		    {
			next_block_id = block_id+next_int;
			if (pc_test_bit(next_block_id, bitmap)) {
			    next++;
			} else {
			    next_count = next;    
			    break;
			}
			next_count = next;
		    }
		    log_mesg(1, 0, 0, debug, "next = %i\n",next);
		}

		if ((next == next_count) &&(nx_current < next)){
		    memcpy(cache_buffer+(image_hdr.block_size*nx_current), buffer, image_hdr.block_size);
		    w_size = 0;
		    nx_current++;
		}

		if ((next == next_count) && (nx_current == next)){
#ifdef _FILE_OFFSET_BITS
		    offset = (off_t)(((block_id-next+1) * image_hdr.block_size)+opt.offset);
		    sf = lseek(dfw, offset, SEEK_SET);
		    if (sf == -1)
			log_mesg(0, 1, 1, debug, "target seek error = %ji, ", (intmax_t)sf);
#endif
		    /// write block from buffer to partition
		    w_size = write_all(&dfw, cache_buffer, (image_hdr.block_size*nx_current), &opt);
		    log_mesg(1, 0, 0, debug, "bs=%i and w=%i, ",(image_hdr.block_size*nx_current), w_size);
		    if (w_size != image_hdr.block_size*nx_current)
			log_mesg(0, 1, 1, debug, "write error %i \n", w_size);
		    next = 1;
		    next_count = next_max_count;
		    nx_current=0;
		}

		copied++;					/// count copied block
		total_write += (unsigned long long) w_size;	/// count copied size

		/// read or write error
		//if ((r_size != w_size) || (r_size != image_hdr.block_size))
		//	log_mesg(0, 1, 1, debug, "read and write different\n");
		log_mesg(1, 0, 0, debug, "end\n");
	    } else {
		/// for restore to raw file, mount -o loop used.
		if ((block_id == (image_hdr.totalblock-1)) && (opt.restore_raw_file)){
		    write_last_block(&dfw, image_hdr.block_size, block_id, &opt);

		} else {
#ifndef _FILE_OFFSET_BITS
		    /// if the block is not used, I just skip it.
		    log_mesg(2, 0, 0, debug, "block_id=%llu, ",block_id);
		    sf = lseek(dfw, image_hdr.block_size, SEEK_CUR);
		    log_mesg(2, 0, 0, debug, "seek=%ji, ", (intmax_t)sf);
		    if (sf == (off_t)-1)
			log_mesg(0, 1, 1, debug, "seek error %ji errno=%i\n", (intmax_t)offset, errno);
		    log_mesg(2, 0, 0, debug, "end\n");
#endif
		}
	    }
	    //if (!opt.quiet)
	//	update_pui(&prog, copied, block_id, done);
	} // end of for
	/// free buffer
	free(cache_buffer);
	free(buffer);
	done = 1;
	pres = pthread_join(prog_thread, &p_result);
	update_pui(&prog, copied, block_id, done);
	sync_data(dfw, &opt);	
    } else if ((opt.restore) && (raw)){
	/// start clone partition to image file

	//write image_head to image file
	w_size = write_all(&dfw, image_hdr_magic, 512, &opt);
	if(w_size == -1)
	    log_mesg(0, 1, 1, debug, "write image_hdr to image error\n");

	block_id = 1;

	buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data
	if(buffer == NULL){
	    log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno));
	}

	do {
	    r_size = 0;
	    w_size = 0;
	    memset(buffer, 0, image_hdr.block_size);

	    log_mesg(1, 0, 0, debug, "block_id=%llu, ",block_id);

	    /// read data from source to buffer
	    r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt);
	    log_mesg(1, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size);
	    if (r_size != (int)image_hdr.block_size){
		if (r_size == 0){
		    //EIO
		    done = 1;
		} else {
		    log_mesg(0, 1, 1, debug, "read error: %s(%i) rsize=%i\n", strerror(errno), errno, r_size);
		}
	    }

	    if (r_size == image_hdr.block_size){
		/// write buffer to target
		w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt);
		log_mesg(2, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size);
		if (w_size != (int)image_hdr.block_size)
		    log_mesg(0, 1, 1, debug, "write error %i \n", w_size);
	    } else if (r_size < image_hdr.block_size){
		/// write readed buffer to target
		w_size = write_all(&dfw, buffer, r_size, &opt);
		log_mesg(2, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size);
		if (w_size != r_size)
		    log_mesg(0, 1, 1, debug, "write error %i \n", w_size);
	    } else {
		w_size = 0;
	    }

	    /// read or write error
	    if (r_size != w_size)
		log_mesg(0, 1, 1, debug, "read and write different\n");
	    log_mesg(1, 0, 0, debug, "end\n");
	    block_id++;
	    copied++;					/// count copied block
	    total_write += (unsigned long long)(w_size);	/// count copied size
	    log_mesg(1, 0, 0, debug, "total=%llu, ", total_write);

	    //if (!opt.quiet)
		//update_pui(&prog, copied, block_id, done);
	} while (done == 0);/// end of for    
	pres = pthread_join(prog_thread, &p_result);
	update_pui(&prog, copied, block_id, done);
	sync_data(dfw, &opt);	
	/// free buffer
	free(buffer);
    }

    print_finish_info(opt);

    close (dfr);    /// close source
    close (dfw);    /// close target
    free(bitmap);   /// free bitmp
    close_pui(pui);
    fprintf(stderr, "Cloned successfully.\n");
    if(opt.debug)
	close_log();
    return 0;	    /// finish
}
Ejemplo n.º 10
0
int
do_http_get(int s, const char *path, const char *hostname,
            size_t expected_bytes, size_t *read_bytes, size_t *write_bytes,
            struct timeval *datarequesttime,
            struct timeval *dataresponsetime,
            struct timeval *datacompletetime,
            struct timeval *dataperctime) {
  char buf[HTTP_BUF_LEN];
  int len; // Length of request, not including \0
  int perc_logged = -1; // Last logged timestamp for fraction of received bytes
  char is_first = 1;

  len = snprintf(buf, HTTP_BUF_LEN, "GET %s HTTP/1.0\r\nPragma: no-cache\r\n"
                                    "Host: %s\r\n\r\n", path, hostname);

  // Check for overflow or error
  if (len >= HTTP_BUF_LEN || len < 0)
    return -1;

  // Write the request
  fprintf(stderr, "Response: %s\n", buf);
  if (write_all(s, buf, len, 1) != len)
    return -1;
  *write_bytes = len;
  // Get when request is sent
  if (gettimeofday(datarequesttime, NULL)) {
    perror("getting datarequesttime");
    return -1;
  }    

  // Half-close the socket
  //if (shutdown(s, SHUT_WR))
  //  return -1;

  // Default, in case no data is returned
  dataresponsetime -> tv_sec = dataresponsetime -> tv_usec = 0;

  // Read the response
  *read_bytes = 0;
  while ((len = read_all(s, buf, HTTP_READ_LEN, 1)) > 0) {
    buf[len] = '\0';
    fprintf(stderr, "Response: %s\n", buf);
    *read_bytes += len;
    // Get when start of response was received
    if (is_first) {
      is_first = 0;
      if (gettimeofday(dataresponsetime, NULL)) {
        perror("getting dataresponsetime");
        return -1;
      }
    }
    // Get when the next 10% of expected bytes are received; this is a
    // while loop for cases when we expect only very few bytes and read
    // more than 10% of them in a single read_all() call.
    while (*read_bytes < expected_bytes &&
        (*read_bytes * 10) / expected_bytes > perc_logged + 1) {
      if (gettimeofday(&dataperctime[++perc_logged], NULL)) {
       perror("getting dataperctime");
       return -1;
      }
    }
  }

  // Get when response is complete
  if (gettimeofday(datacompletetime, NULL)) {
    perror("getting datacompletetime");
    return -1;
  }
  
  return len;
}
Ejemplo n.º 11
0
/** Send a resolve request for <b>hostname</b> to the Tor listening on
 * <b>sockshost</b>:<b>socksport</b>.  Store the resulting IPv4
 * address (in host order) into *<b>result_addr</b>.
 */
static int
do_connect(const char *hostname, const char *filename, uint32_t sockshost, uint16_t socksport,
           int reverse, int version, size_t expected_bytes,
           uint32_t *result_addr, char **result_hostname)
{

  int s;
  struct sockaddr_in socksaddr;
  char *req = NULL;
  int len = 0;
  int retval;

  assert(hostname);
  assert(filename);
  assert(result_addr);
  assert(version == 4 || version == 5);

  *result_addr = 0;
  *result_hostname = NULL;

  // Get time that connection was started
  if (gettimeofday(&starttime, NULL)) {
    perror("getting starttime");
    return -1;
  }

  // Create the socket for connecting to SOCKS server
  s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  if (s<0) {
    perror("creating socket");
    return -1;
  }
  // Get time that socket was created
  if (gettimeofday(&sockettime, NULL)) {
    perror("getting sockettime");
    return -1;
  }

  // Connect to the SOCKS server
  memset(&socksaddr, 0, sizeof(socksaddr));
  socksaddr.sin_family = AF_INET;
  socksaddr.sin_port = htons(socksport);
  socksaddr.sin_addr.s_addr = htonl(sockshost);
  if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) {
    perror("connecting to SOCKS host");
    return -1;
  }
  // Get time that socket was connected
  if (gettimeofday(&connecttime, NULL)) {
    perror("getting connecttime");
    return -1;
  }

  // Negotiate authentication method for SOCKS 5
  if (version == 5) {
    retval = do_socks5_negotiate(s);
    if (retval)
      return retval;
  }  
  // Get time that negotiation was completed
  if (gettimeofday(&negotiatetime, NULL)) {
    perror("getting negotiatetime");
    return -1;
  }

  if ((len = build_socks_connect_request(&req, "", hostname, reverse,
                                         version))<0) {
    fprintf(stderr, "error generating SOCKS request: %d\n", len);
    return -1;
  }
  if (write_all(s, req, len, 1) != len) {
    perror("sending SOCKS request");
    free(req);
    return -1;
  }
  free(req);
  // Get time that request was sent
  if (gettimeofday(&requesttime, NULL)) {
    perror("getting requesttime");
    return -1;
  }

  if (version == 4) {
    char reply_buf[RESPONSE_LEN_4];
    if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) {
      fprintf(stderr, "Error reading SOCKS4 response.\n");
      return -1;
    }
    if (parse_socks4a_connect_response(reply_buf, RESPONSE_LEN_4,
                                       result_addr)<0){
      return -1;
    }
  } else {
    char reply_buf[RESPONSE_LEN_5];
    if (read_all(s, reply_buf, RESPONSE_LEN_5, 1) != RESPONSE_LEN_5) {
      fprintf(stderr, "Error reading SOCKS5 response\n");
      return -1;
    }
    if (parse_socks5_connect_response(reply_buf, RESPONSE_LEN_5, s,
                                      result_addr, result_hostname)<0){
      return -1;
    }
  }
  // Get time that response was received
  if (gettimeofday(&responsetime, NULL)) {
    perror("getting responsetime");
    return -1;
  }

  /*
  char reply_buf[1];
  while (read_all(s, reply_buf, 1, 1) != 0) {
    fprintf(stderr,"Extra data: 0x%x\n", reply_buf[0]);
  } 
  */
  
  // Request a file using HTTP
  do_http_get(s, filename, hostname, expected_bytes, &read_bytes, &write_bytes,
             &datarequesttime, &dataresponsetime, &datacompletetime,
             dataperctime);


  didtimeout = 0;

  // Output status information
  output_status_information();

  return 0;
}
Ejemplo n.º 12
0
// if the image is in a directly supported format return the raw data otherwise decode & return the bitmap
bool MCImageImport(IO_handle p_stream, IO_handle p_mask_stream, MCPoint &r_hotspot, char *&r_name, MCImageCompressedBitmap *&r_compressed, MCImageBitmap *&r_bitmap)
{
	bool t_success = true;

	uindex_t t_width = 0, t_height = 0;

	uint8_t t_head[8];
	uindex_t t_size = 8;

	uint32_t t_compression = F_RLE;

	if (t_success)
		t_success = MCS_read(t_head, sizeof(uint8_t), t_size, p_stream) == IO_NORMAL &&
		t_size == 8 && MCS_seek_cur(p_stream, -8) == IO_NORMAL;

	if (t_success)
	{
		if (memcmp(t_head, "GIF87a", 6) == 0)
			t_compression = F_GIF;
		else if (memcmp(t_head, "GIF89a", 6) == 0)
			t_compression = F_GIF;
		else if (memcmp(t_head, "\211PNG", 4) == 0)
			t_compression = F_PNG;
		else if (memcmp(t_head, "\xff\xd8", 2) == 0)
			t_compression = F_JPEG;
		else if (MCImageGetMetafileGeometry(p_stream, t_width, t_height))
			t_compression = F_PICT;

		if (t_compression != F_RLE)
		{
			t_success = MCImageCreateCompressedBitmap(t_compression, r_compressed);
			if (t_success)
			{
				if (t_success)
					t_success = read_all(p_stream, r_compressed->data, r_compressed->size);

				r_compressed->width = t_width;
				r_compressed->height = t_height;
			}
		}
		else
		{
			MCImageBitmap *t_bitmap = nil;
			
			if (memcmp(t_head, "BM", 2) == 0)
				t_success = MCImageDecodeBMP(p_stream, r_hotspot, t_bitmap);
			else if (memcmp(t_head, "#define", 7) == 0)
				t_success = MCImageDecodeXBM(p_stream, r_hotspot, r_name, t_bitmap);
			else if (memcmp(t_head, "/* XPM", 6) == 0)
				t_success = MCImageDecodeXPM(p_stream, t_bitmap);
			else if (t_head[0] == 'P' && (t_head[1] >= '1' && t_head[1] <= '6'))
			{
				t_success = MCImageDecodeNetPBM(p_stream, t_bitmap);
				// may have a mask image
				if (t_success && p_mask_stream != nil)
				{
					MCImageBitmap *t_mask = nil;
					t_success = MCImageDecodeNetPBM(p_mask_stream, t_mask) &&
						MCImageBitmapApplyMask(t_bitmap, t_mask);
					MCImageFreeBitmap(t_mask);
				}
			}
			else // if all else fails, assume it's an XWD
				t_success = MCImageDecodeXWD(p_stream, r_name, t_bitmap);

			if (t_success)
				r_bitmap = t_bitmap;
			else
				MCImageFreeBitmap(t_bitmap);
		}
	}

	return t_success;
}
Ejemplo n.º 13
0
int spawn(char *argv[], int *status)
{
	pid_t pid;
	int err_pipe[2];

	if (pipe(err_pipe) == -1)
		return -1;

	pid = fork();
	if (pid == -1) {
		/* error */
		return -1;
	} else if (pid == 0) {
		/* child */
		int dev_null, err, i;

		close(err_pipe[0]);
		fcntl(err_pipe[1], F_SETFD, FD_CLOEXEC);

		/* redirect stdout and stderr to /dev/null if possible */
		dev_null = open("/dev/null", O_WRONLY);
		if (dev_null != -1) {
			dup2(dev_null, 1);
			dup2(dev_null, 2);
		}

		/* not interactive, close stdin */
		close(0);

		/* close unused fds */
		for (i = 3; i < 30; i++)
			close(i);

		execvp(argv[0], argv);

		/* error */
		err = errno;
		write_all(err_pipe[1], &err, sizeof(int));
		exit(1);
	} else {
		/* parent */
		int rc, errno_save, child_errno;

		close(err_pipe[1]);
		rc = read_all(err_pipe[0], &child_errno, sizeof(int));
		errno_save = errno;
		close(err_pipe[0]);

		waitpid(pid, status, 0);

		if (rc == -1) {
			errno = errno_save;
			return -1;
		}
		if (rc == sizeof(int)) {
			errno = child_errno;
			return -1;
		}
		if (rc != 0) {
			errno = EMSGSIZE;
			return -1;
		}
		return 0;
	}
}
Ejemplo n.º 14
0
Archivo: buse.c Proyecto: eliq/BUSE
int buse_main(const char* dev_file, const struct buse_operations *aop, void *userdata)
{
  int sp[2];
  int nbd, sk, err, tmp_fd;
  u_int64_t from;
  u_int32_t len;
  ssize_t bytes_read;
  struct nbd_request request;
  struct nbd_reply reply;
  void *chunk;

  assert(!socketpair(AF_UNIX, SOCK_STREAM, 0, sp));

  nbd = open(dev_file, O_RDWR);
  assert(nbd != -1);

  assert(ioctl(nbd, NBD_SET_SIZE, aop->size) != -1);
  assert(ioctl(nbd, NBD_CLEAR_SOCK) != -1);

  if (!fork()) {
    /* The child needs to continue setting things up. */
    close(sp[0]);
    sk = sp[1];

    if(ioctl(nbd, NBD_SET_SOCK, sk) == -1){
      fprintf(stderr, "ioctl(nbd, NBD_SET_SOCK, sk) failed.[%s]\n", strerror(errno));
    }
#if defined NBD_SET_FLAGS && defined NBD_FLAG_SEND_TRIM
    else if(ioctl(nbd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM) == -1){
      fprintf(stderr, "ioctl(nbd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM) failed.[%s]\n", strerror(errno));
    }
#endif
    else{
      err = ioctl(nbd, NBD_DO_IT);
      fprintf(stderr, "nbd device terminated with code %d\n", err);
      if (err == -1)
	fprintf(stderr, "%s\n", strerror(errno));
    }

    ioctl(nbd, NBD_CLEAR_QUE);
    ioctl(nbd, NBD_CLEAR_SOCK);

    exit(0);
  }

  /* The parent opens the device file at least once, to make sure the
   * partition table is updated. Then it closes it and starts serving up
   * requests. */

  tmp_fd = open(dev_file, O_RDONLY);
  assert(tmp_fd != -1);
  close(tmp_fd);

  close(sp[1]);
  sk = sp[0];

  reply.magic = htonl(NBD_REPLY_MAGIC);
  reply.error = htonl(0);

  while ((bytes_read = read(sk, &request, sizeof(request))) > 0) {
    assert(bytes_read == sizeof(request));
    memcpy(reply.handle, request.handle, sizeof(reply.handle));

    len = ntohl(request.len);
    from = ntohll(request.from);
    assert(request.magic == htonl(NBD_REQUEST_MAGIC));

    switch(ntohl(request.type)) {
      /* I may at some point need to deal with the the fact that the
       * official nbd server has a maximum buffer size, and divides up
       * oversized requests into multiple pieces. This applies to reads
       * and writes.
       */
    case NBD_CMD_READ:
      fprintf(stderr, "Request for read of size %d\n", len);
      assert(aop->read);
      chunk = malloc(len);
      reply.error = aop->read(chunk, len, from, userdata);
      write_all(sk, (char*)&reply, sizeof(struct nbd_reply));
      if(reply.error == 0)
	write_all(sk, (char*)chunk, len);
      free(chunk);
      break;
    case NBD_CMD_WRITE:
      fprintf(stderr, "Request for write of size %d\n", len);
      assert(aop->write);
      chunk = malloc(len);
      read_all(sk, chunk, len);
      reply.error = aop->write(chunk, len, from, userdata);
      free(chunk);
      write_all(sk, (char*)&reply, sizeof(struct nbd_reply));
      break;
    case NBD_CMD_DISC:
      /* Handle a disconnect request. */
      assert(aop->disc);
      aop->disc(userdata);
      return 0;
#ifdef NBD_FLAG_SEND_FLUSH
    case NBD_CMD_FLUSH:
      assert(aop->flush);
      reply.error = aop->flush(userdata);
      write_all(sk, (char*)&reply, sizeof(struct nbd_reply));
      break;
#endif
#ifdef NBD_FLAG_SEND_TRIM
    case NBD_CMD_TRIM:
      assert(aop->trim);
      reply.error = aop->trim(from, len, userdata);
      write_all(sk, (char*)&reply, sizeof(struct nbd_reply));
      break;
#endif
    default:
      assert(0);
    }
  }
  if (bytes_read == -1)
    fprintf(stderr, "%s\n", strerror(errno));
  return 0;
}
Ejemplo n.º 15
0
Mod::Mod(tl::FsNode& root) {
	
	auto sprite_dir = root / "sprites"_S;
	auto sound_dir = root / "sounds"_S;

	this->large_sprites = read_full_tga((sprite_dir / "large.tga"_S).try_get_source(), &this->pal);
	this->small_sprites = read_full_tga((sprite_dir / "small.tga"_S).try_get_source());
	this->small_font_sprites = read_full_tga((sprite_dir / "text.tga"_S).try_get_source());
	//this->font_sprites = read_full_tga((sprite_dir / "font.tga"_S).try_get_source(), &this->pal);

	tl::Palette dummyPal;
	tl::read_tga((sprite_dir / "font.tga"_S).try_get_source(), this->font_sprites, dummyPal);
	

	worm_sprites[0] = tl::Image(16, 7 * 3 * 16, 4);
	worm_sprites[1] = tl::Image(16, 7 * 3 * 16, 4);
	muzzle_fire_sprites[0] = tl::Image(16, 7 * 16, 4);
	muzzle_fire_sprites[1] = tl::Image(16, 7 * 16, 4);

	auto worms = large_sprites.crop(tl::RectU(0, 16 * 16, 16, 16 * (16 + 7 * 3)));
	worm_sprites[0].blit(worms);
	worm_sprites[1].blit(worms, 0, 0, 0, tl::ImageSlice::Flip);

	auto muzzle_fire = large_sprites.crop(tl::RectU(0, 16 * 9, 16, 16 * (9 + 7)));
	muzzle_fire_sprites[0].blit(muzzle_fire);
	muzzle_fire_sprites[1].blit(muzzle_fire, 0, 0, 0, tl::ImageSlice::Flip);

	{
		for (u32 y = 0; y < this->large_sprites.height(); ++y) {
			LargeSpriteRow row = {0, 0};
			for (u32 x = 0; x < 16; ++x) {
				auto p = tl::Color(this->large_sprites.unsafe_pixel32(x, y));
				bool draw = p.a() > 0;
				bool half = p.a() == 1 || p.a() == 2;

				bool bit0 = draw;
				bool bit1 = !(!draw || half);
								
				row.bit0 |= bit0 << x;
				row.bit1 |= bit1 << x;
			}

			this->large_sprites_bits.push_back(row);
		}
	}

	auto r = (root / "tc.dat"_S);

	auto src = r.try_get_source();
	auto buf = src.read_all();

	ss::Expander expander(buf);

	//auto* tc = expander.expand_root<TcData>(*(ss::StructOffset<TcDataReader> const*)buf.begin());
	auto* tc = (liero::TcData *)expander.expand(liero::TcData::expand_program(), buf.begin());

	this->tcdata = tc;
	this->weapon_types = tc->weapons().begin();
	this->level_effects = tc->level_effects().begin();
	this->nobject_types = tc->nobjects().begin();
	this->sobject_types = tc->sobjects().begin();

	for (auto& sound_name : tc->sound_names()) {
		tl::Vec<i16> sound_data;
		read_wav((sound_dir / sound_name.get()).try_get_source(), sound_data);

		this->sounds.push_back(move(sound_data));
	}

	this->mod_data = expander.to_buffer();
}
Ejemplo n.º 16
0
/* XXX it would really be good to have a built-in I/O forwarder so
 * that we can make sure the output from this test program looks
 * somewhat reasonable.  It's also the sure-fire way to make sure that
 * we know what's really going on. */
static
int test_run_arr(int nprocs, int arr, int flags,
		 int (*test_func)(int, struct bproc_test_info_t *)) {
    int pid,a,r,i;
    int pfd[2];
    int status;

    struct bproc_test_info_t ti;

    if (nnodes == -1) {
	fprintf(stderr, "bproc_test: call bproc_test_init() first!\n");
	exit(1);
    }

    /* Assign nodes to this arrangement */
    ti.nprocs  = nprocs;
    ti.arr     = arr;
    ti.scratch = 0;
    for (i=0; i < nprocs; i++) {
	if (proc_arr(arr, i) == proc_fe)
	    ti.node[i] = BPROC_NODE_MASTER;
	else if (proc_arr(arr, i) == proc_inv)
	    ti.node[i] = node_inv;
	else {
	    a = proc_arr(arr, i);
	    if (a >= proc_sl_d)
		a -= proc_sl_d - proc_sl;
	    a -= proc_sl;

	    if (a >= nnodes)
		return 2;
	    ti.node[i] = nodes[a];
	}
    }

    /* Setup the first (parent) process */
    pid = bproc_rfork(ti.node[0]);
    if (pid < 0) {
	fprintf(stderr, "bproc_rfork(%d)=%d; errno=%d (%s)\n",
		ti.node[0], pid, errno, bproc_strerror(errno));
	return 3;
    }
    if (pid > 0) {
	if (waitpid(pid, &status, 0) != pid) {
	    fprintf(stderr, "Failed to wait on proc 0: %s\n", strerror(errno));
	    return 1;
	}
	if (!WIFEXITED(status)) {
	    printf(" abnormal exit");
	    return 1;
	} else if (WEXITSTATUS(status) != 0) {
	    printf(" exit_status=%d", WEXITSTATUS(status));
	    return 1;
	} else {
	    return 0;
	}
    }

    /* PROC 0: PARENT */
    ti.pid[0] = getpid();

    if (flags & bproc_test_no_auto_create)
	exit(test_func(0, &ti));	

    /* Create cihld processes */
    for (i=1; i < nprocs; i++) {
	a = proc_arr(arr,i);
	pipe(pfd);
	pid = fork();
	if (pid < 0) {
	    perror("fork");
	    exit(100);
	}
	if (pid == 0) {
	    close(pfd[0]);
	    if (pfd[1] != STDOUT_FILENO) {
		dup2(pfd[1], STDOUT_FILENO);
		close(pfd[1]);
	    }

	    /* We need the cruddy built-in I/O forwarding here because
	     * we use it to inform the parent about the PID *after*
	     * moving.  The side-effect of doing it this way is that
	     * we know that child process is on the node where it
	     * should be before going on. */
	    if (ti.node[i] != ti.node[0]) {
		if (bproc_move(ti.node[i]))
		    exit(101);
	    }

	    /* PROC i: CHILD */
	    if (proc_isdetach(a)) {
		/* Detach self from parent by forking again. */
		pid = fork();
		if (pid < 0)
		    exit(102);
		if (pid > 0)
		    exit(0);
		/* child continues and does stuff */
	    }
	    /* Tell parent about PID */
	    ti.pid[i] = getpid();
	    if (write(STDOUT_FILENO, &ti.pid[i], sizeof(ti.pid[i]))
		!= sizeof(ti.pid[i])) {
		exit(103);
	    }
	    close(STDOUT_FILENO);

	    /* Do the test */
	    exit(test_func(i, &ti));
	}
	/* PROC 0: PARENT */
	close(pfd[1]);
	r = read_all(pfd[0], &ti.pid[i], sizeof(ti.pid[i]));
	if (r != sizeof(ti.pid[i])) {
	    fprintf(stderr, "Failed to get PID from child %d\n", i);
	    exit(104);
	}
	close(pfd[0]);

	if (proc_isdetach(a)) {
	    int status;
	    /* Wait for intermediate process to exit */
	    if (waitpid(pid, &status, 0) != pid)
		exit(105);
	    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
		exit(106);
	}
    }

    exit(test_func(0, &ti));
}
Ejemplo n.º 17
0
/** Send a resolve request for <b>hostname</b> to the Tor listening on
 * <b>sockshost</b>:<b>socksport</b>.  Store the resulting IPv4
 * address (in host order) into *<b>result_addr</b>.
 */
static int
do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
           int reverse, int version,
           tor_addr_t *result_addr, char **result_hostname)
{
    int s = -1;
    struct sockaddr_in socksaddr;
    char *req = NULL;
    ssize_t len = 0;

    tor_assert(hostname);
    tor_assert(result_addr);
    tor_assert(version == 4 || version == 5);

    tor_addr_make_unspec(result_addr);
    *result_hostname = NULL;

    s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
    if (s<0) {
        log_sock_error("creating_socket", -1);
        return -1;
    }

    memset(&socksaddr, 0, sizeof(socksaddr));
    socksaddr.sin_family = AF_INET;
    socksaddr.sin_port = htons(socksport);
    socksaddr.sin_addr.s_addr = htonl(sockshost);
    if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) {
        log_sock_error("connecting to SOCKS host", s);
        goto err;
    }

    if (version == 5) {
        char method_buf[2];
        if (write_all(s, "\x05\x01\x00", 3, 1) != 3) {
            log_err(LD_NET, "Error sending SOCKS5 method list.");
            goto err;
        }
        if (read_all(s, method_buf, 2, 1) != 2) {
            log_err(LD_NET, "Error reading SOCKS5 methods.");
            goto err;
        }
        if (method_buf[0] != '\x05') {
            log_err(LD_NET, "Unrecognized socks version: %u",
                    (unsigned)method_buf[0]);
            goto err;
        }
        if (method_buf[1] != '\x00') {
            log_err(LD_NET, "Unrecognized socks authentication method: %u",
                    (unsigned)method_buf[1]);
            goto err;
        }
    }

    if ((len = build_socks_resolve_request(&req, "", hostname, reverse,
                                           version))<0) {
        log_err(LD_BUG,"Error generating SOCKS request");
        tor_assert(!req);
        goto err;
    }
    if (write_all(s, req, len, 1) != len) {
        log_sock_error("sending SOCKS request", s);
        tor_free(req);
        goto err;
    }
    tor_free(req);

    if (version == 4) {
        char reply_buf[RESPONSE_LEN_4];
        if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) {
            log_err(LD_NET, "Error reading SOCKS4 response.");
            goto err;
        }
        if (parse_socks4a_resolve_response(hostname,
                                           reply_buf, RESPONSE_LEN_4,
                                           result_addr)<0) {
            goto err;
        }
    } else {
        char reply_buf[16];
        if (read_all(s, reply_buf, 4, 1) != 4) {
            log_err(LD_NET, "Error reading SOCKS5 response.");
            goto err;
        }
        if (reply_buf[0] != 5) {
            log_err(LD_NET, "Bad SOCKS5 reply version.");
            goto err;
        }
        /* Give a user some useful feedback about SOCKS5 errors */
        if (reply_buf[1] != 0) {
            log_warn(LD_NET,"Got SOCKS5 status response '%u': %s",
                     (unsigned)reply_buf[1],
                     socks5_reason_to_string(reply_buf[1]));
            if (reply_buf[1] == 4 && !strcasecmpend(hostname, ".onion")) {
                log_warn(LD_NET,
                         "%s is a hidden service; those don't have IP addresses. "
                         "To connect to a hidden service, you need to send the hostname "
                         "to Tor; we suggest an application that uses SOCKS 4a.",
                         hostname);
            }
            goto err;
        }
        if (reply_buf[3] == 1) {
            /* IPv4 address */
            if (read_all(s, reply_buf, 4, 1) != 4) {
                log_err(LD_NET, "Error reading address in socks5 response.");
                goto err;
            }
            tor_addr_from_ipv4n(result_addr, get_uint32(reply_buf));
        } else if (reply_buf[3] == 4) {
            /* IPv6 address */
            if (read_all(s, reply_buf, 16, 1) != 16) {
                log_err(LD_NET, "Error reading address in socks5 response.");
                goto err;
            }
            tor_addr_from_ipv6_bytes(result_addr, reply_buf);
        } else if (reply_buf[3] == 3) {
            /* Domain name */
            size_t result_len;
            if (read_all(s, reply_buf, 1, 1) != 1) {
                log_err(LD_NET, "Error reading address_length in socks5 response.");
                goto err;
            }
            result_len = *(uint8_t*)(reply_buf);
            *result_hostname = tor_malloc(result_len+1);
            if (read_all(s, *result_hostname, result_len, 1) != (int) result_len) {
                log_err(LD_NET, "Error reading hostname in socks5 response.");
                goto err;
            }
            (*result_hostname)[result_len] = '\0';
        }
    }

    tor_close_socket(s);
    return 0;
err:
    tor_close_socket(s);
    return -1;
}
Ejemplo n.º 18
0
ssize_t AudioPacket::read_from_fd(int fd) {
    return read_all(fd, _data, _size);
}
Ejemplo n.º 19
0
void hh_load(value in_filename) {
  CAMLparam1(in_filename);
  FILE* fp = fopen(String_val(in_filename), "rb");

  if (fp == NULL) {
    caml_failwith("Failed to open file");
  }

  uint64_t magic = 0;
  read_all(fileno(fp), (void*)&magic, sizeof magic);
  assert(magic == MAGIC_CONSTANT);

  size_t revlen = 0;
  read_all(fileno(fp), (void*)&revlen, sizeof revlen);
  char revision[revlen];
  read_all(fileno(fp), (void*)revision, revlen * sizeof(char));
  assert(strncmp(revision, BuildInfo_kRevision, revlen) == 0);

  read_all(fileno(fp), (void*)&heap_init_size, sizeof heap_init_size);

  int compressed_size = 0;
  read_all(fileno(fp), (void*)&compressed_size, sizeof compressed_size);
  char* chunk_start = save_start();

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  pthread_t thread;
  decompress_args args;
  int thread_started = 0;

  // see hh_save for a description of what we are parsing here.
  while (compressed_size > 0) {
    char* compressed = malloc(compressed_size * sizeof(char));
    assert(compressed != NULL);
    uintptr_t chunk_size = 0;
    read_all(fileno(fp), (void*)&chunk_size, sizeof chunk_size);
    read_all(fileno(fp), compressed, compressed_size * sizeof(char));
    if (thread_started) {
      intptr_t success = 0;
      int rc = pthread_join(thread, (void*)&success);
      free(args.compressed);
      assert(rc == 0);
      assert(success);
    }
    args.compressed = compressed;
    args.compressed_size = compressed_size;
    args.decompress_start = chunk_start;
    args.decompressed_size = chunk_size;
    pthread_create(&thread, &attr, (void* (*)(void*))decompress, &args);
    thread_started = 1;
    chunk_start += chunk_size;
    read_all(fileno(fp), (void*)&compressed_size, sizeof compressed_size);
  }

  if (thread_started) {
    int success;
    int rc = pthread_join(thread, (void*)&success);
    free(args.compressed);
    assert(rc == 0);
    assert(success);
  }

  fclose(fp);
  CAMLreturn0;
}
Ejemplo n.º 20
0
int filter_png(struct media_info const *info, int out_fd, int in_fd)
{
	FILE			*fp = fdopen(out_fd, "wb");
	struct png_struct_def	*png_ptr = NULL;
	struct png_info_def	*png_info = NULL;
	volatile int		rc = EX_SOFTWARE;
	png_bytep		row_pointers[info->height];
	void * volatile		raw_data = NULL;
	void * volatile		rgb_data = NULL;
	size_t			rgb_stride =
		info->width * ((info->bpp + 7) / 8) * 3;

	if (!fp) {
		perror("fdopen()");
		return EX_OSERR;
	}

	png_ptr =  png_create_write_struct(PNG_LIBPNG_VER_STRING,
					   NULL, NULL, NULL);
	if (!png_ptr)
		goto out;

	if (setjmp(png_jmpbuf(png_ptr)))
		goto out;

	/* allocate memory for raw (YCbCr) image data */
	raw_data = png_malloc(png_ptr, info->stride * info->height);
	if (!raw_data)
		goto out;

	rgb_data = png_malloc(png_ptr, rgb_stride * info->height);
	if (!rgb_data)
		goto out;

	for (size_t y = 0; y < info->height; ++y)
		row_pointers[y] = rgb_data + y * rgb_stride;

	png_info = png_create_info_struct(png_ptr);
	if (!png_info)
		goto out;

	png_init_io(png_ptr, fp);
	png_set_user_limits(png_ptr, info->width, info->height);
	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

	/* atm, only 8bpp support is implemented */
	assert(info->bpp == 8);

	for (;;) {
		bool	eof = false;

		if (read_all(in_fd, raw_data, info->stride * info->height, &eof))
			;		/* noop */
		else if (!eof)
			goto out;
		else
			break;

		convert_yuv422_rgb888(rgb_data, raw_data, info->bpp,
				      info->width, info->height);

		png_set_rows(png_ptr, png_info, row_pointers);

		png_set_IHDR(png_ptr, png_info, info->width, info->height,
			     info->bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
			     PNG_COMPRESSION_TYPE_DEFAULT,
			     PNG_FILTER_TYPE_DEFAULT);
		png_write_png(png_ptr, png_info, PNG_TRANSFORM_IDENTITY, NULL);
		fflush(fp);
		break;
	}

	rc = 0;

out:
	png_free(png_ptr, rgb_data);
	png_free(png_ptr, raw_data);
	png_destroy_write_struct(&png_ptr, &png_info);
	fclose(fp);

	return rc;
}
Ejemplo n.º 21
0
int main(int argc, char **argv){

   int sockfd, connsockfd, cont = 2, i, socketsecundario;
   struct sockaddr_in server, client;
   struct pollfd desc_set[MAX_CLIENT];//Definido para 10 utilizadores em max_client
   struct table_t *table=(struct table_t*)malloc(sizeof(struct table_t));
   char *terminal = malloc(sizeof(char));
   int nbytes, msg_size, count;
   socklen_t size_client;
   // Verifica se foi passado algum argumento
   if (argc != 3 && argc != 5){
      printf("Servidor sem replicação: Uso: ./table_server <porto_servidor> <size_table>\n");
      printf("Servidor com replicação: Uso: ./table_server <porto_servidor> <porto2_servidor> <size_table> <ip_serverSecundario>\n");
      return -1;
   }

   //Ligar servidor replicado
   if(argc == 5){
      socketsecundario = ligarBackup(argv[4], argv[2]);
   }

   // Cria socket TCP
   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
      perror("Erro ao criar socket");
      return -1;
   }
   
   // Preenche estrutura server para bind
   server.sin_family = AF_INET;
   server.sin_addr.s_addr = htonl(INADDR_ANY);
   server.sin_port = htons(atoi(argv[1]));
   // Faz bind
   if (bind(sockfd, (struct sockaddr *) &server, sizeof(server)) < 0){
      perror("Erro ao fazer bind");
      close(sockfd);
      return -1;
   };
   // Faz listen
   if(listen(sockfd, 20) < 0){
      perror("Erro ao executar listen");
      close(sockfd);
      return -1;
   };

   //cria table
   table=table_skel_init(atoi(argv[2])); 

   desc_set[0].fd=fileno(stdin);
   desc_set[0].events=POLLIN;
   desc_set[0].revents=0;
   desc_set[1].fd=sockfd; //Listen socket
   desc_set[1].events=POLLIN;
   desc_set[1].revents=0;
   
   for(i=2; i< MAX_CLIENT; i++){
      desc_set[i].fd=-1;
      desc_set[i].events=0;
      desc_set[i].revents=0;
   }
   
   printf("**Estrutura de dados criada**\n**Servidor 'a espera de dados**\n");	

   //Espera por dados nos sockets abertos
   while(poll(desc_set, MAX_CLIENT, -1) >= 0){ 
      /*Tentativa de nova ligacao*/
      if(desc_set[1].revents & POLLIN){
         connsockfd = accept( desc_set[1].fd, ( struct sockaddr * )&client, &size_client);
         //adiciona connsockfd a desc_set
         desc_set[cont].fd=connsockfd;
         desc_set[cont].events=POLLIN;
         cont++;
      }
      /*Testar se ha algum evento extra por exemplo o pedido de informaçao
      do conteudo actual do server*/
      if(desc_set[0].revents & POLLIN){
         fgets(terminal, MAX_MSG, stdin);
         terminal=strtok(terminal, "\n");
         if(strcmp(terminal, "print")== 0){
            int conta=0;				
            char **tabela;
            tabela = table_get_keys(table);
            printf("A tabela actual e': \n");
            while(tabela[conta]!=NULL){
               printf("Key na posição [%d]: %s", conta, tabela[conta]);
               conta++;
            }
         }else{
            printf("erro! escreva print para apresentar o conteudo actual do server\n");
         }
      }

      for(i=2; i<cont; i++){
         if (desc_set[i].revents & POLLIN) {
            // Lê string enviada pelo cliente do socket referente a conexão
            if((nbytes = read(desc_set[i].fd,&msg_size,sizeof(int))) <= 0){
               //perror("Erro ao receber dados do cliente1");

               close(desc_set[i].fd);
               continue;
            }

            msg_size=ntohl(msg_size);
            char *msg_buf=(char *)malloc(msg_size+1);
            if((nbytes = read_all(desc_set[i].fd,msg_buf,msg_size)) < 0){
               perror("Erro ao receber dados do cliente2");
               close(desc_set[i].fd);
               continue;
            }		

            struct message_t *msg_recebida = buffer_to_message(msg_buf, msg_size);
            free(msg_buf);
	
	    if(argc==5){
            //actualizar o backup de acordo com o tipo de escrita
		
               if((msg_recebida->opcode)==OC_PUT){
                  if(actualizarBackup(msg_recebida->content.entry->key, msg_recebida->content.entry->value,1)==-1)
                     perror("Erro a receber OK do servidor secundario\n");
               }
               if((msg_recebida->opcode)==OC_COND_PUT){
                  if(actualizarBackup(msg_recebida->content.entry->key, msg_recebida->content.entry->value,1)==-1)
                     perror("Erro a receber OK do servidor secundario\n");
               }
               if((msg_recebida->opcode)==OC_DEL){
                  if(actualizarBackup(msg_recebida->content.key, msg_recebida->content.entry->value,0)==-1)
                     perror("Erro a receber OK do servidor secundario\n");
               }
	    }
            
            int res=invoke(msg_recebida);

            //Envia resposta ao cliente depois de converter para formato de rede
            msg_size = message_to_buffer(msg_recebida,&msg_buf);
            msg_size = htonl(msg_size);	
            free_message(msg_recebida);
            // Envia tamanho do buffer ao cliente através do socket referente a conexão
            if((nbytes = write(desc_set[i].fd,(char*)&msg_size,sizeof(int))) != sizeof(int)){
               perror("Erro ao enviar resposta ao cliente");
               close(desc_set[i].fd);
               continue;
            }
            msg_size=ntohl(msg_size);
            if((nbytes = write_all(desc_set[i].fd,msg_buf,msg_size) != msg_size)){
               perror("Erro ao enviar resposta ao cliente");
               close(desc_set[i].fd);
               continue;
            }	  
            //Verifica-se se a ligaçao foi desligada
            if (desc_set[i].revents & POLLHUP){
               close(desc_set[i].fd);
               desc_set[i].fd = -1;
               desc_set[i].events = 0;
            }
         }
      }
   }
   //elimina table
   table_skel_destroy();
   // Fecha socket
   close(connsockfd);
   close(sockfd);
   return 0;
}
Ejemplo n.º 22
0
static int call_daemon(const char *socket_path, int op, char *buf,
		       size_t buflen, int *num, const char **err_context)
{
	char op_buf[8];
	int op_len;
	int s;
	ssize_t ret;
	int32_t reply_len = 0;
	struct sockaddr_un srv_addr;

	if (((op == UUIDD_OP_BULK_TIME_UUID) ||
	     (op == UUIDD_OP_BULK_RANDOM_UUID)) && !num) {
		if (err_context)
			*err_context = _("bad arguments");
		errno = EINVAL;
		return -1;
	}

	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
		if (err_context)
			*err_context = _("socket");
		return -1;
	}

	srv_addr.sun_family = AF_UNIX;
	strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
	srv_addr.sun_path[sizeof(srv_addr.sun_path) - 1] = '\0';

	if (connect(s, (const struct sockaddr *) &srv_addr,
		    sizeof(struct sockaddr_un)) < 0) {
		if (err_context)
			*err_context = _("connect");
		close(s);
		return -1;
	}

	if (op == UUIDD_OP_BULK_RANDOM_UUID) {
		if ((*num) * UUID_LEN > buflen - 4)
			*num = (buflen - 4) / UUID_LEN;
	}
	op_buf[0] = op;
	op_len = 1;
	if ((op == UUIDD_OP_BULK_TIME_UUID) ||
	    (op == UUIDD_OP_BULK_RANDOM_UUID)) {
		memcpy(op_buf + 1, num, sizeof(int));
		op_len += sizeof(int);
	}

	ret = write_all(s, op_buf, op_len);
	if (ret < 0) {
		if (err_context)
			*err_context = _("write");
		close(s);
		return -1;
	}

	ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
	if (ret < 0) {
		if (err_context)
			*err_context = _("read count");
		close(s);
		return -1;
	}
	if (reply_len < 0 || (size_t) reply_len > buflen) {
		if (err_context)
			*err_context = _("bad response length");
		close(s);
		return -1;
	}
	ret = read_all(s, (char *) buf, reply_len);

	if ((ret > 0) && (op == UUIDD_OP_BULK_TIME_UUID)) {
		if (reply_len >= (int) (UUID_LEN + sizeof(int)))
			memcpy(buf + UUID_LEN, num, sizeof(int));
		else
			*num = -1;
	}
	if ((ret > 0) && (op == UUIDD_OP_BULK_RANDOM_UUID)) {
		if (reply_len >= (int) sizeof(int))
			memcpy(buf, num, sizeof(int));
		else
			*num = -1;
	}

	close(s);

	return ret;
}
Ejemplo n.º 23
0
int spawn(char *argv[], int *status, int do_wait)
{
	pid_t pid;
	int err_pipe[2];

	if (pipe(err_pipe) == -1)
		return -1;

	pid = fork();
	if (pid == -1) {
		/* error */
		return -1;
	} else if (pid == 0) {
		/* child */
		int dev_null, err, i;

		/* create grandchild and exit child to avoid zombie processes */
		if (!do_wait) {
			switch (fork()) {
			case 0:
				/* grandchild */
				break;
			case -1:
				/* error */
				_exit(127);
			default:
				/* parent of grandchild */
				_exit(0);
			}
		}

		close(err_pipe[0]);
		fcntl(err_pipe[1], F_SETFD, FD_CLOEXEC);

		/* redirect stdout and stderr to /dev/null if possible */
		dev_null = open("/dev/null", O_WRONLY);
		if (dev_null != -1) {
			dup2(dev_null, 1);
			dup2(dev_null, 2);
		}

		/* not interactive, close stdin */
		close(0);

		/* close unused fds */
		for (i = 3; i < 30; i++)
			close(i);

		execvp(argv[0], argv);

		/* error */
		err = errno;
		write_all(err_pipe[1], &err, sizeof(int));
		exit(1);
	} else {
		/* parent */
		int rc, errno_save, child_errno, tmp;

		close(err_pipe[1]);
		rc = read_all(err_pipe[0], &child_errno, sizeof(int));
		errno_save = errno;
		close(err_pipe[0]);

		if (!do_wait)
			status = &tmp;
		waitpid(pid, status, 0);

		if (rc == -1) {
			errno = errno_save;
			return -1;
		}
		if (rc == sizeof(int)) {
			errno = child_errno;
			return -1;
		}
		if (rc != 0) {
			errno = EMSGSIZE;
			return -1;
		}
		return 0;
	}
}
Ejemplo n.º 24
0
static void server_loop(const char *socket_path, const char *pidfile_path,
			int debug, int timeout, int quiet)
{
	struct sockaddr_un	my_addr, from_addr;
	struct flock		fl;
	socklen_t		fromlen;
	int32_t			reply_len = 0;
	uuid_t			uu;
	mode_t			save_umask;
	char			reply_buf[1024], *cp;
	char			op, str[UUID_STR_LEN];
	int			i, s, ns, len, num;
	int			fd_pidfile, ret;

	fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
	if (fd_pidfile < 0) {
		if (!quiet)
			fprintf(stderr, _("Failed to open/create %s: %m\n"),
				pidfile_path);
		exit(EXIT_FAILURE);
	}
	cleanup_pidfile = pidfile_path;
	cleanup_socket = 0;
	signal(SIGALRM, terminate_intr);
	alarm(30);
	fl.l_type = F_WRLCK;
	fl.l_whence = SEEK_SET;
	fl.l_start = 0;
	fl.l_len = 0;
	fl.l_pid = 0;
	while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) {
		if ((errno == EAGAIN) || (errno == EINTR))
			continue;
		if (!quiet)
			fprintf(stderr, _("Failed to lock %s: %m\n"), pidfile_path);
		exit(EXIT_FAILURE);
	}
	ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0);
	if (ret > 0) {
		if (!quiet)
			printf(_("uuidd daemon already running at pid %s\n"),
			       reply_buf);
		exit(EXIT_FAILURE);
	}
	alarm(0);

	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
		if (!quiet)
			fprintf(stderr, _("Couldn't create unix stream socket: %m"));
		exit(EXIT_FAILURE);
	}

	/*
	 * Make sure the socket isn't using fd numbers 0-2 to avoid it
	 * getting closed by create_daemon()
	 */
	while (!debug && s <= 2) {
		s = dup(s);
		if (s < 0)
			err(EXIT_FAILURE, "dup");
	}

	/*
	 * Create the address we will be binding to.
	 */
	my_addr.sun_family = AF_UNIX;
	strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
	my_addr.sun_path[sizeof(my_addr.sun_path) - 1] = '\0';
	unlink(socket_path);
	save_umask = umask(0);
	if (bind(s, (const struct sockaddr *) &my_addr,
		 sizeof(struct sockaddr_un)) < 0) {
		if (!quiet)
			fprintf(stderr,
				_("Couldn't bind unix socket %s: %m\n"), socket_path);
		exit(EXIT_FAILURE);
	}
	umask(save_umask);

	if (listen(s, SOMAXCONN) < 0) {
		if (!quiet)
			fprintf(stderr, _("Couldn't listen on unix "
					  "socket %s: %m\n"), socket_path);
		exit(EXIT_FAILURE);
	}

	cleanup_socket = socket_path;
	if (!debug)
		create_daemon();
	signal(SIGHUP, terminate_intr);
	signal(SIGINT, terminate_intr);
	signal(SIGTERM, terminate_intr);
	signal(SIGALRM, terminate_intr);
	signal(SIGPIPE, SIG_IGN);

	sprintf(reply_buf, "%8d\n", getpid());
	if (ftruncate(fd_pidfile, 0)) {
		/* Silence warn_unused_result */
	}
	write_all(fd_pidfile, reply_buf, strlen(reply_buf));
	if (fd_pidfile > 1)
		close(fd_pidfile); /* Unlock the pid file */

	while (1) {
		fromlen = sizeof(from_addr);
		if (timeout > 0)
			alarm(timeout);
		ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
		alarm(0);
		if (ns < 0) {
			if ((errno == EAGAIN) || (errno == EINTR))
				continue;
			else
				err(EXIT_FAILURE, "accept");
		}
		len = read(ns, &op, 1);
		if (len != 1) {
			if (len < 0)
				perror("read");
			else
				printf(_("Error reading from client, "
					 "len = %d\n"), len);
			goto shutdown_socket;
		}
		if ((op == UUIDD_OP_BULK_TIME_UUID) ||
		    (op == UUIDD_OP_BULK_RANDOM_UUID)) {
			if (read_all(ns, (char *) &num, sizeof(num)) != 4)
				goto shutdown_socket;
			if (debug)
				printf(_("operation %d, incoming num = %d\n"),
				       op, num);
		} else if (debug)
			printf(_("operation %d\n"), op);

		switch (op) {
		case UUIDD_OP_GETPID:
			sprintf(reply_buf, "%d", getpid());
			reply_len = strlen(reply_buf) + 1;
			break;
		case UUIDD_OP_GET_MAXOP:
			sprintf(reply_buf, "%d", UUIDD_MAX_OP);
			reply_len = strlen(reply_buf) + 1;
			break;
		case UUIDD_OP_TIME_UUID:
			num = 1;
			__uuid_generate_time(uu, &num);
			if (debug) {
				uuid_unparse(uu, str);
				printf(_("Generated time UUID: %s\n"), str);
			}
			memcpy(reply_buf, uu, sizeof(uu));
			reply_len = sizeof(uu);
			break;
		case UUIDD_OP_RANDOM_UUID:
			num = 1;
			__uuid_generate_random(uu, &num);
			if (debug) {
				uuid_unparse(uu, str);
				printf(_("Generated random UUID: %s\n"), str);
			}
			memcpy(reply_buf, uu, sizeof(uu));
			reply_len = sizeof(uu);
			break;
		case UUIDD_OP_BULK_TIME_UUID:
			__uuid_generate_time(uu, &num);
			if (debug) {
				uuid_unparse(uu, str);
				printf(P_("Generated time UUID %s "
					  "and %d following\n",
					  "Generated time UUID %s "
					  "and %d following\n", num - 1),
				       str, num - 1);
			}
			memcpy(reply_buf, uu, sizeof(uu));
			reply_len = sizeof(uu);
			memcpy(reply_buf + reply_len, &num, sizeof(num));
			reply_len += sizeof(num);
			break;
		case UUIDD_OP_BULK_RANDOM_UUID:
			if (num < 0)
				num = 1;
			if (num > 1000)
				num = 1000;
			if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num)))
				num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
			__uuid_generate_random((unsigned char *) reply_buf +
					      sizeof(num), &num);
			if (debug) {
				printf(P_("Generated %d UUID:\n",
					  "Generated %d UUIDs:\n", num), num);
				for (i = 0, cp = reply_buf + sizeof(num);
				     i < num;
				     i++, cp += UUID_LEN) {
					uuid_unparse((unsigned char *)cp, str);
					printf("\t%s\n", str);
				}
			}
			reply_len = (num * UUID_LEN) + sizeof(num);
			memcpy(reply_buf, &num, sizeof(num));
			break;
		default:
			if (debug)
				printf(_("Invalid operation %d\n"), op);
			goto shutdown_socket;
		}
		write_all(ns, (char *) &reply_len, sizeof(reply_len));
		write_all(ns, reply_buf, reply_len);
	shutdown_socket:
		close(ns);
	}
}
Ejemplo n.º 25
0
void client_update(network net, char *address)
{
    int fd = socket_setup(0);

    struct hostent *hp;     /* host information */
    struct sockaddr_in server;    /* server address */

    /* fill in the server's address and data */
    bzero((char*)&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(SERVER_PORT);

    /* look up the address of the server given its name */
    hp = gethostbyname(address);
    if (!hp) {
        perror("no such host");
        fprintf(stderr, "could not obtain address of %s\n", "localhost");
    }

    /* put the host's address into the server address structure */
    memcpy((void *)&server.sin_addr, hp->h_addr_list[0], hp->h_length);
    if (connect(fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
        error("error connecting");
    }

    /* send a message to the server */
    int i;
    //printf("Sending\n");
    for(i = 0; i < net.n; ++i){
        if(net.layers[i].type == CONVOLUTIONAL){
            convolutional_layer layer = net.layers[i];
            write_all(fd, (char*) layer.bias_updates, layer.n*sizeof(float));
            int num = layer.n*layer.c*layer.size*layer.size;
            write_all(fd, (char*) layer.filter_updates, num*sizeof(float));
            memset(layer.bias_updates, 0, layer.n*sizeof(float));
            memset(layer.filter_updates, 0, num*sizeof(float));
        }
        if(net.layers[i].type == CONNECTED){
            connected_layer layer = net.layers[i];
            write_all(fd, (char *)layer.bias_updates, layer.outputs*sizeof(float));
            write_all(fd, (char *)layer.weight_updates, layer.outputs*layer.inputs*sizeof(float));
            memset(layer.bias_updates, 0, layer.outputs*sizeof(float));
            memset(layer.weight_updates, 0, layer.inputs*layer.outputs*sizeof(float));
        }
    }
    //printf("Sent\n");

    for(i = 0; i < net.n; ++i){
        if(net.layers[i].type == CONVOLUTIONAL){
            convolutional_layer layer = net.layers[i];

            read_all(fd, (char*) layer.biases, layer.n*sizeof(float));
            int num = layer.n*layer.c*layer.size*layer.size;
            read_all(fd, (char*) layer.filters, num*sizeof(float));

#ifdef GPU
            push_convolutional_layer(layer);
            #endif
        }
        if(net.layers[i].type == CONNECTED){
            connected_layer layer = net.layers[i];

            read_all(fd, (char *)layer.biases, layer.outputs*sizeof(float));
            read_all(fd, (char *)layer.weights, layer.outputs*layer.inputs*sizeof(float));

#ifdef GPU
            push_connected_layer(layer);
            #endif
        }
    }
    //printf("Updated\n");
    close(fd);
}
Ejemplo n.º 26
0
 void send() {
     int readBytes = read_all(sender, data, DATA_SIZE);
     std::string msg = "read " + std::to_string(readBytes);
     ensure(readBytes != -1, "Couldn't read sent data", msg.c_str());
     write_all(receiver, data, readBytes);
 }
Ejemplo n.º 27
0
static ssize_t
do_getpass(const char *prompt, char *buf, size_t buflen,
           int twice, const or_options_t *options)
{
  if (options->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
    tor_assert(buflen);
    buf[0] = 0;
    return 0;
  }

  char *prompt2 = NULL;
  char *buf2 = NULL;
  int fd = -1;
  ssize_t length = -1;

  if (options->use_keygen_passphrase_fd) {
    twice = 0;
    fd = options->keygen_passphrase_fd;
    length = read_all(fd, buf, buflen-1, 0);
    if (length >= 0)
      buf[length] = 0;
    goto done_reading;
  }

  if (twice) {
    const char msg[] = "One more time:";
    size_t p2len = strlen(prompt) + 1;
    if (p2len < sizeof(msg))
      p2len = sizeof(msg);
    prompt2 = tor_malloc(strlen(prompt)+1);
    memset(prompt2, ' ', p2len);
    memcpy(prompt2 + p2len - sizeof(msg), msg, sizeof(msg));

    buf2 = tor_malloc_zero(buflen);
  }

  while (1) {
    length = tor_getpass(prompt, buf, buflen);
    if (length < 0)
      goto done_reading;

    if (! twice)
      break;

    ssize_t length2 = tor_getpass(prompt2, buf2, buflen);

    if (length != length2 || tor_memneq(buf, buf2, length)) {
      fprintf(stderr, "That didn't match.\n");
    } else {
      break;
    }
  }

 done_reading:
  if (twice) {
    tor_free(prompt2);
    memwipe(buf2, 0, buflen);
    tor_free(buf2);
  }

  if (options->keygen_force_passphrase == FORCE_PASSPHRASE_ON && length == 0)
    return -1;

  return length;
}
Ejemplo n.º 28
0
/*
 *	Authenticate the user with the given password.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, REQUEST *request)
{
	rlm_smsotp_t *inst = instance;
	VALUE_PAIR *state;
	int bufsize;
	int *fdp;
	rlm_rcode_t rcode = RLM_MODULE_FAIL;
	char buffer[1000];
	char output[1000];

	fdp = fr_connection_get(inst->pool);
	if (!fdp) return RLM_MODULE_FAIL;

	/* Get greeting */
	bufsize = read_all(fdp, buffer, sizeof(buffer));
	if (bufsize <= 0) {
		REDEBUG("Failed reading from socket");
		goto done;
	}

	/*
	 *  Look for the 'state' attribute.
	 */
#define WRITE_ALL(_a,_b,_c) if (write_all(_a,_b,_c) < 0) goto done;
	state = fr_pair_find_by_num(request->packet->vps, PW_STATE, 0, TAG_ANY);
	if (state) {
		RDEBUG("Found reply to access challenge");

		/* send username */
		snprintf(output, sizeof(output), "check otp for %s\n",
			 request->username->vp_strvalue);
		WRITE_ALL(fdp, output, strlen(output));

		(void) read_all(fdp, buffer, sizeof(buffer));

		/* send password */
		snprintf(output, sizeof(output), "user otp is %s\n",
			 request->password->vp_strvalue);
		WRITE_ALL(fdp, output, strlen(output));

		(void) read_all(fdp, buffer, sizeof(buffer));

		/* set uuid */
		snprintf(output, sizeof(output), "otp id is %s\n",
			 state->vp_strvalue);
		WRITE_ALL(fdp, output, strlen(output));

		(void) read_all(fdp, buffer, sizeof(buffer));

		/* now check the otp */
		WRITE_ALL(fdp, "get check result\n", 17);

		(void) read_all(fdp, buffer, sizeof(buffer));

		/* end the sesssion */
		WRITE_ALL(fdp, "quit\n", 5);

		RDEBUG("answer is %s", buffer);
		if (strcmp(buffer,"OK") == 0) {
			rcode = RLM_MODULE_OK;
		}

		goto done;
	}

	RDEBUG("Generating OTP");

	/* set username */
	snprintf(output, sizeof(output), "generate otp for %s\n",
		 request->username->vp_strvalue);
	WRITE_ALL(fdp, output, strlen(output));

	(void) read_all(fdp, buffer, sizeof(buffer));

	/* end the sesssion */
	WRITE_ALL(fdp, "quit\n", 5);

	RDEBUG("Unique ID is %s", buffer);

	/* check the return string */
	if (strcmp(buffer,"FAILED") == 0) { /* smsotp script returns a error */
		goto done;
	}

	/*
	 *	Create the challenge, and add it to the reply.
	 */

	pair_make_reply("Reply-Message", inst->challenge, T_OP_EQ);
	pair_make_reply("State", buffer, T_OP_EQ);

	/*
	 *  Mark the packet as an Access-Challenge packet.
	 *
	 *  The server will take care of sending it to the user.
	 */
	request->reply->code = PW_CODE_ACCESS_CHALLENGE;
	DEBUG("rlm_smsotp: Sending Access-Challenge");

	rcode = RLM_MODULE_HANDLED;

done:
	fr_connection_release(inst->pool, fdp);
	return rcode;
}
Ejemplo n.º 29
0
int main(int argc, char **argv) {
	struct option long_options[] = {
		{"help", no_argument, NULL, 'h'},
		{"legal", no_argument, NULL, 'l'},
		{"verbose", no_argument, NULL, 'v'},
		{"quiet", no_argument, NULL, 'q'},
		{"repl", no_argument, NULL, 'r'},
		{"static-fns", no_argument, NULL, 's'},
		{"elide-asserts", no_argument, NULL, 'a'},
		{"cache", required_argument, NULL, 'k'},
		{"eval", required_argument, NULL, 'e'},
		{"theme", required_argument, NULL, 't'},
		{"classpath", required_argument, NULL, 'c'},
		{"auto-cache", no_argument, NULL, 'K'},
		{"init", required_argument, NULL, 'i'},
		{"main", required_argument, NULL, 'm'},

		// development options
		{"javascript", no_argument, NULL, 'j'},
		{"out", required_argument, NULL, 'o'},

		{0, 0, 0, 0}
	};
	int opt, option_index;
	while ((opt = getopt_long(argc, argv, "h?lvrsak:je:t:c:o:Ki:qm:", long_options, &option_index)) != -1) {
		switch (opt) {
		case 'h':
			usage(argv[0]);
			exit(0);
		case 'l':
			legal();
			return 0;
		case 'v':
			verbose = true;
			break;
		case 'q':
			quiet = true;
			break;
		case 'r':
			repl = true;
			break;
		case 's':
			static_fns = true;
			break;
		case 'a':
			elide_asserts = true;
			break;
		case 'k':
			cache_path = argv[optind - 1];
			break;
		case 'K':
			cache_path = ".planck_cache";
			{
				char *path_copy = strdup(cache_path);
				char *dir = dirname(path_copy);
				if (mkdir_p(dir) < 0) {
					fprintf(stderr, "Could not create %s: %s\n", cache_path, strerror(errno));
				}
				free(path_copy);
			}
			break;
		case 'j':
			javascript = true;
			break;
		case 'e':
			num_scripts += 1;
			scripts = realloc(scripts, num_scripts * sizeof(struct script));
			scripts[num_scripts - 1].type = "text";
			scripts[num_scripts - 1].expression = true;
			scripts[num_scripts - 1].source = argv[optind - 1];
			break;
		case 'i':
			num_scripts += 1;
			scripts = realloc(scripts, num_scripts * sizeof(struct script));
			scripts[num_scripts - 1].type = "path";
			scripts[num_scripts - 1].expression = false;
			scripts[num_scripts - 1].source = argv[optind - 1];
			break;
		case 'm':
			main_ns_name = argv[optind - 1];
		case 't':
			theme = argv[optind - 1];
			break;
		case 'c':
			{
				char *classpath = argv[optind - 1];
				char *source = strtok(classpath, ":");
				while (source != NULL) {
					char *type = "src";
					if (str_has_suffix(source, ".jar") == 0) {
						type = "jar";
					}

					num_src_paths += 1;
					src_paths = realloc(src_paths, num_src_paths * sizeof(struct src_path));
					src_paths[num_src_paths - 1].type = type;
					src_paths[num_src_paths - 1].path = strdup(source);

					source = strtok(NULL, ":");
				}

				break;
			}
		case 'o':
			out_path = argv[optind - 1];
			break;
		case '?':
			usage(argv[0]);
			exit(1);
		default:
			printf("unhandled argument: %c\n", opt);
		}
	}

	int num_rest_args = 0;
	char **rest_args = NULL;
	if (optind < argc) {
		num_rest_args = argc - optind;
		rest_args = malloc((argc - optind) * sizeof(char*));
		int i = 0;
		while (optind < argc) {
			rest_args[i++] = argv[optind++];
		}
	}

	if (num_scripts == 0 && main_ns_name == NULL && num_rest_args == 0) {
		repl = true;
	}

	if (main_ns_name != NULL && repl) {
		printf("Only one main-opt can be specified.");
	}

	JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);

	JSStringRef nameRef = JSStringCreateWithUTF8CString("planck");
	JSGlobalContextSetName(ctx, nameRef);

	evaluate_script(ctx, "var global = this;", "<init>");

	register_global_function(ctx, "AMBLY_IMPORT_SCRIPT", function_import_script);
	bootstrap(ctx, out_path);

	register_global_function(ctx, "PLANCK_CONSOLE_LOG", function_console_log);
	register_global_function(ctx, "PLANCK_CONSOLE_ERROR", function_console_error);

	evaluate_script(ctx, "var console = {};"\
			"console.log = PLANCK_CONSOLE_LOG;"\
			"console.error = PLANCK_CONSOLE_ERROR;", "<init>");

	evaluate_script(ctx, "var PLANCK_VERSION = \"" PLANCK_VERSION "\";", "<init>");

	// require app namespaces
	evaluate_script(ctx, "goog.require('planck.repl');", "<init>");

	// without this things won't work
	evaluate_script(ctx, "var window = global;", "<init>");

	register_global_function(ctx, "PLANCK_READ_FILE", function_read_file);
	register_global_function(ctx, "PLANCK_LOAD", function_load);
	register_global_function(ctx, "PLANCK_LOAD_DEPS_CLJS_FILES", function_load_deps_cljs_files);
	register_global_function(ctx, "PLANCK_CACHE", function_cache);

	register_global_function(ctx, "PLANCK_EVAL", function_eval);

	register_global_function(ctx, "PLANCK_GET_TERM_SIZE", function_get_term_size);
	register_global_function(ctx, "PLANCK_PRINT_FN", function_print_fn);
	register_global_function(ctx, "PLANCK_PRINT_ERR_FN", function_print_err_fn);

	register_global_function(ctx, "PLANCK_SET_EXIT_VALUE", function_set_exit_value);

	is_tty = isatty(STDIN_FILENO) == 1;
	register_global_function(ctx, "PLANCK_RAW_READ_STDIN", function_raw_read_stdin);
	register_global_function(ctx, "PLANCK_RAW_WRITE_STDOUT", function_raw_write_stdout);
	register_global_function(ctx, "PLANCK_RAW_FLUSH_STDOUT", function_raw_flush_stdout);
	register_global_function(ctx, "PLANCK_RAW_WRITE_STDERR", function_raw_write_stderr);
	register_global_function(ctx, "PLANCK_RAW_FLUSH_STDERR", function_raw_flush_stderr);

	{
		JSValueRef arguments[num_rest_args];
		for (int i = 0; i < num_rest_args; i++) {
			arguments[i] = c_string_to_value(ctx, rest_args[i]);
		}
		JSValueRef args_ref = JSObjectMakeArray(ctx, num_rest_args, arguments, NULL);

		JSValueRef global_obj = JSContextGetGlobalObject(ctx);
		JSStringRef prop = JSStringCreateWithUTF8CString("PLANCK_INITIAL_COMMAND_LINE_ARGS");
		JSObjectSetProperty(ctx, JSValueToObject(ctx, global_obj, NULL), prop, args_ref, kJSPropertyAttributeNone, NULL);
		JSStringRelease(prop);
	}

	evaluate_script(ctx, "cljs.core.set_print_fn_BANG_.call(null,PLANCK_PRINT_FN);", "<init>");
	evaluate_script(ctx, "cljs.core.set_print_err_fn_BANG_.call(null,PLANCK_PRINT_ERR_FN);", "<init>");

	char *elide_script = str_concat("cljs.core._STAR_assert_STAR_ = ", elide_asserts ? "false" : "true");
	evaluate_script(ctx, elide_script, "<init>");
	free(elide_script);

	{
		JSValueRef arguments[4];
		arguments[0] = JSValueMakeBoolean(ctx, repl);
		arguments[1] = JSValueMakeBoolean(ctx, verbose);
		JSValueRef cache_path_ref = NULL;
		if (cache_path != NULL) {
			JSStringRef cache_path_str = JSStringCreateWithUTF8CString(cache_path);
			cache_path_ref = JSValueMakeString(ctx, cache_path_str);
		}
		arguments[2] = cache_path_ref;
		arguments[3] = JSValueMakeBoolean(ctx, static_fns);
		JSValueRef ex = NULL;
		JSObjectCallAsFunction(ctx, get_function(ctx, "planck.repl", "init"), JSContextGetGlobalObject(ctx), 4, arguments, &ex);
		debug_print_value("planck.repl/init", ctx, ex);
	}

	if (repl) {
		evaluate_source(ctx, "text", "(require '[planck.repl :refer-macros [apropos dir find-doc doc source pst]])", true, false, "cljs.user", "dumb");
	}

	evaluate_script(ctx, "goog.provide('cljs.user');", "<init>");
	evaluate_script(ctx, "goog.require('cljs.core');", "<init>");

	evaluate_script(ctx, "cljs.core._STAR_assert_STAR_ = true;", "<init>");

	// Process init arguments

	for (int i = 0; i < num_scripts; i++) {
		// TODO: exit if not successfull
		evaluate_source(ctx, scripts[i].type, scripts[i].source, scripts[i].expression, false, NULL, theme);
	}

	// Process main arguments

	if (main_ns_name != NULL) {
		run_main_in_ns(ctx, main_ns_name, num_rest_args, rest_args);
	} else if (!repl && num_rest_args > 0) {
		char *path = rest_args[0];

		struct script script;
		if (strcmp(path, "-") == 0) {
			char *source = read_all(stdin);
			script.type = "text";
			script.source = source;
			script.expression = false;
		} else {
			script.type = "path";
			script.source = path;
			script.expression = false;
		}

		evaluate_source(ctx, script.type, script.source, script.expression, false, NULL, theme);
	} else if (repl) {
		if (!quiet) {
			banner();
		}

		char *home = getenv("HOME");
		char *history_path = NULL;
		if (home != NULL) {
			char history_name[] = ".planck_history";
			int len = strlen(home) + strlen(history_name) + 2;
			history_path = malloc(len * sizeof(char));
			snprintf(history_path, len, "%s/%s", home, history_name);

			linenoiseHistoryLoad(history_path);
		}

		char *prompt = javascript ? " > " : " => ";

		char *line;
		while ((line = linenoise(prompt)) != NULL) {
			if (javascript) {
				JSValueRef res = evaluate_script(ctx, line, "<stdin>");
				print_value("", ctx, res);
			} else {
				evaluate_source(ctx, "text", line, true, true, "cljs.user", theme);
			}
			linenoiseHistoryAdd(line);
			if (history_path != NULL) {
				linenoiseHistorySave(history_path);
			}
			free(line);
		}
	}

	return exit_value;
}
Ejemplo n.º 30
0
/**
 * main function - for clone or restore data
 */
int main(int argc, char **argv) {
#ifdef MEMTRACE
	setenv("MALLOC_TRACE", "partclone_mtrace.log", 1);
	mtrace();
#endif
	char*			source;			/// source data
	char*			target;			/// target data
	int			dfr, dfw;		/// file descriptor for source and target
	int			r_size, w_size;		/// read and write size
	unsigned		cs_size = 0;		/// checksum_size
	int			start, stop;		/// start, range, stop number for progress bar
	unsigned long *bitmap = NULL;		/// the point for bitmap data
	int			debug = 0;		/// debug level
	int			tui = 0;		/// text user interface
	int			pui = 0;		/// progress mode(default text)
	
	int			flag;
	int			pres = 0;
	pthread_t		prog_thread;
	void			*p_result;

	static const char *const bad_sectors_warning_msg =
		"*************************************************************************\n"
		"* WARNING: The disk has bad sectors. This means physical damage on the  *\n"
		"* disk surface caused by deterioration, manufacturing faults, or        *\n"
		"* another reason. The reliability of the disk may remain stable or      *\n"
		"* degrade quickly. Use the --rescue option to efficiently save as much  *\n"
		"* data as possible!                                                     *\n"
		"*************************************************************************\n";

	file_system_info fs_info;   /// description of the file system
	image_options    img_opt;

	init_fs_info(&fs_info);
	init_image_options(&img_opt);

	/**
	 * get option and assign to opt structure
	 * check parameter and read from argv
	 */
	parse_options(argc, argv, &opt);

	/**
	 * if "-d / --debug" given
	 * open debug file in "/var/log/partclone.log" for log message 
	 */
	memset(&fs_opt, 0, sizeof(fs_cmd_opt));
	debug = opt.debug;
	fs_opt.debug = debug;
	fs_opt.ignore_fschk = opt.ignore_fschk;

	//if(opt.debug)
	open_log(opt.logfile);

	/**
	 * using Text User Interface
	 */
	if (opt.ncurses) {
		pui = NCURSES;
		log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n");
	} else
		pui = TEXT;

	tui = open_pui(pui, opt.fresh);
	if ((opt.ncurses) && (!tui)) {
		opt.ncurses = 0;
		pui = TEXT;
		log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n");
	}

	/// print partclone info
	print_partclone_info(opt);

#ifndef CHKIMG
	if (geteuid() != 0)
		log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n");
	else
		log_mesg(1, 0, 0, debug, "UID is root.\n");
#endif

	/// ignore crc check
	if (opt.ignore_crc)
		log_mesg(1, 0, 1, debug, "Ignore CRC errors\n");

	/**
	 * open source and target
	 * clone mode, source is device and target is image file/stdout
	 * restore mode, source is image file/stdin and target is device
	 * dd mode, source is device and target is device !!not complete
	 */
	source = opt.source;
	target = opt.target;
	log_mesg(1, 0, 0, debug, "source=%s, target=%s \n", source, target);
	dfr = open_source(source, &opt);
	if (dfr == -1) {
		log_mesg(0, 1, 1, debug, "Error exit\n");
	}

#ifndef CHKIMG
	dfw = open_target(target, &opt);
	if (dfw == -1) {
		log_mesg(0, 1, 1, debug, "Error exit\n");
	}
#else
	dfw = -1;
#endif

	/**
	 * get partition information like super block, bitmap from device or image file.
	 */
	if (opt.clone) {

		log_mesg(1, 0, 0, debug, "Initiate image options - version %s\n", IMAGE_VERSION_CURRENT);

		img_opt.checksum_mode = opt.checksum_mode;
		img_opt.checksum_size = get_checksum_size(opt.checksum_mode, opt.debug);
		img_opt.blocks_per_checksum = opt.blocks_per_checksum;

		cs_size = img_opt.checksum_size;

		log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n");
		log_mesg(0, 0, 1, debug, "Reading Super Block\n");

		/// get Super Block information from partition
		read_super_blocks(source, &fs_info);

		if (img_opt.checksum_mode != CSM_NONE && img_opt.blocks_per_checksum == 0) {

			const unsigned int buffer_capacity = opt.buffer_size > fs_info.block_size
				? opt.buffer_size / fs_info.block_size : 1; // in blocks

			img_opt.blocks_per_checksum = buffer_capacity;

		}
		log_mesg(1, 0, 0, debug, "%u blocks per checksum\n", img_opt.blocks_per_checksum);

		check_mem_size(fs_info, img_opt, opt);

		/// alloc a memory to store bitmap
		bitmap = pc_alloc_bitmap(fs_info.totalblock);
		if (bitmap == NULL) {
			log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__);
		}

		log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap);
		log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

		/// read and check bitmap from partition
		log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... \n");
		read_bitmap(source, fs_info, bitmap, pui);
		update_used_blocks_count(&fs_info, bitmap);

		if (opt.check) {

			unsigned long long needed_space = 0;

			needed_space += sizeof(image_head) + sizeof(file_system_info) + sizeof(image_options);
			needed_space += get_bitmap_size_on_disk(&fs_info, &img_opt, &opt);
			needed_space += cnv_blocks_to_bytes(fs_info.usedblocks, fs_info.block_size, &img_opt);

			check_free_space(&dfw, needed_space);
		}

		log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap);
		log_mesg(1, 0, 0, debug, "Writing super block and bitmap...\n");

		write_image_desc(&dfw, fs_info, img_opt, &opt);
		write_image_bitmap(&dfw, fs_info, img_opt, bitmap, &opt);

		log_mesg(0, 0, 1, debug, "done!\n");

	} else if (opt.restore) {

		log_mesg(1, 0, 0, debug, "restore image hdr - get information from image file\n");
		log_mesg(1, 0, 1, debug, "Reading Super Block\n");

		/// get image information from image file
		load_image_desc(&dfr, &opt, &fs_info, &img_opt);
		cs_size = img_opt.checksum_size;

		check_mem_size(fs_info, img_opt, opt);

		/// alloc a memory to restore bitmap
		bitmap = pc_alloc_bitmap(fs_info.totalblock);
		if (bitmap == NULL) {
			log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__);
		}

		log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap);
		log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

		/// read and check bitmap from image file
		log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait...\n");
		load_image_bitmap(&dfr, opt, fs_info, img_opt, bitmap);

#ifndef CHKIMG
		/// check the dest partition size.
		if (opt.restore_raw_file)
			check_free_space(&dfw, fs_info.device_size);
		else if (opt.check)
			check_size(&dfw, fs_info.device_size);
#endif

		log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap);
		log_mesg(0, 0, 1, debug, "done!\n");

	} else if (opt.dd || opt.domain) {

		log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n");
		log_mesg(1, 0, 1, debug, "Reading Super Block\n");

		/// get Super Block information from partition
		read_super_blocks(source, &fs_info);

		check_mem_size(fs_info, img_opt, opt);

		/// alloc a memory to restore bitmap
		bitmap = pc_alloc_bitmap(fs_info.totalblock);
		if (bitmap == NULL) {
			log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__);
		}

		log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap);
		log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n");

		/// read and check bitmap from partition
		log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... ");
		read_bitmap(source, fs_info, bitmap, pui);

		/// check the dest partition size.
		if (opt.dd && opt.check) {
			check_size(&dfw, fs_info.device_size);
		}

		log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap);
		log_mesg(0, 0, 1, debug, "done!\n");
	}

	log_mesg(1, 0, 0, debug, "print image information\n");

	/// print option to log file
	if (debug)
		print_opt(opt);

	print_file_system_info(fs_info, opt);

	/**
	 * initial progress bar
	 */
	start = 0;				/// start number of progress bar
	stop = (fs_info.usedblocks);		/// get the end of progress number, only used block
	log_mesg(1, 0, 0, debug, "Initial Progress bar\n");
	/// Initial progress bar
	if (opt.no_block_detail)
		flag = NO_BLOCK_DETAIL;
	else
		flag = IO;
	progress_init(&prog, start, stop, fs_info.totalblock, flag, fs_info.block_size);
	copied = 0;				/// initial number is 0

	/**
	 * thread to print progress
	 */
	pres = pthread_create(&prog_thread, NULL, thread_update_pui, NULL);
	if(pres)
	    log_mesg(0, 1, 1, debug, "%s, %i, thread create error\n", __func__, __LINE__);


	/**
	 * start read and write data between source and destination
	 */
	if (opt.clone) {

		const unsigned long long blocks_total = fs_info.totalblock;
		const unsigned int block_size = fs_info.block_size;
		const unsigned int buffer_capacity = opt.buffer_size > block_size ? opt.buffer_size / block_size : 1; // in blocks
		unsigned char checksum[cs_size];
		unsigned int blocks_in_cs, blocks_per_cs, write_size;
		char *read_buffer, *write_buffer;

		blocks_per_cs = img_opt.blocks_per_checksum;

		log_mesg(1, 0, 0, debug, "#\nBuffer capacity = %u, Blocks per cs = %u\n#\n", buffer_capacity, blocks_per_cs);

		write_size = cnv_blocks_to_bytes(buffer_capacity, block_size, &img_opt);

		read_buffer = (char*)malloc(buffer_capacity * block_size);
		write_buffer = (char*)malloc(write_size + cs_size);

		if (read_buffer == NULL || write_buffer == NULL) {
			log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__);
		}

		/// read data from the first block
		if (lseek(dfr, 0, SEEK_SET) == (off_t)-1)
			log_mesg(0, 1, 1, debug, "source seek ERROR:%s\n", strerror(errno));

		log_mesg(0, 0, 0, debug, "Total block %llu\n", blocks_total);

		/// start clone partition to image file
		log_mesg(1, 0, 0, debug, "start backup data...\n");

		blocks_in_cs = 0;
		init_checksum(img_opt.checksum_mode, checksum, debug);

		block_id = 0;
		do {
			/// scan bitmap
			unsigned long long i, blocks_skip, blocks_read;
			unsigned int cs_added = 0, write_offset = 0;
			off_t offset;

			/// skip unused blocks
			for (blocks_skip = 0;
			     block_id + blocks_skip < blocks_total &&
			     !pc_test_bit(block_id + blocks_skip, bitmap);
			     blocks_skip++);
			if (block_id + blocks_skip == blocks_total)
				break;

			if (blocks_skip)
				block_id += blocks_skip;

			/// read blocks
			for (blocks_read = 0;
			     block_id + blocks_read < blocks_total && blocks_read < buffer_capacity &&
			     pc_test_bit(block_id + blocks_read, bitmap);
			     ++blocks_read);
			if (!blocks_read)
				break;

			offset = (off_t)(block_id * block_size);
			if (lseek(dfr, offset, SEEK_SET) == (off_t)-1)
				log_mesg(0, 1, 1, debug, "source seek ERROR:%s\n", strerror(errno));

			r_size = read_all(&dfr, read_buffer, blocks_read * block_size, &opt);
			if (r_size != (int)(blocks_read * block_size)) {
				if ((r_size == -1) && (errno == EIO)) {
					if (opt.rescue) {
						memset(read_buffer, 0, blocks_read * block_size);
						for (r_size = 0; r_size < blocks_read * block_size; r_size += PART_SECTOR_SIZE)
							rescue_sector(&dfr, offset + r_size, read_buffer + r_size, &opt);
					} else
						log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg);
				} else
					log_mesg(0, 1, 1, debug, "read error: %s\n", strerror(errno));
			}

			/// calculate checksum
			for (i = 0; i < blocks_read; ++i) {

				memcpy(write_buffer + write_offset,
					read_buffer + i * block_size, block_size);

				write_offset += block_size;

				update_checksum(checksum, read_buffer + i * block_size, block_size);

				if (blocks_per_cs > 0 && ++blocks_in_cs == blocks_per_cs) {

					memcpy(write_buffer + write_offset, checksum, cs_size);

					++cs_added;
					write_offset += cs_size;

					blocks_in_cs = 0;
					if (opt.reseed_checksum)
						init_checksum(img_opt.checksum_mode, checksum, debug);
				}
			}

			/// write buffer to target
			w_size = write_all(&dfw, write_buffer, write_offset, &opt);
			if (w_size != write_offset)
				log_mesg(0, 1, 1, debug, "image write ERROR:%s\n", strerror(errno));

			/// count copied block
			copied += blocks_read;

			/// next block
			block_id += blocks_read;

			/// read or write error
			if (r_size + cs_added * cs_size != w_size)
				log_mesg(0, 1, 1, debug, "read(%i) and write(%i) different\n", r_size, w_size);

		} while (1);

		if (blocks_in_cs > 0) {

			// Write the checksum for the latest blocks
			w_size = write_all(&dfw, (char*)checksum, cs_size, &opt);
			if (w_size != cs_size)
				log_mesg(0, 1, 1, debug, "image write ERROR:%s\n", strerror(errno));
		}

		free(write_buffer);
		free(read_buffer);

	} else if (opt.restore) {

		const unsigned long long blocks_total = fs_info.totalblock;
		const unsigned int block_size = fs_info.block_size;
		const unsigned int buffer_capacity = opt.buffer_size > block_size ? opt.buffer_size / block_size : 1; // in blocks
		const unsigned int blocks_per_cs = img_opt.blocks_per_checksum;
		unsigned long long blocks_used = fs_info.usedblocks;
		unsigned int blocks_in_cs, buffer_size, read_offset;
		unsigned char checksum[cs_size];
		char *read_buffer, *write_buffer;
		int bugcheck = 0;
		unsigned long long blocks_used_fix = 0, test_block = 0;

		log_mesg(1, 0, 0, debug, "#\nBuffer capacity = %u, Blocks per cs = %u\n#\n", buffer_capacity, blocks_per_cs);

		// fix some super block record incorrect
		for (test_block = 0; test_block < blocks_total; ++test_block)
			if (pc_test_bit(test_block, bitmap))
				blocks_used_fix++;

		if (blocks_used_fix != blocks_used) {
			blocks_used = blocks_used_fix;
			log_mesg(1, 0, 0, debug, "info: fixed used blocks count\n");
		}

		buffer_size = cnv_blocks_to_bytes(buffer_capacity, block_size, &img_opt);

		if (img_opt.image_version != 0x0001)
			read_buffer = (char*)malloc(buffer_size + cs_size);
		else {
			// Allocate more memory in case the image is affected by the 64 bits bug
			read_buffer = (char*)malloc(buffer_size + buffer_capacity * cs_size);
		}
		write_buffer = (char*)malloc(buffer_capacity * block_size);
		if (read_buffer == NULL || write_buffer == NULL) {
			log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__);
		}

#ifndef CHKIMG
		/// seek to the first
		if (lseek(dfw, opt.offset, SEEK_SET) == (off_t)-1)
			log_mesg(0, 1, 1, debug, "target seek ERROR:%s\n", strerror(errno));
#endif

		/// start restore image file to partition
		log_mesg(1, 0, 0, debug, "start restore data...\n");

		blocks_in_cs = 0;
		init_checksum(img_opt.checksum_mode, checksum, debug);

		block_id = 0;
		do {
			unsigned int i;
			unsigned char cs_saved[cs_size];
			unsigned long long blocks_written, bytes_skip;
			unsigned int read_size;
			// max chunk to read using one read(2) syscall
			int blocks_read = copied + buffer_capacity < blocks_used ?
				buffer_capacity : blocks_used - copied;
			if (!blocks_read)
				break;

			read_offset = bugcheck ? 4 : 0;

			log_mesg(1, 0, 0, debug, "blocks_read = %d\n", blocks_read);
			read_size = cnv_blocks_to_bytes(blocks_read, block_size, &img_opt);

			// increase read_size to make room for the checksum
			if (blocks_per_cs > 0) {

				if (bugcheck) {

					read_size += blocks_read * cs_size;

				} else if (blocks_read % blocks_per_cs) {

					// adjust read_size to read the right number of checksum
					unsigned long total_cs  = get_checksum_count(copied + blocks_read, &img_opt);
					unsigned long copied_cs = get_checksum_count(copied, &img_opt);
					unsigned long newer_cs  = get_checksum_count(blocks_read, &img_opt);
					unsigned long extra_cs  = total_cs - copied_cs - newer_cs;

					if ((blocks_read < buffer_capacity) && (blocks_used % blocks_per_cs)) {
						// it is the last read and there is a partial chunk at the end
						++extra_cs;
					}

					read_size += extra_cs * cs_size;

					log_mesg(1, 0, 0, debug, "# extra cs = %u\n", extra_cs);
				}
			}

			// read chunk from image
			log_mesg(1, 0, 0, debug, "read more: ");

			r_size = read_all(&dfr, read_buffer, read_size, &opt);
			if (r_size != read_size)
				log_mesg(0, 1, 1, debug, "read ERROR:%s\n", strerror(errno));

			// read buffer is the follows:
			// <blocks_per_cs><cs1><blocks_per_cs><cs2>...

			// write buffer should be the following:
			// <block1><block2>...

			// fill up write buffer, validate checksum
		recheck:
			memcpy(cs_saved, checksum, cs_size);
			for (i = 0; i < blocks_read; ++i) {

				memcpy(write_buffer + i * block_size,
					read_buffer + read_offset, block_size);

				if (opt.ignore_crc) {
					read_offset += block_size;
					if (++blocks_in_cs == blocks_per_cs)
						read_offset += cs_size;
					continue;
				}

				update_checksum(checksum, read_buffer + read_offset, block_size);

				if (++blocks_in_cs == blocks_per_cs) {

					if (memcmp(read_buffer + read_offset + block_size, checksum, cs_size)) {

						if (bugcheck || img_opt.image_version != 0x0001)
							log_mesg(0, 1, 1, debug, "CRC error, block_id=%llu...\n ", block_id + i);
						else {
							log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), "
								"trying enlarge crc size and recheck again...\n");
							// the bug has written the crc with 4 extra bytes, so the read buffer is like this:
							// <block1><crc1><bug><block2><crc2><bug>...
							read_offset += 4;
							blocks_in_cs -= 1;
							bugcheck = 1;
							memcpy(checksum, cs_saved, cs_size);
							goto recheck;
						}
					}

					read_offset += cs_size;
					if (bugcheck)
						read_offset += cs_size;

					blocks_in_cs = 0;
					if (opt.reseed_checksum)
						init_checksum(img_opt.checksum_mode, checksum, debug);
				}

				read_offset += block_size;
			}

			blocks_written = 0;
			do {
				int blocks_write;

				/// count bytes to skip
				for (bytes_skip = 0;
				     block_id < blocks_total &&
				     !pc_test_bit(block_id, bitmap);
				     block_id++, bytes_skip += block_size);

#ifndef CHKIMG
				/// skip empty blocks
				if (bytes_skip > 0 && lseek(dfw, (off_t)bytes_skip, SEEK_CUR) == (off_t)-1)
					log_mesg(0, 1, 1, debug, "target seek ERROR:%s\n", strerror(errno));
#endif

				/// blocks to write
				for (blocks_write = 0;
				     block_id + blocks_write < blocks_total &&
				     blocks_written + blocks_write < blocks_read &&
				     pc_test_bit(block_id + blocks_write, bitmap);
				     blocks_write++);

#ifndef CHKIMG
				// write blocks
				if (blocks_write > 0) {
					w_size = write_all(&dfw, write_buffer + blocks_written * block_size,
						blocks_write * block_size, &opt);
					if (w_size != blocks_write * block_size) {
						if (!opt.skip_write_error)
							log_mesg(0, 1, 1, debug, "write block %llu ERROR:%s\n", block_id + blocks_written, strerror(errno));
						else
							log_mesg(0, 0, 1, debug, "skip write block %llu error:%s\n", block_id + blocks_written, strerror(errno));
					}
				}
#endif

				blocks_written += blocks_write;
				block_id += blocks_write;
				copied += blocks_write;
			} while (blocks_written < blocks_read);

		} while(1);

		if (blocks_in_cs) {

			log_mesg(1, 0, 0, debug, "check latest chunk's checksum covering %u blocks\n", blocks_in_cs);
			if (memcmp(read_buffer + read_offset, checksum, cs_size))
				log_mesg(0, 1, 1, debug, "CRC error, block_id=%llu...\n ", block_id);
		}

		free(write_buffer);
		free(read_buffer);

#ifndef CHKIMG
		/// restore_raw_file option
		if (opt.restore_raw_file && !pc_test_bit(blocks_total - 1, bitmap)) {
			if (ftruncate(dfw, (off_t)(blocks_total * block_size)) == -1)
				log_mesg(0, 0, 1, debug, "ftruncate ERROR:%s\n", strerror(errno));
		}
#endif

	} else if (opt.dd) {

		char *buffer;
		int block_size = fs_info.block_size;
		unsigned long long blocks_total = fs_info.totalblock;
		int buffer_capacity = block_size < opt.buffer_size ? opt.buffer_size / block_size : 1;

		buffer = (char*)malloc(buffer_capacity * block_size);
		if (buffer == NULL) {
			log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__);
		}

		block_id = 0;

		if (lseek(dfr, 0, SEEK_SET) == (off_t)-1)
			log_mesg(0, 1, 1, debug, "source seek ERROR:%d\n", strerror(errno));

		log_mesg(0, 0, 0, debug, "Total block %llu\n", blocks_total);

		/// start clone partition to partition
		log_mesg(1, 0, 0, debug, "start backup data device-to-device...\n");
		do {
			/// scan bitmap
			unsigned long long blocks_skip, blocks_read;
			off_t offset;

			/// skip unused blocks
			for (blocks_skip = 0;
			     block_id + blocks_skip < blocks_total &&
			     !pc_test_bit(block_id + blocks_skip, bitmap);
			     blocks_skip++);

			if (block_id + blocks_skip == blocks_total)
				break;

			if (blocks_skip)
				block_id += blocks_skip;

			/// read chunk from source
			for (blocks_read = 0;
			     block_id + blocks_read < blocks_total && blocks_read < buffer_capacity &&
			     pc_test_bit(block_id + blocks_read, bitmap);
			     ++blocks_read);

			if (!blocks_read)
				break;

			offset = (off_t)(block_id * block_size);
			if (lseek(dfr, offset, SEEK_SET) == (off_t)-1)
				log_mesg(0, 1, 1, debug, "source seek ERROR:%s\n", strerror(errno));
			if (lseek(dfw, offset + opt.offset, SEEK_SET) == (off_t)-1)
				log_mesg(0, 1, 1, debug, "target seek ERROR:%s\n", strerror(errno));

			r_size = read_all(&dfr, buffer, blocks_read * block_size, &opt);
			if (r_size != (int)(blocks_read * block_size)) {
				if ((r_size == -1) && (errno == EIO)) {
					if (opt.rescue) {
						memset(buffer, 0, blocks_read * block_size);
						for (r_size = 0; r_size < blocks_read * block_size; r_size += PART_SECTOR_SIZE)
							rescue_sector(&dfr, offset + r_size, buffer + r_size, &opt);
					} else
						log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg);
				} else
					log_mesg(0, 1, 1, debug, "source read ERROR %s\n", strerror(errno));
			}

			/// write buffer to target
			w_size = write_all(&dfw, buffer, blocks_read * block_size, &opt);
			if (w_size != (int)(blocks_read * block_size)) {
				if (opt.skip_write_error)
					log_mesg(0, 0, 1, debug, "skip write block %lli error:%s\n", block_id, strerror(errno));
				else
					log_mesg(0, 1, 1, debug, "write block %lli ERROR:%s\n", block_id, strerror(errno));
			}

			/// count copied block
			copied += blocks_read;

			/// next block
			block_id += blocks_read;

			/// read or write error
			if (r_size != w_size) {
				if (opt.skip_write_error)
					log_mesg(0, 0, 1, debug, "read and write different\n");
				else
					log_mesg(0, 1, 1, debug, "read and write different\n");
			}
		} while (1);

		free(buffer);

		/// restore_raw_file option
		if (opt.restore_raw_file && !pc_test_bit(blocks_total - 1, bitmap)) {
			if (ftruncate(dfw, (off_t)(blocks_total * block_size)) == -1)
				log_mesg(0, 0, 1, debug, "ftruncate ERROR:%s\n", strerror(errno));
		}

	} else if (opt.domain) {

		int cmp, nx_current = 0;
		unsigned long long next_block_id = 0;
		log_mesg(0, 0, 0, debug, "Total block %i\n", fs_info.totalblock);
		log_mesg(1, 0, 0, debug, "start writing domain log...\n");
		// write domain log comment and status line
		dprintf(dfw, "# Domain logfile created by %s v%s\n", EXECNAME, VERSION);
		dprintf(dfw, "# Source: %s\n", opt.source);
		dprintf(dfw, "# Offset: 0x%08llX\n", opt.offset_domain);
		dprintf(dfw, "# current_pos  current_status\n");
		dprintf(dfw, "0x%08llX     ?\n", opt.offset_domain + (fs_info.totalblock * fs_info.block_size));
		dprintf(dfw, "#      pos        size  status\n");
		// start logging the used/unused areas
		cmp = pc_test_bit(0, bitmap);
		for (block_id = 0; block_id <= fs_info.totalblock; block_id++) {
			if (block_id < fs_info.totalblock) {
				nx_current = pc_test_bit(block_id, bitmap);
				if (nx_current)
					copied++;
			} else
				nx_current = -1;
			if (nx_current != cmp) {
				dprintf(dfw, "0x%08llX  0x%08llX  %c\n",
					opt.offset_domain + (next_block_id * fs_info.block_size),
					(block_id - next_block_id) * fs_info.block_size,
					cmp ? '+' : '?');
				next_block_id = block_id;
				cmp = nx_current;
			}
			// don't bother updating progress
		} /// end of for
	}

	done = 1;
	pres = pthread_join(prog_thread, &p_result);
	if(pres)
	    log_mesg(0, 1, 1, debug, "%s, %i, thread join error\n", __func__, __LINE__);
	update_pui(&prog, copied, block_id, done);
#ifndef CHKIMG
	sync_data(dfw, &opt);
#endif
	print_finish_info(opt);

	/// close source
	close(dfr);
	/// close target
	if (dfw != -1)
		close(dfw);
	/// free bitmp
	free(bitmap);
	close_pui(pui);
#ifndef CHKIMG
	fprintf(stderr, "Cloned successfully.\n");
#else
	printf("Checked successfully.\n");
#endif
	if (opt.debug)
		close_log();
#ifdef MEMTRACE
	muntrace();
#endif
	return 0;      /// finish
}