/********************************************************** * add_to_free_list * Update the old top of list's pred to point to bp, * Update bp's succ to point to the old top of list * Updates the free_list pointer to point to bp **********************************************************/ void add_to_free_list(void *bp) { printf("in add_to_free - Free list: %p\n", free_list); printf("in add_to_free - bp: %p\n", bp); printf("in add_to_tree - allocated? %d\n", GET_ALLOC(HDRP(bp))); if (free_list == NULL) { PUT(SUCC(bp), NULL); PUT(PRED(bp), NULL); free_list = bp; return; } // char * // for (;;) { // if (SUCC(bp) == NULL) return NULL; // if (GET(SUCC(bp)) == NULL) return NULL; // bp = GET(SUCC(bp)); // } PUT(PRED(free_list), bp); PUT(SUCC(bp), free_list); PUT(PRED(bp), NULL); printf("add_to_free - addr of prev: %p\n", PREV_FR_BP(bp)); printf("add_to_free - addr of succ: %p\n", NEXT_FR_BP(bp)); free_list = bp; }
int (list_insert) (SCL_list_t a_list, size_t a_index, const void* a_data) { S_SCL_list_t* const list = a_list; S_node_t* ilink = list->head; S_node_t* node; if (a_index == 0) return list_push_front (a_list, a_data); if (a_index == a_list->count) return list_push_back (a_list, a_data); if (a_index > a_list->count) return SCL_NOTFOUND; node = SCL_ALLOCATOR (sizeof(S_node_t)); if (node == NULL) return SCL_NOMEM; node->data = a_data; while (--a_index > 0) ilink = SUCC(ilink); PRED(node) = ilink; SUCC(node) = SUCC(ilink); PRED(SUCC(ilink)) = node; SUCC(ilink) = node; list->count += 1; return SCL_OK; }
static void printblock(void *bp) { size_t hsize, halloc, fsize, falloc; hsize = GET_SIZE(HDRP(bp)); halloc = GET_ALLOC(HDRP(bp)); fsize = GET_SIZE(FTRP(bp)); falloc = GET_ALLOC(FTRP(bp)); if (hsize == 0) { printf("%p: EOL\n", bp); return; } printf("%p: header: [%d:%c] footer: [%d:%c]\n", bp, hsize, (halloc ? 'a' : 'f'), fsize, (falloc ? 'a' : 'f')); if(!GET_ALLOC(HDRP(bp))){ printf("%p: Predicessor: [0x%x] Successor: [0x%x]\n", bp, GET(PRED(bp)), GET(SUCC(bp))); } if(bp == heap_listp){ printf("%p: Predicessor: [0x%x] Successor: [0x%x]\n", bp, GET(PRED(bp)), GET(SUCC(bp))); } }
/********************************************************** * find_fit * Traverse the heap searching for a block to fit asize * Return NULL if no free blocks can handle that size * Assumed that asize is aligned **********************************************************/ void * find_fit(size_t asize) { // void *bp = free_list; // if (bp == NULL || SUCC(bp) == NULL) return; // for (; NEXT_FR_BP(bp) != NULL; bp = NEXT_FR_BP(bp)) // { // if (asize <= GET_SIZE(HDRP(bp))) { // if (!GET_ALLOC(HDRP(bp))) { // return bp; // } // } // } // return NULL; if (!free_list) return NULL; char * bp = free_list; printf("find-fit - free_list: %p\n", bp); for (;;) { printf("find-fit - bp in loop: %p\n", bp); printf("find_fit - addr of prev: %p\n", PREV_FR_BP(bp)); printf("find_fit - addr of next: %p\n", NEXT_FR_BP(bp)); printf("asize: %d, free_b_size: %d\n",asize, GET_SIZE(HDRP(bp))); printf("allocated? %d\n", GET_ALLOC(HDRP(bp))); if ((asize <= GET_SIZE(HDRP(bp))) && (!GET_ALLOC(HDRP(bp))) ) { printf("FOUND A SPACE"); return bp; } if (SUCC(bp) == NULL) return NULL; if (GET(SUCC(bp)) == NULL) return NULL; bp = GET(SUCC(bp)); } return NULL; }
/* * Insert a free block to suitable class, * notes: 1. it's independent at first, that is to say, we have already destroy_relationship(cur_blk) * 2. it'll be the first free block in its class */ static void insert(char *cur_blk, size_t asize) { // FIRST find the class to insert in int class_index = 0; class_index = find_class(asize); // see if there has already been any free block in this class // if there is, we need to modify the relationship of the old first free block char *old_first = REAL_ADDR((char *)GET(heap_listp + class_index * HSIZE)); int to_change_old_fisrt = 0; if (old_first != (char *)base_addr) { to_change_old_fisrt = 1; } // here we modify cur_blk's info PUT(HDRP(cur_blk), PACK(asize, 0)); PUT(FTRP(cur_blk), PACK(asize, 0)); PUT(heap_listp + class_index * HSIZE, (unsigned int)((unsigned long)cur_blk - base_addr)); PUT(PRED(cur_blk), 0); PUT(SUCC(cur_blk), 0); // here we modify the relationship of the old first free block if (to_change_old_fisrt == 1) { PUT(PRED(old_first), (unsigned int)((unsigned long)cur_blk - base_addr)); PUT(SUCC(cur_blk), (unsigned int)((unsigned long)old_first - base_addr)); } }
int (list_insert_after) ( SCL_list_t a_list, SCL_iterator_t a_iterator, const void* a_data ) { S_SCL_list_t* const list = a_list; S_node_t* ilink = (S_node_t*)a_iterator; S_node_t* node; if (ilink == list->tail) return list_push_back (a_list, a_data); node = SCL_ALLOCATOR (sizeof(S_node_t)); if (node == NULL) return SCL_NOMEM; node->data = a_data; PRED(node) = ilink; SUCC(node) = SUCC(ilink); PRED(SUCC(ilink)) = node; SUCC(ilink) = node; list->count += 1; return SCL_OK; }
/* * delete_node: Remove a free block pointer from a segregated list. If * necessary, adjust pointers in predecessor and successor blocks * or reset the list head. */ static void delete_node(void *ptr) { int list = 0; size_t size = GET_SIZE(HEAD(ptr)); /* Select segregated list */ while ((list < LISTS - 1) && (size > 1)) { size >>= 1; list++; } if (PRED(ptr) != NULL) { if (SUCC(ptr) != NULL) { SET_PTR(SUCC_PTR(PRED(ptr)), SUCC(ptr)); SET_PTR(PRED_PTR(SUCC(ptr)), PRED(ptr)); } else { SET_PTR(SUCC_PTR(PRED(ptr)), NULL); free_lists[list] = PRED(ptr); } } else { if (SUCC(ptr) != NULL) { SET_PTR(PRED_PTR(SUCC(ptr)), NULL); } else { free_lists[list] = NULL; } } return; }
BOOL MIONet_HasEvent (void *pmFilePtr, EventDescriptor *pmEvent) { NetRecord *myNetRecord = (NetRecord *) pmFilePtr; int myPos, myAvail; if (pmEvent -> mode == EventMode_NetAccept) { return MDIONet_HasConnected (&myNetRecord -> socket, myNetRecord -> s_original, myNetRecord -> sockAddr); } // if (!nr->connected) connected is never set to true! // return FALSE; MyReadAhead (myNetRecord); myPos = myNetRecord -> tail; switch (pmEvent -> mode) { case EventMode_InputToken: while ((myPos != myNetRecord -> head) && isspace (myNetRecord -> buf [myPos])) { myPos = SUCC (myPos); } if (myPos == myNetRecord -> head) { return FALSE; } while (myPos != myNetRecord -> head) { if (!isspace (myNetRecord -> buf [myPos])) { return TRUE; } myPos = SUCC (myPos); } return FALSE; case EventMode_InputLine: while (myPos != myNetRecord -> head) { if (myNetRecord -> buf [myPos] == '\n') { return TRUE; } myPos = SUCC (myPos); } return FALSE; case EventMode_InputCount: myAvail = MyBytesAvailable (myNetRecord); return ((myNetRecord -> atEOF) || (myAvail >= pmEvent -> count)); } // switch return FALSE; // Stops bitching } // MIONet_HasEvent
OOTint MIONet_Available (OOTint pmNetID, OOTint pmType) { NetRecord *myNetRecord = MyGetNetRecord (pmNetID); int myPos; if (!stMDNetInitialized) { ABORT_WITH_ERRNO (E_NET_INIT_FAILED); // Never reaches here } MyReadAhead (myNetRecord); myPos = myNetRecord -> tail; switch (pmType) { case NA_BYTES: return MyBytesAvailable (myNetRecord); case NA_TOKEN: while ((myPos != myNetRecord -> head) && isspace (myNetRecord -> buf [myPos])) myPos = SUCC (myPos); if (myPos == myNetRecord -> head) return 0; while (myPos != myNetRecord->head) { if (!isspace(myNetRecord -> buf[myPos])) { return 1; } myPos = SUCC (myPos); } return 0; case NA_LINE: while (myPos != myNetRecord -> head) { if (myNetRecord -> buf[myPos] == '\n') { return 1; } myPos = SUCC(myPos); } return 0; default: return 0; } // switch } // MIONet_Available
void (list_splice) (SCL_list_t a_list1, size_t a_index, SCL_list_t a_list2) { S_SCL_list_t* const list1 = a_list1; S_SCL_list_t* const list2 = a_list2; if (a_index == 0) { list_join (list2, list1); list1->head = list2->head; list1->tail = list2->tail; list1->count = list2->count; list2->head = NULL; list2->tail = NULL; list2->count = 0; return; } if (list1->count <= a_index) { list_join (list1, list2); return; } { S_node_t* node1; S_node_t* node2; S_node_t* next; node1 = list1->head; node2 = list2->head; if (node2 == NULL) return; while (--a_index > 0) node1 = SUCC(node1); next = SUCC(node1); SUCC(node1) = node2; PRED(node2) = node1; node1 = list2->tail; SUCC(node1) = next; if (next != NULL) PRED(next) = node1; list1->count += list2->count; list2->head = NULL; list2->tail = NULL; list2->count = 0; } return; }
static void add_lst(void *ptr){ void *temp_bp = root_listp; root_listp = ptr; //change root to new free block printf("Cur root: %x, size: %d, alloc: %d \n", root_listp, GET_SIZE(HDRP(root_listp)), GET_ALLOC(HDRP(root_listp))); printf("current succ: %x, cur_pred: %x\n", SUCC(temp_bp), PRED(temp_bp)); printf("current succ: %x, cur_pred: %x\n", SUCC(root_listp), PRED(root_listp) ); if (GET(SUCC(ptr)) && GET(PRED(ptr))){ debug_me(); PUT(SUCC(ptr), temp_bp); //change current succ pointer to the recent free block debug_me(); PUT(PRED(temp_bp), ptr); //change recent free block pred to the current new root ptr } printf("Add successful yeh!\n"); }
/********************************************************** * remove_from_free_list * Update bp's pred's succ to be bp's succ * Update bp's succ's pred to be bp's pred * **********************************************************/ void remove_from_free_list(void *bp) { if (bp == NULL) return; if (PRED(bp) == NULL) return; if (SUCC(bp) == NULL) return; char * pred_addr = PREV_FR_BP(bp); char * succ_addr = NEXT_FR_BP(bp); if (pred_addr != NULL) { PUT(SUCC(pred_addr), succ_addr); } if (succ_addr != NULL) { PUT(PRED(succ_addr), pred_addr); } }
/* * Initialize: return -1 on error, 0 on success. */ int mm_init(void) { // We have a set of pointers at the beginning of heap. // Each pointer points to the first free block of its size class. // Each pointer points to NULL as default if ((heap_listp = mem_sbrk(CLASSES_NUM * HSIZE)) == (void *)-1) return -1; for (int i = 0; i < CLASSES_NUM; i++) { PUT(heap_listp + i * HSIZE, 0); } // Then we have a prologue block // to avoid troubles when coalesce if ((prologue_blk = mem_sbrk(EXTRA)) == (void *)-1) return -1; prologue_blk += 3 * HSIZE; PUT(HDRP(prologue_blk), PACK(EXTRA, 1)); PUT(SUCC(prologue_blk), 0); PUT(PRED(prologue_blk), 0); PUT(FTRP(prologue_blk), PACK(EXTRA, 1)); prologue_blk -= 2 * HSIZE; base_addr = (unsigned long)prologue_blk; return 0; }
void mem_validate(mem_pool_t *m){ mheader_t *h; //mutex_lock (&m->lock); mheader_t* limit = (mheader_t*)((size_t)m->store+m->size); for (h=(mheader_t*)m->store; h<limit; h=SUCC(h)) { assert2( (h->pool == m) , "bad block $%x[$%x]:$%hx on pool[$%x]\n" , h, h->size , h->magic, h->pool ); assert2( (h->magic == MEMORY_BLOCK_MAGIC) || (h->magic == MEMORY_HOLE_MAGIC) , "$%x[$%x]:bad magic %2s=$%hx\n" , h, h->size, &h->magic, (int)(h->magic) ); assert2( ( (h->size == MEM_ALIGN(h->size)) && (h->size >= (MEM_HSIZE+ SIZEOF_ALIGN)) && (h->size <= ((size_t)limit - (size_t)h) ) ) , "bad block $%x size $%x\n" , h, h->size ); } //mutex_unlock (&m->lock); }
void mem_dump(mem_pool_t *m){ mheader_t *h; //mutex_lock (&m->lock); debug_printf ("\npool $%x:", m); mheader_t* limit = (mheader_t*)((size_t)m->store+m->size); for (h=(mheader_t*)m->store; h<limit; h=SUCC(h)) { if (h->pool != m){ debug_printf ("bad block $%x[$%x]:$%hx on pool[$%x]\n" , h, h->size , h->magic, h->pool); break; } if (h->magic == MEMORY_BLOCK_MAGIC) debug_printf ("$%x[$%x] ", h, h->size); else if (h->magic == MEMORY_HOLE_MAGIC) debug_printf ("$%x[$%x]:->$%x\n", h, h->size, NEXT(h)); else { debug_printf ("$%x[$%x]:bad magic %2s=$%hx\n", h, h->size, &h->magic, (int)(h->magic)); break; } if ( (h->size != MEM_ALIGN(h->size)) || (h->size < (MEM_HSIZE+ SIZEOF_ALIGN)) || ( h->size > ((size_t)limit - (size_t)h) ) ) { debug_printf ("bad block $%x size $%x\n", h, h->size); break; } } //mutex_unlock (&m->lock); }
FB::variant ibrowserAPI::getDeviceInfo(const std::vector<std::string>& domains,F_ADD) { THREAD(&ibrowserAPI::getDeviceInfo, domains); std::vector<std::string> result; for(int i=0;i<domains.size();i++) { std::string domain = domains[i]; plist_t node = NULL; int ret = 0; if(LOCKDOWN_E_SUCCESS != (ret = lockdownd_get_value(lockdownd_client, domain.empty()?NULL:domain.c_str(), NULL, &node)) ) { ERRO("lockdownd_get_value"); } char *xml_doc=NULL; uint32_t xml_length; plist_to_xml(node, &xml_doc, &xml_length); plist_free(node); result.insert(result.end(),std::string(xml_doc)); free(xml_doc); } SUCC(result); return result; }
int mm_init(void) { debug_me(); char *bp; /* Create the initial empty heap */ if ((heap_listp = mem_sbrk(4*SWORD)) == (void *)-1) return -1; PUT(heap_listp, 0); /* Alignment padding */ PUT(heap_listp + (1*SWORD), PACK(DWORD, 1)); /* Prologue header */ PUT(heap_listp + (2*SWORD), PACK(DWORD, 1)); /* Prologue footer */ PUT(heap_listp + (3*SWORD), PACK(0, 1)); /* Epilogue header */ heap_listp += (2*SWORD); /* Extend the empty heap with a free block of CHUNKSIZE bytes */ printf("Start init\n"); if ( (bp = extend_heap(CHUNKSIZE/SWORD)) == NULL) return -1; PUT(SUCC(bp), NULL); PUT(PRED(bp), NULL); root_listp = bp; mm_check(); printf("Done init()\n"); return 0; }
static int run_stop(int ac, char **av) { int i, j, k, found = 0; if (ac == 1) { ERR(fptys, "Invalid or incomplete command\r\n"); return 1; } j = atoi(av[1]); i = 0; k = 0; for (i = 0; i < MAX_DAEMONS; i++) { if (vpcs_list[i].pid == 0) continue; k++; if (k != j) continue; SUCC(fptys, "VPCS PID %d is terminated\r\n", vpcs_list[i].pid); kill(vpcs_list[i].pid, SIGUSR2); vpcs_list[i].pid = 0; if (vpcs_list[i].cmdline) free(vpcs_list[i].cmdline); found = 1; break; } if (!found) ERR(fptys, "VPCS id %s does not exist\r\n", av[1]); return 0; }
FB::variant ibrowserAPI::getAppList(F_ADD) { THREAD(&ibrowserAPI::getAppList); char *xml_doc=NULL; uint32_t xml_length=0; plist_t node = NULL; plist_t client_opts = instproxy_client_options_new(); instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); if(INSTPROXY_E_SUCCESS != instproxy_browse(instproxy_client,client_opts,&node)) { ERRO("instproxy_browse"); } instproxy_client_options_free(client_opts); plist_to_xml(node, &xml_doc, &xml_length); plist_free(node); SUCC(xml_doc); return xml_doc; }
static void remove_lst(void *ptr){ void *cur_pred = GET(PRED(ptr)); //get pointer of pred void *cur_suc = GET(SUCC(ptr)); // get pointer of suc if (cur_pred != NULL && cur_suc != NULL){ PUT(cur_pred, cur_suc); // swap to merge them together PUT(cur_suc + SWORD, cur_pred); } }
void* (list_access) (SCL_list_t a_list, size_t a_index) { const S_SCL_list_t* const list = a_list; const S_node_t* node = list->head; if (list->count <= a_index) return NULL; while (a_index-- > 0) node = SUCC(node); return (void*)node->data; }
void* (list_remove_at) (SCL_list_t a_list, SCL_iterator_t a_iterator) { S_SCL_list_t* const list = a_list; S_node_t* node = (S_node_t*)a_iterator; const void* data; if (SUCC(node) != NULL) PRED(SUCC(node)) = PRED(node); if (PRED(node) != NULL) SUCC(PRED(node)) = SUCC(node); if (list->head == node) list->head = SUCC(node); if (list->tail == node) list->tail = PRED(node); data = node->data; list->count -= 1; SCL_DEALLOCATOR (node); return (void*)data; }
SCL_iterator_t (list_at) (SCL_list_t a_list, size_t a_index) { const S_SCL_list_t* const list = a_list; const S_node_t* node = list->head; if (list->count <= a_index) return NULL; while (a_index-- > 0) node = SUCC(node); return (void*)node; }
void (list_reverse) (SCL_list_t a_list) { S_SCL_list_t* const list = a_list; S_node_t* t; S_node_t* node; node = list->head; list->head = list->tail; list->tail = node; while (node != NULL) { t = SUCC(node); SUCC(node) = PRED(node); node = PRED(node) = t; } return; }
/* * mm_checkheap - Check the heap for consistency */ void mm_checkheap(int verbose) { //printf("************ CHECK BEGIN ***************\n"); char *bp = heap_listp; char *checkAll = heap_listp; int countblocks = -1; if (verbose) { printf("Heap: (%p)\n", heap_listp); } if ((GET_SIZE(HDRP(heap_listp)) != OVERHEAD) || !GET_ALLOC(HDRP(heap_listp))) { printf("Bad prologue header\n"); } checkblock(heap_listp); while(GET(SUCC(bp)) != 0){ if(verbose == 1) printblock(bp); checkblock(bp); //countblocks++; bp = (char*)GET(SUCC(bp)); } if(verbose == 1) printblock(bp); for (checkAll = heap_listp; GET_SIZE(HDRP(checkAll)) > 0; checkAll = NEXT_BLKP(checkAll)) { if(!GET_ALLOC(HDRP(checkAll)) && !block_in_free_list(checkAll)){ printf("Block is marked free but not in free list\n"); } checkblock(checkAll); countblocks++; } //printf("Number of free blocks: %d\n", freeblockcount); //printf("Total number of blocks: %d\n", countblocks); if ((GET_SIZE(HDRP(checkAll)) != 0) || !(GET_ALLOC(HDRP(checkAll)))) { printf("Bad epilogue header\n"); } //printf("****************** CHECK END ********************\n"); }
static int block_in_free_list(void *bp){ // fara í gegnum heap_listp listann void* freelist = heap_listp; // fáum segfoult á loopuna hér að neðan do{ if(freelist == bp) return 1; freelist = (void*)GET(SUCC(freelist)); } while(freelist != 0); return 0; }
/* * delete_node: Remove a free block pointer from a segregated list. If * necessary, adjust pointers in predecessor and successor blocks * or reset the list head. */ static void delete_node(void *ptr) { //int list = 0; size_t size = GET_SIZE(HDRP(ptr)); /* Select segregated list */ /* while ((list < LISTS - 1) && (size > 1)) { size >>= 1; list++; }*/ if (PRED(ptr) != NULL) { if (SUCC(ptr) != NULL) { SET_PTR(SUCC_PTR(PRED(ptr)), SUCC(ptr)); SET_PTR(PRED_PTR(SUCC(ptr)), PRED(ptr)); } else { SET_PTR(SUCC_PTR(PRED(ptr)), NULL); // free_lists[list] = PRED(ptr); } } else { //intptr_t header1 = header + SUCC(ptr); if (SUCC(ptr) != NULL) { SET_PTR(PRED_PTR(SUCC(ptr)), NULL); head = SUCC(ptr); } else { head = 0; // free_lists[list] = NULL; } } return; }
/* * mm_checkheap */ void mm_checkheap(int verbose) { // this method prints free blocks of each class if (verbose == 1) { dbg_printf("\n-----------------------------------------------------\n"); for (int i = 0; i < CLASSES_NUM; i++) { dbg_printf(" Class: %d\n", i + 1); if (REAL_ADDR(GET(heap_listp + i * HSIZE)) != (char *)base_addr) { char *cur_blk = REAL_ADDR((char *)GET(heap_listp + i * HSIZE)); while (1) { print_blk(cur_blk); if (REAL_ADDR(GET(SUCC(cur_blk))) == (char *)base_addr) break; cur_blk = REAL_ADDR((char *)GET(SUCC(cur_blk))); } } } } // this method prints all blocks in heap sequentially else if (verbose == 2) { dbg_printf("\n-----------------------------------------------------\n"); char *cur_blk = prologue_blk + 2 * HSIZE; while (1) { print_blk(cur_blk); if ((unsigned long)NEXT_BLKP(cur_blk) > (unsigned long)mem_heap_hi()) break; else cur_blk = (char *)NEXT_BLKP(cur_blk); } } }
static void delete_node(void *bp) { int listNum = 0; size_t size = GET_SIZE(HDRP(bp)); while ((listNum < LISTS - 1) && (size > 1)) { size >>= 1; listNum++; } if (PRED(bp) != NULL) { if (SUCC(bp) != NULL) { STORE(SUCC_PTR(PRED(bp)), SUCC(bp)); STORE(PRED_PTR(SUCC(bp)), PRED(bp)); } else { STORE(SUCC_PTR(PRED(bp)), NULL); *(seg_listp + listNum) = PRED(bp); } } else { if (SUCC(bp) != NULL) { STORE(PRED_PTR(SUCC(bp)), NULL); } else { *(seg_listp + listNum) = NULL; } } return; }
FB::variant ibrowserAPI::uploadFile(const std::string& fileName, const boost::optional<FB::JSObjectPtr>& pcb, F_ADD) { if(fileName.empty()) return false; THREAD(&ibrowserAPI::uploadFile,fileName,pcb); const char *file_name=fileName.c_str(); char target_file[1024]; sprintf(target_file, "%s/%s",uploadFileDir.c_str(), basename((char *)file_name)); uint64_t target_file_handle = 0; if (AFC_E_SUCCESS != afc_file_open(afc_client, target_file, AFC_FOPEN_WRONLY, &target_file_handle)){ ERRO("afc_file_open error!"); } FILE *file_handle= fopen(file_name, "r"); if (!file_handle) { afc_remove_path(afc_client, target_file); ERRO("open file error!"); } off_t fileSize = 0; struct stat st; if (stat(file_name, &st) == 0) fileSize = st.st_size; static int read_buf_size = 1024; char read_buf[read_buf_size]; int bytes_read; uint32_t bytes_written = 0; uint32_t doneSize = 0; while((bytes_read = fread(read_buf, 1, read_buf_size, file_handle)) >0 ) { if (AFC_E_SUCCESS != afc_file_write(afc_client, target_file_handle, read_buf, bytes_read, &bytes_written) || bytes_read !=bytes_written) { ERRO("afc_file_write error!"); } memset(read_buf, 0, read_buf_size); doneSize = doneSize + bytes_read; if(pcb && fileSize > 0) (*pcb)->InvokeAsync("", FB::variant_list_of((double)doneSize/fileSize)); } SUCC(target_file); return target_file; }