static void
on_bus_acquired (GDBusConnection  *connection,
                 const gchar      *name,
                 gpointer          user_data)
{
        Daemon *daemon;
        GError *local_error = NULL;
        GError **error = &local_error;

        if (!ensure_directory (ICONDIR, error)) {
                goto out;
        }

        if (!ensure_directory (USERDIR, error)) {
                goto out;
        }

        daemon = daemon_new ();
        if (daemon == NULL) {
                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                             "Failed to initialize daemon");
                goto out;
        }

        openlog ("accounts-daemon", LOG_PID, LOG_DAEMON);
        syslog (LOG_INFO, "started daemon version %s", VERSION);
        closelog ();
        openlog ("accounts-daemon", 0, LOG_AUTHPRIV);

 out:
        if (local_error != NULL) {
                g_printerr ("%s\n", local_error->message);
                g_clear_error (&local_error);
                g_main_loop_quit (loop);
        }
}
Example #2
0
int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
    int ret = 0;
    char* name = basename(mount_point);
    
    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        ui_print("%s.img没有发现. 放弃还原 %s.\n", name, mount_point);
        return 0;
    }

    ensure_directory(mount_point);

    unyaffs_callback callback = NULL;
    if (0 != stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info)) {
        callback = yaffs_callback;
    }

    ui_print("还原 %s...\n", name);
    /*
    if (0 != (ret = ensure_root_path_unmounted(root))) {
        ui_print("Can't unmount %s!\n", mount_point);
        return ret;
    }
    */
    if (0 != (ret = format_volume(mount_point))) {
        ui_print("格式化时出错 %s!\n", mount_point);
        return ret;
    }
    
    if (0 != (ret = ensure_path_mounted(mount_point))) {
        ui_print("不能挂载 %s!\n", mount_point);
        return ret;
    }
    
    if (0 != (ret = unyaffs(tmp, mount_point, callback))) {
        ui_print("还原时出错 %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_path_unmounted(mount_point);
    }
    
    return 0;
}
Example #3
0
int tarbackup_restore_partition_extended(const char* backup_path, const char* root, int umount_when_finished) {
    int ret;
    char mount_point[PATH_MAX];
    translate_root_path(root, mount_point, PATH_MAX);
    char* name = basename(mount_point);

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.tar", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        ui_print("%s.tar not found. Skipping restore of %s.\n", name, mount_point);
        return 0;
    }

    ensure_directory(mount_point);

    ui_print("Restoring %s...\n", name);
    if (0 != (ret = ensure_root_path_unmounted(root))) {
        ui_print("Can't unmount %s!\n", mount_point);
        return ret;
    }

    if (0 != (ret = format_root_device(root))) {
        ui_print("Error while formatting %s!\n", root);
        return ret;
    }

    if (0 != (ret = ensure_root_path_mounted(root))) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }

    sprintf(tmp, "tar -x -f %s/%s.tar", backup_path, name);
    if (0 != __system(tmp)) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_root_path_unmounted(root);
    }

    return 0;
}
Example #4
0
static int dedupe_compress_wrapper(const char* backup_path, const char* backup_file_image, int callback) {
    char tmp[PATH_MAX];
    char blob_dir[PATH_MAX];
    strcpy(blob_dir, backup_file_image);
    char *d = dirname(blob_dir);
    strcpy(blob_dir, d);
    d = dirname(blob_dir);
    strcpy(blob_dir, d);
    d = dirname(blob_dir);
    strcpy(blob_dir, d);
    strcat(blob_dir, "/blobs");
    ensure_directory(blob_dir);

    if (!(nandroid_backup_bitfield & NANDROID_FIELD_DEDUPE_CLEARED_SPACE)) {
        nandroid_backup_bitfield |= NANDROID_FIELD_DEDUPE_CLEARED_SPACE;
        nandroid_dedupe_gc(blob_dir);
    }

    sprintf(tmp, "dedupe c %s %s %s.dup %s", backup_path, blob_dir, backup_file_image, strcmp(backup_path, "/data") == 0 && is_data_media() ? "./media" : "");

    FILE *fp = __popen(tmp, "r");
    if (fp == NULL) {
#ifndef USE_CHINESE_FONT
        ui_print("Unable to execute dedupe.\n");
#else
        ui_print("无法进行增量备份。\n");
#endif
        return -1;
    }

    while (fgets(tmp, PATH_MAX, fp) != NULL) {
        tmp[PATH_MAX - 1] = '\0';
        if (callback)
            nandroid_callback(tmp);
    }

    return __pclose(fp);
}
Example #5
0
int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
    int ret = 0;
    char* name = basename(mount_point);

    nandroid_restore_handler restore_handler = NULL;
    const char *filesystems[] = { "yaffs2", "ext2", "ext3", "ext4", "vfat", "rfs", NULL };
    const char* backup_filesystem = NULL;
    Volume *vol = volume_for_path(mount_point);
    const char *device = NULL;
    if (vol != NULL)
        device = vol->device;

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        // can't find the backup, it may be the new backup format?
        // iterate through the backup types
        printf("couldn't find old .img format\n");
        char *filesystem;
        int i = 0;
        while ((filesystem = filesystems[i]) != NULL) {
            sprintf(tmp, "%s/%s.%s.img", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = unyaffs_wrapper;
                break;
            }
            sprintf(tmp, "%s/%s.%s.tar", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = tar_extract_wrapper;
                break;
            }
            sprintf(tmp, "%s/%s.%s.dup", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = dedupe_extract_wrapper;
                break;
            }
            i++;
        }

        if (backup_filesystem == NULL || restore_handler == NULL) {
            //ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point);
            ui_print("No %s backup found(img, tar, dup). Skipping restore of %s.\n", name, mount_point);
            return 0;
        }
        else {
            printf("Found new backup image: %s\n", tmp);
        }

        // If the fs_type of this volume is "auto" or mount_point is /data
        // and is_data_media, let's revert
        // to using a rm -rf, rather than trying to do a
        // ext3/ext4/whatever format.
        // This is because some phones (like DroidX) will freak out if you
        // reformat the /system or /data partitions, and not boot due to
        // a locked bootloader.
        // Other devices, like the Galaxy Nexus, XOOM, and Galaxy Tab 10.1
        // have a /sdcard symlinked to /data/media.
        // Or of volume does not exist (.android_secure), just rm -rf.
        if (vol == NULL || 0 == strcmp(vol->fs_type, "auto"))
            backup_filesystem = NULL;
        if (0 == strcmp(vol->mount_point, "/data") && is_data_media())
            backup_filesystem = NULL;
    }

    ensure_directory(mount_point);

    int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) != 0;
    compute_archive_stats(tmp);

    ui_print("Restoring %s...\n", name);
    if (backup_filesystem == NULL) {
        if (0 != (ret = format_volume(mount_point))) {
            ui_print("Error while formatting %s!\n", mount_point);
            return ret;
        }
    }
    else if (0 != (ret = format_device(device, mount_point, backup_filesystem))) {
        ui_print("Error while formatting %s!\n", mount_point);
        return ret;
    }

    if (0 != (ret = ensure_path_mounted(mount_point))) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }

    if (restore_handler == NULL)
        restore_handler = get_restore_handler(mount_point);
    if (restore_handler == NULL) {
        ui_print("Error finding an appropriate restore handler.\n");
        return -2;
    }
    if (0 != (ret = restore_handler(tmp, mount_point, callback))) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_path_unmounted(mount_point);
    }
    
    return 0;
}
Example #6
0
int nandroid_backup(const char* backup_path)
{
    nandroid_backup_bitfield = 0;
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    refresh_default_backup_handler();
    
    if (ensure_path_mounted(backup_path) != 0) {
        return print_and_error("Can't mount backup path.\n");
    }
    
    Volume* volume = volume_for_path(backup_path);
    if (NULL == volume)
        return print_and_error("Unable to find volume for backup path.\n");
    if (is_data_media_volume_path(volume->mount_point))
        volume = volume_for_path("/data");
    int ret;
    struct statfs s;
    if (NULL != volume) {
        if (0 != (ret = statfs(volume->mount_point, &s)))
            return print_and_error("Unable to stat backup path.\n");
        uint64_t bavail = s.f_bavail;
        uint64_t bsize = s.f_bsize;
        uint64_t sdcard_free = bavail * bsize;
        uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
        ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
        if (sdcard_free_mb < 150)
            ui_print("There may not be enough free space to complete backup... continuing...\n");
    }
    char tmp[PATH_MAX];
    ensure_directory(backup_path);

    if (backup_boot && 0 != (ret = nandroid_backup_partition(backup_path, "/boot")))
        return ret;

    if (backup_recovery && 0 != (ret = nandroid_backup_partition(backup_path, "/recovery")))
        return ret;

    Volume *vol = volume_for_path("/wimax");
    if (backup_wimax && vol != NULL && 0 == stat(vol->device, &s))
    {
        char serialno[PROPERTY_VALUE_MAX];
        ui_print("Backing up WiMAX...\n");
        serialno[0] = 0;
        property_get("ro.serialno", serialno, "");
        sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno);
        ret = backup_raw_partition(vol->fs_type, vol->device, tmp);
        if (0 != ret)
            return print_and_error("Error while dumping WiMAX image!\n");
    }

    //2 copies of efs are made: tarball and raw backup
    if (backup_efs) {
        //first backup in raw format, returns 0 on success (or if skipped), else 1
        if (0 != custom_backup_raw_handler(backup_path, "/efs")) {
            ui_print("EFS raw image backup failed! Trying tar backup...\n");
        }
        //second backup in tar format
        sprintf(tmp, "%s/efs_tar", backup_path);
        ensure_directory(tmp);
        if (0 != (ret = nandroid_backup_partition(tmp, "/efs")))
            return ret;
    }
    
    if (backup_modem) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/modem")))
            return ret;
    }

    if (backup_system && 0 != (ret = nandroid_backup_partition(backup_path, "/system")))
        return ret;


    if (is_custom_backup && backup_preload) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) {
            ui_print("Failed to backup /preload!\n");
            return ret;
        }
    }
    else if (!is_custom_backup
#ifdef PHILZ_TOUCH_RECOVERY
                && nandroid_add_preload
#endif
            )
    {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/preload"))) {
            ui_print("Failed to backup preload! Try to disable it.\n");
            ui_print("Skipping /preload...\n");
            //return ret;
        }
    }

    if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/data")))
        return ret;

    if (has_datadata()) {
        if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/datadata")))
            return ret;
    }

    if (is_data_media() || 0 != stat("/sdcard/.android_secure", &s)) {
        ui_print("No /sdcard/.android_secure found. Skipping backup of applications on external storage.\n");
    }
    else {
        if (backup_data && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0)))
            return ret;
    }

    if (backup_cache && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0)))
        return ret;

    if (backup_sdext) {
        vol = volume_for_path("/sd-ext");
        if (vol == NULL || 0 != stat(vol->device, &s))
        {
            ui_print("No sd-ext found. Skipping backup of sd-ext.\n");
        }
        else
        {
            if (0 != ensure_path_mounted("/sd-ext"))
                ui_print("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n");
            else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext")))
                return ret;
        }
    }

#ifdef PHILZ_TOUCH_RECOVERY
    if (enable_md5sum)
#endif
    {
        ui_print("Generating md5 sum...\n");
        sprintf(tmp, "nandroid-md5.sh %s", backup_path);
        if (0 != (ret = __system(tmp))) {
            ui_print("Error while generating md5 sum!\n");
            return ret;
        }
    }

    sprintf(tmp, "chmod -R 777 %s ; chmod -R u+r,u+w,g+r,g+w,o+r,o+w /sdcard/clockworkmod ; chmod u+x,g+x,o+x /sdcard/clockworkmod/backup ; chmod u+x,g+x,o+x /sdcard/clockworkmod/blobs", backup_path);
    __system(tmp);
    sync();
    ui_set_background(BACKGROUND_ICON_NONE);
    ui_reset_progress();
    ui_print("\nBackup complete!\n");
    return 0;
}
int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
    int ret = 0;
    char* name = basename(mount_point);

    nandroid_restore_handler restore_handler = NULL;
    const char *filesystems[] = { "yaffs2", "ext2", "ext3", "ext4", "vfat", "rfs", NULL };
    const char* backup_filesystem = NULL;
    Volume *vol = volume_for_path(mount_point);
    const char *device = NULL;
    if (vol != NULL)
        device = vol->device;

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    struct stat file_info;
    if (strcmp(backup_path, "-") == 0) {
        if (vol)
            backup_filesystem = vol->fs_type;
        restore_handler = tar_extract_wrapper;
        strcpy(tmp, "/proc/self/fd/0");
    }
    else if (0 != (ret = statfs(tmp, &file_info))) {
        // can't find the backup, it may be the new backup format?
        // iterate through the backup types
        printf("找不到默认\n");
        char *filesystem;
        int i = 0;
        while ((filesystem = filesystems[i]) != NULL) {
            sprintf(tmp, "%s/%s.%s.img", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = unyaffs_wrapper;
                break;
            }
            sprintf(tmp, "%s/%s.%s.tar", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = tar_extract_wrapper;
                break;
            }
            sprintf(tmp, "%s/%s.%s.dup", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = dedupe_extract_wrapper;
                break;
            }
            i++;
        }

        if (backup_filesystem == NULL || restore_handler == NULL) {
            ui_print("%s.镜像没找到,因此跳过该处恢复. %s.\n", name, mount_point);
            return 0;
        }
        else {
            printf("找到新的可恢复镜像: %s\n", tmp);
        }
    }

    // If the fs_type of this volume is "auto" or mount_point is /data
    // and is_data_media, let's revert
    // to using a rm -rf, rather than trying to do a
    // ext3/ext4/whatever format.
    // This is because some phones (like DroidX) will freak out if you
    // reformat the /system or /data partitions, and not boot due to
    // a locked bootloader.
    // Other devices, like the Galaxy Nexus, XOOM, and Galaxy Tab 10.1
    // have a /sdcard symlinked to /data/media.
    // Or of volume does not exist (.android_secure), just rm -rf.
    if (vol == NULL || 0 == strcmp(vol->fs_type, "auto"))
        backup_filesystem = NULL;
    if (0 == strcmp(vol->mount_point, "/data") && is_data_media())
        backup_filesystem = NULL;

    ensure_directory(mount_point);

    int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) != 0;

    ui_print("正在恢复 %s...\n", name);
    if (backup_filesystem == NULL) {
        if (0 != (ret = format_volume(mount_point))) {
            ui_print("格式化下列分区失败 %s!\n", mount_point);
            return ret;
        }
    }
    else if (0 != (ret = format_device(device, mount_point, backup_filesystem))) {
        ui_print("格式化下列分区失败 %s!\n", mount_point);
        return ret;
    }

    if (0 != (ret = ensure_path_mounted(mount_point))) {
        ui_print("挂载下列分区失败 %s!\n", mount_point);
        return ret;
    }

    if (restore_handler == NULL)
        restore_handler = get_restore_handler(mount_point);

    // override restore handler for undump
    if (strcmp(backup_path, "-") == 0) {
        restore_handler = tar_undump_wrapper;
    }

    if (restore_handler == NULL) {
        ui_print("找不到合适的方案\n");
        return -2;
    }

    if (0 != (ret = restore_handler(tmp, mount_point, callback))) {
        ui_print("恢复失败: %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_path_unmounted(mount_point);
    }

    return 0;
}
int nandroid_backup(const char* backup_path)
{
    nandroid_backup_bitfield = 0;
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    refresh_default_backup_handler();

    if (ensure_path_mounted(backup_path) != 0) {
        return print_and_error("无法挂载备份时需要的存储器.\n");
    }

    Volume* volume = volume_for_path(backup_path);
    if (NULL == volume)
        return print_and_error("找不到备份需要的存储器.\n");
    if (is_data_media_volume_path(volume->mount_point))
        volume = volume_for_path("/data");
    int ret;
    struct statfs s;
    if (NULL != volume) {
        if (0 != (ret = statfs(volume->mount_point, &s)))
            return print_and_error("找不到备份路径,因此无法开始.\n");
        uint64_t bavail = s.f_bavail;
        uint64_t bsize = s.f_bsize;
        uint64_t sdcard_free = bavail * bsize;
        uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
        ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
        if (sdcard_free_mb < 150)
            ui_print("可能是你的机器空间不足了,继续中...\n");
    }
    char tmp[PATH_MAX];
    ensure_directory(backup_path);

    if (0 != (ret = nandroid_backup_partition(backup_path, "/boot")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/uboot")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery")))
        return ret;

    Volume *vol = volume_for_path("/wimax");
    if (vol != NULL && 0 == stat(vol->device, &s))
    {
        char serialno[PROPERTY_VALUE_MAX];
        ui_print("正在备份WiMAX...\n");
        serialno[0] = 0;
        property_get("ro.serialno", serialno, "");
        sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno);
        ret = backup_raw_partition(vol->fs_type, vol->device, tmp);
        if (0 != ret)
            return print_and_error("打包或生成WiMAX镜像失败\n");
    }

    if (0 != (ret = nandroid_backup_partition(backup_path, "/system")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/data")))
        return ret;

    if (has_datadata()) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata")))
            return ret;
    }

    if (is_data_media() || 0 != stat("/sdcard/.android_secure", &s)) {
        ui_print("没找到 /sdcard/.android_secure. 跳过外部程序备份.\n");
    }
    else {
        if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0)))
            return ret;
    }

    if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0)))
        return ret;

    vol = volume_for_path("/sd-ext");
    if (vol == NULL || 0 != stat(vol->device, &s))
    {
        ui_print("没找到SD-EXT,因此跳过该处备份.\n");
    }
    else
    {
        if (0 != ensure_path_mounted("/sd-ext"))
            ui_print("没法挂载SD-EXT,可能是你的机器不支持该选项,跳过该部分的备份\n");
        else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext")))
            return ret;
    }

    ui_print("生成md5 校验值...\n");
    sprintf(tmp, "nandroid-md5.sh %s", backup_path);
    if (0 != (ret = __system(tmp))) {
        ui_print("MD5校验值生成失败\n");
        return ret;
    }

    sprintf(tmp, "cp /tmp/recovery.log %s/recovery.log", backup_path);
    __system(tmp);

    sprintf(tmp, "chmod -R 777 %s ; chmod -R u+r,u+w,g+r,g+w,o+r,o+w /sdcard/clockworkmod ; chmod u+x,g+x,o+x /sdcard/clockworkmod/backup ; chmod u+x,g+x,o+x /sdcard/clockworkmod/blobs", backup_path);
    __system(tmp);
    sync();
    ui_set_background(BACKGROUND_ICON_NONE);
    ui_reset_progress();
    ui_print("\n备份完成!\n");
    return 0;
}
Example #9
0
/* XXX Should better explicitely specify
 * uncomp_size and file_times instead of pfhdr!
 */
char *map_new_file (DWORD flags, char *filename,
		    char *pathname_part, int size,
		    WORD wFatDate, WORD wFatTime,
		    NOTIFYPROC notify)
{
    HANDLE hFile, hFileMapping;
    char *dst;
    FILETIME ft;

  try_again:
    if (!flags)
	flags = CREATE_NEW;
    hFile = CreateFile (filename,
			GENERIC_WRITE | GENERIC_READ,
			0, NULL,
			flags,
			FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
	DWORD x = GetLastError();
	switch (x) {
	case ERROR_FILE_EXISTS:
	    if (notify && notify (CAN_OVERWRITE, filename))
	       	hFile = CreateFile (filename,
				    GENERIC_WRITE | GENERIC_READ,
				    0, NULL,
				    CREATE_ALWAYS,
				    FILE_ATTRIBUTE_NORMAL, NULL);
	    else {
		if (notify)
		    notify (FILE_OVERWRITTEN, filename);
		return NULL;
	    }
	    break;
	case ERROR_PATH_NOT_FOUND:
	    if (ensure_directory (filename, pathname_part, notify))
		goto try_again;
	    else
		return FALSE;
	    break;
	default:
	    SetLastError (x);
	    break;
	}
    }
    if (hFile == INVALID_HANDLE_VALUE) {
	if (notify)
	    notify (SYSTEM_ERROR, "CreateFile (%s)", filename);
	return NULL;
    }

    if (notify)
	notify (FILE_CREATED, filename);

    DosDateTimeToFileTime (wFatDate, wFatTime, &ft);
    SetFileTime (hFile, &ft, &ft, &ft);


    if (size == 0) {
	/* We cannot map a zero-length file (Also it makes
	   no sense */
	CloseHandle (hFile);
	return NULL;
    }

    hFileMapping = CreateFileMapping (hFile,
				      NULL, PAGE_READWRITE, 0, size, NULL);

    CloseHandle (hFile);

    if (hFileMapping == INVALID_HANDLE_VALUE) {
	if (notify)
	    notify (SYSTEM_ERROR, "CreateFileMapping (%s)", filename);
	return NULL;
    }

    dst = MapViewOfFile (hFileMapping,
			 FILE_MAP_WRITE, 0, 0, 0);

    CloseHandle (hFileMapping);

    if (!dst) {
	if (notify)
	    notify (SYSTEM_ERROR, "MapViewOfFile (%s)", filename);
	return NULL;
    }
    return dst;
}
Example #10
0
int nandroid_backup(const char* backup_path)
{
    nandroid_backup_bitfield = 0;
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    refresh_default_backup_handler();
    
    if (ensure_path_mounted(backup_path) != 0) {
        return print_and_error("Can't mount backup path.\n");
    }
    
    Volume* volume = volume_for_path(backup_path);
    if (NULL == volume)
        return print_and_error("Unable to find volume for backup path.\n");
    if (is_data_media_volume_path(volume->mount_point))
        volume = volume_for_path("/data");
    int ret;
    struct statfs s;
    if (NULL != volume) {
        if (0 != (ret = statfs(volume->mount_point, &s)))
            return print_and_error("Unable to stat backup path.\n");
        uint64_t bavail = s.f_bavail;
        uint64_t bsize = s.f_bsize;
        uint64_t sdcard_free = bavail * bsize;
        uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
        ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
        if (sdcard_free_mb < 150)
            ui_print("There may not be enough free space to complete backup... continuing...\n");
    }
    char tmp[PATH_MAX];
    ensure_directory(backup_path);

    if (0 != (ret = nandroid_backup_partition(backup_path, "/boot")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery")))
        return ret;

    Volume *vol = volume_for_path("/wimax");
    if (vol != NULL && 0 == stat(vol->device, &s))
    {
        char serialno[PROPERTY_VALUE_MAX];
        ui_print("Backing up WiMAX...\n");
        serialno[0] = 0;
        property_get("ro.serialno", serialno, "");
        sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno);
        ret = backup_raw_partition(vol->fs_type, vol->device, tmp);
        if (0 != ret)
            return print_and_error("Error while dumping WiMAX image!\n");
    }

    if (0 != (ret = nandroid_backup_partition(backup_path, "/system")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/preload")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/data")))
        return ret;

    if (has_datadata()) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata")))
            return ret;
    }

    if (is_data_media() || 0 != stat("/sdcard/.android_secure", &s)) {
        ui_print("No /sdcard/.android_secure found. Skipping backup of applications on external storage.\n");
    }
    else {
        if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0)))
            return ret;
    }

    if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0)))
        return ret;

    vol = volume_for_path("/sd-ext");
    if (vol == NULL || 0 != stat(vol->device, &s))
    {
        ui_print("No sd-ext found. Skipping backup of sd-ext.\n");
    }
    else
    {
        if (0 != ensure_path_mounted("/sd-ext"))
            ui_print("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n");
        else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext")))
            return ret;
    }

    ui_print("Generating md5 sum...\n");
    sprintf(tmp, "nandroid-md5.sh %s", backup_path);
    if (0 != (ret = __system(tmp))) {
        ui_print("Error while generating md5 sum!\n");
        return ret;
    }
    
    sprintf(tmp, "chmod -R 777 %s ; chmod -R u+r,u+w,g+r,g+w,o+r,o+w /sdcard/clockworkmod ; chmod u+x,g+x,o+x /sdcard/clockworkmod/backup ; chmod u+x,g+x,o+x /sdcard/clockworkmod/blobs", backup_path);
    __system(tmp);
    sync();
    ui_set_background(BACKGROUND_ICON_NONE);
    ui_reset_progress();
    ui_print("\nBackup complete!\n");
    return 0;
}
Example #11
0
int nandroid_restore_partition_extended(const char* backup_path, const char* root, int umount_when_finished) {
    int ret = 0;
    char mount_point[PATH_MAX];
    translate_root_path(root, mount_point, PATH_MAX);
    char* name = basename(mount_point);
    
    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point);
        return 0;
    }

    ensure_directory(mount_point);

    unyaffs_callback callback = NULL;
    if (0 != stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info)) {
        callback = yaffs_callback;
    }

    ui_print("Restoring %s...\n", name);
    /*
    if (0 != (ret = ensure_root_path_unmounted(root))) {
        ui_print("Can't unmount %s!\n", mount_point);
        return ret;
    }
    */
    if (0 != (ret = format_root_device(root))) {
        ui_print("Error while formatting %s!\n", root);
        return ret;
    }
    
    if (0 != (ret = ensure_root_path_mounted(root))) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }
    
    /* mumbozver
    if (0 != (ret = unyaffs(tmp, mount_point, callback))) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }
*/

    char tmp1[PATH_MAX];
    sprintf(tmp1, "%s/%s.img", backup_path, name);
    char tar1[PATH_MAX+35];
    sprintf(tar1, "tar xpf %s -C /", tmp1);

    if (0 != (ret = __system (tar1))) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_root_path_unmounted(root);
    }
    
    return 0;
}
Example #12
0
int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
    int ret = 0;
    char* name = basename(mount_point);

    nandroid_restore_handler restore_handler = NULL;
    const char *filesystems[] = { "yaffs2", "ext2", "ext3", "ext4", "vfat", "rfs", NULL };
    const char* backup_filesystem = NULL;
    Volume *vol = volume_for_path(mount_point);
    const char *device = NULL;
    if (vol != NULL)
        device = vol->device;

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        // can't find the backup, it may be the new backup format?
        // iterate through the backup types
        printf("couldn't find default\n");
        char *filesystem;
        int i = 0;
        while ((filesystem = filesystems[i]) != NULL) {
            sprintf(tmp, "%s/%s.%s.img", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = unyaffs_wrapper;
                break;
            }
            sprintf(tmp, "%s/%s.%s.tar", backup_path, name, filesystem);
            if (0 == (ret = statfs(tmp, &file_info))) {
                backup_filesystem = filesystem;
                restore_handler = tar_extract_wrapper;
                break;
            }
            i++;
        }

        if (backup_filesystem == NULL || restore_handler == NULL) {
            ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point);
            return 0;
        }
        else {
            printf("Found new backup image: %s\n", tmp);
        }

        // If the fs_type of this volume is "auto", let's revert to using a
        // rm -rf, rather than trying to do a ext3/ext4/whatever format.
        // This is because some phones (like DroidX) will freak out if you
        // reformat the /system or /data partitions, and not boot due to
        // a locked bootloader.
        // The "auto" fs type preserves the file system, and does not
        // trigger that lock.
        // Or of volume does not exist (.android_secure), just rm -rf.
        if (vol == NULL || 0 == strcmp(vol->fs_type, "auto"))
            backup_filesystem = NULL;
    }
    else {
        // Force legacy tar extraction to old CWM2 backup files
        restore_handler = tar_extract_wrapper_legacy;
    }

    ensure_directory(mount_point);

    int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) != 0;

    ui_print("Restoring %s...\n", name);
    if (backup_filesystem == NULL) {
        if (0 != (ret = format_volume(mount_point))) {
            ui_print("Error while formatting %s!\n", mount_point);
            return ret;
        }
    }
    else if (0 != (ret = format_device(device, mount_point, backup_filesystem))) {
        ui_print("Error while formatting %s!\n", mount_point);
        return ret;
    }

    if (0 != (ret = ensure_path_mounted(mount_point))) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }

    if (restore_handler == NULL)
        restore_handler = get_restore_handler(mount_point);
    if (restore_handler == NULL) {
        ui_print("Error finding an appropriate restore handler.\n");
        return -2;
    }
    if (0 != (ret = restore_handler(tmp, mount_point, callback))) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_path_unmounted(mount_point);
    }
    
    return 0;
}
Example #13
0
int nandroid_backup(const char* backup_path) {
    nandroid_backup_bitfield = 0;
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    refresh_default_backup_handler();

    if (ensure_path_mounted(backup_path) != 0) {
#ifndef USE_CHINESE_FONT
        return print_and_error("Can't mount backup path.\n");
#else
        return print_and_error("无法挂载备份路径。\n");
#endif
    }

    Volume* volume;
    if (is_data_media_volume_path(backup_path))
        volume = volume_for_path("/data");
    else
        volume = volume_for_path(backup_path);
    if (NULL == volume)
#ifndef USE_CHINESE_FONT
        return print_and_error("Unable to find volume for backup path.\n");
#else
        return print_and_error("无法找到备份路径所在卷。\n");
#endif
    int ret;
    struct statfs sfs;
    struct stat s;
    if (NULL != volume) {
        if (0 != (ret = statfs(volume->mount_point, &sfs)))
#ifndef USE_CHINESE_FONT
            return print_and_error("Unable to stat backup path.\n");
#else
            return print_and_error("无法统计备份路径。\n");
#endif
        uint64_t bavail = sfs.f_bavail;
        uint64_t bsize = sfs.f_bsize;
        uint64_t sdcard_free = bavail * bsize;
        uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
#ifndef USE_CHINESE_FONT
        ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
#else
        ui_print("SD 卡剩余空间: %lluMB\n", sdcard_free_mb);
#endif
        if (sdcard_free_mb < 150)
#ifndef USE_CHINESE_FONT
            ui_print("There may not be enough free space to complete backup... continuing...\n");
#else
            ui_print("可能没有足够的空间完成备份... 继续...\n");
#endif
    }
    char tmp[PATH_MAX];
    ensure_directory(backup_path);

    if (0 != (ret = nandroid_backup_partition(backup_path, "/boot")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery")))
        return ret;

    Volume *vol = volume_for_path("/wimax");
    if (vol != NULL && 0 == stat(vol->blk_device, &s)) {
        char serialno[PROPERTY_VALUE_MAX];
#ifndef USE_CHINESE_FONT
        ui_print("Backing up WiMAX...\n");
#else
        ui_print("正在备份 WiMAX...\n");
#endif
        serialno[0] = 0;
        property_get("ro.serialno", serialno, "");
        sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno);
        ret = backup_raw_partition(vol->fs_type, vol->blk_device, tmp);
        if (0 != ret)
#ifndef USE_CHINESE_FONT
            return print_and_error("Error while dumping WiMAX image!\n");
#else
            return print_and_error("导出 WiMAX 镜像时出错!\n");
#endif
    }

    if (0 != (ret = nandroid_backup_partition(backup_path, "/system")))
        return ret;

    if (0 != (ret = nandroid_backup_partition(backup_path, "/data")))
        return ret;

    if (has_datadata()) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata")))
            return ret;
    }

    if (is_data_media() || 0 != stat(get_android_secure_path(), &s)) {
#ifndef USE_CHINESE_FONT
        ui_print("No .android_secure found. Skipping backup of applications on external storage.\n");
#else
        ui_print("未找到 .android_secure。跳过备份安装在外置存储卡上的应用程序。\n");
#endif
    } else {
        if (0 != (ret = nandroid_backup_partition_extended(backup_path, get_android_secure_path(), 0)))
            return ret;
    }

    if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0)))
        return ret;

    vol = volume_for_path("/sd-ext");
    if (vol == NULL || 0 != stat(vol->blk_device, &s)) {
#ifndef USE_CHINESE_FONT
        LOGI("No sd-ext found. Skipping backup of sd-ext.\n");
#else
        LOGI("未找到 sd-ext。跳过对 sd-ext 的备份。\n");
#endif
    } else {
        if (0 != ensure_path_mounted("/sd-ext"))
#ifndef USE_CHINESE_FONT
            LOGI("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n");
#else
            LOGI("无法挂载 sd-ext。此设备可能不支持对 sd-ext 进行备份,跳过对sd-ext的备份。\n");
#endif
        else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext")))
            return ret;
    }
Example #14
0
int twrp_backup(const char* backup_path) {
    // keep this for extra security and keep close to stock code
    // refresh_default_backup_handler() mounts /sdcard. We stat it in nandroid_backup_partition_extended() for callback
    nandroid_backup_bitfield = 0;
    refresh_default_backup_handler();

    if (ensure_path_mounted(backup_path) != 0)
        return print_and_error("Can't mount backup path.\n", NANDROID_ERROR_GENERAL);

    int ret;
    struct statfs s;

    // refresh size stats for backup_path
    // this will also ensure volume for backup path != NULL
    if (0 != Get_Size_Via_statfs(backup_path))
        return print_and_error("Unable to stat backup path.\n", NANDROID_ERROR_GENERAL);

    // estimate backup size and ensure we have enough free space available on backup_path
    if (check_backup_size(backup_path) < 0)
        return print_and_error("Not enough free space: backup cancelled.\n", NANDROID_ERROR_GENERAL);

    // moved after backup size check to fix pause before showing low space prompt
    // this is caused by friendly log view triggering on ui_set_background(BACKGROUND_ICON_INSTALLING) call
    // also, it is expected to have the background installing icon when we actually start backup
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    nandroid_start_msec = timenow_msec(); // starts backup monitoring timer for total backup time
#ifdef PHILZ_TOUCH_RECOVERY
    last_key_ev = nandroid_start_msec; // support dim screen timeout during nandroid operation
#endif

    char tmp[PATH_MAX];
    ensure_directory(backup_path, 0755);

    if (backup_boot && volume_for_path(BOOT_PARTITION_MOUNT_POINT) != NULL &&
            0 != (ret = nandroid_backup_partition(backup_path, BOOT_PARTITION_MOUNT_POINT)))
        return print_and_error(NULL, ret);

    if (backup_recovery && volume_for_path("/recovery") != NULL &&
            0 != (ret = nandroid_backup_partition(backup_path, "/recovery")))
        return print_and_error(NULL, ret);

#ifdef BOARD_USE_MTK_LAYOUT
    if ((backup_boot || backup_recovery) && volume_for_path("/uboot") != NULL &&
            0 != (ret = nandroid_backup_partition(backup_path, "/uboot")))
        return print_and_error(NULL, ret);
#endif

    Volume *vol = volume_for_path("/efs");
    if (backup_efs &&  NULL != vol) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/efs")))
            return print_and_error(NULL, ret);
    }

    vol = volume_for_path("/misc");
    if (backup_misc && NULL != vol) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/misc")))
            return print_and_error(NULL, ret);
    }

    vol = volume_for_path("/modem");
    if (backup_modem && NULL != vol) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/modem")))
            return print_and_error(NULL, ret);
    }

    vol = volume_for_path("/radio");
    if (backup_radio && NULL != vol) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/radio")))
            return print_and_error(NULL, ret);
    }

    if (backup_system && 0 != (ret = nandroid_backup_partition(backup_path, "/system")))
        return print_and_error(NULL, ret);

    vol = volume_for_path("/preload");
    if (backup_preload && NULL != vol) {
        if (0 != (ret = nandroid_backup_partition(backup_path, "/preload")))
            return print_and_error(NULL, ret);
    }

    if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/data")))
        return print_and_error(NULL, ret);

    if (has_datadata()) {
        if (backup_data && 0 != (ret = nandroid_backup_partition(backup_path, "/datadata")))
            return print_and_error(NULL, ret);
    }

    // handle .android_secure on external and internal storage
    set_android_secure_path(tmp);
    if (backup_data && android_secure_ext) {
        if (0 != (ret = nandroid_backup_partition_extended(backup_path, tmp, 0)))
            return print_and_error(NULL, ret);
    }

    if (backup_cache && 0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0)))
        return print_and_error(NULL, ret);

    if (backup_sdext) {
        if (0 != ensure_path_mounted("/sd-ext")) {
            LOGI("No sd-ext found. Skipping backup of sd-ext.\n");
        } else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) {
            return print_and_error(NULL, ret);
        }
    }

    // handle extra partitions
    int i;
    int extra_partitions_num = get_extra_partitions_state();
    for (i = 0; i < extra_partitions_num; ++i) {
        if (extra_partition[i].backup_state && 0 != (ret = nandroid_backup_partition(backup_path, extra_partition[i].mount_point)))
            return print_and_error(NULL, ret);
    }

    if (enable_md5sum.value) {
        if (0 != (ret = gen_twrp_md5sum(backup_path)))
            return print_and_error(NULL, ret);
    }

    sprintf(tmp, "chmod -R 777 %s", backup_path);
    __system(tmp);

    finish_nandroid_job();
    show_backup_stats(backup_path);
    if (reboot_after_nandroid)
        reboot_main_system(ANDROID_RB_RESTART, 0, 0);
    return 0;
}
Example #15
0
// set value of key in config file
int write_config_file(const char* config_file, const char* key, const char* value) {
    if (ensure_path_mounted(config_file) != 0) {
        LOGE("Cannot mount path for settings file: %s\n", config_file);
        return -1;
    }

    char config_file_tmp[PATH_MAX];
    char tmp[PATH_MAX];
    sprintf(config_file_tmp, "%s.tmp", config_file);
    sprintf(tmp, "%s", DirName(config_file_tmp));
    ensure_directory(tmp, 0755);
    delete_a_file(config_file_tmp);

    FILE *f_tmp = fopen(config_file_tmp, "wb");
    if (f_tmp == NULL) {
        LOGE("failed to create temporary settings file!\n");
        return -1;
    }

    FILE *fp = fopen(config_file, "rb");
    if (fp == NULL) {
        // we need to create a new settings file: write an info header
        const char* header[] = {
            "#PhilZ Touch Settings File\n",
            "#Edit only in appropriate UNIX format (Notepad+++...)\n",
            "#Entries are in the form of:\n",
            "#key=value\n",
            "#Do not add spaces in between!\n",
            "\n",
            NULL
        };

        int i;
        for(i = 0; header[i] != NULL; i++) {
            fwrite(header[i], 1, strlen(header[i]), f_tmp);
        }
    } else {
        // parse existing config file and write new temporary file.
        char line[PROPERTY_VALUE_MAX];
        while (fgets(line, sizeof(line), fp) != NULL) {
            // ignore any existing line with key we want to set
            if (strstr(line, key) != NULL && strncmp(line, key, strlen(key)) == 0 && line[strlen(key)] == '=')
                continue;
            // ensure trailing \n, in case some one got a bad editor...
            if (line[strlen(line) - 1] != '\n')
                strcat(line, "\n");
            fwrite(line, 1, strlen(line), f_tmp);
        }
        fclose(fp);
    }

    // write new key=value entry
    char new_entry[PROPERTY_VALUE_MAX];
    sprintf(new_entry, "%s=%s\n", key, value);
    fwrite(new_entry, 1, strlen(new_entry), f_tmp);
    fclose(f_tmp);

    if (rename(config_file_tmp, config_file) != 0) {
        LOGE("failed to rename temporary settings file!\n");
        return -1;
    }

    // if we are editing recovery settings file, create a second copy on primary storage
    if (strcmp(PHILZ_SETTINGS_FILE, config_file) == 0) {
        sprintf(tmp, "%s/%s", get_primary_storage_path(), PHILZ_SETTINGS_FILE2);
        if (copy_a_file(config_file, tmp) != 0)
            LOGE("failed duplicating settings file to primary storage!\n");
    }

    LOGI("%s was set to %s\n", key, value);
    return 0;
}
Example #16
0
int web_main(void * _ed, struct MHD_Connection * con, const char * url,
		      const char * method, const char * version,
		      const char *upload_data, size_t * upload_data_size,
		     void ** con_cls){
  UNUSED(url); UNUSED(version); UNUSED(upload_data); UNUSED(upload_data_size);
  UNUSED(method); UNUSED(con_cls); UNUSED(_ed);
  const char * file = "page.html";

  bool style_loc = strcmp((char *) url + 1, "style.css") == 0;
  if(style_loc)
    file = "style.css";
  else if(0 == strcmp((char *) url + 1, (char *) "favicon.png"))
    file = "favicon.png";
  
  char fnamebuffer[100];
  logd("'%s' %s %s %i\n", url, method, version, upload_data_size);
  logd("File: %s\n", file);
  if(url == strstr(url, "/sharesinfo")){
    // Send back json code describing all the available shares.

    file = "shareinfo_data";
    
    dirscan dir = scan_directories("shareinfo");
    
    FILE * outfile = fopen(file, "w");
    fprintf(outfile, "[");
    for(size_t i = 0; i < dir.cnt; i++){
      logd("looking in: %s\n", dir.files[i]);
      char fnamebuffer2[100];
      sprintf(fnamebuffer2, "shareinfo/%s", dir.files[i]);
      void * rdbuffer = read_file_to_string(fnamebuffer2);
      ASSERT(rdbuffer != NULL);
      void *ptr = rdbuffer;
      char * dirname = udpc_unpack_string(&ptr);
      char * name = udpc_unpack_string(&ptr);
      char * user = udpc_unpack_string(&ptr);
      fprintf(outfile, "{\"path\": \"%s\", \"name\":\"%s\", \"user\":\"%s\"}%s\n",dirname, name, user, (i == dir.cnt -1) ? "" : ",");
      dealloc(rdbuffer);
    }
    fprintf(outfile, "]");
    fclose(outfile);
    dirscan_clean(&dir);
  }else if(url == strstr(url,"/shares/")){
    // fetch the active shares item inside the shares folder
    
    char * shareid = (char *) url + strlen("/shares/");
    logd("Shareid: %s\n", shareid);
    char * shareinfo_filename = fmtstr("shareinfo/%s", shareid);
    void * buffer = read_file_to_string(shareinfo_filename);
    if(buffer == NULL)
      goto error;
    void * bufptr = buffer;
    char * dir = udpc_unpack_string(&bufptr);
    char * name = udpc_unpack_string(&bufptr);
    char * user = udpc_unpack_string(&bufptr);
    service_descriptor sd;
    if(!udpc_get_service_descriptor(user, &sd)){
      logd("Unable to parse service name: '%s'\n", user);
      dealloc(buffer);
      goto error;
    }

    logd("path: %s, name: %s, user: %s\n", dir, name, user);
    update_dirfile(dir, name, user);
    sprintf(fnamebuffer, "shares/%s.json", name);
    dealloc(buffer);
    logd("Sending: %s\n", fnamebuffer);
    file = fnamebuffer;
  }
  if(strcmp(url, "/add_share") == 0){ 
    const char * path = MHD_lookup_connection_value(con, MHD_GET_ARGUMENT_KIND, "path");
    const char * name = MHD_lookup_connection_value(con, MHD_GET_ARGUMENT_KIND, "name");
    const char * user = MHD_lookup_connection_value(con, MHD_GET_ARGUMENT_KIND, "user");
    logd("path: %s, name: %s, user: %s\n", path, name, user);
    if(path == NULL || name == NULL || user == NULL){
      goto error;
    }
    service_descriptor sd;
    if(!udpc_get_service_descriptor(user, &sd)){
      logd("Unable to parse service name: '%s'\n", user);
      goto error;
    }
    logd("Service descriptor seems ok \n");
    ensure_directory("shareinfo/");
    char * sharepath = fmtstr("shareinfo/%s", name);
    struct stat filest;
    stat(sharepath, &filest);
    dealloc(sharepath);
    
    if(S_ISREG(filest.st_mode)){
      logd("File exists!\n");
    }else{
      struct stat dirst;
      stat(path, &dirst);
      if(!S_ISDIR(dirst.st_mode)){
	logd("Dir does not exist.. creating a new one..\n");
	int path_len = strlen(path);
	if(path[path_len] !='/'){
	  char * npath = fmtstr("%s/", path);
	  ensure_directory(npath);
	  dealloc(npath);
	}else{
	  ensure_directory(path);
	}
      }
      logd("Updating dirfile!\n");
      update_dirfile(path, name, user);
      logd("Done..\n");
    }
    const char * r = "\"OK\"";
    struct MHD_Response * response = MHD_create_response_from_data(strlen(r),
								   (void *) r,
								   0,
								   MHD_NO);
    int ret = MHD_queue_response(con, MHD_HTTP_OK, response);
    MHD_destroy_response(response);
    return ret;
  }

  size_t filesize = 0;
  void * pg = read_file_to_buffer(file, &filesize);
  struct MHD_Response * response = MHD_create_response_from_data(filesize,
					   pg,
					   1,
					   MHD_NO);
  int ret = MHD_queue_response(con, MHD_HTTP_OK, response);
  MHD_destroy_response(response);
  return ret;

 error:;
  const char * error_str = "<html><body>400</body></html>";
  response = MHD_create_response_from_data(strlen(error_str) + 1,
					   (void *) error_str,
					   0,
					   MHD_NO);
  ret = MHD_queue_response(con, MHD_HTTP_BAD_REQUEST, response);
  MHD_destroy_response(response);
  return ret;
}