示例#1
0
static int real_delete_files (zfile *zf)
{
    int attr = 0;         /* attributes of zip file */
    FILE *fr = NULL;      /* for reading from original zipfile */
    char tempzip[FILENAME_MAX]; /* filename for temp zipfile */
    int err = 0;

    *tempzip = '\0';

    err = zipfile_write_check(zf, ZIP_DO_DELETE, &attr);
    if (err) {
	return err;
    }

    trace(1, "opening original zip file for reading\n");
    fr = fopen(zf->fname, "rb");
    if (fr == NULL) {
	return ziperr(ZE_NAME, zf->fname);
    }

    strcpy(tempzip, zf->fname);
    zf->fp = ztempfile(tempzip);
    if (zf->fp == NULL) {
	fprintf(stderr, " real_delete_files: ztempfile failed\n");
	fclose(fr);
	ziperr(ZE_TEMP, tempzip);
	return ZE_TEMP;
    }

    /* reset to start of file */
    zf->tempzn = 0;

    err = process_delfiles(zf, fr);

    if (!err) {
	err = write_central_and_end(zf, tempzip);
    }

    fclose(zf->fp);
    zf->fp = NULL;
    fclose(fr);
	
    if (!err) {
	/* Replace old zip file with new zip file, leaving only the new one */
	trace(1, "moving %s into position as %s\n", tempzip, zf->fname);
	err = replace_file(zf->fname, tempzip);
	if (err) {
	    ziperr(err, "was replacing %s", zf->fname);
	} else if (attr) {
	    chmod(zf->fname, attr);
	}
    }

    if (err && *tempzip != '\0') {
	/* clean up */
	gretl_remove(tempzip);
    }

    return err;
}
示例#2
0
static int recurse_dir(const char *search_str, const char *replace_str, char *dir_name)
{
  
  DIR *dir = opendir(dir_name);
  if (dir == NULL) {
      return 3;
  }
  
  int ret = 0;
  int ret_one = 0;
  struct dirent *dirp;
  while ( (dirp = readdir(dir)) != NULL ) {
    if ( strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0 ) {
      continue;
    }
    
    // dir + "/" + name 
    char *full_path = malloc(strlen(dir_name) + strlen(dirp->d_name) + 1);
    strcat(full_path, dir_name);
    strcat(full_path, "/");
    strcat(full_path, dirp->d_name);
    
    ret_one = replace_file(search_str, replace_str, full_path, 1);
    
    free(full_path);
    if (ret_one == 1 && ret < 2) {
      ret = 1;
    }
    if (ret_one > 1) {
      ret += 2;
    }
  }
  
  return ret;
};
示例#3
0
static bool fix_file_contexts()
{
    autoclose::file fp_old(autoclose::fopen("/file_contexts", "rb"));
    if (!fp_old) {
        if (errno == ENOENT) {
            return true;
        } else {
            LOGE("Failed to open /file_contexts: %s", strerror(errno));
            return false;
        }
    }

    autoclose::file fp_new(autoclose::fopen("/file_contexts.new", "wb"));
    if (!fp_new) {
        LOGE("Failed to open /file_contexts.new for writing: %s",
             strerror(errno));
        return false;
    }

    char *line = nullptr;
    size_t len = 0;
    ssize_t read = 0;

    auto free_line = util::finally([&] {
        free(line);
    });

    while ((read = getline(&line, &len, fp_old.get())) >= 0) {
        if (util::starts_with(line, "/data/media(")
                && !strstr(line, "<<none>>")) {
            continue;
        }

        if (fwrite(line, 1, read, fp_new.get()) != (std::size_t) read) {
            LOGE("Failed to write to /file_contexts.new: %s", strerror(errno));
            return false;
        }
    }

    static const char *new_contexts =
        "\n"
        "/data/media              <<none>>\n"
        "/data/media/[0-9]+(/.*)? <<none>>\n"
        "/raw(/.*)?               <<none>>\n"
        "/data/multiboot(/.*)?    <<none>>\n"
        "/cache/multiboot(/.*)?   <<none>>\n"
        "/system/multiboot(/.*)?  <<none>>\n";
    fputs(new_contexts, fp_new.get());

    return replace_file("/file_contexts", "/file_contexts.new");
}
CondorFile * CondorFileTable::open_file_unique( char *logical_name, int flags, int mode )
{

	int match = find_logical_name( logical_name );
	if( match==-1 || !pointers[match]->file ) {
		char *url = NULL;
		lookup_url( (char*)logical_name, &url );
		if( url ) {
			match = find_url( url );
			if( match==-1 ) {
				CondorFile *f = open_url_retry( url, flags, mode );
				free( url );
				return f;
			}
			free( url );
		}
	}

	CondorFilePointer *p = pointers[match];
	CondorFile *old_file;

	if( needs_reopen( p->flags, flags ) ) {
		flags &= ~(O_RDONLY);
		flags &= ~(O_WRONLY);
		flags |= O_RDWR;

		p->file->flush();

		CondorFile *f = open_url_retry( p->file->get_url(), flags, mode );
		if(!f) return 0;

		old_file = p->file;
		if( old_file->close()!=0 ) return 0;

		replace_file( old_file, f );

		/* Even though old_file is aliasing p->file here, and
			then we're deleting old_file, There is no
			returning a freed pointer error at the end of the
			function because replace_file() will *always*
			be able to replace the entry in the pointers[]
			table (aliased by p) indexed with old_file (being
			actually p->file) with the updated value of f.
		*/

		delete old_file;
	}

	return p->file;
}
示例#5
0
/** Filters a file in-place. This is performed by creating a temporary
    file, writing the output to the temporary file, then deleting the
    original file and renaming the temporary file to the original file.

    To save unnecessary updation of time stamps, if no changes were made
    to the original file, then the temporary file is deleted and the
    original file is left as-is. If any errors occur, then an error
    message will be displayed and the program will be terminated.

    @param input_file_name Name of the input file. Must not be @c NULL.
    Note that @c "-" is <b>NOT</b> recognised as standard input/output. */
static void process_file_in_place(
    const char *input_file_name,
    jmp_buf *jmp_if_error)
{
    /* temp_file_name: Name of the temporary file */
    /* input_file: Input file object stream */
    /* output_file: Temporary output file object stream */
    /* on_clean_stream_error: Handler for I/O errors in clean_stream() */
    char temp_file_name[PATH_MAX];
    FILE *input_file;
    FILE *temp_file;
    jmp_buf on_clean_stream_error;

    /* Open the input file and create a temporary output file. */
    open_file(input_file_name, INPUT_MODE, &input_file, jmp_if_error);
    create_temp_file(input_file_name, OUTPUT_MODE,
                     temp_file_name, &temp_file, jmp_if_error);

    /* Filter the input file contents into the temporary file. */
    if(setjmp(on_clean_stream_error))
    {
        /* Execution branches here if clean_stream() encounters an I/O error */
        error(0, errno, "%s", input_file_name);
        close_remove_file(temp_file, temp_file_name, jmp_if_error);
        longjmp(*jmp_if_error, TRUE);
        /* Non-local return */
    }
    switch(clean_stream(input_file, temp_file, &on_clean_stream_error))
    {
    case CSR_STREAM_UNMODIFIED:
        /* No modifications were made to the stream, so the
           temporary file is identical to the input file. So we can
           avoid unnecessarily updating the time stamps on the input
           file, we'll close and remove the temporary file name
           instead. Close the input file as well. */
        close_remove_file(temp_file, temp_file_name, jmp_if_error);
        close_file(input_file, input_file_name, jmp_if_error);
        break;
    case CSR_STREAM_MODIFIED:
        /* Modifications were made to the stream content. The
           temporary file and input files are not identical. Close
           both files, then delete the input file and rename the
           temporary file to the input file. */
        close_file_guarantee_complete_or_remove(
            temp_file, temp_file_name, jmp_if_error);
        close_file(input_file, input_file_name, jmp_if_error);
        replace_file(input_file_name, temp_file_name, jmp_if_error);
        break;
    }
}
示例#6
0
static bool fix_arter97()
{
    const char *path = "/init.mount.sh";
    const char *path_new = "/init.mount.sh.new";
    const char *fstab = "/fstab.samsungexynos7420";

    struct stat sb;
    if (stat(path, &sb) < 0 || stat(fstab, &sb) < 0) {
        return true;
    }

    autoclose::file fp(autoclose::fopen(path, "r"));
    if (!fp) {
        LOGE("Failed to open %s for reading: %s", path, strerror(errno));
        return false;
    }

    autoclose::file fp_new(autoclose::fopen(path_new, "w"));
    if (!fp_new) {
        LOGE("Failed to open %s for writing: %s", path_new, strerror(errno));
        return false;
    }

    // Strip everything from /init.mount.sh except for the shebang line
    {
        char *line = nullptr;
        size_t len = 0;
        ssize_t read = 0;

        auto free_line = util::finally([&] {
            free(line);
        });

        while ((read = getline(&line, &len, fp.get())) >= 0) {
            fputs(line, fp_new.get());
            break;
        }
    }

    fp.reset();
    fp_new.reset();

    replace_file(path, path_new);

    return true;
}
示例#7
0
static pngquant_error write_image(png8_image *output_image, png24_image *output_image24, const char *outname, struct pngquant_options *options)
{
    FILE *outfile;
    char *tempname = NULL;

    if (options->using_stdout) {
        set_binary_mode(stdout);
        outfile = stdout;

        if (output_image) {
            verbose_printf(options, "  writing %d-color image to stdout", output_image->num_palette);
        } else {
            verbose_printf(options, "  writing truecolor image to stdout");
        }
    } else {
        tempname = temp_filename(outname);
        if (!tempname) return OUT_OF_MEMORY_ERROR;

        if ((outfile = fopen(tempname, "wb")) == NULL) {
            fprintf(stderr, "  error: cannot open '%s' for writing\n", tempname);
            free(tempname);
            return CANT_WRITE_ERROR;
        }

        if (output_image) {
            verbose_printf(options, "  writing %d-color image as %s", output_image->num_palette, filename_part(outname));
        } else {
            verbose_printf(options, "  writing truecolor image as %s", filename_part(outname));
        }
    }

    pngquant_error retval;
    #pragma omp critical (libpng)
    {
        if (output_image) {
            retval = rwpng_write_image8(outfile, output_image);
        } else {
            retval = rwpng_write_image24(outfile, output_image24);
        }
    }

    if (!options->using_stdout) {
        fclose(outfile);

        if (SUCCESS == retval) {
            // Image has been written to a temporary file and then moved over destination.
            // This makes replacement atomic and avoids damaging destination file on write error.
            if (!replace_file(tempname, outname, options->force)) {
                retval = CANT_WRITE_ERROR;
            }
        }

        if (retval) {
            unlink(tempname);
        }
    }
    free(tempname);

    if (retval && retval != TOO_LARGE_FILE) {
        fprintf(stderr, "  error: failed writing image to %s\n", outname);
    }

    return retval;
}
示例#8
0
static bool strip_manual_mounts()
{
    autoclose::dir dir(autoclose::opendir("/"));
    if (!dir) {
        return true;
    }

    struct dirent *ent;
    while ((ent = readdir(dir.get()))) {
        // Look for *.rc files
        if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0
                || !util::ends_with(ent->d_name, ".rc")) {
            continue;
        }

        std::string path("/");
        path += ent->d_name;

        autoclose::file fp(autoclose::fopen(path.c_str(), "r"));
        if (!fp) {
            LOGE("Failed to open %s for reading: %s",
                 path.c_str(), strerror(errno));
            continue;
        }

        char *line = nullptr;
        size_t len = 0;
        ssize_t read = 0;

        auto free_line = util::finally([&] {
            free(line);
        });

        std::size_t count = 0;
        std::unordered_set<std::size_t> comment_out;

        // Find out which lines need to be commented out
        while ((read = getline(&line, &len, fp.get())) >= 0) {
            if (strstr(line, "mount")
                    && (strstr(line, "/system")
                        || strstr(line, "/cache")
                        || strstr(line, "/data"))) {
                std::vector<std::string> tokens = util::tokenize(line, " \t\n");
                if (tokens.size() >= 4 && tokens[0] == "mount"
                        && (tokens[3] == "/system"
                            || tokens[3] == "/cache"
                            || tokens[3] == "/data")) {
                    comment_out.insert(count);
                }
            }

            ++count;
        }

        if (comment_out.empty()) {
            continue;
        }

        // Go back to beginning of file for reread
        rewind(fp.get());
        count = 0;

        std::string new_path(path);
        new_path += ".new";

        autoclose::file fp_new(autoclose::fopen(new_path.c_str(), "w"));
        if (!fp_new) {
            LOGE("Failed to open %s for writing: %s",
                 new_path.c_str(), strerror(errno));
            continue;
        }

        // Actually comment out the lines
        while ((read = getline(&line, &len, fp.get())) >= 0) {
            if (comment_out.find(count) != comment_out.end()) {
                fputs("#", fp_new.get());
            }
            fputs(line, fp_new.get());

            ++count;
        }

        replace_file(path.c_str(), new_path.c_str());
    }

    return true;
}
示例#9
0
static bool add_mbtool_services()
{
    autoclose::file fp_old(autoclose::fopen("/init.rc", "rb"));
    if (!fp_old) {
        if (errno == ENOENT) {
            return true;
        } else {
            LOGE("Failed to open /init.rc: %s", strerror(errno));
            return false;
        }
    }

    autoclose::file fp_new(autoclose::fopen("/init.rc.new", "wb"));
    if (!fp_new) {
        LOGE("Failed to open /init.rc.new for writing: %s",
             strerror(errno));
        return false;
    }

    char *line = nullptr;
    size_t len = 0;
    ssize_t read = 0;

    auto free_line = util::finally([&] {
        free(line);
    });

    bool has_init_multiboot_rc = false;
    bool has_disabled_installd = false;
    bool inside_service = false;

    while ((read = getline(&line, &len, fp_old.get())) >= 0) {
        if (strstr(line, "import /init.multiboot.rc")) {
            has_init_multiboot_rc = true;
        }

        if (util::starts_with(line, "service")) {
            inside_service = strstr(line, "installd") != nullptr;
        } else if (inside_service && is_completely_whitespace(line)) {
            inside_service = false;
        }

        if (inside_service && strstr(line, "disabled")) {
            has_disabled_installd = true;
        }
    }

    rewind(fp_old.get());

    while ((read = getline(&line, &len, fp_old.get())) >= 0) {
        // Load /init.multiboot.rc
        if (!has_init_multiboot_rc && line[0] != '#') {
            has_init_multiboot_rc = true;
            fputs("import /init.multiboot.rc\n", fp_new.get());
        }

        if (fwrite(line, 1, read, fp_new.get()) != (std::size_t) read) {
            LOGE("Failed to write to /init.rc.new: %s", strerror(errno));
            return false;
        }

        // Disable installd. mbtool's appsync will spawn it on demand
        if (!has_disabled_installd
                && util::starts_with(line, "service")
                && strstr(line, "installd")) {
            fputs("    disabled\n", fp_new.get());
        }
    }

    if (!replace_file("/init.rc", "/init.rc.new")) {
        return false;
    }

    // Create /init.multiboot.rc
    autoclose::file fp_multiboot(autoclose::fopen("/init.multiboot.rc", "wb"));
    if (!fp_multiboot) {
        LOGE("Failed to open /init.multiboot.rc for writing: %s",
             strerror(errno));
        return false;
    }

    static const char *init_multiboot_rc =
        "service mbtooldaemon /mbtool daemon\n"
        "    class main\n"
        "    user root\n"
        "    oneshot\n"
        "\n"
        "service appsync /mbtool appsync\n"
        "    class main\n"
        "    socket installd stream 600 system system\n";

    fputs(init_multiboot_rc, fp_multiboot.get());

    fchmod(fileno(fp_multiboot.get()), 0750);

    return true;
}
示例#10
0
/**
 * The main can be called in three modes
 * 
 *   sedlite - replace stdin to stdout
 *   rsif - replace string in file (clone of )
 *   rsifr - rsif recusivly
 * 
 * It is not called with options e.g. -R  so that you can replace -R with -V and dont need to do any escaping
 * 
 */
int main(int argc, char *argv[])
{

  /* sedlite mode only stream editing stdin and write to stdout */
  // if ! length correct balk
  if ( argc < 3 ) {
    
    fprintf(stderr, "Usage: %s [search] [replace] [files...]\n", argv[0]);
    return 10;
    
  }

  // read command line args
  char *search_str = argv[1];
  char *replace_str = argv[2];
  
  if ( argc == 3) {
    
    return replace(search_str, replace_str, stdin, stdout);
    
  }
  
  /*
   * rsif and rsifr mode works on files and recursivly on files and directories 
   * 
   * Check the end of arg[0] so it may be called ./rsifr or /usr/bin/rsifr
   */
  char *bin_name = argv[0];
  int bin_len = strlen(bin_name);
  int is_rsif = 0;
  int is_rsifr = 0;
  int recurse = 0;
  if ( strcmp("rsifr", bin_name + bin_len - 5) == 0 ) {
    is_rsifr = 1;
    recurse = 1;
  }
  if ( strcmp("rsif",bin_name + bin_len - 4) == 0 ) {
    is_rsif = 1;
  }
  
  if ( (is_rsif || is_rsifr) && argc > 3) {
    
    int i, ret, changed;
    ret = 0; 
    changed = 1;
    
    for (i = 3; i < argc; i++) {
      
      char *file_name = argv[i];
      
      int ret_one = replace_file(search_str, replace_str, file_name, recurse);
      if (ret_one == 0) {
	changed = 0;
      }
      else if (ret_one > 1) {
	ret += ret_one;
      }
    }
    
    // TODO unlink the tmp file
    if (ret > 1) {
      return ret;
    }
    else {
      return changed;
    }
  }
  
  return 23;
  
};
示例#11
0
static bool update_remote_files(void *param, obs_data_t *remote_file)
{
	struct update_info *info = param;

	struct file_update_data data = {
		.name = obs_data_get_string(remote_file, "name"),
		.version = (int)obs_data_get_int(remote_file, "version")
	};

	enum_files(info->cache_package, newer_than_cache, &data);
	if (!data.newer && data.found)
		return true;

	if (!do_relative_http_request(info, info->remote_url, data.name))
		return true;

	if (info->callback) {
		struct file_download_data download_data;
		bool confirm;

		download_data.name = data.name;
		download_data.version = data.version;
		download_data.buffer.da = info->file_data.da;

		confirm = info->callback(info->param, &download_data);

		info->file_data.da = download_data.buffer.da;

		if (!confirm) {
			info("Update file '%s' (version %d) rejected",
					data.name, data.version);
			return true;
		}
	}

	write_file_data(info, info->temp, data.name);
	replace_file(info->temp, info->cache, data.name);

	info("Successfully updated file '%s' (version %d)",
			data.name, data.version);
	return true;
}

static void update_save_metadata(struct update_info *info)
{
	struct dstr path = { 0 };

	if (!info->etag_remote)
		return;

	dstr_copy(&path, info->cache);
	dstr_cat(&path, "meta.json");

	obs_data_t *data;
	data = obs_data_create();
	obs_data_set_string(data, "etag", info->etag_remote);
	obs_data_save_json(data, path.array);
	obs_data_release(data);
}

static void update_remote_version(struct update_info *info, int cur_version)
{
	int remote_version;
	long response_code;

	if (!do_http_request(info, info->url, &response_code))
		return;

	if (response_code == 304)
		return;

	if (!info->file_data.array || info->file_data.array[0] != '{') {
		warn("Remote package does not exist or is not valid json");
		return;
	}

	update_save_metadata(info);

	info->remote_package = obs_data_create_from_json(
			(char*)info->file_data.array);
	if (!info->remote_package) {
		warn("Failed to initialize remote package json");
		return;
	}

	remote_version = (int)obs_data_get_int(info->remote_package, "version");
	if (remote_version <= cur_version)
		return;

	write_file_data(info, info->temp, "package.json");

	info->remote_url = obs_data_get_string(info->remote_package, "url");
	if (!info->remote_url) {
		warn("No remote url in package file");
		return;
	}

	/* download new files */
	enum_files(info->remote_package, update_remote_files, info);

	replace_file(info->temp, info->cache, "package.json");

	info("Successfully updated package (version %d)", remote_version);
	return;
}
示例#12
0
文件: grub2.c 项目: noryb009/lick
int fix_grub2_inner(lickdir_t *lick, grub2_fix_function function, char original_drive) {
    char drive = original_drive;
    if(!drive) {
        drive = mount_uefi_partition();
        if(!drive) {
            lick->err = strdup2("Could not mount UEFI partition.");
            return 0;
        }
    }

    char *lick_grub = strdup2("?:/efi/lick/" GRUB2_EFI);
    char *lick_shim = strdup2("?:/efi/lick/shim.efi");
    char *lick_mokmanager = strdup2("?:/efi/lick/" MOKMANAGER_EFI);
    char *boot_grub = strdup2("?:/efi/boot/" GRUB2_EFI);
    char *boot_shim = strdup2("?:/efi/boot/shim.efi");
    char *boot_mokmanager = strdup2("?:/efi/boot/" MOKMANAGER_EFI);
    char *boot_file = strdup("?:/efi/boot/bootx64.efi");
    char *boot_file_backup = strdup2("?:/efi/boot/bootx64-orig.efi");
    char *ms_loader = strdup2("?:/efi/microsoft/boot/bootmgfw.efi");
    char *ms_loader_backup = strdup2("?:/efi/microsoft/boot/bootmgfw-backup.efi");
    char *grub_cfg = unix_path(concat_strs(2, lick->drive, "/lickgrub.cfg"));
    char *grub_menu = NULL;

    lick_grub[0] = drive;
    lick_shim[0] = drive;
    lick_mokmanager[0] = drive;
    boot_grub[0] = drive;
    boot_shim[0] = drive;
    boot_mokmanager[0] = drive;
    ms_loader[0] = drive;
    ms_loader_backup[0] = drive;
    boot_file[0] = drive;
    boot_file_backup[0] = drive;

    const char *fatal_warning =
        "WARNING! The fix has only been half applied.\n"
        "The system may not boot when rebooted.\n"
        "Find out why renaming files on the UEFI partition is not working,\n"
        "then move `/EFI/Microsoft` to `/EFI/Microsoft-backup`.";

    grub2_fix_status status = GRUB2_FIX_UNINSTALLED;

    if(path_exists(boot_grub) || path_exists(boot_mokmanager)
            || path_exists(ms_loader_backup)
            || path_exists(boot_file_backup)) {
        if(path_exists(boot_grub) && path_exists(boot_mokmanager)
                && path_exists(ms_loader_backup)
                && path_exists(boot_file_backup))
            status = GRUB2_FIX_INSTALLED;
        else
            status = GRUB2_FIX_PARTLY_INSTALLED;
    }

    int ret = 0;

    if(function == GRUB2_FIX_CHECK) {
        if(status == GRUB2_FIX_INSTALLED)
            ret = 1;
    } else if(status == GRUB2_FIX_PARTLY_INSTALLED)
        lick->err = strdup2("Partial boot fix applied.");
    else if(function == GRUB2_FIX_INSTALL && status == GRUB2_FIX_INSTALLED)
        lick->err = strdup2("Boot fix already applied!");
    else if(function == GRUB2_FIX_UNINSTALL && status == GRUB2_FIX_UNINSTALLED)
        ret = 1;
    else if(function == GRUB2_FIX_INSTALL) {
        /* Steps:
         * 1) Copy `/EFI/LICK/{grubx64,shim,MokManager}.efi` to `/EFI/Boot/`
         * 2) Rename `/EFI/Boot/bootx64.efi` to `bootx64-orig.efi`
         * 3) Rename `/EFI/Boot/shim.efi` to `bootx64.efi`
         * 4) Rename `/EFI/Microsoft/Boot/bootmgfw.efi` to `bootmgfw-backup.efi`
         */
        do {
            int fail = 1;
            do {
                if(!copy_file(boot_grub, lick_grub))
                    break;
                if(!copy_file(boot_shim, lick_shim))
                    break;
                if(!copy_file(boot_mokmanager, lick_mokmanager))
                    break;
                if(!copy_file(boot_file_backup, boot_file))
                    break;

                attrib_t boot_attrs = attrib_open(boot_file);
                if(!replace_file(boot_file, boot_shim)) {
                    attrib_save(boot_file, boot_attrs);
                    lick->err = strdup2("Could not overwrite boot file.");
                    break;
                }
                if(!rename_file(ms_loader_backup, ms_loader)) {
                    // Try to restore the backup.
                    if(!replace_file(boot_file, boot_file_backup)) {
                        // At this point we are stuck with the fix being
                        // half applied. Realistically, this should never occur.
                        attrib_save(boot_file, boot_attrs);
                        lick->err = strdup2(fatal_warning);
                        fail = 0;
                        break;
                    }
                    lick->err = strdup2("Could not rename directory.");
                    break;
                }

                attrib_save(boot_file_backup, boot_attrs);
                fail = 0;
            } while(0);

            if(fail) {
                unlink_file(boot_grub);
                unlink_file(boot_shim);
                unlink_file(boot_mokmanager);
                unlink_file(boot_file_backup);
                if(!lick->err)
                    lick->err = strdup2("Could not copy files on EFI partition.");
                break;
            }

            // Edit grub menu.
            FILE *f = fopen(grub_cfg, "r");
            if(!f) {
                if(!lick->err)
                    lick->err = strdup2("Successfully installed, but could not modify configuration file.");
                break;
            }
            grub_menu = file_to_str(f);
            fclose(f);
            char *grub_menu_lower = lower_str(strdup2(grub_menu));

            // Search for `/efi/microsoft` (case insensitive)
            // and replace with `/efi/microsoft-backup`
            // First, find the number of `/efi/microsoft`
            size_t cnt = 0;
            const char *str = grub_menu_lower;
            const char *needle = "/efi/microsoft/boot/bootmgfw.efi";
            const char *replacement = "/efi/microsoft/boot/bootmgfw-backup.efi";
            for(;;) {
                str = strstr(str, needle);
                if(!str)
                    break;
                ++cnt;
                ++str; // Increment string to find the next occurrance.
            }

            if(cnt > 0) {
                /* Here, there are 3 strings:
                 * - The original menu, grub_menu.
                 *   This is pointed to by start and str_normal.
                 * - The lowercase menu, grub_menu_lower.
                 *   This is pointed to by str.
                 * - The new menu, new_grub_menu.
                 *   This is pointed to by dst.
                 */
                size_t newsize = strlen(grub_menu)
                    + cnt * (strlen(replacement) - strlen(needle))
                    + 1;
                char *new_grub_menu = malloc(newsize);
                char *dst = new_grub_menu;

                const char *start = grub_menu;
                str = grub_menu_lower;
                for(size_t i = 0; i < cnt; ++i) {
                    str = strstr(str, needle);
                    const char *str_normal = str - grub_menu_lower + grub_menu;
                    // Print everything from start to str.
                    size_t len = str_normal - start;
                    memcpy(dst, start, len);
                    dst += len;
                    strcpy(dst, replacement);
                    str += strlen(needle);
                    dst += strlen(replacement);

                    start = str_normal + strlen(needle);
                }
                strcpy(dst, start);
                grub_menu[newsize - 1] = '\0';

                f = fopen(grub_cfg, "w");
                if(!f) {
                    if(!lick->err)
                        lick->err = strdup2("Successfully installed, but could not modify configuration file.");
                    free(new_grub_menu);
                    free(grub_menu_lower);
                    break;
                }
                fprintf(f, "%s", new_grub_menu);
                fclose(f);
                free(new_grub_menu);
                free(grub_menu_lower);
            }
            ret = 1;
        } while(0);
    } else {
        /* Steps:
         * 1) Rename `/EFI/Microsoft/Boot/bootmgfw-backup.efi` to `bootmgfw.efi`
         * 2) Rename `/EFI/Boot/bootx64-orig.efi` to `bootx64.efi`
         * 3) Delete `/EFI/Boot/{grubx64,MokManager}.efi`
         */
        do {
            if(!rename_file(ms_loader, ms_loader_backup)) {
                lick->err = strdup2("Could not rename directory.");
                break;
            }
            attrib_t boot_attrs = attrib_open(boot_file_backup);
            if(!replace_file(boot_file, boot_file_backup)) {
                attrib_save(boot_file_backup, boot_attrs);
                if(!rename_file(ms_loader_backup, ms_loader)) {
                    lick->err = strdup2(fatal_warning);
                    break;
                }
                lick->err = strdup2("Could not replace boot file.");
                break;
            }
            attrib_save(boot_file, boot_attrs);

            unlink_file(boot_grub);
            unlink_file(boot_mokmanager);
            ret = 1;
        } while(0);
    }

    if(!original_drive)
        unmount_uefi_partition(drive);
    free(lick_grub);
    free(lick_shim);
    free(lick_mokmanager);
    free(boot_grub);
    free(boot_shim);
    free(boot_mokmanager);
    free(ms_loader);
    free(ms_loader_backup);
    free(boot_file);
    free(boot_file_backup);
    free(grub_cfg);
    free(grub_menu);
    return ret;
}
示例#13
0
文件: FindAndReplace.c 项目: goTJ/tj
// {{{ void gogodir()
void gogodir()
{
	DIR *dp;
	struct dirent *dirp;
	struct stat fst;
	char buf[MAX_PATH_LENGTH];
	
	if(!(dp=opendir("."))){
		getcwd(buf, MAX_PATH_LENGTH);
		fprintf(stderr, "Can't open directory %s: ", buf);
		perror(NULL);
		return;
	}
	// surf file 
	while((dirp=readdir(dp)) != NULL){
		// skip "." and ".."
		if(!strcmp(dirp->d_name, "..") || !strcmp(dirp->d_name, "."))
			continue;
		// get lstat
		if(lstat(dirp->d_name, &fst) == -1){
			getcwd(buf, MAX_PATH_LENGTH);
			fprintf(stderr, "Can't get lstat of %s: ", strcat(strcat(buf, "/"), dirp->d_name));
			perror(NULL);
			continue;
		}
		// check if filename contain pattern
		// and get the stat of the target of linkfile if the file is a symbolic link file
		if(strstr(dirp->d_name, pattern) != NULL){
			output_stat(dirp->d_name, &fst);
			if(S_ISLNK(fst.st_mode)){
				if(stat(dirp->d_name, &fst) == -1){
					getcwd(buf, MAX_PATH_LENGTH);
					fprintf(stderr, "Can't get stat of %s: ", strcat(strcat(buf, "/"), dirp->d_name));
					perror(NULL);
					continue;
				}
			}
			// replace file if necessary and possible
			if(needreplace && S_ISREG(fst.st_mode)){
				replace_file(dirp->d_name);
			}
		}else{
			if(S_ISLNK(fst.st_mode)){
				if(stat(dirp->d_name, &fst) == -1){
					getcwd(buf, MAX_PATH_LENGTH);
					fprintf(stderr, "Can't get stat of %s: ", strcat(strcat(buf, "/"), dirp->d_name));
					perror(NULL);
					continue;
				}
			}
		}
		// chdir if the file is a directory
		if(S_ISDIR(fst.st_mode)){
			if(!isvisit(fst.st_ino, fst.st_dev)){
				insert(fst.st_ino, fst.st_dev);
				getcwd(buf, MAX_PATH_LENGTH);
				if(chdir(dirp->d_name) != -1){
					gogodir();
					chdir(buf);
				}else{
					fprintf(stderr, "Can't chdir to %s: ", strcat(strcat(buf, "/"), dirp->d_name));
					perror(NULL);
				}
			}
		}
	}
	closedir(dp);
} // }}}
示例#14
0
static int real_archive_files (const char *targ, const char **filenames, 
			       int level, ZipOption opt, int task,
			       GError **gerr)
{
    int attr;             /* attributes of zip file */
    flist *f;             /* steps through found linked list */
    int i;                /* arg counter, root directory flag */
    int k;                /* marked counter, comment size, entry count */
    int openerr = 0;      /* true if there were any ZE_OPEN errors */
    guint32 t;            /* file time, length of central directory */
    zlist **w;            /* pointer to last link in zfiles list */
    zlist *z;             /* steps through zfiles linked list */
    FILE *fr = NULL;      /* for reading from original zipfile */
    char tempzip[FILENAME_MAX]; /* name for temporary zipfile */
    int err = 0;
    zfile zf;

    *tempzip = '\0';

    if (level < 0 || level > 9) {
	fprintf(stderr, "invalid compression level %d: setting to 6\n", level);
	level = 6;
    }

    zfile_init(&zf, level, opt);

    trace(1, "real_archive_files: targ = '%s'\n", targ);

    zf.fname = g_strdup(targ);
    if (zf.fname == NULL) {
	err = ziperr(ZE_MEM, "was processing arguments");
	goto bailout;
    }

    if (task != ZIP_DO_NEW) {
	/* if ZIP_DO_NEW, disregard any existing zipfile */
	err = read_zipfile(&zf, ZIP_DO_ZIP);
	if (err) {
	    err = ziperr(err, zf.fname);
	    goto bailout;
	}
    } 

    /* assemble list of filenames to be added/updated */
    k = 0;
    for (i=0; filenames[i] != NULL; i++) {
	if (!gretl_file_test(filenames[i], G_FILE_TEST_EXISTS)) {
	    err = ziperr(ZE_OPEN, "file '%s' was not found", filenames[i]);
	    goto bailout;
	}
	err = add_filenames(filenames[i], &zf);
	if (err) {
	    ziperr(err, filenames[i]);
	    goto bailout;
	} else {
	    k++;
	}
    }

    if (k == 0) {
	err = ziperr(ZE_NONE, NULL);
	goto bailout;
    }

    if (zf.zcount) {
	free(zf.zsort);
	zf.zsort = NULL;
    }

    /* For each marked entry, check if it exists, and, if updating,
       compare date with entry in existing zipfile.  Unmark if it
       doesn't exist or is too old, else update marked count.
    */
    k = 0; 
    for (z = zfiles; z != NULL; z = z->nxt) {
	if (z->mark == MARK_ZIP) {
	    if (dont_keep_file(z, &zf)) {
		z->mark = MARK_NONE;
	    } else {
		k++;
	    }
	}
    }

    /* Remove entries from "found" list that do not exist or are
       otherwise invalid
    */
    for (f = found; f != NULL; ) {
	t = file_mod_time(f->name, NULL, NULL, NULL, &zf);
	if (t == 0 || !fnamecmp(f->zname, zf.fname)) {
	    f = flist_expel(f, &zf.fcount);
	} else {
	    f = f->nxt;
	}
    }

    err = zipfile_write_check(&zf, task, &attr);
    if (err) {
	goto bailout;
    }

    if (zfiles != NULL || zf.zstart) {
	trace(1, "opening original zip file for reading\n");
	fr = fopen(zf.fname, "rb");
	if (fr == NULL) {
	    err = ziperr(ZE_NAME, zf.fname);
	    goto bailout;
	}
    }

    strcpy(tempzip, zf.fname);
    zf.fp = ztempfile(tempzip);
    if (zf.fp == NULL) {
	fprintf(stderr, " real_archive_files: ztempfile failed\n");
	err = ziperr(ZE_TEMP, tempzip);
	goto bailout;
    }

    if (zf.zstart > 0) {
	/* copy initial chunk of old zipfile as is */
	err = fcopy(fr, zf.fp, zf.zstart);
	if (err != Z_OK) {
	    err = ziperr(err, (err == ZE_TEMP)? tempzip : zf.fname);
	    goto bailout;
	}
    }

    zf.tempzn = zf.zstart;
    trace(2, "after initial read, tempzn = %d\n", (int) zf.tempzn);

    err = process_zfiles(&zf, fr, &w, &openerr);
    if (err) {
	fclose(zf.fp);
	if (fr != NULL) {
	    fclose(fr);
	}
	goto bailout;
    }

    /* Process the edited found list, adding them to the zip file */
    trace(2, "now zipping up new entries, fcount=%u\n", (unsigned) zf.fcount);
  
    for (f = found; f != NULL; f = flist_expel(f, &zf.fcount)) {
	/* add a new zfiles entry and set the name */
	z = zlist_entry_new(f);
	if (z == NULL) {
	    err = ziperr(ZE_MEM, "was adding files to zip file");
	    goto bailout;
	}	    

	err = zipup(&zf, z);

	if (err && err != ZE_OPEN && err != ZE_MISS) {
	    err = ziperr(err, "was zipping %s", z->zname);
	    goto bailout;
	}

	if (err == ZE_OPEN || err == ZE_MISS) {
	    openerr = 1;
	    if (err == ZE_OPEN) {
		perror("zip warning");
	    } 
	    free_zlist_entry(z);
	} else {
	    *w = z;
	    w = &z->nxt;
	    zf.zcount += 1;
	}
    }

    err = write_central_and_end(&zf, tempzip);
    fclose(zf.fp);
    zf.fp = NULL;

    if (fr != NULL) {
	fclose(fr);
    }

    /* Replace old zip file with new zip file, leaving only the new one */
    if (!err) {
	trace(1, "moving %s into position as %s\n", tempzip, zf.fname);
	err = replace_file(zf.fname, tempzip);
	if (err) {
	    ziperr(err, "was replacing %s", zf.fname);
	} else if (attr) {
	    chmod(zf.fname, attr);
	}
    }

 bailout:

    zlib_deflate_free(&zf);

    if (err && *tempzip != '\0') {
	/* clean up */
	gretl_remove(tempzip);
    }

    zip_finish(&zf);

    if (err && gerr != NULL) {
	make_gerr(err, gerr);
    }

    trace(1, "returning err = %d\n", err);

    return err;
}