static char *cleanse_path(char *inpath) { char *newpath; // Remove "." and ".." newpath = malloc(strlen(inpath)); memcpy(newpath, "/", 2); char *token; char *remainder = inpath; while ((token = strsep(&remainder, "/"))) { if (token[0] == 0 || str_is_equal(token, ".")) { continue; } else if (str_is_equal(token, "..")) { char *lastslash = strrchr(newpath, '/'); if (lastslash > newpath) *lastslash = 0; else newpath[1] = 0; } else { if (strlen(newpath) > 1) strcat(newpath, "/"); strcat(newpath, token); } } free(inpath); return newpath; }
static afc_error_t remove_path(char *path, bool recurse) { afc_error_t result; char **infolist = NULL; bool is_dir; result = afc_get_file_info(afc, path, &infolist); if (result != AFC_E_SUCCESS) { if (result != AFC_E_OBJECT_NOT_FOUND) afc_warn(result, "%s: stat failed: %s", __func__, path); return result; } if (recurse && is_directory(path, &is_dir) == AFC_E_SUCCESS && is_dir) { char **list = NULL; result = afc_read_directory(afc, path, &list); if (result != AFC_E_SUCCESS) { afc_warn(result, "%s", path); return result; } for (int i = 0; list[i] && result == AFC_E_SUCCESS; i++) { if (str_is_equal(list[i], ".")) ; // NOP else if (str_is_equal(list[i], "..")) ; // NOP else { char *subdir_path; if (asprintf(&subdir_path, "%s/%s", path, list[i]) > 0) { result = remove_path(subdir_path, recurse); free(subdir_path); } else { warn("%s: %s", __func__, "asprintf"); } } free(list[i]); } free(list); } if (recurse) printf("removing: %s\n", path); result = afc_remove_path(afc, path); if (result != AFC_E_SUCCESS) afc_warn(result, "%s", path); return result; }
static afc_error_t cmd_mv(int argc, const char *argv[]) { afc_error_t result; const char *filename; char *source_path, *target_path; char **infolist; bool target_is_dir; if (argc != 2) { warnx("usage: mv <source> <target>"); return -1; } source_path = build_absolute_path(argv[0]); target_path = build_absolute_path(argv[1]); if (source_path && target_path) { result = afc_get_file_info(afc, target_path, &infolist); if (result == AFC_E_SUCCESS) { for (int i = 0; infolist[i] != NULL; i++) { if (str_is_equal(infolist[i], "st_ifmt")) target_is_dir = str_is_equal(infolist[i+1], "S_IFDIR"); free(infolist[i]); } free(infolist); if (target_is_dir) { filename = basename((char *) argv[0]); target_path = realloc(target_path, strlen(filename) + 2); strcat(target_path, "/"); strcat(target_path, filename); result = AFC_E_SUCCESS; } } else if (result == AFC_E_OBJECT_NOT_FOUND) { result = AFC_E_SUCCESS; } if (result == AFC_E_SUCCESS) { result = afc_rename_path(afc, source_path, target_path); if (result != AFC_E_SUCCESS) afc_warn(result, "rename %s", argv[0]); } } else { result = AFC_E_INTERNAL_ERROR; } free(source_path); free(target_path); return result; }
void _xfce_rc_simple_delete_group (XfceRc *rc, const gchar *name, gboolean global) { XfceRcSimple *simple = XFCE_RC_SIMPLE (rc); Group *group; Entry *entry; Entry *next; if (name == NULL) name = NULL_GROUP; for (group = simple->gfirst; group != NULL; group = group->next) { if (str_is_equal (group->name, name)) { if (simple->group == group || str_is_equal (name, NULL_GROUP)) { /* don't delete current group or the default group, just clear them */ for (entry = group->efirst; entry != NULL; entry = next) { next = entry->next; simple_entry_free (entry); } group->efirst = group->elast = NULL; } else { /* unlink group from group list */ if (group->prev != NULL) group->prev->next = group->next; else simple->gfirst = group->next; if (group->next != NULL) group->next->prev = group->prev; else simple->glast = group->prev; /* delete this group */ simple_group_free (group); } simple->dirty = TRUE; break; } } }
void _xfce_rc_simple_delete_entry (XfceRc *rc, const gchar *key, gboolean global) { XfceRcSimple *simple = XFCE_RC_SIMPLE (rc); Entry *entry; for (entry = simple->group->efirst; entry != NULL; entry = entry->next) { if (str_is_equal (entry->key, key)) { if (entry->prev != NULL) entry->prev->next = entry->next; else simple->group->efirst = entry->next; if (entry->next != NULL) entry->next->prev = entry->prev; else simple->group->elast = entry->prev; /* delete this entry */ simple_entry_free (entry); simple->dirty = TRUE; break; } } }
static afc_error_t cmd_rm(int argc, const char *argv[]) { afc_error_t result; char *path = NULL; bool recurse = false; if (argc < 1) { warnx("usage: rm [-r] <file> ..."); return AFC_E_INVALID_ARG; } if (argc > 1 && (recurse = str_is_equal("-r", argv[0]))) { argc--; argv++; } for (int i = 0; i < argc; i++) { path = build_absolute_path(argv[i]); if (!path) return AFC_E_INTERNAL_ERROR; result = remove_path(path, recurse); free(path); if (result == AFC_E_OBJECT_NOT_FOUND) afc_warn(result, "%s", argv[i]); return result; } return AFC_E_SUCCESS; }
static Group* simple_add_group (XfceRcSimple *simple, const gchar *name) { Group *group; for (group = simple->gfirst; group != NULL; group = group->next) if (str_is_equal (group->name, name)) return group; group = g_slice_new (Group); group->name = g_string_chunk_insert (simple->string_chunk, name); group->efirst = NULL; group->elast = NULL; if (G_UNLIKELY (simple->gfirst == NULL)) { group->next = group->prev = NULL; simple->gfirst = simple->glast = group; } else { group->next = NULL; group->prev = simple->glast; simple->glast->next = group; simple->glast = group; } return group; }
const gchar* _xfce_rc_simple_get_group (const XfceRc *rc) { const XfceRcSimple *simple = XFCE_RC_SIMPLE_CONST (rc); if (str_is_equal (simple->group->name, NULL_GROUP)) return NULL; else return simple->group->name; }
void _xfce_rc_simple_set_group (XfceRc *rc, const gchar *name) { XfceRcSimple *simple = XFCE_RC_SIMPLE (rc); if (name == NULL) name = NULL_GROUP; if (!str_is_equal (simple->group->name, name)) simple->group = simple_add_group (simple, name); }
static gboolean simple_write (XfceRcSimple *simple, const gchar *filename) { LEntry *lentry; Entry *entry; Group *group; gchar buffer[LINE_MAX]; FILE *fp; fp = fopen (filename, "w"); if (G_UNLIKELY (fp == NULL)) { g_critical ("Unable to open file %s for writing: %s", filename, g_strerror (errno)); return FALSE; } for (group = simple->gfirst; group != NULL; group = group->next) { /* don't store empty groups */ if (group->efirst == NULL) continue; /* NULL_GROUP has no header */ if (!str_is_equal (group->name, NULL_GROUP)) fprintf (fp, "[%s]\n", group->name); for (entry = group->efirst; entry != NULL; entry = entry->next) { simple_escape (buffer, LINE_MAX, entry->value); fprintf (fp, "%s=%s\n", entry->key, buffer); for (lentry = entry->lfirst; lentry != NULL; lentry = lentry->next) { simple_escape (buffer, LINE_MAX, lentry->value); fprintf (fp, "%s[%s]=%s\n", entry->key, lentry->locale, buffer); } } fprintf (fp, "\n"); } if (ferror (fp)) { g_critical ("Unable to write to file %s: Unexpected internal error", filename); fclose (fp); unlink (filename); return FALSE; } fclose (fp); return TRUE; }
static char * infolist_get_value(char **infolist, char *property) { char *value = NULL; for (int j = 0; infolist[j] != NULL; j += 2) { if (str_is_equal(property, infolist[j])) { value = infolist[j+1]; break; } } return value; }
gboolean _xfce_rc_simple_has_entry (const XfceRc *rc, const gchar *key) { const XfceRcSimple *simple = XFCE_RC_SIMPLE_CONST (rc); const Entry *entry; for (entry = simple->group->efirst; entry != NULL; entry = entry->next) if (str_is_equal (entry->key, key)) break; return entry != NULL; }
const gchar* _xfce_rc_simple_read_entry (const XfceRc *rc, const gchar *key, gboolean translated) { const XfceRcSimple *simple = XFCE_RC_SIMPLE_CONST (rc); LEntry *lentry; Entry *entry; const gchar *best_value; guint best_match; guint match; for (entry = simple->group->efirst; entry != NULL; entry = entry->next) if (str_is_equal (entry->key, key)) break; if (G_LIKELY (entry != NULL)) { /* check for localized entry (best fit!) */ if (G_LIKELY (translated && rc->locale != NULL)) { best_match = XFCE_LOCALE_NO_MATCH; best_value = NULL; for (lentry = entry->lfirst; lentry != NULL; lentry = lentry->next) { match = xfce_locale_match (rc->locale, lentry->locale); if (match == XFCE_LOCALE_FULL_MATCH) { /* FULL MATCH */ return lentry->value; } else if (match > best_match) { best_match = match; best_value = lentry->value; } } if (best_value != NULL) return best_value; /* FALL-THROUGH */ } return entry->value; } return NULL; }
static char *build_absolute_path(const char *inpath) { char *path; if (inpath[0] == '/') path = strdup(inpath); else { if (asprintf(&path, "%s/%s", str_is_equal(cwd, "/") ? "" : cwd, inpath) == -1) { warn("asprintf"); return NULL; } } for (int i = strlen(path); i > 1 && path[i] == '/'; i--) path[i] = 0; return path; }
gboolean _xfce_rc_simple_has_group (const XfceRc *rc, const gchar *name) { const XfceRcSimple *simple = XFCE_RC_SIMPLE_CONST (rc); const Group *group; /* the NULL group always exists */ if (name == NULL) return TRUE; for (group = simple->gfirst; group != NULL; group = group->next) if (str_is_equal (group->name, name)) break; return group != NULL; }
static afc_error_t cmd_ln(int argc, const char *argv[]) { afc_error_t result; int type = AFC_HARDLINK; char *source_path = NULL; char *target_path = NULL; if (argc == 3 && str_is_equal("-s", argv[0])) { type = AFC_SYMLINK; argc--; argv++; } if (argc != 2) { warnx("usage: ln [-s] <source> <target>"); return AFC_E_INVALID_ARG; } if (type == AFC_HARDLINK) source_path = build_absolute_path(argv[0]); else source_path = strdup(argv[0]); target_path = build_absolute_path(argv[1]); if (!source_path || !target_path) { free(source_path); free(target_path); return AFC_E_INTERNAL_ERROR; } // warnx("%s: %s -> %s\n", type == AFC_HARDLINK ? "hard link" : "sym link", source_path, target_path); result = afc_make_link(afc, type, source_path, target_path); if (result == AFC_E_OBJECT_NOT_FOUND) afc_warn(result, "%s", argv[0]); else if (result != AFC_E_SUCCESS) afc_warn(result, "afc_make_link"); free(source_path); free(target_path); return result; }
static afc_error_t is_directory(char *path, bool *is_dir) { afc_error_t result; char **infolist = NULL; char *value; result = afc_get_file_info(afc, path, &infolist); if (result != AFC_E_SUCCESS) { if (result != AFC_E_OBJECT_NOT_FOUND) afc_warn(result, "%s: stat failed: %s", __func__, path); return result; } if ((value = infolist_get_value(infolist, "st_ifmt"))) *is_dir = str_is_equal(value, "S_IFDIR"); infolist_free(infolist); return result; }
static int str_to_cmd(const char *str) { if (str_is_equal(str, "-")) return CMD_INTERACTIVE; else if (str_is_equal(str, "cd")) return CMD_CD; else if (str_is_equal(str, "pwd")) return CMD_PWD; else if (str_is_equal(str, "ls")) return CMD_LS; else if (str_is_equal(str, "mkdir")) return CMD_MKDIR; else if (str_is_equal(str, "ln")) return CMD_LN; else if (str_is_equal(str, "rm")) return CMD_RM; else if (str_is_equal(str, "mv")) return CMD_MV; else if (str_is_equal(str, "cp")) return CMD_CP; else if (str_is_equal(str, "cat")) return CMD_CAT; else if (str_is_equal(str, "stat")) return CMD_STAT; else if (str_is_equal(str, "quit")) return CMD_QUIT; return CMD_UNKNOWN; }
int main(int argc, const char **argv) { char *errmsg = ""; idevice_t device = NULL; lockdownd_client_t client = NULL; lockdownd_service_descriptor_t service = NULL; house_arrest_client_t hac = NULL; const char *service_name = "com.apple.afc"; const char *appid = NULL; char *device_name = NULL; int result = 0; char* udid = NULL; int cmd = CMD_INTERACTIVE; const char *cmdstr = NULL; int i; cwd = strdup("/"); /* parse cmdline args */ for (i = 1; i < argc; i++) { if (str_is_equal(argv[i], "-d") || str_is_equal(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (str_is_equal(argv[i], "-u") || str_is_equal(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); exit(EXIT_FAILURE); } udid = strdup(argv[i]); continue; } else if (str_is_equal(argv[i], "-2") || str_is_equal(argv[i], "--afc2")) { service_name = "com.apple.afc2"; continue; } else if (str_is_equal(argv[i], "-a") || str_is_equal(argv[i], "--appid")) { if (++i >= argc) { print_usage(argc, argv); exit(EXIT_FAILURE); } appid = argv[i]; } else if (str_is_equal(argv[i], "-h") || str_is_equal(argv[i], "--help")) { print_usage(argc, argv); exit(EXIT_SUCCESS); } else if ((cmd = str_to_cmd(argv[i])) != CMD_UNKNOWN) { cmdstr = argv[i]; i++; break; } } argc -= i; argv += i; /* Connect to device */ if (udid) { result = idevice_new(&device, udid); if (result != IDEVICE_E_SUCCESS) errx(EXIT_FAILURE, "No device found with udid %s, is it plugged in?", udid); } else { result = idevice_new(&device, NULL); if (result != IDEVICE_E_SUCCESS) errx(EXIT_FAILURE, "No device found, is it plugged in?"); idevice_get_udid(device, &udid); } /* Connect to lockdownd */ result = lockdownd_client_new_with_handshake(device, &client, "afccl"); if (result != LOCKDOWN_E_SUCCESS) { asprintf(&errmsg, "ERROR: Connecting to lockdownd service failed!"); goto bail; } result = lockdownd_get_device_name(client, &device_name); if ((result != LOCKDOWN_E_SUCCESS) || !device_name) { asprintf(&errmsg, "ERROR: Could not get device name!"); goto bail; } if (appid) { result = lockdownd_start_service(client, "com.apple.mobile.house_arrest", &service); if (result != LOCKDOWN_E_SUCCESS || !service || !service->port) { asprintf(&errmsg, "error starting house arrest service: (%d) %s", result, afc_strerror(result)); goto bail; } if (client) { lockdownd_client_free(client); client = NULL; } if (house_arrest_client_new(device, service, &hac) != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "could not connect to house_arrest service!\n"); goto bail; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } result = house_arrest_send_command(hac, "VendDocuments", appid); if (result != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "error %d when trying to get VendDocuments\n", result); goto bail; } plist_t dict = NULL; if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "hmmm....\n"); goto bail; } } plist_t node = plist_dict_get_item(dict, "Error"); if (node) { char *str = NULL; plist_get_string_val(node, &str); asprintf(&errmsg, "Error: %s\n", str); if (str) free(str); plist_free(dict); dict = NULL; goto bail; } node = plist_dict_get_item(dict, "Status"); if (node) { char *str = NULL; plist_get_string_val(node, &str); if (str && (strcmp(str, "Complete") != 0)) { printf("Warning: Status is not 'Complete' but '%s'\n", str); } if (str) free(str); } if (dict) { plist_free(dict); } afc_error_t ae = afc_client_new_from_house_arrest_client(hac, &afc); if (ae != AFC_E_SUCCESS) { printf("afc error %d\n", ae); } } else { result = lockdownd_start_service(client, service_name, &service); if (result != LOCKDOWN_E_SUCCESS || !service || !service->port) { asprintf(&errmsg, "error starting AFC service: (%d) %s", result, afc_strerror(result)); goto bail; } /* Connect to AFC */ result = afc_client_new(device, service, &afc); lockdownd_client_free(client); idevice_free(device); if (result != AFC_E_SUCCESS) { errx(EXIT_FAILURE, "AFC connection failed (%d) %s", result, afc_strerror(result)); } } result = do_cmd(cmd, argc, argv); if (hac) house_arrest_client_free(hac); afc_client_free(afc); exit(result == 0 ? EXIT_SUCCESS : EXIT_FAILURE); bail: if (hac) house_arrest_client_free(hac); if (service) lockdownd_service_descriptor_free(service); if (client) lockdownd_client_free(client); if (device) idevice_free(device); errx(EXIT_FAILURE, "%s", errmsg); }
static Entry* simple_add_entry (XfceRcSimple *simple, const gchar *key, const gchar *value, const gchar *locale) { LEntry *lentry_before; LEntry *lentry; Entry *entry; gint result; for (entry = simple->group->efirst; entry != NULL; entry = entry->next) if (str_is_equal (entry->key, key)) break; if (G_UNLIKELY (entry == NULL)) { entry = g_slice_new (Entry); entry->key = g_string_chunk_insert (simple->string_chunk, key); entry->value = g_string_chunk_insert (simple->string_chunk, value); entry->lfirst = NULL; entry->llast = NULL; if (simple->group->efirst == NULL) { entry->next = entry->prev = NULL; simple->group->efirst = simple->group->elast = entry; } else { entry->next = NULL; entry->prev = simple->group->elast; simple->group->elast->next = entry; simple->group->elast = entry; } if (locale == NULL) return entry; } if (G_UNLIKELY (locale == NULL)) { /* overwrite existing value */ if (!str_is_equal (entry->value, value)) entry->value = g_string_chunk_insert (simple->string_chunk, value); } else { /* Add the localized value. Note the optimization used within here: We store * the locales in alphabetic order (e.g. de, fr, ...). And we start the search * at the end of the locales list, since locales are usually sorted in the * rc files. Once we notice that the locale in question is less than the * current list locale, we cancel the search and remember the list element as * the element before the new list element (remember the sorting order). This * makes parsing a usual resource config file with lots of locales amazingly * fast. */ lentry_before = NULL; for (lentry = entry->llast; lentry != NULL; lentry = lentry->prev) { result = strcmp (lentry->locale, locale); if (result == 0) break; else if (result < 0) { lentry_before = lentry; lentry = NULL; break; } } if (G_LIKELY (lentry == NULL)) { /* create new localized entry */ lentry = g_slice_new (LEntry); lentry->locale = g_string_chunk_insert (simple->string_chunk, locale); lentry->value = g_string_chunk_insert (simple->string_chunk, value); if (G_UNLIKELY (entry->lfirst == NULL)) { lentry->next = lentry->prev = NULL; entry->lfirst = entry->llast = lentry; } else if (lentry_before != NULL) { lentry->next = lentry_before->next; lentry->prev = lentry_before; if (G_UNLIKELY (lentry_before->next != NULL)) lentry_before->next->prev = lentry; else entry->llast = lentry; lentry_before->next = lentry; } else { lentry->next = NULL; lentry->prev = entry->llast; entry->llast->next = lentry; entry->llast = lentry; } } else { /* overwrite value in existing localized entry */ if (G_LIKELY (!str_is_equal (lentry->value, value))) lentry->value = g_string_chunk_insert (simple->string_chunk, value); } } return entry; }