static int flush_entry(fatfile_t* file) { fat_updateFileEntry(file); fatfile_t* child = file->child; // update child while(child) { flush_entry(child); child = child->next; } return 0; }
static int fat_flush(fatfs_t* fatfs) { // flush dir entry flush_entry(fatfs->root); // write fat data int start_pos = fatfs->reserved_sectors * fatfs->bytes_per_sector; int bytes = write(fatfs->device, fatfs->fat_data, fatfs->fat_size, start_pos); assert(bytes == fatfs->fat_size); // flush iobuf iobuf_t* ptr = fatfs->iobuflist; while(ptr) // 查找缓冲块 { if(ptr->dirty) // 刷新缓冲块 { printk("write cluster %d\n", ptr->cluster_idx); if (fat_rwCluster(fatfs, ptr->cluster_idx, ptr->cluster_buf, FAT_WRITE) < 0) { printk("write cluster %d error\n", ptr->cluster_idx); return -1; } ptr->dirty = 0; } ptr = ptr->next; } return 0; }
/* This should run pretty quick, its called a lot */ iconv_t e_iconv_open(const char *oto, const char *ofrom) { const char *to, *from; char *tofrom; struct _iconv_cache *ic; struct _iconv_cache_node *in; int errnosav; iconv_t ip; to = e_iconv_charset_name (oto); from = e_iconv_charset_name (ofrom); /* e_iconv_charset_name() could return NULL in case of invalid charset. So, we need to check them here. */ if (to == NULL || from == NULL) { errno = EINVAL; return (iconv_t) -1; } tofrom = g_alloca (strlen (to) + strlen (from) + 2); sprintf(tofrom, "%s%%%s", to, from); LOCK(); ic = g_hash_table_lookup(iconv_cache, tofrom); if (ic) { e_dlist_remove((EDListNode *)ic); } else { struct _iconv_cache *last = (struct _iconv_cache *)iconv_cache_list.tailpred; struct _iconv_cache *prev; prev = last->prev; while (prev && iconv_cache_size > E_ICONV_CACHE_SIZE) { in = (struct _iconv_cache_node *)last->open.head; if (in->next && !in->busy) { cd(printf("Flushing iconv converter '%s'\n", last->conv)); e_dlist_remove((EDListNode *)last); g_hash_table_remove(iconv_cache, last->conv); flush_entry(last); iconv_cache_size--; } last = prev; prev = last->prev; } iconv_cache_size++; ic = g_malloc(sizeof(*ic)); e_dlist_init(&ic->open); ic->conv = g_strdup(tofrom); g_hash_table_insert(iconv_cache, ic->conv, ic); cd(printf("Creating iconv converter '%s'\n", ic->conv)); } e_dlist_addhead(&iconv_cache_list, (EDListNode *)ic); /* If we have a free iconv, use it */ in = (struct _iconv_cache_node *)ic->open.tailpred; if (in->prev && !in->busy) { cd(printf("using existing iconv converter '%s'\n", ic->conv)); ip = in->ip; if (ip != (iconv_t)-1) { /* work around some broken iconv implementations * that die if the length arguments are NULL */ size_t buggy_iconv_len = 0; char *buggy_iconv_buf = NULL; /* resets the converter */ iconv(ip, &buggy_iconv_buf, &buggy_iconv_len, &buggy_iconv_buf, &buggy_iconv_len); in->busy = TRUE; e_dlist_remove((EDListNode *)in); e_dlist_addhead(&ic->open, (EDListNode *)in); } } else { cd(printf("creating new iconv converter '%s'\n", ic->conv)); ip = iconv_open(to, from); in = g_malloc(sizeof(*in)); in->ip = ip; in->parent = ic; e_dlist_addhead(&ic->open, (EDListNode *)in); if (ip != (iconv_t)-1) { g_hash_table_insert(iconv_cache_open, ip, in); in->busy = TRUE; } else { errnosav = errno; /* g_warning("Could not open converter for '%s' to '%s' charset", from, to); */ in->busy = FALSE; errno = errnosav; } } UNLOCK(); return ip; }
/* This should run pretty quick, its called a lot */ iconv_t camel_iconv_open (const gchar *oto, const gchar *ofrom) { const gchar *to, *from; gchar *tofrom; struct _iconv_cache *ic; struct _iconv_cache_node *in; gint errnosav; iconv_t ip; if (oto == NULL || ofrom == NULL) { errno = EINVAL; return (iconv_t) -1; } to = camel_iconv_charset_name (oto); from = camel_iconv_charset_name (ofrom); tofrom = g_alloca (strlen (to) + strlen (from) + 2); sprintf (tofrom, "%s%%%s", to, from); G_LOCK (iconv); ic = g_hash_table_lookup (iconv_cache, tofrom); if (ic) { g_queue_remove (&iconv_cache_list, ic); } else { GList *link; link = g_queue_peek_tail_link (&iconv_cache_list); while (link != NULL && iconv_cache_list.length > E_ICONV_CACHE_SIZE) { GList *prev = g_list_previous (link); ic = (struct _iconv_cache *) link->data; in = g_queue_peek_head (&ic->open); if (in != NULL && !in->busy) { cd (printf ("Flushing iconv converter '%s'\n", ic->conv)); g_queue_delete_link (&iconv_cache_list, link); g_hash_table_remove (iconv_cache, ic->conv); flush_entry (ic); } link = prev; } ic = g_malloc (sizeof (*ic)); g_queue_init (&ic->open); ic->conv = g_strdup (tofrom); g_hash_table_insert (iconv_cache, ic->conv, ic); cd (printf ("Creating iconv converter '%s'\n", ic->conv)); } g_queue_push_head (&iconv_cache_list, ic); /* If we have a free iconv, use it */ in = g_queue_peek_tail (&ic->open); if (in != NULL && !in->busy) { cd (printf ("using existing iconv converter '%s'\n", ic->conv)); ip = in->ip; if (ip != (iconv_t) - 1) { /* work around some broken iconv implementations * that die if the length arguments are NULL */ gsize buggy_iconv_len = 0; gchar *buggy_iconv_buf = NULL; /* resets the converter */ iconv (ip, &buggy_iconv_buf, &buggy_iconv_len, &buggy_iconv_buf, &buggy_iconv_len); in->busy = TRUE; g_queue_remove (&ic->open, in); g_queue_push_head (&ic->open, in); } } else { cd (printf ("creating new iconv converter '%s'\n", ic->conv)); ip = iconv_open (to, from); in = g_malloc (sizeof (*in)); in->ip = ip; in->parent = ic; g_queue_push_head (&ic->open, in); if (ip != (iconv_t) - 1) { g_hash_table_insert (iconv_cache_open, ip, in); in->busy = TRUE; } else { errnosav = errno; g_warning ("Could not open converter for '%s' to '%s' charset", from, to); in->busy = FALSE; errno = errnosav; } } G_UNLOCK (iconv); return ip; }