/**************************************************************************** * DESCRIPTION: Return true if a framing or overrun error is present * RETURN: true if error * ALGORITHM: autobaud - if there are a lot of errors, switch baud rate * NOTES: Clears any error flags. *****************************************************************************/ bool RS485_ReceiveError( void) { bool ReceiveError = false; uint8_t dummy_data; /* check for framing error */ #if 0 if (BIT_CHECK(UCSRA, FE0)) { /* FIXME: how do I clear the error flags? */ BITMASK_CLEAR(UCSRA, (_BV(FE) | _BV(DOR) | _BV(UPE))); ReceiveError = true; } #endif /* check for overrun error */ if (BIT_CHECK(UCSRA, DOR)) { /* flush the receive buffer */ do { dummy_data = UDR; } while (BIT_CHECK(UCSRA, RXC)); ReceiveError = true; } return ReceiveError; }
void rs485_bytes_send( uint8_t * buffer, /* data to send */ uint16_t nbytes) { /* number of bytes of data */ led_on(LED_2); while (!BIT_CHECK(UCSR0A, UDRE0)) { /* do nothing - wait until Tx buffer is empty */ } while (nbytes) { /* Send the data byte */ UDR0 = *buffer; while (!BIT_CHECK(UCSR0A, UDRE0)) { /* do nothing - wait until Tx buffer is empty */ } buffer++; nbytes--; } /* was the frame sent? */ while (!BIT_CHECK(UCSR0A, TXC0)) { /* do nothing - wait until the entire frame in the Transmit Shift Register has been shifted out */ } /* Clear the Transmit Complete flag by writing a one to it. */ BIT_SET(UCSR0A, TXC0); timer_reset(TIMER_SILENCE); led_off_delay(LED_2, 1); return; }
/************************************************************************* * Description: Get the state of the test pin * Returns: true if on, false if off. * Notes: none *************************************************************************/ static inline bool test_pin_state( void) { #if (BDK_VERSION==4) return (BIT_CHECK(PIND, PD5)); #else return (BIT_CHECK(PINB, PB0)); #endif }
result_t compress_directory(struct pak_file* pak, struct paki_args* args, const char* subdir) { result_t r; char directory[DH_PATH_MAX]; char filepath[DH_PATH_MAX]; char fullfilepath[DH_PATH_MAX]; strcpy(directory, args->path); if (subdir[0] != 0) { path_join(directory, directory, subdir, NULL); } WIN32_FIND_DATA fdata; char filter[DH_PATH_MAX]; path_join(filter, directory, "*", NULL); HANDLE find_hdl = FindFirstFile(filter, &fdata); if (find_hdl == INVALID_HANDLE_VALUE) { printf(TERM_BOLDRED "Creating pak failed: directory '%s' does not exist.\n" TERM_RESET, directory); return RET_FAIL; } /* read directory recuresively, and compress files into pak */ BOOL fr = TRUE; while (fr) { if (!str_isequal(fdata.cFileName, ".") && !str_isequal(fdata.cFileName, "..")) { filepath[0] = 0; if (subdir[0] != 0) { strcpy(filepath, subdir); } if (!BIT_CHECK(fdata.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) { /* put the file into the archive */ path_join(filepath, filepath, fdata.cFileName, NULL); path_join(fullfilepath, directory, fdata.cFileName, NULL); r = archive_put(pak, args, fullfilepath, filepath); if (IS_OK(r) && BIT_CHECK(args->usage, PAKI_USAGE_VERBOSE)) { puts(filepath); } else if (IS_FAIL(r)) { err_sendtolog(FALSE); args->err_cnt ++; } args->file_cnt ++; } else { /* it's a directory, recurse */ path_join(filepath, filepath, fdata.cFileName, NULL); compress_directory(pak, args, filepath); } } fr = FindNextFile(find_hdl, &fdata); } FindClose(find_hdl); return RET_OK; }
uint32_t awaitCommandResponse() { // NOTE: for dependencies between error flags and command complete in MMCHS_STAT see page 3157f while ( 1 ) { // NOTE: CTO occured, is mutually exclusive with CC and the errors CIE, CEB and CERR cannot occur with CTO. if ( isCommandTimeout() ) { // NOTE: CTO can occur at the same time as CCRC: it indicates a command abort due to a contention on CMD line. In this case no CC appears. if ( BIT_CHECK( MMCHS_STAT, MMCHS_STAT_CCRC_BIT ) ) { // NOTE: f**k it, don't care for this type of error } clearInterruptBits( MMCHS_STAT_CTO_BIT | MMCHS_STAT_CCRC_BIT ); // always need to reset CMD line after error resetMMCICmdLine( 0xFF ); // reset DATA line after error occured during a command which transmits data resetMMCIDataLine( 0xFF ); // return 1 to indicate failure return 1; } // command complete else if ( isCommandComplete() ) { clearCommandComplete(); // NOTE: CC is set upon CIE, CEB, CCRC (if no CTO) and CERR => need to check for those errors anyway although command has completed if ( BIT_CHECK( MMCHS_STAT, MMCHS_STAT_CIE_BIT ) || BIT_CHECK( MMCHS_STAT, MMCHS_STAT_CEB_BIT ) || BIT_CHECK( MMCHS_STAT, MMCHS_STAT_CCRC_BIT ) || BIT_CHECK( MMCHS_STAT, MMCHS_STAT_CERR_BIT ) ) { clearInterruptBits( MMCHS_STAT_CIE_BIT | MMCHS_STAT_CEB_BIT | MMCHS_STAT_CCRC_BIT | MMCHS_STAT_CERR_BIT ); // Command index error / Command end bit error / Command CRC Error / Card error ? // return 1 to indicate failure return 1; } return 0; } else { // not yet completed, check again } } }
uint32_t setBusPower( bool enable ) { if ( enable ) { uint32_t i = 0; BIT_SET( MMCHS_HCTL, MMCHS_HCTL_SDBP_BIT ); for ( i = 0xFF; i > 0; --i ) { if ( BIT_CHECK( MMCHS_HCTL, MMCHS_HCTL_SDBP_BIT ) ) { return 0; } } return 1; } else { BIT_CLEAR( MMCHS_HCTL, MMCHS_HCTL_SDBP_BIT ); } return 0; }
unsigned int get_random_number_from_candidate_list_and_remove_it(CandidateListType *list, unsigned int index) { unsigned int randomIndex; // index of the selected candidate in the list unsigned int count; // number of remaining candidates in the list unsigned int candidate; // selected candidate assert(NULL != list && index < (NROWS*NCOLS) && "get_random_number_from_candidate_list_and_remove_it(): Bad input"); // 1. count how many remaining numbers we have (how many set bits) count = count_bits(list[index]); assert(count > 0 && "get_random_number_from_candidate_list_and_remove_it(): No candidate remaining"); // 2. generate random index (will be 0 when count is 1) randomIndex = (unsigned int) arc4random() % count; // 3. get the corresponding candidate for (candidate = 0; candidate < NCOLS; ++candidate) { if (BIT_CHECK(list[index],candidate)) { if (0 == randomIndex) { break; } else { --randomIndex; } } } assert(0 <= candidate && candidate < NCOLS && 0 == randomIndex && "get_random_number_from_candidate_list_and_remove_it(): Bad index"); // 4. remove it from the candidate list BIT_CLEAR(list[index],candidate); return (unsigned int)(candidate+1); // Indices start at 0 but values start at 1, need to increase }
static void crea_POWER_CR(int c) { REGFN_BEGIN(POWER_CR); int i; for(i = 0; i < POWER_CR_SIZE(c); i++) { POWER_CR_SKIP(c); BIT_CHECK(i, i, (c==0?powercr9_strings:powercr7_strings)[i]); } CREA_END(); }
static void crea_REG_SPICNT(int c) { REGFN_BEGIN(REG_SPICNT); int i; for(i = 0; i < 16; i++) { REG_SPICNT_SKIP(c); if(REG_SPICNT_ISCHECK(c)) { BIT_CHECK(i, i, spicnt_strings[i]); } else if(i == 0) { BIT_COMBO(i, "0-1", spicnt_strings[0]); BIT_COMBO_ADD(i, "0= 4Mhz"); BIT_COMBO_ADD(i, "1= 2Mhz"); BIT_COMBO_ADD(i, "2= 1Mhz"); BIT_COMBO_ADD(i, "3= 512Khz"); BIT_COMBO_END(i); } else if(i == 8) { BIT_COMBO(i, "8-9", spicnt_strings[8]); BIT_COMBO_ADD(i, "0= Power management device"); BIT_COMBO_ADD(i, "1= Firmware"); BIT_COMBO_ADD(i, "2= Touchscreen/Microphone"); BIT_COMBO_ADD(i, "3= Reserved/Prohibited"); BIT_COMBO_END(i); } else if(i == 10) { BIT_COMBO(i, "10", spicnt_strings[10]); BIT_COMBO_ADD(i, "0= 8 bits"); BIT_COMBO_ADD(i, "1= 16 bits"); BIT_COMBO_END(i); } } CREA_END(); }
static void crea_REG_IPCFIFOCNT(int c) { REGFN_BEGIN(REG_IPCFIFOCNT); int i; for(i = 0; i < 16; i++) { FIFOCNT_SKIP(c); BIT_CHECK(i, i, fifocnt_strings[i]); } CREA_END(); }
static void crea_REG_IF(int c) { REGFN_BEGIN(REG_IF); int i; for(i = 0; i < 24; i++) { INTERRUPT_SKIP(c); BIT_CHECK(i, i, interrupt_strings[i]); } CREA_END(); }
void PS2WaitInputBuffer() { for(;;) { /* Check if the input buffer flag is clear. */ if(!BIT_CHECK(PS2ReadStatus(), 1)) { break; } } }
void eng_release() { if (g_eng == NULL) return; rs_release_resources(); lod_releasemgr(); #if !defined(_DEBUG_) pak_close(&g_eng->data_pak); #endif prf_releasemgr(); sct_release(); wld_releasemgr(); scn_releasemgr(); cmp_releasemgr(); phx_release(); hud_release(); gfx_release(); rs_reportleaks(); rs_releasemgr(); tsk_releasemgr(); if (g_eng->timer != NULL) timer_destroyinstance(g_eng->timer); /* check for main memory leaks */ if (BIT_CHECK(g_eng->params.flags, ENG_FLAG_DEV)) { int leak_cnt = mem_freelist_getleaks(&g_eng->data_freelist, NULL); if (leak_cnt > 0) log_printf(LOG_WARNING, "%d leaks found on dynamic 'data' memory", leak_cnt); } mem_freelist_destroy(&g_eng->data_freelist); mem_stack_destroy(&g_eng->lsr_stack); log_print(LOG_TEXT, "engine released."); if (BIT_CHECK(g_eng->params.flags, ENG_FLAG_CONSOLE)) { log_outputfunc(FALSE, NULL, NULL); con_release(); } FREE(g_eng); g_eng = NULL; }
void load_pak(struct paki_args* args) { result_t r; struct pak_file pak; char filename[DH_PATH_MAX]; path_norm(args->pakfile, args->pakfile); path_tounix(args->path, args->path); r = pak_open(&pak, mem_heap(), args->pakfile, 0); if (IS_FAIL(r)) { err_sendtolog(FALSE); return; } uint file_id = pak_findfile(&pak, args->path); if (file_id == INVALID_INDEX) { printf(TERM_BOLDRED "Extract failed: file '%s' not found in pak.\n" TERM_RESET, args->path); pak_close(&pak); return; } path_getfullfilename(filename, args->path); file_t f = fio_createdisk(filename); if (f == NULL) { printf(TERM_BOLDRED "Extract failed: could not create '%s' for writing.\n" TERM_RESET, filename); pak_close(&pak); err_sendtolog(FALSE); return; } file_t src_file = pak_getfile(&pak, mem_heap(), mem_heap(), file_id, 0); if (src_file == NULL) { pak_close(&pak); fio_close(f); err_sendtolog(FALSE); return; } size_t size; struct allocator* alloc; void* buffer = fio_detachmem(src_file, &size, &alloc); fio_write(f, buffer, size, 1); A_FREE(alloc, buffer); fio_close(f); pak_close(&pak); if (BIT_CHECK(args->usage, PAKI_USAGE_VERBOSE)) { printf(TERM_WHITE "%s -> %s\n" TERM_RESET, args->path, filename); } args->file_cnt ++; // report printf(TERM_BOLDWHITE "Finished: total %d file(s) - %d error(s), %d warning(s)\n" TERM_RESET, args->file_cnt, args->err_cnt, args->warn_cnt); }
result_t gfx_csm_resize(uint width, uint height) { if (BIT_CHECK(eng_get_params()->flags, ENG_FLAG_DEV)) { csm_destroy_prevrt(); if (IS_FAIL(csm_create_prevrt(width, height))) return RET_FAIL; } return RET_OK; }
uint32_t isCardBusy() { uint32_t busyBit = BIT_CHECK( MMCHS_RSP10, MMCHS_RSP10_BUSY_BIT ); uint32_t busyFlag = busyBit == 0; // NOTE: if bit 31 of RSP10 is 0 then card is busy return busyFlag; }
void rs_add_flags(uint flags) { BIT_REMOVE(flags, RS_FLAG_PREPARE_BGLOAD); if (!BIT_CHECK(g_rs.flags, RS_FLAG_PREPARE_BGLOAD)) BIT_REMOVE(flags, RS_FLAG_BGLOADING); BIT_ADD(g_rs.flags, flags); }
void MultibootDumpInfo(multiboot_info_t* multiboot_info) { printf("Multiboot Information:\n"); printf(" Flags: 0x%X\n", multiboot_info->flags); printf(" Bootloader: %s\n", multiboot_info->boot_loader_name); if(BIT_CHECK(multiboot_info->flags, 0)) { printf(" Lower memory: %uKB\n", multiboot_info->mem_lower); uint32_t mem_upper_mb = multiboot_info->mem_upper / 1024; printf(" Upper memory: %uKB (%uMB)\n", multiboot_info->mem_upper, mem_upper_mb); } if(BIT_CHECK(multiboot_info->flags, 1)) { printf(" Boot device: 0x%X\n", multiboot_info->boot_device); } if(BIT_CHECK(multiboot_info->flags, 2)) { printf(" Command line: %s\n", multiboot_info->cmdline); } if(BIT_CHECK(multiboot_info->flags, 3)) { printf(" Module Information:\n"); printf(" Count: %d\n", multiboot_info->mods_count); printf(" Modules start at: 0x%X\n", multiboot_info->mods_addr); multiboot_module_t* module = (multiboot_module_t*) multiboot_info->mods_addr; for(size_t i = 0; i < multiboot_info->mods_count; i++) { printf(" Module #%d, Start: 0x%X, End: 0x%X, Cmdline: %s\n", i, module->mod_start, module->mod_end, module->cmdline); module++; } } if(BIT_CHECK(multiboot_info->flags, 4) && BIT_CHECK(multiboot_info->flags, 5)) { KernelPanic("Invalid Mutliboot flags! Bits 4 and 5 both set.\n", NULL); } if(BIT_CHECK(multiboot_info->flags, 4)) { multiboot_aout_symbol_table_t* aout_symbol_table = &(multiboot_info->u.aout_sym); } if(BIT_CHECK(multiboot_info->flags, 5)) { multiboot_elf_section_header_table_t* elf_header = &(multiboot_info->u.elf_sec); } if(BIT_CHECK(multiboot_info->flags, 6)) { printf(" Memory Map Information:\n"); printf(" Map address: 0x%X\n", multiboot_info->mmap_addr); printf(" Map length: 0x%X\n", multiboot_info->mmap_length); multiboot_memory_map_t* memory_map = (multiboot_memory_map_t*) multiboot_info->mmap_addr; for(; memory_map < multiboot_info->mmap_addr + multiboot_info->mmap_length; memory_map = (multiboot_memory_map_t*) ((uint32_t) memory_map + memory_map->size + sizeof(memory_map->size))) { printf(" Size: 0x%X, Base Address: 0x%X%X, Length: 0x%X%X, Type: 0x%X\n", memory_map->size, memory_map->base_addr >> 32, memory_map->base_addr & 0xFFFFFFFF, memory_map->length >> 32, memory_map->length & 0xFFFFFFFF, memory_map->type); } }
/* * kicker: 0 * who call : PMIC * i_max: mA * condition: persentage decrease 1%, then update i_max */ void kicker_pbm_by_dlpt(unsigned int i_max) { struct pbm *pwrctrl = &pbm_ctrl; struct mrp mrpmgr; mrpmgr.loading_dlpt = ma_to_mw(i_max); if (BIT_CHECK(pwrctrl->hpf_en, KR_DLPT)) mtk_power_budget_manager(KR_DLPT, &mrpmgr); }
/* * kicker: 4 * who call : Flash * condition: on/off */ void kicker_pbm_by_flash(bool status) { struct pbm *pwrctrl = &pbm_ctrl; struct mrp mrpmgr; mrpmgr.switch_flash = status; if (BIT_CHECK(pwrctrl->hpf_en, KR_FLASH)) mtk_power_budget_manager(KR_FLASH, &mrpmgr); }
void PS2WaitOutputBuffer() { uint8_t response; for(;;) { response = PS2ReadStatus(); /* Check if the output buffer flag is set. */ if(BIT_CHECK(PS2ReadStatus(), 0)) { break; } } }
void csm_drawbatchnode(gfx_cmdqueue cmdqueue, struct gfx_batch_node* bnode, struct gfx_shader* shader, uint xforms_shared_idx) { struct scn_render_model* rmodel = (struct scn_render_model*)bnode->ritem; struct gfx_model* gmodel = rmodel->gmodel; struct gfx_model_mesh* mesh = &gmodel->meshes[gmodel->nodes[rmodel->node_idx].mesh_id]; struct gfx_model_geo* geo = &gmodel->geos[mesh->geo_id]; /* set transform matricesbind only for shared mode (we have updated the buffer in a prepass) */ struct gfx_cblock* cb_xforms = g_csm->cb_xforms; if (cb_xforms->shared_buff != NULL) { sharedbuffer_pos_t pos = bnode->meta_data; gfx_shader_bindcblock_shared(cmdqueue, shader, g_csm->cb_xforms, cb_xforms->shared_buff->gpu_buff, GFX_SHAREDBUFFER_OFFSET(pos), GFX_SHAREDBUFFER_SIZE(pos), xforms_shared_idx); } else { gfx_cb_set3mvp(g_csm->cb_xforms, SHADER_NAME(c_mats), bnode->instance_mats, bnode->instance_cnt); gfx_shader_updatecblock(cmdqueue, g_csm->cb_xforms); } /* skin data */ if (bnode->poses[0] != NULL) { struct gfx_cblock* tb_skins = g_csm->tb_skins; for (uint i = 0, cnt = bnode->instance_cnt; i < cnt; i++) { const struct gfx_model_posegpu* pose = bnode->poses[i]; gfx_cb_set3mv_offset(tb_skins, 0, pose->skin_mats, pose->mat_cnt, i*GFX_SKIN_BONES_MAX*sizeof(struct vec4f)*3); } gfx_shader_updatecblock(cmdqueue, tb_skins); } /* draw */ if (bnode->sub_idx == INVALID_INDEX) { gfx_draw_indexedinstance(cmdqueue, GFX_PRIMITIVE_TRIANGLELIST, 0, geo->tri_cnt*3, geo->ib_type, bnode->instance_cnt, GFX_DRAWCALL_SUNSHADOW); } else { uint mtl_id = mesh->submeshes[bnode->sub_idx].mtl_id; uint subset_idx = mesh->submeshes[bnode->sub_idx].subset_id; struct gfx_model_geosubset* subset = &geo->subsets[subset_idx]; int is_doublesided = BIT_CHECK(gmodel->mtls[mtl_id].flags, GFX_MODEL_MTLFLAG_DOUBLESIDED); if (is_doublesided) gfx_output_setrasterstate(cmdqueue, g_csm->rs_bias_doublesided); gfx_draw_indexedinstance(cmdqueue, GFX_PRIMITIVE_TRIANGLELIST, subset->ib_idx, subset->idx_cnt, geo->ib_type, bnode->instance_cnt, GFX_DRAWCALL_SUNSHADOW); /* switch back */ if (is_doublesided) gfx_output_setrasterstate(cmdqueue, g_csm->rs_bias); } }
/* * kicker: 1 * who call : MD * condition: on/off */ void kicker_pbm_by_md(enum md_id id, bool status) { struct pbm *pwrctrl = &pbm_ctrl; struct mrp mrpmgr; mrpmgr.idMD = id; mrpmgr.switch_md = status; if (BIT_CHECK(pwrctrl->hpf_en, KR_MD)) mtk_power_budget_manager(KR_MD, &mrpmgr); }
/* * kicker: 2 * who call : CPU * loading: mW * condition: opp changed */ void kicker_pbm_by_cpu(unsigned int loading, int core, int voltage) { struct pbm *pwrctrl = &pbm_ctrl; struct mrp mrpmgr; mrpmgr.loading_cpu = loading; mrpmgr.cpu_num = core; mrpmgr.cpu_volt = voltage; if (BIT_CHECK(pwrctrl->hpf_en, KR_CPU)) mtk_power_budget_manager(KR_CPU, &mrpmgr); }
/* * kicker: 3 * who call : GPU * loading: mW * condition: opp changed */ void kicker_pbm_by_gpu(bool status, unsigned int loading, int voltage) { struct pbm *pwrctrl = &pbm_ctrl; struct mrp mrpmgr; mrpmgr.switch_gpu = status; mrpmgr.loading_gpu = loading; mrpmgr.gpu_volt = voltage; if (BIT_CHECK(pwrctrl->hpf_en, KR_GPU)) mtk_power_budget_manager(KR_GPU, &mrpmgr); }
/************************************************************************* * Description: Get the state of the LED * Returns: true if on, false if off. * Notes: none *************************************************************************/ bool led_state( uint8_t index) { switch (index) { case 0: return (BIT_CHECK(PIND, PIND7)); case 1: return (BIT_CHECK(PIND, PIND6)); case 2: #if (BDK_VERSION==4) return (BIT_CHECK(PINB, PINC0)); #else return (BIT_CHECK(PINC, PINC7)); #endif case 3: #if (BDK_VERSION==4) return (BIT_CHECK(PINB, PINC4)); #else return (BIT_CHECK(PINC, PINC6)); #endif default: break; } return false; }
/************************************************************************* * Description: Get the state of the LED * Returns: true if on, false if off. * Notes: none *************************************************************************/ bool led_state( uint8_t index) { switch (index) { case LED_1: return (BIT_CHECK(PIND, PD7)); break; case LED_2: return (BIT_CHECK(PIND, PD6)); break; case LED_3: return (BIT_CHECK(PINC, PC7)); break; case LED_4: return (BIT_CHECK(PINC, PC6)); break; default: break; } return false; }
/**************************************************************************** * DESCRIPTION: Waits on the SilenceTimer for 40 bits. * RETURN: none * ALGORITHM: none * NOTES: none *****************************************************************************/ void RS485_Turnaround_Delay( void) { uint8_t nbytes = 4; RS485_Transmitter_Enable(false); while (nbytes) { while (!BIT_CHECK(UCSR0A, UDRE0)) { /* do nothing - wait until Tx buffer is empty */ } /* Send the data byte */ UDR0 = 0xff; nbytes--; } /* was the frame sent? */ while (!BIT_CHECK(UCSR0A, TXC0)) { /* do nothing - wait until the entire frame in the Transmit Shift Register has been shifted out */ } /* Clear the Transmit Complete flag by writing a one to it. */ BIT_SET(UCSR0A, TXC0); }
/**************************************************************************** * DESCRIPTION: Return true if data is available * RETURN: true if data is available, with the data in the parameter set * ALGORITHM: none * NOTES: none *****************************************************************************/ bool RS485_DataAvailable( uint8_t * data) { bool DataAvailable = false; /* check for data */ if (BIT_CHECK(UCSRA, RXC)) { *data = UDR; DataAvailable = true; } return DataAvailable; }
result_t compress_directory(struct pak_file* pak, struct paki_args* args, const char* subdir) { result_t r; char directory[DH_PATH_MAX]; char filepath[DH_PATH_MAX]; char fullfilepath[DH_PATH_MAX]; strcpy(directory, args->path); if (subdir[0] != 0) { path_join(directory, path_norm(directory, directory), subdir, NULL); } DIR* dir = opendir(directory); if (dir == NULL) { printf(TERM_BOLDRED "Creating pak failed: directory '%s' does not exist.\n" TERM_RESET, directory); return RET_FAIL; } /* read directory recuresively, and compress files into pak */ struct dirent* ent = readdir(dir); while (ent != NULL) { if (!str_isequal(ent->d_name, ".") && !str_isequal(ent->d_name, "..")) { filepath[0] = 0; if (subdir[0] != 0) strcpy(filepath, subdir); if (ent->d_type != DT_DIR) { // put the file into the archive path_join(filepath, filepath, ent->d_name, NULL); path_join(fullfilepath, directory, ent->d_name, NULL); r = archive_put(pak, args, fullfilepath, filepath); if (IS_OK(r) && BIT_CHECK(args->usage, PAKI_USAGE_VERBOSE)) { puts(filepath); } else if (IS_FAIL(r)) { err_sendtolog(FALSE); args->err_cnt ++; } args->file_cnt ++; } else { // it's a directory, recurse path_join(filepath, filepath, ent->d_name, NULL); compress_directory(pak, args, filepath); } } ent = readdir(dir); } closedir(dir); return RET_OK; }