示例#1
0
/* Allocate _length number of bytes of free memory and returns the 
   address of the allocated portion. Returns 0 when out of memory. */ 
extern Addr my_malloc(unsigned int _length) {
	// Round up to the size we need
	int needed_size = basic_logarithm(_length);
	
	// Check if there is already a free block of the needed size
	if (freelist[needed_size][0] != NULL) {
		// There is already a block free
		Header* available = freelist[needed_size][0];
		remove_header(available);
		available->is_allocated = true;
		return (void*) get_free_space(available);
	}
	else {
		// There isn't a block free
		// We need to break up a bigger block
		
		// Find the smallest available
		int power = needed_size + 1;
		
		while (power < 32 && freelist[power][0] == NULL) {
			power++;
		}
		if (power == 32) {
			// No block big enough free
			//printf("None big enough\n");
			return NULL;
		}
		assert(freelist[power][0] != NULL);
		Header* header, *split;
		while (freelist[needed_size][0] == NULL) {
			header = freelist[power][0];
			remove_header(header);
			split = split_block(header);
			if (header == split) {
				// Block can't split further
				header->is_allocated = true;
				return get_free_space(header);
			}
			else if (split == NULL) {
				// Split failed
				return NULL;
			}
			else {
				header->size -= 1;
				split->size = header->size - 1;
				add_header(header);
				add_header(split);
			}
			power--;
		}
		// We have a block ready
		Header* ready = freelist[needed_size][0];
		remove_header(ready);
		ready->is_allocated = true;
		return get_free_space(ready);
	}
}
示例#2
0
文件: mm.c 项目: MrLoh/TI3-Uebungen
//versucht einen Speicherbereich mit <byteCount> vielen Bytes zu reservieren
//Falls dies nicht gelingt wird ein NULL (0) Pointer zurueckgeliefert
void* my_malloc(int byteCount)
{
    if(!b_initialized)
        initialize();
    //Wenn der insgesamt verfuegbare Speicherplatz kleiner ist
    //als der angeforderte, koennen wir gleich aufhoeren!
    if(byteCount > get_free_space())
        return(NULL);

    //SUCHE NACH EINEM GEEIGNETEN FREIEN SPEICHERBLOCK, MIT MEHR ALS <byteCount>
    //VIELEN BYTES
    memoryBlock* block = head;
    while(block != NULL)
    {
        if(block->dataLength > byteCount && block->state == not_allocated)
            goto allocate_memory;
        block = block->nextBlock;
    }
    // FALLS ES KEIN PASSENDES ELEMENT GIBT, GEBEN WIR NULL ZURÜCK.
    return(NULL);

    //Der Knoten block hat genuegend Speicherplatz
    allocate_memory:
        // UNTERTEILUNG DIESES BLOCKS, SO DASS NICHT UNNÖTIG VIEL SPEICHERPLATZ VERBRAUCHT WIRD
        // UND RÜCKGABE DES ZEIGERS AUF DEN ZU BENUTZENDEN SPEICHERBEREICH
        return splitBlock(block, byteCount)->data;
}
示例#3
0
文件: page.cpp 项目: nickman/Akumuli
aku_Status PageHeader::add_entry( const aku_ParamId param
                                , const aku_Timestamp timestamp
                                , const aku_MemRange &range )
{
    if (count != 0) {
        // Require >= timestamp
        if (timestamp < page_index(count - 1)->timestamp) {
            return AKU_EBAD_ARG;
        }
    }

    const auto SPACE_REQUIRED = sizeof(aku_Entry)              // entry header
                              + range.length                   // data size (in bytes)
                              + sizeof(aku_EntryIndexRecord);  // offset inside page_index

    const auto ENTRY_SIZE = sizeof(aku_Entry) + range.length;

    if (!range.length) {
        return AKU_EBAD_DATA;
    }
    if (SPACE_REQUIRED > get_free_space()) {
        return AKU_EOVERFLOW;
    }
    char* free_slot = payload + next_offset;
    aku_Entry* entry = reinterpret_cast<aku_Entry*>(free_slot);
    entry->param_id = param;
    entry->length = range.length;
    memcpy((void*)&entry->value, range.address, range.length);
    page_index(count)->offset = next_offset;
    page_index(count)->timestamp = timestamp;
    next_offset += ENTRY_SIZE;
    count++;
    return AKU_SUCCESS;
}
示例#4
0
static int atcmd_tty_write(struct tty_struct *tty,
		const unsigned char *buf, int len)
{
	struct atcmd_tty_info *info = tty->driver_data;
	struct atcmd_tty_info *other_tty_info;
	struct buf_fifo *write_buffer;
	int avail, remain, buf_size;
	char *write_addr;

	other_tty_info = info->other_tty;
	write_buffer = info->write_buffer;

	mutex_lock(write_buffer->lock);
	
	write_addr = write_buffer->buf_addr + write_buffer->head;
	buf_size = write_buffer->size;

	/* if we're writing to tty, we will
	 * never be able to write more data 
	 * than there is currently space for
	 */
	avail = get_free_space(write_buffer);
	if (avail == 0) {
		mutex_unlock(write_buffer->lock);
		return 0;
	}

	if (len > avail)
		len = avail;

	/* handle ring buffer operation */
	if (write_buffer->head < write_buffer->tail) {
		memcpy(write_addr, buf, len);
		write_buffer->head += len;
	} else {
		int write_len = len;
		remain = buf_size - write_buffer->head;
		if (remain < len) {
			memcpy(write_addr, buf, remain);
			buf += remain;
			write_len -= remain;
			write_buffer->head = 0;
			write_addr = write_buffer->buf_addr;
		}
		memcpy(write_addr, buf, write_len);
		write_buffer->head += write_len;
		write_buffer->head %= buf_size;
	}
	write_buffer->count += len;

	wake_lock_timeout(&info->wake_lock, HZ / 2);
	
	/* invoke other tty's read operation */
	if (other_tty_info->open_count)
		schedule_delayed_work(&other_tty_info->work, 0);

	mutex_unlock(write_buffer->lock);

	return len;
}
示例#5
0
JNIEXPORT jint JNICALL
Java_gnu_javax_sound_sampled_gstreamer_lines_GstPipeline_available
  (JNIEnv *env, jclass clazz, jobject pointer, jint mode)
{
  jint result = -1;
 
#ifndef WITHOUT_FILESYSTEM
  
  GstNativePipeline *jpipeline = NULL;
  jpipeline = (GstNativePipeline *) get_object_from_pointer (env, pointer,
                                                             pointerDataFID);
                                                                                                         
  if (mode == READ)
    {
      result = get_free_space (jpipeline->priv->fd);
    }
  else
    {
# if defined (FIONREAD)      
      if (ioctl (jpipeline->priv->fd, FIONREAD, &result) == -1)
        g_warning("IMPLEMENT ME: ioctl failed");
        
# else /* not defined (FIONREAD) */
      g_warning("IMPLEMENT ME: !defined (FIONREAD");
# endif /* defined (FIONREAD) */
    
    } /* if (mode == READ) */
    
#endif  /* not WITHOUT_FILESYSTEM */

  return result;
}
示例#6
0
文件: mm.c 项目: Sanuye/TI3-C
//versucht einen Speicherbereich mit <byteCount> vielen Bytes zu reservieren
//Falls dies nicht gelingt wird ein NULL (0) Pointer zurueckgeliefert
void* my_malloc(int byteCount)
{
	if(!b_initialized)
	{
		initialize();
	}
	//DEBUG
	//printf("mAllocating..%d\n",byteCount);
	//Wenn der insgesamt verfuegbare Speicherplatz kleiner ist
	//als der angeforderte, koennen wir gleich aufhoeren!
	if(byteCount > get_free_space())
	{
		return(NULL);
	}
	memoryBlock *block = head;
	//TODO - WIP - seems finished - needs testing - works
	//SUCHE NACH EINEM GEEIGNETEN FREIEN SPEICHERBLOCK, MIT MEHR ALS <byteCount>
	//VIELEN BYTES
	// + memoryBlockHeaderSize ? nvm .. bei einer anforderung die die gesamte blockgroesse benoetigt muss kein header fuer einen splitBlock beruecksichtigt werden
	memoryBlock *return_blockData = NULL;
	while(block != NULL)
	{
		if(block->state == not_allocated){
			if(block->dataLength >= byteCount){
				if(return_blockData == NULL){
					return_blockData = block;
				}else{
					if(return_blockData->dataLength > block->dataLength){
						return_blockData = block;
					}
				}
			}
		}
		block = block->nextBlock;
	}
	// FALLS ES KEIN PASSENDES ELEMENT GIBT, GEBEN WIR NULL ZURUECK.
	if(return_blockData == NULL){
		return NULL;
	}
	// Der Knoten block hat genuegend Speicherplatz
	//if((return_blockData->dataLength) >= (byteCount+memoryBlockHeaderSize)){
		//UNTERTEILUNG DIESES BLOCKS, SO DASS NICHT UNNOETIG VIEL SPEICHERPLATZ VERBRAUCHT WIRD#
		splitBlock(return_blockData,byteCount);
	//}else{
		//ERROR
		//printf("Nicht genug Platz fuer Speicher %d UND header %d in %d",byteCount,memoryBlockHeaderSize,return_blockData->dataLength);

		//return NULL;
	//}
	// UND MARKIERE DIESEN BLOCK
	return_blockData->state = allocated;
	//DEBUG
	//printf("mAllocated!\n");
	//RueCKGABE DES ZEIGERS AUF DEN ZU BENUTZENDEN SPEICHERBEREICH
	return return_blockData->data;
}
示例#7
0
文件: base.cpp 项目: cmberryau/cmd
void base_c::build_unit(u8 unit_type, game_c_ptr game)
{
	iprintf("\x1b[0;0HBuilding Unit");
	vector_2d_u8_t free_space, base_grid;
	base_grid.x = grid.x;
	base_grid.y = grid.y;
	
	free_space = get_free_space(base_grid, game->get_map());
	game->make_unit(team_id, free_space.x, free_space.y, unit_type);
}
示例#8
0
/**
 * Reads image data from an Aravis ArvBuffer and saves a png file to filename
 * TODO: Add error checking and all that stuff (this code is demonstrative)
 */
bool arv_buffer_save_png(ArvBuffer * buffer, const char * filename)
{
	fprintf(stderr,"Free space is %d\n", get_free_space());
	if (get_free_space() < 50000000) return false;
	// TODO: This only works on image buffers
	assert(arv_buffer_get_payload_type(buffer) == ARV_BUFFER_PAYLOAD_TYPE_IMAGE);
	
	size_t buffer_size;
	char * buffer_data = (char*)arv_buffer_get_data(buffer, &buffer_size); // raw data
	int width; int height;
	arv_buffer_get_image_region(buffer, NULL, NULL, &width, &height); // get width/height
	int bit_depth = ARV_PIXEL_FORMAT_BIT_PER_PIXEL(arv_buffer_get_image_pixel_format(buffer)); // bit(s) per pixel
	fprintf(stderr, "Bit depth is %d\n", bit_depth);
	//TODO: Deal with non-png compliant pixel formats?
	// EG: ARV_PIXEL_FORMAT_MONO_14 is 14 bits per pixel, so conversion to PNG loses data
	
	int arv_row_stride = width * bit_depth/8; // bytes per row, for constructing row pointers
	int color_type = PNG_COLOR_TYPE_GRAY; //TODO: Check for other types?
	
	// boilerplate libpng stuff without error checking (setjmp? Seriously? How many kittens have to die?)
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_infop info_ptr = png_create_info_struct(png_ptr);
	unlink(filename);
	FILE * f = fopen(filename, "wb");
	assert(f != NULL);
	png_init_io(png_ptr, f);
	png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);

	
	// Need to create pointers to each row of pixels for libpng
	png_bytepp rows = (png_bytepp)(png_malloc(png_ptr, height*sizeof(png_bytep)));
	int i =0;
	for (i = 0; i < height; ++i)
		rows[i] = (png_bytep)(buffer_data + (height - i)*arv_row_stride);
	// Actually write image
	png_write_image(png_ptr, rows);
	png_write_end(png_ptr, NULL); // cleanup
	fclose(f);
	return true;
}
示例#9
0
文件: page.cpp 项目: nickman/Akumuli
aku_Status PageHeader::add_chunk(const aku_MemRange range, const uint32_t free_space_required, uint32_t* out_offset) {
    const auto
        SPACE_REQUIRED = range.length + free_space_required,
        SPACE_NEEDED = range.length;
    if (get_free_space() < SPACE_REQUIRED) {
        return AKU_EOVERFLOW;
    }
    *out_offset = next_offset;
    char* free_slot = payload + next_offset;
    memcpy((void*)free_slot, range.address, SPACE_NEEDED);
    next_offset += SPACE_NEEDED;
    return AKU_SUCCESS;
}
示例#10
0
static int atcmd_tty_write_room(struct tty_struct *tty)
{
	struct atcmd_tty_info *info = tty->driver_data;
	struct buf_fifo *write_buffer;
	int avail;

	write_buffer = info->write_buffer;

	mutex_lock(write_buffer->lock);
	avail = get_free_space(write_buffer);
	mutex_unlock(write_buffer->lock);
	
	return avail;
}
示例#11
0
bool arv_buffer_save_raw(ArvBuffer * buffer, const char * filename)
{	
	if (get_free_space() < 50000000) return false;
	size_t buffer_size;
	char * buffer_data = (char*)arv_buffer_get_data(buffer, &buffer_size); // raw data
	int width; int height;
	arv_buffer_get_image_region(buffer, NULL, NULL, &width, &height); // get width/height
	int bit_depth = ARV_PIXEL_FORMAT_BIT_PER_PIXEL(arv_buffer_get_image_pixel_format(buffer)); // bit(s) per pixel
	
	FILE * f = fopen(filename, "wb");
	assert(f != NULL);
	fwrite(buffer_data, 1, buffer_size, f);
	fclose(f);		
	return true;
}
示例#12
0
int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
			  const char *name)
{
  unsigned int entry_size = node_entry_size(name);

  if ((parentoffset & 0x3) || (get_free_space (fdt) < entry_size))
    return -1;

  /* The new node entry will increase the size of the structure block: rearrange
     blocks such that there is sufficient free space between the structure and
     the strings block, then add the new node entry. */
  if (rearrange_blocks (fdt, entry_size) < 0)
    return -1;
  return add_subnode (fdt, parentoffset, name);
}
示例#13
0
static int atcmd_tty_chars_in_buffer(struct tty_struct *tty)
{
	struct atcmd_tty_info *info = tty->driver_data;
	struct buf_fifo *read_buffer;
	int n_read, buf_size;

	read_buffer = info->read_buffer;
	buf_size = read_buffer->size;
	
	mutex_lock(read_buffer->lock);
	n_read = buf_size - get_free_space(read_buffer);
	mutex_unlock(read_buffer->lock);

	return n_read;
}
示例#14
0
文件: page.cpp 项目: nickman/Akumuli
void PageHeader::get_stats(aku_StorageStats* rcv_stats) {
    uint64_t used_space = 0,
             free_space = 0,
              n_entries = 0;

    auto all = length;
    auto free = get_free_space();
    used_space = all - free;
    free_space = free;
    n_entries = count;

    rcv_stats->free_space += free_space;
    rcv_stats->used_space += used_space;
    rcv_stats->n_entries += n_entries;
    rcv_stats->n_volumes += 1;
}
示例#15
0
文件: mm.c 项目: Peabrain/studium
// Diese Funktion gibt eine Uebersicht ueber die vorhandenen Speicherbloecke aus
void status()
{
	if(!b_initialized)
	{
		initialize();
	}
	memoryBlock *block = head;
	int count = 0;
	printf("Uebersicht des Speichers: %d / %d Speicher frei\n", get_free_space(), memorySize);
	printf("------------------------------------------------\n");
	printf("#  at\t\t allocated\t space\t data\t\t\tnext block\n");
	while(block != NULL)
	{

		printf("%d  %p\t %s \t\t %d\t [%p,%p]\t%p\n", ++count, block, boolStr[block->state], block->dataSize, (block->data), ((char*)block->data + block->dataSize-1), (block->nextMemBlock));
		block = block->nextMemBlock;
	}
	printf("\n\n");
}
示例#16
0
文件: vma.c 项目: xsyann/netmalloc
static int create_vm_area_struct(struct task_struct *task,
                                 struct vm_area_struct **vma,
                                 struct vm_operations_struct *vm_ops,
                                 unsigned long size)
{
        *vma = kzalloc(sizeof(**vma), GFP_KERNEL);
        if (*vma == NULL)
                return -ENOMEM;
        INIT_LIST_HEAD(&(*vma)->anon_vma_chain);
        (*vma)->vm_mm = task->mm;
        (*vma)->vm_start = get_free_space(current->mm, size);
        (*vma)->vm_end = (*vma)->vm_start + size;
        PR_DEBUG(D_MED, "Creating vma at %016lx-%016lx",
                 (*vma)->vm_start, (*vma)->vm_end);
        (*vma)->vm_flags = VM_READ | VM_WRITE | VM_EXEC | VM_MIXEDMAP;
        (*vma)->vm_page_prot = vm_get_page_prot((*vma)->vm_flags);
        (*vma)->vm_ops = vm_ops;
        return 0;
}
示例#17
0
文件: mm.c 项目: Sanuye/TI3-C
//Diese Funktion gibt eine Uebersicht ueber die vorhandenen Speicherbloecke aus
void status()
{
	if(!b_initialized)
	{
		initialize();
		b_initialized = 1;
	}
	memoryBlock *block = head;
	int count = 0;
	printf("Uebersicht des Speichers: %d / %d Speicher frei\n", get_free_space(), memorySize);
	printf("------------------------------------------------\n");
	printf("#  at\t\t allocated\t space\t data\t\t\tnext block\n");
	while(block != NULL)
	{
		//TODO: WARNINGS - evtl (void*) pointer casten vor den  memoryBlock pointern? Wer auch immer das Framework erstellt hat, hat wohl ein paar Warnings ignoriert...
		printf("%d  %p\t %s \t\t %d\t [%p,%p]\t%p\n", ++count, /*added cast*/(void*)block, boolStr[block->state], block->dataLength, (block->data), (char*)block->data + block->dataLength-1, /*added void cast*/(void*)(block->nextBlock));
		block = block->nextBlock;
	}
	printf("\n\n");
}
示例#18
0
文件: mm.c 项目: pandemie/WS10TI3
//versucht einen Speicherbereich mit <byteCount> vielen Bytes zu reservieren
//Falls dies nicht gelingt wird ein NULL (0) Pointer zurueckgeliefert
void* my_malloc(int byteCount)
{
    if(!b_initialized)
    {
        initialize();
    }
    //Wenn der insgesamt verfuegbare Speicherplatz kleiner ist
    //als der angeforderte, koennen wir gleich aufhoeren!
    if(byteCount > get_free_space())
    {
        return(NULL);
    }
    //TODO - DONE
    //SUCHE NACH EINEM GEEIGNETEN FREIEN SPEICHERBLOCK, MIT MEHR ALS <byteCount>
    //VIELEN BYTES
    memoryBlock* block = head;
    while ( 1 ){
        // Keine geeigneter Block gefunden
        if ( block == NULL ){
            // jetzt m�sste man anfangen zu defragmentieren
            // geht nur leider ohne virtuelle Speicheradressen nicht,
            // da sonst die von uns zur�ckgegebenen Pointer ung�ltig werden
            return NULL;
        }

        // Einen Block gefunden, der gro� genug ist
        if ( block->state == not_allocated && block->dataLength >= byteCount ){
            break;
        }

        block = block->nextBlock;
    }

    //UNTERTEILUNG DIESES BLOCKS, SO DASS NICHT UNN�TIG VIEL SPEICHERPLATZ VERBRAUCHT WIRD
    block = splitBlock ( block, byteCount );

    //R�CKGABE DES ZEIGERS AUF DEN ZU BENUTZENDEN SPEICHERBEREICH
    block->state = allocated;
    return (void *) block->data;
}
示例#19
0
static unsigned int try_to_flush_duplicates(const char *new_key, unsigned int buf_len)
{
    unsigned int key_size, new_record_size, ret = 0, can_rollback = 0;
    struct record record, previous_record;
    char sector_buff[STORAGE_SIZE];
    struct iter_state is;

    memcpy(sector_buff, STORAGE_ADDRESS, STORAGE_SIZE);
    if(check_for_duplicates(sector_buff)
       || key_exists(sector_buff, new_key, &sector_buff[STORAGE_SIZE], 0, NULL)
       || check_for_empty_records(sector_buff)) {
        fs_erase();
        record_iter_init(&is, sector_buff, STORAGE_SIZE);
        while(record_iter_next(&is, &record, NULL)) {
            if(is_empty(&record))
                continue;
            if(!key_exists((char *)STORAGE_ADDRESS, record.key, STORAGE_ADDRESS + STORAGE_SIZE, 1, NULL)) {
                struct record rec;

                if(!key_exists(sector_buff, record.key, &sector_buff[STORAGE_SIZE], 0, &rec))
                    continue;
                if(strcmp(new_key, record.key) == 0) { // If we are about to write this key we don't keep the old value.
                    previous_record = rec; // This holds the old record in case we need it back (for instance if new record is too long)
                    can_rollback = 1;
                } else
                    fs_write(record.key, rec.value, rec.value_len);
            }
        }
        ret = 1;
    }

    key_size = strlen(new_key) + 1;
    new_record_size = key_size + buf_len + sizeof(new_record_size);
    if(can_rollback && new_record_size > get_free_space()) {
        fs_write(new_key, previous_record.value, previous_record.value_len);
    }

    return ret;
}
示例#20
0
文件: mm.c 项目: Peabrain/studium
// Versucht einen Speicherbereich mit <byteCount> vielen Bytes zu reservieren
// Falls dies nicht gelingt wird ein NULL (0) Pointer zurueckgeliefert
void* my_malloc(int byteCount)
{
	if(!b_initialized)
	{
		initialize();
	}
	// Wenn der insgesamt verfuegbare Speicherplatz kleiner ist
	// als der angeforderte, koennen wir gleich aufhoeren!
	if(byteCount > get_free_space())
	{
		return(NULL);
	}
	memoryBlock *block = head;
	// TODO
	// SUCHE NACH EINEM GEEIGNETEN FREIEN SPEICHERBLOCK, MIT MEHR ALS <byteCount>
	// VIELEN BYTES
	//

	do
	{
		if(block->state == not_allocated && block->dataSize >= byteCount + memoryBlockHeaderSize) break;
		block = block->nextMemBlock;
	}
	while(block != 0);

	// FALLS ES KEIN PASSENDES ELEMENT GIBT, GEBEN WIR NULL ZURUECK.
	if(block == 0) return 0;

	// Der Knoten block hat genuegend Speicherplatz

	// UNTERTEILUNG DIESES BLOCKS, SO DASS NICHT UNNOETIG VIEL SPEICHERPLATZ VERBRAUCHT WIRD
	// UND MARKIERE DIESEN BLOCK
	block = splitBlock(block,byteCount);
	block->state = allocated;

	// RUECKGABE DES ZEIGERS AUF DEN ZU BENUTZENDEN SPEICHERBEREICH
	return block->data;
}
示例#21
0
static void
remove_old_files (TnyFsStreamCache *self, gint64 required_size)
{

	/* 1. we obtain a list of non active files
	 * 2. we sort the list (first uncomplete, then old)
	 * 3. we get items in list and remove them until we have the required size
	 */
	GList *cached_files_list;
	TnyFsStreamCachePriv *priv = TNY_FS_STREAM_CACHE_GET_PRIVATE (self);
	gint64 available_size;

	/* 1. we obtain a list of non active files */
	cached_files_list = NULL;
	g_static_mutex_lock (priv->cache_lock);
	g_hash_table_foreach (priv->cached_files, (GHFunc) get_inactive_files_list, &cached_files_list);
	g_static_mutex_unlock (priv->cache_lock);

	/* 2. we sort the list (first uncomplete, then old) */
	cached_files_list = g_list_sort (cached_files_list, (GCompareFunc) remove_priority);

	/* 3. we get items in list and remove them until we have the required size */
	available_size = get_free_space (self);
	while (available_size < required_size) {
		TnyCachedFile *cached_file = (TnyCachedFile *) cached_files_list->data;
		available_size += tny_cached_file_get_expected_size (cached_file);
		g_static_mutex_lock (priv->cache_lock);
		g_hash_table_remove (priv->cached_files, tny_cached_file_get_id (cached_file));
		g_static_mutex_unlock (priv->cache_lock);
		tny_cached_file_remove (cached_file);
		cached_files_list = g_list_delete_link (cached_files_list, cached_files_list);
		g_object_unref (cached_file);
	}

	g_list_foreach (cached_files_list, (GFunc) g_object_unref, NULL);
	g_list_free (cached_files_list);
	
}
示例#22
0
uint32_t buffer_write(char* buffer, const unsigned char* buf, uint32_t len,
                      int on_full) {
  uint32_t free;
  uint32_t bytes;
  uint32_t head;
  uint32_t size;
  uint32_t written;

  if (is_full(buffer)) return on_full;
  free = get_free_space(buffer);
  bytes = free > len ? len : free;
  head = get_head(buffer);
  size = get_size(buffer);
  written = 0;
  while (written < bytes) {
    // TODO(ricow): consider using memmove here instead;
    char* value_pointer = buffer + kDataIndex + head;
    *value_pointer = buf[written];
    head = (head + 1) % size;
    written++;
  }
  set_head(buffer, head);
  return written;
}
示例#23
0
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
		       const void *val, grub_uint32_t len)
{
  grub_uint32_t *prop;
  int prop_name_present = 0;
  grub_uint32_t nameoff = 0;

  if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3)
      || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt
                           + grub_fdt_get_off_dt_struct (fdt) + nodeoffset))
          != FDT_BEGIN_NODE))
    return -1;
  prop = find_prop (fdt, nodeoffset, name);
  if (prop)
    {
	  grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)),
                                        sizeof(grub_uint32_t));
	  grub_uint32_t i;

      prop_name_present = 1;
	  for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++)
        *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP);
      if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t)))
        {
          /* Length of new property value is greater than the space allocated
             for the current value: a new entry needs to be created, so save the
             nameoff field of the current entry and replace the current entry
             with NOP tokens. */
          nameoff = grub_be_to_cpu32 (*(prop + 2));
          *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP);
          prop = NULL;
        }
    }
  if (!prop || !prop_name_present) {
    unsigned int needed_space = 0;

    if (!prop)
      needed_space = prop_entry_size(len);
    if (!prop_name_present)
      needed_space += grub_strlen (name) + 1;
    if (needed_space > get_free_space (fdt))
      return -1;
    if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0)
      return -1;
  }
  if (!prop_name_present) {
    /* Append the property name at the end of the strings block. */
    nameoff = grub_fdt_get_size_dt_strings (fdt);
    grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff,
                 name);
    grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt)
                                  + grub_strlen (name) + 1);
  }
  if (!prop) {
    char *node_name = (char *) ((grub_addr_t) fdt
                                + grub_fdt_get_off_dt_struct (fdt) + nodeoffset
                                + sizeof(grub_uint32_t));

    prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4));
    grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop,
                  struct_end(fdt) - (grub_addr_t) prop);
    grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt)
                                 + prop_entry_size(len));
    *prop = grub_cpu_to_be32_compile_time (FDT_PROP);
    *(prop + 2) = grub_cpu_to_be32 (nameoff);
  }
  *(prop + 1) = grub_cpu_to_be32 (len);

  /* Insert padding bytes at the end of the value; if they are not needed, they
     will be overwritten by the following memcpy. */
  *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0;

  grub_memcpy (prop + 3, val, len);
  return 0;
}
示例#24
0
static void atcmd_tty_read(struct work_struct *work)
{
	struct atcmd_tty_info *info =
		container_of(work, struct atcmd_tty_info, work.work);
	struct buf_fifo *read_buffer;
	struct tty_struct *tty = info->tty;
	unsigned char *ptr;
	int n_read;
	int avail, remain, buf_size;
	char *read_addr;

	read_buffer = info->read_buffer;

	mutex_lock(read_buffer->lock);

	read_addr = read_buffer->buf_addr + read_buffer->tail;
	buf_size = read_buffer->size;


	if (!tty) {
		mutex_unlock(read_buffer->lock);
		return;
	}
	
	for (;;) {
		if (test_bit(TTY_THROTTLED, &tty->flags))
			break;
		
		n_read = buf_size - get_free_space(read_buffer);
		if (n_read == 0)
			break;

		avail = tty_prepare_flip_string(tty, &ptr, n_read);
		if (avail <= 0) {
			schedule_delayed_work(&info->work, (30 / 1000) * HZ);
			mutex_unlock(read_buffer->lock);
			return;
		}

		if (read_buffer->head > read_buffer->tail) {
			memcpy(ptr, read_addr, avail);
			read_buffer->tail += avail;
		} else {
			int read_len = avail;
			remain = buf_size - read_buffer->tail;
			if (remain < avail) {
				memcpy(ptr, read_addr, remain);
				ptr += remain;
				read_len -= remain;
				read_buffer->tail = 0;
				read_addr = read_buffer->buf_addr;
			}
			memcpy(ptr, read_addr, read_len);
			read_buffer->tail += read_len;
			read_buffer->tail %= buf_size;
		}
		read_buffer->count -= avail;

		wake_lock_timeout(&info->wake_lock, HZ / 2);
		tty_flip_buffer_push(tty);
	}

	mutex_unlock(read_buffer->lock);

	if (info->other_tty->tty)
		tty_wakeup(info->other_tty->tty);

	return;
}
string copy_prepare(string appfolder, string operation, string foldername, string fw_folder, string app)
{
	DIR *dp;
	struct dirent *dirp;
	int findex=0, mountblind=0, numfiles_total=0, numfiles_current=1, j=0, i=0, showprogress=0;
	double copy_totalsize=0, copy_currentsize=0, source_size=0, dest_size=0, freespace_size=0;
	string source_paths[100], dest_paths[100], check_paths[100];
	string check_path, sourcefile, destfile, filename, dest, source, title;
	string *files_list = NULL, *final_list_source = NULL, *final_list_dest = NULL;  //Pointer for an array to hold the filenames.
	string ret="";

	if (operation=="backup")
	{
		check_path=appfolder+"/apps/"+app+"/"+fw_folder;
		dp = opendir (check_path.c_str());
		if (dp == NULL) return "Cannot open directory "+check_path;
		while ( (dirp = readdir(dp) ) )
		{
			if ( strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0 && strcmp(dirp->d_name, "") != 0)
			{
				if (dirp->d_type == DT_DIR)
				{
					check_paths[findex]=check_path+"/"+dirp->d_name;
					source_paths[findex]=correct_path(dirp->d_name,2);
					dest_paths[findex]=appfolder+"/backups/"+foldername+"/"+dirp->d_name;
					if (source_paths[findex].find("dev_blind")!=string::npos) mountblind=1;
					findex++;
				}
				//check zip files
			}
		}
		closedir(dp);
		title="Backing up files ...";
	}
	else if (operation=="restore")
	{
		check_path=appfolder+"/backups/"+foldername;
		dp = opendir (check_path.c_str());
		if (dp == NULL) return "Cannot open directory "+check_path;
		while ( (dirp = readdir(dp) ) )
		{
			if ( strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0 && strcmp(dirp->d_name, "") != 0 && dirp->d_type == DT_DIR)
			{
				source_paths[findex]=check_path + "/" + dirp->d_name;
				dest_paths[findex]=correct_path(dirp->d_name,2);
				if (dest_paths[findex].find("dev_blind")!=string::npos) mountblind=1;
				findex++;
			}
		}
		closedir(dp);
		title="Restoring files ...";
	}
	else if (operation=="install")
	{
		check_path=appfolder+"/apps/"+app+"/"+fw_folder;
		dp = opendir (check_path.c_str());
		if (dp == NULL) return "Cannot open directory "+check_path;
		while ( (dirp = readdir(dp) ) )
		{
			if ( strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0 && strcmp(dirp->d_name, "") != 0 && dirp->d_type == DT_DIR)
			{
				source_paths[findex]=check_path + "/" + dirp->d_name;
				dest_paths[findex]=correct_path(dirp->d_name,2);
				if (dest_paths[findex].find("dev_blind")!=string::npos) mountblind=1;
				findex++;
			}
			//check zip files
		}
		closedir(dp);
		title="Copying files ...";
	}

	if (mountblind==1)
	{
		if (is_dev_blind_mounted()!=0) mount_dev_blind();
		if (is_dev_blind_mounted()!=0) return "Dev_blind not mounted!";
		if (exists("/dev_flash/vsh/resource/explore/xmb/xmbmp.cfg")!=0) create_file("/dev_blind/vsh/resource/explore/xmb/xmbmp.cfg");
	}

	//count files
	final_list_source = new string[5000];
	final_list_dest = new string[5000];
	for(j=0;j<findex;j++)
	{
		if (operation=="backup") check_path=check_paths[j];
		else check_path=source_paths[j];
		//Mess.Dialog(MSG_OK,("check_path: "+check_path).c_str());
		files_list=recursiveListing(check_path);
		i=0;
		while (strcmp(files_list[i].c_str(),"") != 0)
		{
			files_list[i].replace(files_list[i].find(check_path), check_path.size()+1, "");
			sourcefile=source_paths[j]+"/"+files_list[i];
			destfile=dest_paths[j]+"/"+files_list[i];
			//Mess.Dialog(MSG_OK,(operation+"\nsource: "+sourcefile+"\ndest:"+destfile).c_str());
			if (!(operation=="backup" && exists(sourcefile.c_str())!=0))
			{
				copy_totalsize+=get_filesize(sourcefile.c_str());
				final_list_source[numfiles_total]=sourcefile;
				final_list_dest[numfiles_total]=destfile;
				filename=final_list_source[i].substr(final_list_source[i].find_last_of("/")+1);
				source=final_list_source[i].substr(0,final_list_source[i].find_last_of("/")+1);
				dest=final_list_dest[i].substr(0,final_list_dest[i].find_last_of("/")+1);
				//Mess.Dialog(MSG_OK,(operation+"\nsource: "+final_list_source[numfiles_total]+"\ndest:"+final_list_dest[numfiles_total]).c_str());
				if (dest.find("dev_blind")!=string::npos) mountblind=1;
				numfiles_total+=1;
			}
			i++;
		}
	}

	//only show progress bar if total size bigger than 512KB
	if (copy_totalsize < 1048576/2) showprogress=-1;

	//copy files
	i=0;
	if (showprogress==0) Mess.SingleProgressBarDialog(title.c_str(), "Processing files...");
	while (strcmp(final_list_source[i].c_str(),"") != 0)
	{
		sourcefile=final_list_source[i];
		destfile=final_list_dest[i];
		source_size=get_filesize(sourcefile.c_str());
		dest_size=get_filesize(destfile.c_str());
		filename=final_list_source[i].substr(final_list_source[i].find_last_of("/")+1);
		source=final_list_source[i].substr(0,final_list_source[i].find_last_of("/")+1);
		dest=final_list_dest[i].substr(0,final_list_dest[i].find_last_of("/")+1);
		freespace_size=get_free_space(dest.c_str())+dest_size;
		if (source_size >= freespace_size)
		{
			if (showprogress==0) Mess.ProgressBarDialogAbort();
			return "Not enough space to copy the file ("+filename+") to destination path ("+dest+").";
		}
		else
		{
			if (mkdir_full(dest)!=0)
			{
				if (showprogress==0) Mess.ProgressBarDialogAbort();
				return "Could not create directory ("+dest+").";
			}
			ret=copy_file(title, source.c_str(), dest.c_str(), filename.c_str(),source_size, copy_currentsize, copy_totalsize, numfiles_current, numfiles_total,0,showprogress);
			if (ret != "")
			{
				if (showprogress==0) Mess.ProgressBarDialogAbort();
				return ret;
			}
		}
		copy_currentsize=copy_currentsize+source_size;
		numfiles_current++;
		i++;
	}
	if (showprogress==0) Mess.ProgressBarDialogAbort();

	//check files
	i=0;
	copy_currentsize=0;
	numfiles_current=1;
	title="Checking files ...";
	if (showprogress==0) Mess.SingleProgressBarDialog(title.c_str(), "Processing files...");
	while (strcmp(final_list_source[i].c_str(),"") != 0)
	{
		sourcefile=final_list_source[i];
		destfile=final_list_dest[i];
		source_size=get_filesize(sourcefile.c_str());
		filename=final_list_source[i].substr(final_list_source[i].find_last_of("/")+1);
		source=final_list_source[i].substr(0,final_list_source[i].find_last_of("/")+1);
		dest=final_list_dest[i].substr(0,final_list_dest[i].find_last_of("/")+1);
		ret=copy_file(title, source.c_str(), dest.c_str(), filename.c_str(),source_size, copy_currentsize, copy_totalsize, numfiles_current, numfiles_total,1,showprogress);
		if (ret != "")
		{
			if (showprogress==0) Mess.ProgressBarDialogAbort();
			return ret;
		}
		copy_currentsize=copy_currentsize+source_size;
		numfiles_current++;
		i++;
	}
	if (showprogress==0) Mess.ProgressBarDialogAbort();

	return "";
}
示例#26
0
int main(int argc, char **argv) {

    if (argc != 4)
    {
        fprintf(stderr, "Usage: readimg <image file name> filepath \n");
        exit(1);
    }
    
    // open source file
    int fd_src = open(argv[2], O_RDONLY);
    if (fd_src < 0){
        fprintf(stderr, "No such file exists in the native file system \n");
        exit(ENOENT);
    }

    int filesize_src = lseek(fd_src, 0, SEEK_END);
    // mmap cannot map size 0 file.
    if (filesize_src <= 0){
        fprintf(stderr, "The source file is empty \n");
        exit(ENOENT);
    }

    int req_block_num = (filesize_src - 1) / EXT2_BLOCK_SIZE + 1;

    // open the image
    int fd = open(argv[1], O_RDWR);
    if (fd < 0){
        fprintf(stderr, "No such virtual disk exists \n");
        exit(ENOENT);   
    }

    // map the virtual disk and source file on memory
    ptr_disk = mmap(NULL, BLOCK_NUM * BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    unsigned char* ptr_disk_src = mmap(NULL, filesize_src, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_src, 0);
    if (ptr_disk == MAP_FAILED || ptr_disk_src == MAP_FAILED)
    {
       perror("mmap");
       exit(1);
    }

    struct ext2_group_desc *ptr_group_desc = (struct ext2_group_desc *)(ptr_disk + EXT2_SB_OFFSET + EXT2_BLOCK_SIZE);
    // get the inode table
    struct ext2_inode *ptr_inode = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table);
    unsigned char *bm_inode = (ptr_disk + (ptr_group_desc -> bg_inode_bitmap) * BLOCK_SIZE);
    unsigned char *bm_block = (ptr_disk + (ptr_group_desc -> bg_block_bitmap) * BLOCK_SIZE);
    struct ext2_super_block *ptr_super_block = (struct ext2_super_block *)(ptr_disk + EXT2_SB_OFFSET);
    char *ptr_path_src = strdup(argv[2]);
    char *ptr_path_dest = strdup(argv[3]);
    char *table_path_src[10];
    char *table_path_dest[10];
    int count_path_src = get_path_table(table_path_src, ptr_path_src);
    int count_path_dest = get_path_table(table_path_dest, ptr_path_dest);

    // Find the destination directory in the virtual disk
    struct ext2_dir_entry_2 *ptr_dir_dest = recurse_inode(ptr_inode + 1, table_path_dest, count_path_dest, 0, ptr_group_desc->bg_inode_table);

    if(ptr_dir_dest == 0)
    {
        printf("No such directory exists on virtual disk\n");
        return -1;
    }

    int table_new_block[req_block_num];
    int copy_flag = 0;

    int i = 0;
    while(i < req_block_num)
    {
        int free_block = get_free_block(bm_block, ptr_super_block);
        SETBIT(bm_block, free_block);
        table_new_block[i] = free_block;

        if(filesize_src - copy_flag <= BLOCK_SIZE)
        {
            memcpy(ptr_disk + EXT2_BLOCK_SIZE * (free_block + 1), ptr_disk_src + BLOCK_SIZE * i, filesize_src - copy_flag - 1);
        }
        else
        {
            memcpy(ptr_disk + EXT2_BLOCK_SIZE * (free_block + 1), ptr_disk_src + BLOCK_SIZE * i, EXT2_BLOCK_SIZE);
            copy_flag += BLOCK_SIZE;
        }
        i++;
    }

    int block_id_inderect;
    if(req_block_num > 11)
    {
        block_id_inderect = get_free_block(bm_block, ptr_super_block);
        int *indirect_block = (int *)(ptr_disk + EXT2_BLOCK_SIZE * (block_id_inderect + 1));
        SETBIT(bm_block, block_id_inderect);
        for(i = 12; i < req_block_num; i++)
        {
            *indirect_block = table_new_block[i];
            indirect_block++;
        }
    }

    int fr_inode = get_free_inode(bm_inode, ptr_super_block);
    struct ext2_inode *node_new = ptr_inode + (fr_inode);
    SETBIT(bm_inode, fr_inode);
    node_new->i_links_count = 1;
    node_new->i_mode = EXT2_S_IFREG;
    node_new->i_size = filesize_src;
    node_new->i_blocks = req_block_num * 2;

    i = 0;
    while (i < 11 && req_block_num != i)
    {
        node_new->i_block[i] = table_new_block[i];
        i++;
    }

    if(req_block_num > 11)
    {
        node_new -> i_block[12] = block_id_inderect;
    }

    struct ext2_inode *in_src = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table);
    struct ext2_inode *in_cur = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table);
    in_src = in_src + ptr_dir_dest -> inode - 1;
    in_cur = in_cur + ptr_dir_dest -> inode - 1;
    in_cur->i_links_count++;

    int len_req = strlen(table_path_src[count_path_src - 1]) + 8;
    struct ext2_dir_entry_2 *ptr_dir = get_free_space(in_cur, len_req);

    if(ptr_dir == 0)
    {
        int free_block_new = get_free_block(bm_block, ptr_super_block);
        ptr_dir = (void*)ptr_disk + EXT2_BLOCK_SIZE * (free_block_new + 1);
        ptr_dir -> inode = fr_inode + 1;
        ptr_dir -> name_len = strlen(table_path_dest[count_path_dest - 1]);
        ptr_dir -> file_type = EXT2_FT_DIR;
        strcpy(ptr_dir -> name, table_path_dest[count_path_dest - 1]);
        ptr_dir -> rec_len = BLOCK_SIZE;
        
        in_src -> i_blocks += 2;
        in_src ->i_block[in_src -> i_size / BLOCK_SIZE] = free_block_new + 1;
        in_src -> i_size += BLOCK_SIZE;
    }
    else
    {
        int new_rec_len = ptr_dir -> rec_len - (4 * (ptr_dir -> name_len) + 8);
        ptr_dir -> rec_len = 4 * (ptr_dir -> name_len) + 8;
        ptr_dir = (void*)ptr_dir + ptr_dir -> rec_len;
        ptr_dir -> rec_len = new_rec_len;
        ptr_dir -> inode = fr_inode + 1;
        ptr_dir -> name_len = strlen(table_path_dest[count_path_dest - 1]);
        ptr_dir -> file_type = EXT2_FT_REG_FILE;
        strcpy(ptr_dir -> name, table_path_dest[count_path_dest - 1]);
    }
    ptr_group_desc->bg_used_dirs_count++;
    return 0;
}
示例#27
0
/* Expands macros in the *format string advancing the pointer as it goes.  The
 * opt represents conditional expression state, should be zero for non-recursive
 * calls.  Returns newly allocated string, which should be freed by the
 * caller. */
static LineWithAttrs
parse_view_macros(view_t *view, const char **format, const char macros[],
		int opt)
{
	const dir_entry_t *const curr = get_current_entry(view);
	LineWithAttrs result = { .line = strdup(""), .attrs = strdup("") };
	char c;
	int nexpansions = 0;
	int has_expander = 0;

	if(curr == NULL)
	{
		return result;
	}

	while((c = **format) != '\0')
	{
		size_t width = 0;
		int left_align = 0;
		char buf[PATH_MAX + 1];
		const char *const next = ++*format;
		int skip, ok;

		if(c != '%' ||
				(!char_is_one_of(macros, *next) && !isdigit(*next) &&
				 (*next != '=' || has_expander)))
		{
			if(strappendch(&result.line, &result.line_len, c) != 0)
			{
				break;
			}
			continue;
		}

		if(*next == '=')
		{
			(void)sync_attrs(&result, 0);

			if(strappend(&result.line, &result.line_len, "%=") != 0 ||
					strappendch(&result.attrs, &result.attrs_len, '=') != 0)
			{
				break;
			}
			++*format;
			has_expander = 1;
			continue;
		}

		if(*next == '-')
		{
			left_align = 1;
			++*format;
		}

		while(isdigit(**format))
		{
			width = width*10 + *(*format)++ - '0';
		}
		c = *(*format)++;

		skip = 0;
		ok = 1;
		buf[0] = '\0';
		switch(c)
		{
			case 'a':
				friendly_size_notation(get_free_space(curr_view->curr_dir), sizeof(buf),
						buf);
				break;
			case 't':
				format_entry_name(curr, NF_FULL, sizeof(buf), buf);
				break;
			case 'T':
				if(curr->type == FT_LINK)
				{
					char full_path[PATH_MAX + 1];
					char link_path[PATH_MAX + 1];  //add by sim1
					get_full_path_of(curr, sizeof(full_path), full_path);
					//mod by sim1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
					if(get_link_target(full_path, link_path, sizeof(link_path)) != 0)
					{
						copy_str(buf, sizeof(buf), "Failed to resolve link");
					}
					else
					{
						snprintf(buf, sizeof(buf), " -> %s", link_path);
					}
					//mod by sim1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				}
				break;
			case 'f':
				get_short_path_of(view, curr, NF_FULL, 0, sizeof(buf), buf);
				break;
			case 'A':
#ifndef _WIN32
				get_perm_string(buf, sizeof(buf), curr->mode);
#else
				copy_str(buf, sizeof(buf), attr_str_long(curr->attrs));
#endif
				break;
			case 'u':
				get_uid_string(curr, 0, sizeof(buf), buf);
				break;
			case 'g':
				get_gid_string(curr, 0, sizeof(buf), buf);
				break;
			case 's':
				friendly_size_notation(fentry_get_size(view, curr), sizeof(buf), buf);
				break;
			//add by sim1 ************************************************
			case 'r':
				{
					char path[PATH_MAX] = {0};
					get_full_path_at(view, view->list_pos, sizeof(path), path);
					(void)get_rating_string(buf, sizeof(buf), path);
				}
				break;
			case 'n':
				{
					int nitems = !fentry_is_dir(curr) ? 0 : (int)fentry_get_nitems(view, curr);
					snprintf(buf, sizeof(buf), "%d", nitems);
				}
				break;
			//add by sim1 ************************************************
			case 'E':
				{
					uint64_t size = 0U;

					typedef int (*iter_f)(view_t *view, dir_entry_t **entry);
					/* No current element for visual mode, since it can contain truly
					 * empty selection when cursor is on ../ directory. */
					iter_f iter = vle_mode_is(VISUAL_MODE) ? &iter_selected_entries
					                                       : &iter_selection_or_current;

					dir_entry_t *entry = NULL;
					while(iter(view, &entry))
					{
						size += fentry_get_size(view, entry);
					}

					friendly_size_notation(size, sizeof(buf), buf);
				}
				break;
			case 'd':
				{
					struct tm *tm_ptr = localtime(&curr->mtime);
					strftime(buf, sizeof(buf), cfg.time_format, tm_ptr);
				}
				break;
			case '-':
			case 'x':
				skip = expand_num(buf, sizeof(buf), view->filtered);
				break;
			case 'l':
				skip = expand_num(buf, sizeof(buf), view->list_pos + 1);
				break;
			case 'L':
				skip = expand_num(buf, sizeof(buf), view->list_rows + view->filtered);
				break;
			case 'S':
				skip = expand_num(buf, sizeof(buf), view->list_rows);
				break;
			case '%':
				copy_str(buf, sizeof(buf), "%");
				break;
			case 'z':
				copy_str(buf, sizeof(buf), get_tip());
				break;
			case 'D':
				if(curr_stats.number_of_windows == 1)
				{
					view_t *const other = (view == curr_view) ? other_view : curr_view;
					//mod by sim1
					//copy_str(buf, sizeof(buf), replace_home_part(other->curr_dir));
					snprintf(buf, sizeof(buf), " ‖ %s", replace_home_part(other->curr_dir));
				}
				break;
			case '[':
				{
					LineWithAttrs opt = parse_view_macros(view, format, macros, 1);
					copy_str(buf, sizeof(buf), opt.line);
					free(opt.line);

					char *attrs = opt.attrs;
					if(sync_attrs(&result, 0) && opt.attrs_len > 0U)
					{
						if(*attrs != ' ')
						{
							result.attrs[result.attrs_len - 1U] = *attrs;
						}
						++attrs;
					}
					strappend(&result.attrs, &result.attrs_len, attrs);
					free(opt.attrs);
					break;
				}
			case ']':
				if(opt)
				{
					if(nexpansions == 0)
					{
						replace_string(&result.line, "");
						replace_string(&result.attrs, "");
						result.line_len = 0U;
						result.attrs_len = 0U;
					}
					if(sync_attrs(&result, 0))
					{
						result.attrs[--result.attrs_len] = '\0';
					}
					return result;
				}

				LOG_INFO_MSG("Unmatched %%]");
				ok = 0;
				break;
			case '{':
				{
					/* Try to find matching closing bracket
					 * TODO: implement the way to escape it, so that the expr may contain
					 * closing brackets */
					const char *e = strchr(*format, '}');
					char *expr = NULL, *resstr = NULL;
					var_t res = var_false();
					ParsingErrors parsing_error;

					/* If there's no matching closing bracket, just add the opening one
					 * literally */
					if(e == NULL)
					{
						ok = 0;
						break;
					}

					/* Create a NULL-terminated copy of the given expr.
					 * TODO: we could temporarily use buf for that, to avoid extra
					 * allocation, but explicitly named variable reads better. */
					expr = calloc(e - (*format) + 1 /* NUL-term */, 1);
					memcpy(expr, *format, e - (*format));

					/* Try to parse expr, and convert the res to string if succeed. */
					parsing_error = parse(expr, 0, &res);
					if(parsing_error == PE_NO_ERROR)
					{
						resstr = var_to_str(res);
					}

					if(resstr != NULL)
					{
						copy_str(buf, sizeof(buf), resstr);
					}
					else
					{
						copy_str(buf, sizeof(buf), "<Invalid expr>");
					}

					var_free(res);
					free(resstr);
					free(expr);

					*format = e + 1 /* closing bracket */;
				}
				break;
			case '*':
				if(width > 9)
				{
					snprintf(buf, sizeof(buf), "%%%d*", (int)width);
					width = 0;
					break;
				}
				(void)sync_attrs(&result, 1);
				result.attrs[result.attrs_len - 1] = '0' + width;
				width = 0;
				break;

			default:
				LOG_INFO_MSG("Unexpected %%-sequence: %%%c", c);
				ok = 0;
				break;
		}

		if(char_is_one_of("tTAugsEd", c) && fentry_is_fake(curr))
		{
			buf[0] = '\0';
		}

		if(!ok)
		{
			*format = next;
			if(strappendch(&result.line, &result.line_len, '%') != 0)
			{
				break;
			}
			continue;
		}

		check_expanded_str(buf, skip, &nexpansions);
		stralign(buf, width, ' ', left_align);

		if(strappend(&result.line, &result.line_len, buf) != 0)
		{
			break;
		}
	}

	/* Unmatched %[. */
	if(opt)
	{
		(void)strprepend(&result.line, &result.line_len, "%[");
	}

	if(sync_attrs(&result, 0))
	{
		result.attrs[--result.attrs_len] = '\0';
	}
	return result;
}

/* Makes sure that result->attrs has at least as many elements as result->line
 * contains characters + extra_width.  Returns non-zero if result->attrs has
 * extra characters compared to result->line. */
static int
sync_attrs(LineWithAttrs *result, int extra_width)
{
	const size_t nchars = utf8_strsw(result->line) + extra_width;
	if(result->attrs_len < nchars)
	{
		char *const new_attrs = format_str("%s%*s", result->attrs,
				(int)(nchars - result->attrs_len), "");
		free(result->attrs);
		result->attrs = new_attrs;
		result->attrs_len = nchars;
	}
	return (result->attrs_len > nchars);
}

/* Prints number into the buffer.  Returns non-zero if numeric value is
 * "empty" (zero). */
static int
expand_num(char buf[], size_t buf_len, int val)
{
	snprintf(buf, buf_len, "%d", val);
	return (val == 0);
}