std::string prefix = "Archiving: "; prefix += basename(archive_name.c_str()); prefix += " ";
std::string prefix = "Archiving '" + basename(archive_name.c_str()) + "': ";
bool CreateArchive(    IUINotification* notify,    const char* folder,    const char* extension,    OutputFactory output_factory){    std::list<std::string> files;    BuildFileList(folder, "", files);    // we need to be in the parent of the folder we're archiving    DirectoryState ds__;    SetCurrentDirectory(folder);    SetCurrentDirectory("..");    // figure out our archive file name    std::string archive_name = folder;    archive_name += extension;    // calculate the message prefix    std::string prefix = "Archiving: ";    prefix += basename(archive_name.c_str());    prefix += " ";    // check to see if the archive already exists    if (file_exists(archive_name.c_str())) {        std::string message =            "Archive '" + archive_name + "' already exists.  Overwrite?";        UIResult r = notify->YesNoCancel(message.c_str(), UI_WARNING);        if (r == UI_NO) {            return true;        } else if (r == UI_CANCEL) {            return false;        }    }    // open output file    std::auto_ptr<IOutputFile> out(output_factory(archive_name.c_str()));    if (!out.get()) {        std::string message = "Can't open archive '";        message += archive_name;        message += "' for writing.  Continue?";        UIResult r = notify->YesNo(message.c_str(), UI_ERROR);        return (r == UI_YES);    }    // list of unprocessed files    std::list<std::string> unprocessed_files;    tar_block b;    // add every file to the archive    std::list<std::string>::iterator i = files.begin();    bool cancelled = false;    for (; cancelled == false && i != files.end(); ++i) {        bool is_dir = is_directory(*i);        int size = (is_dir ? 0 : file_size(i->c_str()));        // open the input file        FILE* file;        int mode;        if (is_dir) {            file = NULL;            mode = 0755;        } else {            file = fopen(i->c_str(), "rb");            if (!file) {                unprocessed_files.push_back(*i);                continue;            }            mode = 0644;        }        memset(&b, 0, sizeof(b));        tar_posix_header& h = b.header;        // fill the header        if (!fit_name(h, i->c_str())) {            unprocessed_files.push_back(*i);            continue;        }        notify->SetMessage((prefix + *i).c_str());        int_to_oct_nonull(h.mode,  mode, 8);        int_to_oct_nonull(h.uid,   0,    8);        int_to_oct_nonull(h.gid,   0,    8);        int_to_oct_nonull(h.size,  size, 12);        int_to_oct_nonull(h.mtime, 0,    12);        memset(h.chksum, ' ', 8);  // prefill checksum        h.typeflag = (is_dir ? '5' : '0');        strcpy(h.linkname, "");        strcpy(h.magic, "ustar");        memset(h.version, '0', 2);        strcpy(h.uname, "user");        strcpy(h.gname, "group");        // calculate checksum        unsigned chksum = 0;        for (int j = 0; j < TAR_BLOCK_SIZE; j++) {            chksum += b.buffer[j];        }        int_to_oct_nonull(h.chksum, chksum, 8);                    out->Write(&b, TAR_BLOCK_SIZE);        if (!is_dir) {            // write the file contents            const int num_blocks = (size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;            int bytes_left = size;            while (bytes_left > 0) {                int to_write = min(bytes_left, TAR_BLOCK_SIZE);                memset(&b, 0, TAR_BLOCK_SIZE);                fread(&b, 1, to_write, file);                out->Write(&b, TAR_BLOCK_SIZE);                bytes_left -= to_write;                // update progress bar                notify->SetProgress((size - bytes_left) * 255 / size);                // should we cancel?                if (notify->ShouldCancel()) {                    cancelled = true;                    break;                }            }            fclose(file);        }    }    // if the user cancelled, try to remove the file    delete out.release();    if (cancelled) {        remove(archive_name.c_str());    }    return true;}