3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <sys/types.h>
44 #define SIM_CACHE_MODE 0600
45 #define SIM_CACHE_BASEPATH STORAGEDIR "/%s-%i"
46 #define SIM_CACHE_VERSION SIM_CACHE_BASEPATH "/version"
47 #define SIM_CACHE_PATH SIM_CACHE_BASEPATH "/%04x"
48 #define SIM_CACHE_HEADER_SIZE 39
49 #define SIM_FILE_INFO_SIZE 7
50 #define SIM_IMAGE_CACHE_BASEPATH STORAGEDIR "/%s-%i/images"
51 #define SIM_IMAGE_CACHE_PATH SIM_IMAGE_CACHE_BASEPATH "/%d.xpm"
53 #define SIM_FS_VERSION 2
55 static gboolean sim_fs_op_next(gpointer user_data);
56 static gboolean sim_fs_op_read_record(gpointer user);
57 static gboolean sim_fs_op_read_block(gpointer user_data);
61 unsigned char *buffer;
62 enum ofono_sim_file_structure structure;
63 unsigned short offset;
72 struct ofono_sim_context *context;
75 static void sim_fs_op_free(struct sim_fs_op *node)
84 unsigned char bitmap[32];
86 struct ofono_sim *sim;
87 const struct ofono_sim_driver *driver;
91 void sim_fs_free(struct sim_fs *fs)
97 g_source_remove(fs->op_source);
102 * Note: users of sim_fs must not assume that the callback happens
103 * for operations still in progress
106 g_queue_foreach(fs->op_q, (GFunc) sim_fs_op_free, NULL);
107 g_queue_free(fs->op_q);
112 sim_fs_context_free(fs->contexts->data);
118 struct ofono_watchlist_item item;
122 struct ofono_sim_context {
124 struct ofono_watchlist *file_watches;
127 struct sim_fs *sim_fs_new(struct ofono_sim *sim,
128 const struct ofono_sim_driver *driver)
132 fs = g_try_new0(struct sim_fs, 1);
143 struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs)
145 struct ofono_sim_context *context =
146 g_try_new0(struct ofono_sim_context, 1);
152 fs->contexts = g_slist_prepend(fs->contexts, context);
157 void sim_fs_context_free(struct ofono_sim_context *context)
159 struct sim_fs *fs = context->fs;
161 struct sim_fs_op *op;
164 while ((op = g_queue_peek_nth(fs->op_q, n)) != NULL) {
165 if (op->context != context) {
178 g_queue_remove(fs->op_q, op);
182 if (context->file_watches)
183 __ofono_watchlist_free(context->file_watches);
185 fs->contexts = g_slist_remove(fs->contexts, context);
189 unsigned int sim_fs_file_watch_add(struct ofono_sim_context *context, int id,
190 ofono_sim_file_changed_cb_t cb,
192 ofono_destroy_func destroy)
194 struct file_watch *watch;
199 if (context->file_watches == NULL)
200 context->file_watches = __ofono_watchlist_new(g_free);
202 watch = g_new0(struct file_watch, 1);
205 watch->item.notify = cb;
206 watch->item.notify_data = userdata;
207 watch->item.destroy = destroy;
209 return __ofono_watchlist_add_item(context->file_watches,
210 (struct ofono_watchlist_item *) watch);
213 void sim_fs_file_watch_remove(struct ofono_sim_context *context,
216 __ofono_watchlist_remove_item(context->file_watches, id);
219 void sim_fs_notify_file_watches(struct sim_fs *fs, int id)
223 for (l = fs->contexts; l; l = l->next) {
224 struct ofono_sim_context *context = l->data;
227 for (k = context->file_watches->items; k; k = k->next) {
228 struct file_watch *w = k->data;
229 ofono_sim_file_changed_cb_t notify = w->item.notify;
231 if (id == -1 || w->ef == id)
232 notify(w->ef, w->item.notify_data);
238 static void sim_fs_end_current(struct sim_fs *fs)
240 struct sim_fs_op *op = g_queue_pop_head(fs->op_q);
242 if (g_queue_get_length(fs->op_q) > 0)
243 fs->op_source = g_idle_add(sim_fs_op_next, fs);
250 memset(fs->bitmap, 0, sizeof(fs->bitmap));
255 static void sim_fs_op_error(struct sim_fs *fs)
257 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
259 if (op->cb == NULL) {
260 sim_fs_end_current(fs);
264 if (op->info_only == TRUE)
265 ((sim_fs_read_info_cb_t) op->cb)
266 (0, 0, 0, 0, op->userdata);
267 else if (op->is_read == TRUE)
268 ((ofono_sim_file_read_cb_t) op->cb)
269 (0, 0, 0, 0, 0, op->userdata);
271 ((ofono_sim_file_write_cb_t) op->cb)
274 sim_fs_end_current(fs);
277 static gboolean cache_block(struct sim_fs *fs, int block, int block_len,
278 const unsigned char *data, int num_bytes)
288 if (lseek(fs->fd, block * block_len +
289 SIM_CACHE_HEADER_SIZE, SEEK_SET) == (off_t) -1)
292 r = TFR(write(fs->fd, data, num_bytes));
297 /* update present bit for this block */
301 /* lseek to correct byte (skip file info) */
302 lseek(fs->fd, offset + SIM_FILE_INFO_SIZE, SEEK_SET);
304 b = fs->bitmap[offset];
307 r = TFR(write(fs->fd, &b, sizeof(b)));
312 fs->bitmap[offset] = b;
317 static void sim_fs_op_write_cb(const struct ofono_error *error, void *data)
319 struct sim_fs *fs = data;
320 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
321 ofono_sim_file_write_cb_t cb = op->cb;
324 sim_fs_end_current(fs);
328 if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
333 sim_fs_end_current(fs);
336 static void sim_fs_op_read_block_cb(const struct ofono_error *error,
337 const unsigned char *data, int len,
340 struct sim_fs *fs = user;
341 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
348 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
353 start_block = op->offset / 256;
354 end_block = (op->offset + (op->num_bytes - 1)) / 256;
356 if (op->current == start_block) {
358 dataoff = op->offset % 256;
359 tocopy = MIN(256 - op->offset % 256,
360 op->num_bytes - op->current * 256);
362 bufoff = (op->current - start_block - 1) * 256 +
365 tocopy = MIN(256, op->num_bytes - op->current * 256);
368 DBG("bufoff: %d, dataoff: %d, tocopy: %d",
369 bufoff, dataoff, tocopy);
371 memcpy(op->buffer + bufoff, data + dataoff, tocopy);
372 cache_block(fs, op->current, 256, data, len);
374 if (op->cb == NULL) {
375 sim_fs_end_current(fs);
381 if (op->current > end_block) {
382 ofono_sim_file_read_cb_t cb = op->cb;
384 cb(1, op->num_bytes, 0, op->buffer,
385 op->record_length, op->userdata);
387 sim_fs_end_current(fs);
389 fs->op_source = g_idle_add(sim_fs_op_read_block, fs);
393 static gboolean sim_fs_op_read_block(gpointer user_data)
395 struct sim_fs *fs = user_data;
396 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
399 unsigned short read_bytes;
403 if (op->cb == NULL) {
404 sim_fs_end_current(fs);
408 start_block = op->offset / 256;
409 end_block = (op->offset + (op->num_bytes - 1)) / 256;
411 if (op->current == start_block) {
412 op->buffer = g_try_new0(unsigned char, op->num_bytes);
414 if (op->buffer == NULL) {
420 while (fs->fd != -1 && op->current <= end_block) {
421 int offset = op->current / 8;
422 int bit = 1 << op->current % 8;
427 if ((fs->bitmap[offset] & bit) == 0)
430 if (op->current == start_block) {
432 seekoff = SIM_CACHE_HEADER_SIZE + op->current * 256 +
434 toread = MIN(256 - op->offset % 256,
435 op->num_bytes - op->current * 256);
437 bufoff = (op->current - start_block - 1) * 256 +
439 seekoff = SIM_CACHE_HEADER_SIZE + op->current * 256;
440 toread = MIN(256, op->num_bytes - op->current * 256);
443 DBG("bufoff: %d, seekoff: %d, toread: %d",
444 bufoff, seekoff, toread);
446 if (lseek(fs->fd, seekoff, SEEK_SET) == (off_t) -1)
449 if (TFR(read(fs->fd, op->buffer + bufoff, toread)) != toread)
455 if (op->current > end_block) {
456 ofono_sim_file_read_cb_t cb = op->cb;
458 cb(1, op->num_bytes, 0, op->buffer,
459 op->record_length, op->userdata);
461 sim_fs_end_current(fs);
466 if (fs->driver->read_file_transparent == NULL) {
471 read_bytes = MIN(op->length - op->current * 256, 256);
472 fs->driver->read_file_transparent(fs->sim, op->id,
475 sim_fs_op_read_block_cb, fs);
480 static void sim_fs_op_retrieve_cb(const struct ofono_error *error,
481 const unsigned char *data, int len,
484 struct sim_fs *fs = user;
485 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
486 int total = op->length / op->record_length;
487 ofono_sim_file_read_cb_t cb = op->cb;
489 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
494 cache_block(fs, op->current - 1, op->record_length,
495 data, op->record_length);
498 sim_fs_end_current(fs);
502 cb(1, op->length, op->current, data, op->record_length, op->userdata);
504 if (op->current < total) {
506 fs->op_source = g_idle_add(sim_fs_op_read_record, fs);
508 sim_fs_end_current(fs);
512 static gboolean sim_fs_op_read_record(gpointer user)
514 struct sim_fs *fs = user;
515 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
516 const struct ofono_sim_driver *driver = fs->driver;
517 int total = op->length / op->record_length;
518 unsigned char buf[256];
522 if (op->cb == NULL) {
523 sim_fs_end_current(fs);
527 while (fs->fd != -1 && op->current <= total) {
528 int offset = (op->current - 1) / 8;
529 int bit = 1 << ((op->current - 1) % 8);
530 ofono_sim_file_read_cb_t cb = op->cb;
532 if ((fs->bitmap[offset] & bit) == 0)
535 if (lseek(fs->fd, (op->current - 1) * op->record_length +
536 SIM_CACHE_HEADER_SIZE, SEEK_SET) == (off_t) -1)
539 if (TFR(read(fs->fd, buf, op->record_length)) !=
543 cb(1, op->length, op->current,
544 buf, op->record_length, op->userdata);
549 if (op->current > total) {
550 sim_fs_end_current(fs);
555 switch (op->structure) {
556 case OFONO_SIM_FILE_STRUCTURE_FIXED:
557 if (driver->read_file_linear == NULL) {
562 driver->read_file_linear(fs->sim, op->id, op->current,
564 sim_fs_op_retrieve_cb, fs);
566 case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
567 if (driver->read_file_cyclic == NULL) {
572 driver->read_file_cyclic(fs->sim, op->id, op->current,
574 sim_fs_op_retrieve_cb, fs);
577 ofono_error("Unrecognized file structure, this can't happen");
583 static void sim_fs_op_cache_fileinfo(struct sim_fs *fs,
584 const struct ofono_error *error,
586 enum ofono_sim_file_structure structure,
588 const unsigned char access[3],
589 unsigned char file_status)
591 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
592 const char *imsi = ofono_sim_get_imsi(fs->sim);
593 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
594 enum sim_file_access update;
595 enum sim_file_access invalidate;
596 enum sim_file_access rehabilitate;
597 unsigned char fileinfo[SIM_CACHE_HEADER_SIZE];
601 /* TS 11.11, Section 9.3 */
602 update = file_access_condition_decode(access[0] & 0xf);
603 rehabilitate = file_access_condition_decode((access[2] >> 4) & 0xf);
604 invalidate = file_access_condition_decode(access[2] & 0xf);
606 /* Never cache card holder writable files */
607 cache = (update == SIM_FILE_ACCESS_ADM ||
608 update == SIM_FILE_ACCESS_NEVER) &&
609 (invalidate == SIM_FILE_ACCESS_ADM ||
610 invalidate == SIM_FILE_ACCESS_NEVER) &&
611 (rehabilitate == SIM_FILE_ACCESS_ADM ||
612 rehabilitate == SIM_FILE_ACCESS_NEVER);
614 if (imsi == NULL || phase == OFONO_SIM_PHASE_UNKNOWN || cache == FALSE)
617 memset(fileinfo, 0, SIM_CACHE_HEADER_SIZE);
619 fileinfo[0] = error->type;
620 fileinfo[1] = length >> 8;
621 fileinfo[2] = length & 0xff;
622 fileinfo[3] = structure;
623 fileinfo[4] = record_length >> 8;
624 fileinfo[5] = record_length & 0xff;
625 fileinfo[6] = file_status;
627 path = g_strdup_printf(SIM_CACHE_PATH, imsi, phase, op->id);
628 fs->fd = TFR(open(path, O_WRONLY | O_CREAT | O_TRUNC, SIM_CACHE_MODE));
634 if (TFR(write(fs->fd, fileinfo, SIM_CACHE_HEADER_SIZE)) ==
635 SIM_CACHE_HEADER_SIZE)
642 static void sim_fs_op_info_cb(const struct ofono_error *error, int length,
643 enum ofono_sim_file_structure structure,
645 const unsigned char access[3],
646 unsigned char file_status,
649 struct sim_fs *fs = data;
650 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
652 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
657 sim_fs_op_cache_fileinfo(fs, error, length, structure, record_length,
658 access, file_status);
660 if (structure != op->structure) {
661 ofono_error("Requested file structure differs from SIM: %x",
667 if (op->cb == NULL) {
668 sim_fs_end_current(fs);
672 op->structure = structure;
675 if (structure == OFONO_SIM_FILE_STRUCTURE_TRANSPARENT) {
676 if (op->num_bytes == 0)
677 op->num_bytes = op->length;
679 op->record_length = length;
680 op->current = op->offset / 256;
682 if (op->info_only == FALSE)
683 fs->op_source = g_idle_add(sim_fs_op_read_block, fs);
685 op->record_length = record_length;
688 if (op->info_only == FALSE)
689 fs->op_source = g_idle_add(sim_fs_op_read_record, fs);
692 if (op->info_only == TRUE) {
694 * It's an info-only request, so there is no need to request
695 * actual contents of the EF. Just return the EF-info.
697 sim_fs_read_info_cb_t cb = op->cb;
699 cb(1, file_status, op->length,
700 op->record_length, op->userdata);
702 sim_fs_end_current(fs);
706 static gboolean sim_fs_op_check_cached(struct sim_fs *fs)
708 const char *imsi = ofono_sim_get_imsi(fs->sim);
709 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
710 struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
714 unsigned char fileinfo[SIM_CACHE_HEADER_SIZE];
717 enum ofono_sim_file_structure structure;
719 unsigned char file_status;
721 if (imsi == NULL || phase == OFONO_SIM_PHASE_UNKNOWN)
724 path = g_strdup_printf(SIM_CACHE_PATH, imsi, phase, op->id);
729 fd = TFR(open(path, O_RDWR));
734 DBG("Error %i opening cache file for "
735 "fileid %04x, IMSI %s",
736 errno, op->id, imsi);
741 len = TFR(read(fd, fileinfo, SIM_CACHE_HEADER_SIZE));
743 if (len != SIM_CACHE_HEADER_SIZE)
746 error_type = fileinfo[0];
747 file_length = (fileinfo[1] << 8) | fileinfo[2];
748 structure = fileinfo[3];
749 record_length = (fileinfo[4] << 8) | fileinfo[5];
750 file_status = fileinfo[6];
752 if (structure == OFONO_SIM_FILE_STRUCTURE_TRANSPARENT)
753 record_length = file_length;
755 if (record_length == 0 || file_length < record_length)
758 op->length = file_length;
759 op->record_length = record_length;
760 memcpy(fs->bitmap, fileinfo + SIM_FILE_INFO_SIZE,
761 SIM_CACHE_HEADER_SIZE - SIM_FILE_INFO_SIZE);
764 if (error_type != OFONO_ERROR_TYPE_NO_ERROR ||
765 structure != op->structure) {
770 if (op->info_only == TRUE) {
772 * It's an info-only request, so there is no need to request
773 * actual contents of the EF. Just return the EF-info.
775 sim_fs_read_info_cb_t cb = op->cb;
777 cb(1, file_status, op->length,
778 op->record_length, op->userdata);
780 sim_fs_end_current(fs);
781 } else if (structure == OFONO_SIM_FILE_STRUCTURE_TRANSPARENT) {
782 if (op->num_bytes == 0)
783 op->num_bytes = op->length;
785 op->current = op->offset / 256;
786 fs->op_source = g_idle_add(sim_fs_op_read_block, fs);
789 fs->op_source = g_idle_add(sim_fs_op_read_record, fs);
799 static gboolean sim_fs_op_next(gpointer user_data)
801 struct sim_fs *fs = user_data;
802 const struct ofono_sim_driver *driver = fs->driver;
803 struct sim_fs_op *op;
807 if (fs->op_q == NULL)
810 op = g_queue_peek_head(fs->op_q);
812 if (op->cb == NULL) {
813 sim_fs_end_current(fs);
817 if (op->is_read == TRUE) {
818 if (sim_fs_op_check_cached(fs))
821 driver->read_file_info(fs->sim, op->id, sim_fs_op_info_cb, fs);
823 switch (op->structure) {
824 case OFONO_SIM_FILE_STRUCTURE_TRANSPARENT:
825 driver->write_file_transparent(fs->sim, op->id, 0,
826 op->length, op->buffer,
827 sim_fs_op_write_cb, fs);
829 case OFONO_SIM_FILE_STRUCTURE_FIXED:
830 driver->write_file_linear(fs->sim, op->id, op->current,
831 op->length, op->buffer,
832 sim_fs_op_write_cb, fs);
834 case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
835 driver->write_file_cyclic(fs->sim, op->id,
836 op->length, op->buffer,
837 sim_fs_op_write_cb, fs);
840 ofono_error("Unrecognized file structure, "
841 "this can't happen");
851 int sim_fs_read_info(struct ofono_sim_context *context, int id,
852 enum ofono_sim_file_structure expected_type,
853 sim_fs_read_info_cb_t cb, void *data)
855 struct sim_fs *fs = context->fs;
856 struct sim_fs_op *op;
861 if (fs->driver == NULL)
864 if (fs->driver->read_file_info == NULL)
867 if (fs->op_q == NULL)
868 fs->op_q = g_queue_new();
870 op = g_try_new0(struct sim_fs_op, 1);
875 op->structure = expected_type;
879 op->info_only = TRUE;
880 op->context = context;
882 g_queue_push_tail(fs->op_q, op);
884 if (g_queue_get_length(fs->op_q) == 1)
885 fs->op_source = g_idle_add(sim_fs_op_next, fs);
890 int sim_fs_read(struct ofono_sim_context *context, int id,
891 enum ofono_sim_file_structure expected_type,
892 unsigned short offset, unsigned short num_bytes,
893 ofono_sim_file_read_cb_t cb, void *data)
895 struct sim_fs *fs = context->fs;
896 struct sim_fs_op *op;
901 if (fs->driver == NULL)
904 if (fs->driver->read_file_info == NULL) {
905 cb(0, 0, 0, NULL, 0, data);
909 if (fs->op_q == NULL)
910 fs->op_q = g_queue_new();
912 op = g_try_new0(struct sim_fs_op, 1);
917 op->structure = expected_type;
922 op->num_bytes = num_bytes;
923 op->info_only = FALSE;
924 op->context = context;
926 g_queue_push_tail(fs->op_q, op);
928 if (g_queue_get_length(fs->op_q) == 1)
929 fs->op_source = g_idle_add(sim_fs_op_next, fs);
934 int sim_fs_write(struct ofono_sim_context *context, int id,
935 ofono_sim_file_write_cb_t cb,
936 enum ofono_sim_file_structure structure, int record,
937 const unsigned char *data, int length, void *userdata)
939 struct sim_fs *fs = context->fs;
940 struct sim_fs_op *op;
941 gconstpointer fn = NULL;
946 if (fs->driver == NULL)
950 case OFONO_SIM_FILE_STRUCTURE_TRANSPARENT:
951 fn = fs->driver->write_file_transparent;
953 case OFONO_SIM_FILE_STRUCTURE_FIXED:
954 fn = fs->driver->write_file_linear;
956 case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
957 fn = fs->driver->write_file_cyclic;
960 ofono_error("Unrecognized file structure, this can't happen");
966 if (fs->op_q == NULL)
967 fs->op_q = g_queue_new();
969 op = g_try_new0(struct sim_fs_op, 1);
975 op->userdata = userdata;
977 op->buffer = g_memdup(data, length);
978 op->structure = structure;
980 op->current = record;
981 op->context = context;
983 g_queue_push_tail(fs->op_q, op);
985 if (g_queue_get_length(fs->op_q) == 1)
986 fs->op_source = g_idle_add(sim_fs_op_next, fs);
991 void sim_fs_cache_image(struct sim_fs *fs, const char *image, int id)
994 enum ofono_sim_phase phase;
996 if (fs == NULL || image == NULL)
999 imsi = ofono_sim_get_imsi(fs->sim);
1003 phase = ofono_sim_get_phase(fs->sim);
1004 if (phase == OFONO_SIM_PHASE_UNKNOWN)
1007 write_file((const unsigned char *) image, strlen(image),
1008 SIM_CACHE_MODE, SIM_IMAGE_CACHE_PATH, imsi,
1012 char *sim_fs_get_cached_image(struct sim_fs *fs, int id)
1015 enum ofono_sim_phase phase;
1016 unsigned short image_length;
1026 imsi = ofono_sim_get_imsi(fs->sim);
1030 phase = ofono_sim_get_phase(fs->sim);
1031 if (phase == OFONO_SIM_PHASE_UNKNOWN)
1034 path = g_strdup_printf(SIM_IMAGE_CACHE_PATH, imsi, phase, id);
1036 TFR(stat(path, &st_buf));
1037 fd = TFR(open(path, O_RDONLY));
1043 image_length = st_buf.st_size;
1044 buffer = g_try_new0(char, image_length + 1);
1046 if (buffer == NULL) {
1051 len = TFR(read(fd, buffer, image_length));
1054 if (len != image_length) {
1062 static void remove_cachefile(const char *imsi, enum ofono_sim_phase phase,
1063 const struct dirent *file)
1068 if (file->d_type != DT_REG)
1071 if (sscanf(file->d_name, "%4x", &id) != 1)
1074 path = g_strdup_printf(SIM_CACHE_PATH, imsi, phase, id);
1079 static void remove_imagefile(const char *imsi, enum ofono_sim_phase phase,
1080 const struct dirent *file)
1085 if (file->d_type != DT_REG)
1088 if (sscanf(file->d_name, "%d", &id) != 1)
1091 path = g_strdup_printf(SIM_IMAGE_CACHE_PATH, imsi, phase, id);
1096 void sim_fs_check_version(struct sim_fs *fs)
1098 const char *imsi = ofono_sim_get_imsi(fs->sim);
1099 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
1100 unsigned char version;
1102 if (imsi == NULL || phase == OFONO_SIM_PHASE_UNKNOWN)
1105 if (read_file(&version, 1, SIM_CACHE_VERSION, imsi, phase) == 1)
1106 if (version == SIM_FS_VERSION)
1109 sim_fs_cache_flush(fs);
1111 version = SIM_FS_VERSION;
1112 write_file(&version, 1, SIM_CACHE_MODE, SIM_CACHE_VERSION, imsi, phase);
1115 void sim_fs_cache_flush(struct sim_fs *fs)
1117 const char *imsi = ofono_sim_get_imsi(fs->sim);
1118 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
1119 char *path = g_strdup_printf(SIM_CACHE_BASEPATH, imsi, phase);
1120 struct dirent **entries;
1121 int len = scandir(path, &entries, NULL, alphasort);
1126 /* Remove all file ids */
1128 remove_cachefile(imsi, phase, entries[len]);
1129 g_free(entries[len]);
1135 sim_fs_image_cache_flush(fs);
1138 void sim_fs_cache_flush_file(struct sim_fs *fs, int id)
1140 const char *imsi = ofono_sim_get_imsi(fs->sim);
1141 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
1142 char *path = g_strdup_printf(SIM_CACHE_PATH, imsi, phase, id);
1148 void sim_fs_image_cache_flush(struct sim_fs *fs)
1150 const char *imsi = ofono_sim_get_imsi(fs->sim);
1151 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
1152 char *path = g_strdup_printf(SIM_IMAGE_CACHE_BASEPATH, imsi, phase);
1153 struct dirent **entries;
1154 int len = scandir(path, &entries, NULL, alphasort);
1161 /* Remove everything */
1163 remove_imagefile(imsi, phase, entries[len]);
1164 g_free(entries[len]);
1170 void sim_fs_image_cache_flush_file(struct sim_fs *fs, int id)
1172 const char *imsi = ofono_sim_get_imsi(fs->sim);
1173 enum ofono_sim_phase phase = ofono_sim_get_phase(fs->sim);
1174 char *path = g_strdup_printf(SIM_IMAGE_CACHE_PATH, imsi, phase, id);