void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	int dst_fd;
	int res;

	if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
		char *slash = strrchr(file_header->name, '/');
		if (slash) {
			*slash = '\0';
			bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
			*slash = '/';
		}
	}

	if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
		/* Remove the entry if it exists */
		if ((!S_ISDIR(file_header->mode))
		 && (unlink(file_header->name) == -1)
		 && (errno != ENOENT)
		) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}
	else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
		/* Remove the existing entry if its older than the extracted entry */
		struct stat existing_sb;
		if (lstat(file_header->name, &existing_sb) == -1) {
			if (errno != ENOENT) {
				bb_perror_msg_and_die("can't stat old file");
			}
		}
		else if (existing_sb.st_mtime >= file_header->mtime) {
			if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
				bb_error_msg("%s not created: newer or "
					"same age file exists", file_header->name);
			}
			data_skip(archive_handle);
			return;
		}
		else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}

	/* Handle hard links separately
	 * We identified hard links as regular files of size 0 with a symlink */
	if (S_ISREG(file_header->mode)
	 && file_header->link_target
	 && file_header->size == 0
	) {
		/* hard link */
		res = link(file_header->link_target, file_header->name);
		if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
			bb_perror_msg("can't create %slink "
					"from %s to %s", "hard",
					file_header->name,
					file_header->link_target);
		}
	} else {
		/* Create the filesystem entry */
		switch (file_header->mode & S_IFMT) {
		case S_IFREG: {
			/* Regular file */
			int flags = O_WRONLY | O_CREAT | O_EXCL;
			if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
				flags = O_WRONLY | O_CREAT | O_TRUNC;
			dst_fd = xopen3(file_header->name,
				flags,
				file_header->mode
				);
			bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
			close(dst_fd);
			break;
		}
		case S_IFDIR:
			res = mkdir(file_header->name, file_header->mode);
			if ((res == -1)
			 && (errno != EISDIR) /* btw, Linux doesn't return this */
			 && (errno != EEXIST)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't make dir %s", file_header->name);
			}
			break;
		case S_IFLNK:
			/* Symlink */
			res = symlink(file_header->link_target, file_header->name);
			if ((res == -1)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't create %slink "
					"from %s to %s", "sym",
					file_header->name,
					file_header->link_target);
			}
			break;
		case S_IFSOCK:
		case S_IFBLK:
		case S_IFCHR:
		case S_IFIFO:
			res = mknod(file_header->name, file_header->mode, file_header->device);
			if ((res == -1)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't create node %s", file_header->name);
			}
			break;
		default:
			bb_error_msg_and_die("unrecognized file type");
		}
	}

	if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
#if ENABLE_FEATURE_TAR_UNAME_GNAME
		if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
			uid_t uid = file_header->uid;
			gid_t gid = file_header->gid;

			if (file_header->tar__uname) {
//TODO: cache last name/id pair?
				struct passwd *pwd = getpwnam(file_header->tar__uname);
				if (pwd) uid = pwd->pw_uid;
			}
			if (file_header->tar__gname) {
				struct group *grp = getgrnam(file_header->tar__gname);
				if (grp) gid = grp->gr_gid;
			}
			/* GNU tar 1.15.1 uses chown, not lchown */
			chown(file_header->name, uid, gid);
		} else
#endif
			chown(file_header->name, file_header->uid, file_header->gid);
	}
	if (!S_ISLNK(file_header->mode)) {
		/* uclibc has no lchmod, glibc is even stranger -
		 * it has lchmod which seems to do nothing!
		 * so we use chmod... */
		if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
			chmod(file_header->name, file_header->mode);
		}
		/* same for utime */
		if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
			struct timeval t[2];

			t[1].tv_sec = t[0].tv_sec = file_header->mtime;
			t[1].tv_usec = t[0].tv_usec = 0;
			utimes(file_header->name, t);
		}
	}
}
Exemple #2
0
HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
{
	char* p;
	int index;
	int length;
	struct stat fileStat;
	WIN32_FILE_SEARCH* pFileSearch;
	ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
	pFileSearch = (WIN32_FILE_SEARCH*) calloc(1, sizeof(WIN32_FILE_SEARCH));
	if (!pFileSearch)
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return INVALID_HANDLE_VALUE;
	}
	/* Separate lpFileName into path and pattern components */
	p = strrchr(lpFileName, '/');

	if (!p)
		p = strrchr(lpFileName, '\\');

	index = (p - lpFileName);
	length = (p - lpFileName);
	pFileSearch->lpPath = (LPSTR) malloc(length + 1);
	if (!pFileSearch->lpPath)
	{
		free(pFileSearch);
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return INVALID_HANDLE_VALUE;
	}
	CopyMemory(pFileSearch->lpPath, lpFileName, length);
	pFileSearch->lpPath[length] = '\0';
	length = strlen(lpFileName) - index;
	pFileSearch->lpPattern = (LPSTR) malloc(length + 1);
	if (!pFileSearch->lpPattern)
	{
		free(pFileSearch->lpPath);
		free(pFileSearch);
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return INVALID_HANDLE_VALUE;
	}
	CopyMemory(pFileSearch->lpPattern, &lpFileName[index + 1], length);
	pFileSearch->lpPattern[length] = '\0';

	/* Check if the path is a directory */

	if (lstat(pFileSearch->lpPath, &fileStat) < 0)
	{
		FindClose(pFileSearch);
		return INVALID_HANDLE_VALUE; /* stat error */
	}

	if (S_ISDIR(fileStat.st_mode) == 0)
	{
		FindClose(pFileSearch);
		return INVALID_HANDLE_VALUE; /* not a directory */
	}

	/* Open directory for reading */
	pFileSearch->pDir = opendir(pFileSearch->lpPath);

	if (!pFileSearch->pDir)
	{
		FindClose(pFileSearch);
		return INVALID_HANDLE_VALUE; /* failed to open directory */
	}

	while ((pFileSearch->pDirent = readdir(pFileSearch->pDir)) != NULL)
	{
		if ((strcmp(pFileSearch->pDirent->d_name, ".") == 0) || (strcmp(pFileSearch->pDirent->d_name, "..") == 0))
		{
			/* skip "." and ".." */
			continue;
		}

		if (FilePatternMatchA(pFileSearch->pDirent->d_name, pFileSearch->lpPattern))
		{
			strcpy(lpFindFileData->cFileName, pFileSearch->pDirent->d_name);
			return (HANDLE) pFileSearch;
		}
	}

	FindClose(pFileSearch);
	return INVALID_HANDLE_VALUE;
}
Exemple #3
0
void RemoveFile(char *File)
{
    struct stat FileStats;
    int Status;

    /* Get the file's information */
    if(lstat(File, &FileStats) == -1)
    {    
        perror("Error:\n\t");
        return;
    }

    /* If the file is a regular file, then delete it */
    if(S_ISREG(FileStats.st_mode))
    {
        /* Attempt to delete the file, and print a message
         * telling whether deletion was successful */
        if(unlink(File) == -1)
        {    
            perror("Error:\n\t");
            return;
        }
        else 
        {    
            fprintf(stdout, "File %s removed\n", File);
        }
    }
    /* If the file is a directory, loop over its contents and
     * pass each one to the FileRemove function */
    else if(S_ISDIR(FileStats.st_mode))
    {    
        DIR *Directory;
        struct dirent *Entry;

        /* Attempt to open the directory */
        if((Directory = opendir(File)) == NULL)
        {    
            perror("Error:\n\t");
            return;
        }
        else
        {
            char FullDirPath[PATH_MAX];
            char FullFilePath[PATH_MAX];

            /* Get the full path of the directory */
            if(realpath(File, FullDirPath) == NULL)
            {
                perror("Error:\n\t");
                return;
            }

            /* Loop over the directory contents */
            while((Entry = readdir(Directory)) != NULL)
            {
                /* Don't try to remove . or .. from the directory */
                if(strcmp(Entry->d_name, ".") != 0 && \
                   strcmp(Entry->d_name, "..") != 0)
                {
                    /* Get the full file path of the entry and remove
                     * it */
                    memset(FullFilePath, 0, PATH_MAX);
                    strcat(FullFilePath, FullDirPath);
                    strcat(FullFilePath, "/");
                    strcat(FullFilePath, Entry->d_name);
                    RemoveFile(FullFilePath);
                }
            }

            /* Close the directory */
            if(closedir(Directory) == -1)
            {
                perror("Error:\n\t");
                return;
            }

            /* Remove the directory itself */
            if(rmdir(File) == -1)
            {
                perror("Error\n\t");
                return;
            }

            fprintf(stdout, "Directory %s removed\n", File);
        }
    }
    /* If the file is a symbolic link, then delete it */
    else if(S_ISLNK(FileStats.st_mode))
    {
        /* Attempt to delete the symbolic link, and print a message
         * telling whether deletion was successful */
        if(unlink(File) == -1)
        {
            perror("Error:\n\t");
            return;
        }
        else
        {
            fprintf(stdout, "Symbolic link %s removed\n", File);
        }
    }
    /* If the file is not a directory, regular file, or symbolic
     * link, print an error message */
    else
    {
        fprintf(stderr, "Error: %s is not a directory or regular"
                        " file\n", File);
    }

    return;
}
bool CExtUpdate::readBackupList(const std::string & dstPath)
{
	char buf[PATH_MAX];
	static struct stat FileInfo;
	vector<std::string>::iterator it;
	
	f1 = fopen(backupList.c_str(), "r");
	if (f1 == NULL) {
		f1 = fopen(backupList.c_str(), "w");
		if (f1 != NULL) {
			char tmp1[1024];
			snprintf(tmp1, sizeof(tmp1), "Log=%d\nLogFile=%s\n\n%s\n\n", fLogEnabled, fLogfile.c_str(), defaultBackup.c_str());
			fwrite(tmp1, 1, strlen(tmp1), f1);
			fclose(f1);
		}
		else
			return ErrorReset(0, "cannot create missing backuplist file: " + backupList);
	}

	f1 = fopen(backupList.c_str(), "r");
	if (f1 == NULL)
		return ErrorReset(0, "cannot read backuplist file: " + backupList);
	fpos_t fz;
	fseek(f1, 0, SEEK_END);
	fgetpos(f1, &fz);
	fseek(f1, 0, SEEK_SET);
	if (fz.__pos == 0)
		return ErrorReset(CLOSE_F1, "backuplist filesize is 0");
	size_t pos;
	std::string line;

	// read blacklist and config vars
	copyList.clear();
	blackList.clear();
	deleteList.clear();
	while(fgets(buf, sizeof(buf), f1) != NULL) {
		std::string tmpLine;
		line = buf;
		line = trim(line);
		// ignore comments
		if (line.find_first_of("#") == 0) {
			// config vars
			if (line.find_first_of(":") == 1) {
				if (line.length() > 1)
					readConfig(line);
			}
			continue;
		}
		pos = line.find_first_of("#");
		if (pos != std::string::npos) {
			line = line.substr(0, pos);
			line = trim(line);
		}
		// find blackList entry
		if (line.find_first_of("-") == 0) {
			tmpLine = line.substr(1);
			if ((tmpLine.length() > 1) && (lstat(tmpLine.c_str(), &FileInfo) != -1)) {
				if (S_ISREG(FileInfo.st_mode))
					blackList.push_back(tmpLine);
			}
		}
		// find deleteList entry
		else if (line.find_first_of("~") == 0) {
			tmpLine = line.substr(1);
			if (checkSpecialFolders(tmpLine, false))
				continue;
			tmpLine = dstPath + tmpLine;
			if (line.length() > 2)
				deleteList.push_back(tmpLine);
		}
		// find copyList entry
		else {
			tmpLine = (line.find_first_of("+") == 0) ? line.substr(1) : line; // '+' add entry = default
			if (checkSpecialFolders(tmpLine, true))
				continue;
			if (tmpLine.length() > 1)
				copyList.push_back(tmpLine);
		}
	}
	fclose(f1);

	// read DeleteList
	for(it = deleteList.begin(); it != deleteList.end(); ++it) {
		line = *it;
		if ((line.find("*") != std::string::npos) || (line.find("?") != std::string::npos)) {
			// Wildcards
			WRITE_UPDATE_LOG("delete file list: %s\n", line.c_str());
			deleteFileList(line.c_str());
		}
		else if (lstat(line.c_str(), &FileInfo) != -1) {
			if (S_ISREG(FileInfo.st_mode)) {
				// File
				WRITE_UPDATE_LOG("delete file: %s\n", line.c_str());
				unlink(line.c_str());
			}
			else if (S_ISDIR(FileInfo.st_mode)){
				// Directory
				WRITE_UPDATE_LOG("delete directory: %s\n", line.c_str());
				FileHelpers->removeDir(line.c_str());
			}
		}
	}
	sync();

	if (get_fs_usage(mountPkt.c_str(), total, used, &bsize))
		free2 = (total * bsize) / 1024 - (used * bsize) / 1024;

	// read copyList
	for(it = copyList.begin(); it != copyList.end(); ++it) {
		line = *it;
		line = trim(line);
		// remove '/' from line end
		size_t len = line.length();
		pos = line.find_last_of("/");
		if (len == pos+1)
			line = line.substr(0, pos);
		std::string dst = dstPath + line;
		if ((line.find("*") != std::string::npos) || (line.find("?") != std::string::npos)) {
			// Wildcards
			DBG_MSG("Wildcards: %s\n", dst.c_str());
			WRITE_UPDATE_LOG("\n");
			WRITE_UPDATE_LOG("--------------------\n");
			WRITE_UPDATE_LOG("Wildcards: %s\n", dst.c_str());
			copyFileList(line, dstPath);
		}
		else {
			if (lstat(line.c_str(), &FileInfo) != -1) {
				if (S_ISREG(FileInfo.st_mode)) {
					// one file only
					pos = dst.find_last_of("/");
					std::string dir = dst.substr(0, pos);
					FileHelpers->createDir(dir.c_str(), 0755);
					DBG_MSG("file: %s => %s\n", line.c_str(), dst.c_str());
					WRITE_UPDATE_LOG("\n");
					WRITE_UPDATE_LOG("file: %s => %s\n", line.c_str(), dst.c_str());
					WRITE_UPDATE_LOG("--------------------\n");
					std::string save = (isBlacklistEntry(line)) ? ".save" : "";
					if (!FileHelpers->copyFile(line.c_str(), (dst + save).c_str(), FileInfo.st_mode & 0x0FFF))
						return ErrorReset(0, "copyFile error");
				}
				else if (S_ISDIR(FileInfo.st_mode)) {
					// directory
					DBG_MSG("directory: %s => %s\n", line.c_str(), dst.c_str());
					WRITE_UPDATE_LOG("\n");
					WRITE_UPDATE_LOG("directory: %s => %s\n", line.c_str(), dst.c_str());
					WRITE_UPDATE_LOG("--------------------\n");
					FileHelpers->copyDir(line.c_str(), dst.c_str(), true);
				}
			}
		
		}
	}
	sync();

	if (get_fs_usage(mountPkt.c_str(), total, used, &bsize)) {
		uint64_t flashWarning = 1000; // 1MB
		uint64_t flashError   = 600;  // 600KB
		char buf1[1024];
		total = (total * bsize) / 1024;
		free3 = total - (used * bsize) / 1024;
		printf("##### [%s] %llu KB free org, %llu KB free after delete, %llu KB free now\n", __FUNCTION__, free1, free2, free3);
		memset(buf1, '\0', sizeof(buf1));
		if (free3 <= flashError) {
			snprintf(buf1, sizeof(buf1)-1, g_Locale->getText(LOCALE_FLASHUPDATE_UPDATE_WITH_SETTINGS_ERROR), free3, total);
			ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, buf1, CMessageBox::mbrOk, CMessageBox::mbOk, NEUTRINO_ICON_ERROR);
			flashErrorFlag = true;
			return false;
		}
		else if (free3 <= flashWarning) {
			snprintf(buf1, sizeof(buf1)-1, g_Locale->getText(LOCALE_FLASHUPDATE_UPDATE_WITH_SETTINGS_WARNING), free3, total);
		    	if (ShowMsgUTF(LOCALE_MESSAGEBOX_INFO, buf1, CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo, NEUTRINO_ICON_INFO) != CMessageBox::mbrYes) {
				flashErrorFlag = true;
				return false;
		    	}
		}
	}
	return true;
}
static u32 build_default_directory_structure()
{
	u32 inode;
	u32 root_inode;
	struct dentry dentries = {
			.filename = "lost+found",
			.file_type = EXT4_FT_DIR,
			.mode = S_IRWXU,
			.uid = 0,
			.gid = 0,
			.mtime = 0,
	};
	root_inode = make_directory(0, 1, &dentries, 1);
	inode = make_directory(root_inode, 0, NULL, 0);
	*dentries.inode = inode;
	inode_set_permissions(inode, dentries.mode,
		dentries.uid, dentries.gid, dentries.mtime);

	return root_inode;
}

#ifndef USE_MINGW
/* Read a local directory and create the same tree in the generated filesystem.
   Calls itself recursively with each directory in the given directory.
   full_path is an absolute or relative path, with a trailing slash, to the
   directory on disk that should be copied, or NULL if this is a directory
   that does not exist on disk (e.g. lost+found).
   dir_path is an absolute path, with trailing slash, to the same directory
   if the image were mounted at the specified mount point */
static u32 build_directory_structure(const char *full_path, const char *dir_path,
		u32 dir_inode, fs_config_func_t fs_config_func,
		struct selabel_handle *sehnd, int verbose)
{
	int entries = 0;
	struct dentry *dentries;
	struct dirent **namelist = NULL;
	struct stat stat;
	int ret;
	int i;
	u32 inode;
	u32 entry_inode;
	u32 dirs = 0;
	bool needs_lost_and_found = false;

	if (full_path) {
		entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
		if (entries < 0) {
			error_errno("scandir");
			return EXT4_ALLOCATE_FAILED;
		}
	}

	if (dir_inode == 0) {
		/* root directory, check if lost+found already exists */
		for (i = 0; i < entries; i++)
			if (strcmp(namelist[i]->d_name, "lost+found") == 0)
				break;
		if (i == entries)
			needs_lost_and_found = true;
	}

	dentries = calloc(entries, sizeof(struct dentry));
	if (dentries == NULL)
		critical_error_errno("malloc");

	for (i = 0; i < entries; i++) {
		dentries[i].filename = strdup(namelist[i]->d_name);
		if (dentries[i].filename == NULL)
			critical_error_errno("strdup");

		asprintf(&dentries[i].path, "%s%s", dir_path, namelist[i]->d_name);
		asprintf(&dentries[i].full_path, "%s%s", full_path, namelist[i]->d_name);

		free(namelist[i]);

		ret = lstat(dentries[i].full_path, &stat);
		if (ret < 0) {
			error_errno("lstat");
			i--;
			entries--;
			continue;
		}

		dentries[i].size = stat.st_size;
		dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
		dentries[i].mtime = stat.st_mtime;
		uint64_t capabilities;
		if (fs_config_func != NULL) {
#ifdef ANDROID
			unsigned int mode = 0;
			unsigned int uid = 0;
			unsigned int gid = 0;
			int dir = S_ISDIR(stat.st_mode);
			fs_config_func(dentries[i].path, dir, &uid, &gid, &mode, &capabilities);
			dentries[i].mode = mode;
			dentries[i].uid = uid;
			dentries[i].gid = gid;
			dentries[i].capabilities = capabilities;
#else
			error("can't set android permissions - built without android support");
#endif
		}
#ifndef USE_MINGW
		if (sehnd) {
			if (selabel_lookup(sehnd, &dentries[i].secon, dentries[i].path, stat.st_mode) < 0) {
				error("cannot lookup security context for %s", dentries[i].path);
			}

			if (dentries[i].secon && verbose)
				printf("Labeling %s as %s\n", dentries[i].path, dentries[i].secon);
		}
#endif

		if (S_ISREG(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_REG_FILE;
		} else if (S_ISDIR(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_DIR;
			dirs++;
		} else if (S_ISCHR(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_CHRDEV;
		} else if (S_ISBLK(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_BLKDEV;
		} else if (S_ISFIFO(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_FIFO;
		} else if (S_ISSOCK(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_SOCK;
		} else if (S_ISLNK(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_SYMLINK;
			dentries[i].link = calloc(info.block_size, 1);
			readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1);
		} else {
			error("unknown file type on %s", dentries[i].path);
			i--;
			entries--;
		}
	}
	free(namelist);

	if (needs_lost_and_found) {
		/* insert a lost+found directory at the beginning of the dentries */
		struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry));
		memset(tmp, 0, sizeof(struct dentry));
		memcpy(tmp + 1, dentries, entries * sizeof(struct dentry));
		dentries = tmp;

		dentries[0].filename = strdup("lost+found");
		asprintf(&dentries[0].path, "%slost+found", dir_path);
		dentries[0].full_path = NULL;
		dentries[0].size = 0;
		dentries[0].mode = S_IRWXU;
		dentries[0].file_type = EXT4_FT_DIR;
		dentries[0].uid = 0;
		dentries[0].gid = 0;
		if (sehnd) {
			if (selabel_lookup(sehnd, &dentries[0].secon, dentries[0].path, dentries[0].mode) < 0)
				error("cannot lookup security context for %s", dentries[0].path);
		}
		entries++;
		dirs++;
	}

	inode = make_directory(dir_inode, entries, dentries, dirs);

	for (i = 0; i < entries; i++) {
		if (dentries[i].file_type == EXT4_FT_REG_FILE) {
			entry_inode = make_file(dentries[i].full_path, dentries[i].size);
		} else if (dentries[i].file_type == EXT4_FT_DIR) {
			char *subdir_full_path = NULL;
			char *subdir_dir_path;
			if (dentries[i].full_path) {
				ret = asprintf(&subdir_full_path, "%s/", dentries[i].full_path);
				if (ret < 0)
					critical_error_errno("asprintf");
			}
			ret = asprintf(&subdir_dir_path, "%s/", dentries[i].path);
			if (ret < 0)
				critical_error_errno("asprintf");
			entry_inode = build_directory_structure(subdir_full_path,
					subdir_dir_path, inode, fs_config_func, sehnd, verbose);
			free(subdir_full_path);
			free(subdir_dir_path);
		} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
			entry_inode = make_link(dentries[i].link);
		} else {
			error("unknown file type on %s", dentries[i].path);
			entry_inode = 0;
		}
		*dentries[i].inode = entry_inode;

		ret = inode_set_permissions(entry_inode, dentries[i].mode,
			dentries[i].uid, dentries[i].gid,
			dentries[i].mtime);
		if (ret)
			error("failed to set permissions on %s\n", dentries[i].path);

		/*
		 * It's important to call inode_set_selinux() before
		 * inode_set_capabilities(). Extended attributes need to
		 * be stored sorted order, and we guarantee this by making
		 * the calls in the proper order.
		 * Please see xattr_assert_sane() in contents.c
		 */
		ret = inode_set_selinux(entry_inode, dentries[i].secon);
		if (ret)
			error("failed to set SELinux context on %s\n", dentries[i].path);
		ret = inode_set_capabilities(entry_inode, dentries[i].capabilities);
		if (ret)
			error("failed to set capability on %s\n", dentries[i].path);

		free(dentries[i].path);
		free(dentries[i].full_path);
		free(dentries[i].link);
		free((void *)dentries[i].filename);
		free(dentries[i].secon);
	}

	free(dentries);
	return inode;
}
Exemple #6
0
/*
 * Download fullfiles from the list of files.
 *
 * Return 0 on success or a negative number or errors.
 */
int download_fullfiles(struct list *files, int *num_downloads)
{
	struct swupd_curl_parallel_handle *download_handle;
	struct list *iter;
	struct list *need_download = NULL;
	struct file *file;
	struct stat stat;
	struct download_progress download_progress = { 0, 0, 0 };
	unsigned int complete = 0;
	unsigned int list_length;
	const unsigned int MAX_FILES = 1000;

	if (!files) {
		/* nothing needs to be downloaded */
		return SWUPD_OK;
	}

	/* make a new list with only the files we actually need to download */
	for (iter = list_head(files); iter; iter = iter->next) {
		char *targetfile;
		file = iter->data;

		if (file->is_deleted || file->do_not_update) {
			continue;
		}

		string_or_die(&targetfile, "%s/staged/%s", state_dir, file->hash);
		if (lstat(targetfile, &stat) != 0 || !verify_file(file, targetfile)) {
			need_download = list_append_data(need_download, file);
		}

		free_string(&targetfile);
	}

	if (!need_download) {
		/* no file needs to be downloaded */
		info("No extra files need to be downloaded\n");
		progress_complete_step();
		return 0;
	}

	/* we need to download some files, so set up curl */
	download_handle = swupd_curl_parallel_download_start(get_max_xfer(MAX_XFER));
	swupd_curl_parallel_download_set_callbacks(download_handle, download_successful, download_error, NULL);
	if (!download_handle) {
		/* If we hit this point, the network is accessible but we were
		 * unable to download the needed files. This is a terminal error
		 * and we need good logging */
		return -SWUPD_COULDNT_DOWNLOAD_FILE;
	}

	/* getting the size of many files can be very expensive, so if
	 * the files are not too many, get their size, otherwise just use their count
	 * to report progress */
	list_length = list_len(need_download);
	if (list_length < MAX_FILES) {
		download_progress.total_download_size = fullfile_query_total_download_size(need_download);
		if (download_progress.total_download_size > 0) {
			/* enable the progress callback */
			swupd_curl_parallel_download_set_progress_callbacks(download_handle, swupd_progress_callback, &download_progress);
		} else {
			debug("Couldn't get the size of the files to download, using number of files instead\n");
			download_progress.total_download_size = 0;
		}
	} else {
		debug("Too many files to calculate download size (%d files), maximum is %d. Using number of files instead\n", list_length, MAX_FILES);
	}

	/* download loop */
	info("Starting download of remaining update content. This may take a while...\n");

	for (iter = list_head(need_download); iter; iter = iter->next) {
		file = iter->data;

		if (file->is_mix) {
			download_mix_file(file);
		} else {
			download_file(download_handle, file);
		}

		/* fall back for progress reporting when the download size
		* could not be determined */
		if (download_progress.total_download_size == 0) {
			complete++;
			progress_report(complete, list_length);
		}
	}
	info("\n");
	list_free_list(need_download);

	return swupd_curl_parallel_download_end(download_handle, num_downloads);
}
Exemple #7
0
static int dev_create(char *root, dev_res *dev)
{
	char buf1[STR_SIZE];
	char buf2[STR_SIZE];
	struct stat st, st2;
	int ret;
	const char* udev_paths[] = {
		"/lib/udev/devices",
		"/etc/udev/devices",
		NULL};
	int i;

	if (!dev->name[0])
		return 0;
	if (check_var(root, "VE_ROOT is not set"))
		return VZ_VE_ROOT_NOTSET;
	/* If device does not exist inside CT get
	* information from CT0 and create it
	*/
	snprintf(buf1, sizeof(buf1), "%s/dev/%s", root, dev->name);
	ret = lstat(buf1, &st);
	if (ret && errno != ENOENT) {
		logger(-1, errno, "Unable to stat device %s", buf1);
		return VZ_SET_DEVICES;
	} else if (!ret)
		return 0;
	snprintf(buf2, sizeof(buf2), "/dev/%s", dev->name);
	if (stat(buf2, &st)) {
		if (errno == ENOENT)
			logger(-1, 0, "Incorrect name or no such device %s",
				buf2);
		else
			logger(-1, errno, "Unable to stat device %s", buf2);
		return VZ_SET_DEVICES;
	}
	if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
		logger(-1, 0, "The %s is not block or character device", buf2);
		return VZ_SET_DEVICES;
	}
	if (make_dir(buf1, 0))
		return VZ_SET_DEVICES;
	if (mknod(buf1, st.st_mode, st.st_rdev)) {
		logger(-1, errno, "Unable to create device %s", buf1);
		return VZ_SET_DEVICES;
	}
	/* Try to create static device node for udev */
	for (i = 0; udev_paths[i] != NULL; i++) {
		if (stat(udev_paths[i], &st2) == 0) {
			if (S_ISDIR(st2.st_mode)) {
				snprintf(buf1, sizeof(buf1),
						"%s/%s/%s",
						root, udev_paths[i],
						dev->name);
				make_dir(buf1, 0);
				mknod(buf1, st.st_mode, st.st_rdev);
				break;
			}
		}
	}
	return 0;
}
Exemple #8
0
int
main (void)
{
  /* Remove any leftovers from a previous partial run.  */
  ignore_value (system ("rm -rf " BASE "*"));

  /* Setup.  */
  ASSERT (mkdir (BASE "dir", 0700) == 0);
  ASSERT (close (creat (BASE "dir/file", 0600)) == 0);

  /* Basic error conditions.  */
  errno = 0;
  ASSERT (remove ("") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (remove ("nosuch") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (remove ("nosuch/") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (remove (".") == -1);
  ASSERT (errno == EINVAL || errno == EBUSY);
  /* Resulting errno after ".." or "/" is too varied to test; it is
     reasonable to see any of EINVAL, EEXIST, ENOTEMPTY, EACCES.  */
  ASSERT (remove ("..") == -1);
  ASSERT (remove ("/") == -1);
  ASSERT (remove ("///") == -1);
  errno = 0;
  ASSERT (remove (BASE "dir/file/") == -1);
  ASSERT (errno == ENOTDIR);

  /* Non-empty directory.  */
  errno = 0;
  ASSERT (remove (BASE "dir") == -1);
  ASSERT (errno == EEXIST || errno == ENOTEMPTY);

  /* Non-directory.  */
  ASSERT (remove (BASE "dir/file") == 0);

  /* Empty directory.  */
  errno = 0;
  ASSERT (remove (BASE "dir/.//") == -1);
  ASSERT (errno == EINVAL || errno == EBUSY);
  ASSERT (remove (BASE "dir") == 0);

  /* Test symlink behavior.  Specifying trailing slash should remove
     referent directory, or cause ENOTDIR failure, but not touch
     symlink.  */
  if (symlink (BASE "dir", BASE "link") != 0)
    {
      fputs ("skipping test: symlinks not supported on this file system\n",
             stderr);
      return 77;
    }
  ASSERT (mkdir (BASE "dir", 0700) == 0);
  errno = 0;
  if (remove (BASE "link/") == 0)
    {
      struct stat st;
      errno = 0;
      ASSERT (stat (BASE "link", &st) == -1);
      ASSERT (errno == ENOENT);
    }
  else
    ASSERT (remove (BASE "dir") == 0);
  {
    struct stat st;
    ASSERT (lstat (BASE "link", &st) == 0);
    ASSERT (S_ISLNK (st.st_mode));
  }
  ASSERT (remove (BASE "link") == 0);
  /* Trailing slash on symlink to non-directory is an error.  */
  ASSERT (symlink (BASE "loop", BASE "loop") == 0);
  errno = 0;
  ASSERT (remove (BASE "loop/") == -1);
  ASSERT (errno == ELOOP || errno == ENOTDIR);
  ASSERT (remove (BASE "loop") == 0);
  ASSERT (close (creat (BASE "file", 0600)) == 0);
  ASSERT (symlink (BASE "file", BASE "link") == 0);
  errno = 0;
  ASSERT (remove (BASE "link/") == -1);
  ASSERT (errno == ENOTDIR);
  ASSERT (remove (BASE "link") == 0);
  ASSERT (remove (BASE "file") == 0);

  return 0;
}
Exemple #9
0
int vzctl2_get_free_envid(unsigned *neweid, const char *dst,
		const char *unused)
{
	int i;
	struct vzctl_conf_simple conf;
	char file[STR_SIZE];
	char lckfile[STR_SIZE];
	char dstlck[PATH_MAX];
	struct stat st;
	int check_ve_private = 0;
	int check_ve_root = 0;
	int check_dst = 0;
	int fail_cnt = 0;
	int fd;
	ctid_t ctid = {};

	vzctl_parse_conf_simple(ctid, GLOBAL_CFG, &conf);

	if (conf.ve_private_orig != NULL && strstr(conf.ve_private_orig, "$VEID"))
		check_ve_private = 1;
	if (conf.ve_root_orig != NULL && strstr(conf.ve_root_orig, "$VEID"))
		check_ve_root = 1;
	if (dst != NULL && strstr(dst, "$VEID")) {
		snprintf(dstlck, sizeof(dstlck), "%s.lck", dst);
		check_dst = 1;
	}

	*neweid = 0;
	for (i = START_ID; i < INT_MAX/2 && fail_cnt < GET_FREE_ENVID_FAIL_MAX; i++) {
		ctid_t ctid = {i, };
		/* Check for VEID.conf */
		vzctl2_get_env_conf_path(ctid, file, sizeof(file));
		if (lstat(file, &st)) {
			if (errno != ENOENT) {
				logger(-1, errno, "Failed to stat %s", file);
				fail_cnt++;
				continue;
			}
		} else
			continue;
		/* lock envid */
		snprintf(lckfile, sizeof(lckfile), "%s.lck", file);
		fd = open(lckfile, O_CREAT|O_EXCL, 0644);
		if (fd == -1) {
			if (errno != EEXIST) {
				fail_cnt++;
				logger(-1, errno, "Failed to create %s", lckfile);
			}
			continue;
		}
		close(fd);

		/* check if PATH(s) exist */
		if ((check_ve_private && !is_dst_free(conf.ve_private_orig, ctid, &fail_cnt)) ||
		    (check_ve_root && !is_dst_free(conf.ve_root_orig, ctid, &fail_cnt)) ||
		    (check_dst &&
			(!is_dst_free(dst, ctid, &fail_cnt) || !is_dst_free(dstlck, ctid, &fail_cnt))))
		{
			/* unlock envid */
			unlink(lckfile);
			continue;
		}
		*neweid = i;
		break;
	}
	vzctl_free_conf_simple(&conf);

	if (*neweid == 0)
		return vzctl_err(-1, 0,  "Failed to get unused Countainer id");

	return 0;
}
Exemple #10
0
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	struct group *gptr;
	const char *arg, *cp, *printer;
	char *p;
	char buf[BUFSIZ];
	int c, i, f, errs;
	int	 ret, didlink;
	struct stat stb;
	struct stat statb1, statb2;
	struct printer myprinter, *pp = &myprinter;

	printer = NULL;
	euid = geteuid();
	uid = getuid();
	PRIV_END
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, cleanup);
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
		signal(SIGQUIT, cleanup);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, cleanup);

	progname = argv[0];
	gethostname(local_host, sizeof(local_host));
	openlog("lpd", 0, LOG_LPR);

	errs = 0;
	while ((c = getopt(argc, argv,
			   ":#:1:2:3:4:C:J:L:P:T:U:Z:cdfghi:lnmprstvw:"))
	       != -1)
		switch (c) {
		case '#':		/* n copies */
			i = strtol(optarg, &p, 10);
			if (*p)
				errx(1, "Bad argument to -#, number expected");
			if (i > 0)
				ncopies = i;
			break;

		case '1':		/* troff fonts */
		case '2':
		case '3':
		case '4':
			fonts[optopt - '1'] = optarg;
			break;

		case 'C':		/* classification spec */
			hdr++;
			class = optarg;
			break;

		case 'J':		/* job name */
			hdr++;
			jobname = optarg;
			break;

		case 'P':		/* specifiy printer name */
			printer = optarg;
			break;

		case 'L':               /* pr's locale */
			locale = optarg;
			break;

		case 'T':		/* pr's title line */
			title = optarg;
			break;

		case 'U':		/* user name */
			hdr++;
			Uflag = optarg;
			break;

		case 'Z':
			Zflag = optarg;
			break;

		case 'c':		/* print cifplot output */
		case 'd':		/* print tex output (dvi files) */
		case 'g':		/* print graph(1G) output */
		case 'l':		/* literal output */
		case 'n':		/* print ditroff output */
		case 't':		/* print troff output (cat files) */
		case 'p':		/* print using ``pr'' */
		case 'v':		/* print vplot output */
			format = optopt;
			break;

		case 'f':		/* print fortran output */
			format = 'r';
			break;

		case 'h':		/* nulifiy header page */
			hdr = 0;
			break;

		case 'i':		/* indent output */
			iflag++;
			indent = strtol(optarg, &p, 10);
			if (*p)
				errx(1, "Bad argument to -i, number expected");
			break;

		case 'm':		/* send mail when done */
			mailflg++;
			break;

		case 'q':		/* just queue job */
			qflag++;
			break;

		case 'r':		/* remove file when done */
			rflag++;
			break;

		case 's':		/* try to link files */
			sflag++;
			break;

		case 'w':		/* versatec page width */
			width = optarg;
			break;

		case ':':		/* catch "missing argument" error */
			if (optopt == 'i') {
				iflag++; /* -i without args is valid */
				indent = 8;
			} else
				errs++;
			break;

		default:
			errs++;
		}
	argc -= optind;
	argv += optind;
	if (errs)
		usage();
	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;
	chkprinter(printer, pp);
	if (pp->no_copies && ncopies > 1)
		errx(1, "multiple copies are not allowed");
	if (pp->max_copies > 0 && ncopies > pp->max_copies)
		errx(1, "only %ld copies are allowed", pp->max_copies);
	/*
	 * Get the identity of the person doing the lpr using the same
	 * algorithm as lprm.  Actually, not quite -- lprm will override
	 * the login name with "root" if the user is running as root;
	 * the daemon actually checks for the string "root" in its
	 * permission checking.  Sigh.
	 */
	userid = getuid();
	if (Uflag) {
		if (userid != 0 && userid != pp->daemon_user)
			errx(1, "only privileged users may use the `-U' flag");
		lpr_username = Uflag;		/* -U person doing 'lpr' */
	} else {
		lpr_username = getlogin();	/* person doing 'lpr' */
		if (userid != pp->daemon_user || lpr_username == 0) {
			if ((pw = getpwuid(userid)) == NULL)
				errx(1, "Who are you?");
			lpr_username = pw->pw_name;
		}
	}

	/*
	 * Check for restricted group access.
	 */
	if (pp->restrict_grp != NULL && userid != pp->daemon_user) {
		if ((gptr = getgrnam(pp->restrict_grp)) == NULL)
			errx(1, "Restricted group specified incorrectly");
		if (gptr->gr_gid != getgid()) {
			while (*gptr->gr_mem != NULL) {
				if ((strcmp(lpr_username, *gptr->gr_mem)) == 0)
					break;
				gptr->gr_mem++;
			}
			if (*gptr->gr_mem == NULL)
				errx(1, "Not a member of the restricted group");
		}
	}
	/*
	 * Check to make sure queuing is enabled if userid is not root.
	 */
	lock_file_name(pp, buf, sizeof buf);
	if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
		errx(1, "Printer queue is disabled");
	/*
	 * Initialize the control file.
	 */
	mktemps(pp);
	tfd = nfile(tfname);
	PRIV_START
	(void) fchown(tfd, pp->daemon_user, -1);
	/* owned by daemon for protection */
	PRIV_END
	card('H', local_host);
	card('P', lpr_username);
	card('C', class);
	if (hdr && !pp->no_header) {
		if (jobname == NULL) {
			if (argc == 0)
				jobname = "stdin";
			else
				jobname = ((arg = strrchr(argv[0], '/'))
					   ? arg + 1 : argv[0]);
		}
		card('J', jobname);
		card('L', lpr_username);
	}
	if (format != 'p' && Zflag != 0)
		card('Z', Zflag);
	if (iflag)
		card('I', itoa(indent));
	if (mailflg)
		card('M', lpr_username);
	if (format == 't' || format == 'n' || format == 'd')
		for (i = 0; i < 4; i++)
			if (fonts[i] != NULL)
				card('1'+i, fonts[i]);
	if (width != NULL)
		card('W', width);
	/*
	 * XXX
	 * Our use of `Z' here is incompatible with LPRng's
	 * use.  We assume that the only use of our existing
	 * `Z' card is as shown for `p' format (pr) files.
	 */
	if (format == 'p') {
		char *s;

		if (locale)
			card('Z', locale);
		else if ((s = setlocale(LC_TIME, "")) != NULL)
			card('Z', s);
	}

	/*
	 * Read the files and spool them.
	 */
	if (argc == 0)
		copy(pp, 0, " ");
	else while (argc--) {
		if (argv[0][0] == '-' && argv[0][1] == '\0') {
			/* use stdin */
			copy(pp, 0, " ");
			argv++;
			continue;
		}
		if ((f = test(arg = *argv++)) < 0)
			continue;	/* file unreasonable */

		if (sflag && (cp = linked(arg)) != NULL) {
			(void)snprintf(buf, sizeof(buf), "%ju %ju",
			    (uintmax_t)statb.st_dev, (uintmax_t)statb.st_ino);
			card('S', buf);
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			if (f)
				card('U', cp);
			card('N', arg);
			dfname[inchar]++;
			nact++;
			continue;
		}
		if (sflag)
			printf("%s: %s: not linked, copying instead\n",
			    progname, arg);

		if (f) {
			/*
			 * The user wants the file removed after it is copied
			 * to the spool area, so see if the file can be moved
			 * instead of copy/unlink'ed.  This is much faster and
			 * uses less spool space than copying the file.  This
			 * can be very significant when running services like
			 * samba, pcnfs, CAP, et al.
			 */
			PRIV_START
			didlink = 0;
			/*
			 * There are several things to check to avoid any
			 * security issues.  Some of these are redundant
			 * under BSD's, but are necessary when lpr is built
			 * under some other OS's (which I do do...)
			 */
			if (lstat(arg, &statb1) < 0)
				goto nohardlink;
			if (S_ISLNK(statb1.st_mode))
				goto nohardlink;
			if (link(arg, dfname) != 0)
				goto nohardlink;
			didlink = 1;
			/*
			 * Make sure the user hasn't tried to trick us via
			 * any race conditions
			 */
			if (lstat(dfname, &statb2) < 0)
				goto nohardlink;
			if (statb1.st_dev != statb2.st_dev)
				goto nohardlink;
			if (statb1.st_ino != statb2.st_ino)
				goto nohardlink;
			/*
			 * Skip if the file already had multiple hard links,
			 * because changing the owner and access-bits would
			 * change ALL versions of the file
			 */
			if (statb2.st_nlink > 2)
				goto nohardlink;
			/*
			 * If we can access and remove the original file
			 * without special setuid-ness then this method is
			 * safe.  Otherwise, abandon the move and fall back
			 * to the (usual) copy method.
			 */
			PRIV_END
			ret = access(dfname, R_OK);
			if (ret == 0)
				ret = unlink(arg);
			PRIV_START
			if (ret != 0)
				goto nohardlink;
			/*
			 * Unlink of user file was successful.  Change the
			 * owner and permissions, add entries to the control
			 * file, and skip the file copying step.
			 */
			chown(dfname, pp->daemon_user, getegid());
			chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
			PRIV_END
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			card('N', arg);
			nact++;
			continue;
		nohardlink:
			if (didlink)
				unlink(dfname);
			PRIV_END           /* restore old uid */
		} /* end: if (f) */

		if ((i = open(arg, O_RDONLY)) < 0) {
			printf("%s: cannot open %s\n", progname, arg);
		} else {
			copy(pp, i, arg);
			(void) close(i);
			if (f && unlink(arg) < 0)
				printf("%s: %s: not removed\n", progname, arg);
		}
	}

	if (nact) {
		(void) close(tfd);
		tfname[inchar]--;
		/*
		 * Touch the control file to fix position in the queue.
		 */
		PRIV_START
		if ((tfd = open(tfname, O_RDWR)) >= 0) {
			char touch_c;

			if (read(tfd, &touch_c, 1) == 1 &&
			    lseek(tfd, (off_t)0, 0) == 0 &&
			    write(tfd, &touch_c, 1) != 1) {
				printf("%s: cannot touch %s\n", progname,
				    tfname);
				tfname[inchar]++;
				cleanup(0);
			}
			(void) close(tfd);
		}
		if (link(tfname, cfname) < 0) {
			printf("%s: cannot rename %s\n", progname, cfname);
			tfname[inchar]++;
			cleanup(0);
		}
		unlink(tfname);
		PRIV_END
		if (qflag)		/* just q things up */
			exit(0);
		if (!startdaemon(pp))
			printf("jobs queued, but cannot start daemon.\n");
		exit(0);
	}
	cleanup(0);
	return (1);
	/* NOTREACHED */
}
Exemple #11
0
static int process_data_dir_file(struct asfd *asfd,
	struct bu *bu, struct bu *b, const char *path,
	struct sbuf *sb, enum action act, struct sdirs *sdirs,
	struct conf **cconfs)
{
	int ret=-1;
	int patches=0;
	char *dpath=NULL;
	struct stat dstatp;
	const char *tmp=NULL;
	const char *best=NULL;
	static char *tmppath1=NULL;
	static char *tmppath2=NULL;
	struct cntr *cntr=NULL;
	if(cconfs) cntr=get_cntr(cconfs);

	if((!tmppath1 && !(tmppath1=prepend_s(bu->path, "tmp1")))
	  || (!tmppath2 && !(tmppath2=prepend_s(bu->path, "tmp2"))))
		goto end;

	best=path;
	tmp=tmppath1;
	// Now go down the list, applying any deltas.
	for(b=b->prev; b && b->next!=bu; b=b->prev)
	{
		free_w(&dpath);
		if(!(dpath=prepend_s(b->delta, sb->protocol1->datapth.buf)))
			goto end;

		if(lstat(dpath, &dstatp) || !S_ISREG(dstatp.st_mode))
			continue;

		if(!patches)
		{
			// Need to gunzip the first one.
			if(inflate_or_link_oldfile(asfd, best, tmp,
				cconfs, sb->compression))
			{
				logw(asfd, cntr,
				  "problem when inflating %s\n", best);
				ret=0;
				goto end;
			}
			best=tmp;
			if(tmp==tmppath1) tmp=tmppath2;
			else tmp=tmppath1;
		}

		if(do_patch(best, dpath, tmp,
			0 /* do not gzip the result */,
			sb->compression /* from the manifest */))
		{
			logw(asfd, cntr, "problem when patching %s with %s\n", path, b->timestamp);
			ret=0;
			goto end;
		}

		best=tmp;
		if(tmp==tmppath1) tmp=tmppath2;
		else tmp=tmppath1;
		unlink(tmp);
		patches++;
	}

	switch(act)
	{
		case ACTION_RESTORE:
			if(do_send_file(asfd, sb, patches, best, cntr))
				goto end;
			break;
		case ACTION_VERIFY:
			if(verify_file(asfd, sb, patches, best, cntr))
				goto end;
			break;
		default:
			logp("Unknown action: %d\n", act);
			goto end;
	}
	cntr_add(cntr, sb->path.cmd, 0);
	cntr_add_bytes(cntr, strtoull(sb->endfile.buf, NULL, 10));

	ret=0;
end:
	free_w(&dpath);
	if(tmppath1) unlink(tmppath1);
	if(tmppath2) unlink(tmppath2);
	free_w(&tmppath1);
	free_w(&tmppath2);
	return ret;
}
/*
 * remove_tablespace_directories: attempt to remove filesystem infrastructure
 *
 * Returns TRUE if successful, FALSE if some subdirectory is not empty
 *
 * redo indicates we are redoing a drop from XLOG; okay if nothing there
 */
static bool
remove_tablespace_directories(Oid tablespaceoid, bool redo)
{
    char	   *location;
    DIR		   *dirdesc;
    struct dirent *de;
    char	   *subfile;
    struct stat st;

    location = (char *) palloc(10 + 10 + 1);
    sprintf(location, "pg_tblspc/%u", tablespaceoid);

    /*
     * Check if the tablespace still contains any files.  We try to rmdir each
     * per-database directory we find in it.  rmdir failure implies there are
     * still files in that subdirectory, so give up.  (We do not have to worry
     * about undoing any already completed rmdirs, since the next attempt to
     * use the tablespace from that database will simply recreate the
     * subdirectory via TablespaceCreateDbspace.)
     *
     * Since we hold TablespaceCreateLock, no one else should be creating any
     * fresh subdirectories in parallel. It is possible that new files are
     * being created within subdirectories, though, so the rmdir call could
     * fail.  Worst consequence is a less friendly error message.
     */
    dirdesc = AllocateDir(location);
    if (dirdesc == NULL)
    {
        if (redo && errno == ENOENT)
        {
            pfree(location);
            return true;
        }
        /* else let ReadDir report the error */
    }

    while ((de = ReadDir(dirdesc, location)) != NULL)
    {
        /* Note we ignore PG_VERSION for the nonce */
        if (strcmp(de->d_name, ".") == 0 ||
                strcmp(de->d_name, "..") == 0 ||
                strcmp(de->d_name, "PG_VERSION") == 0)
            continue;

        subfile = palloc(strlen(location) + 1 + strlen(de->d_name) + 1);
        sprintf(subfile, "%s/%s", location, de->d_name);

        /* This check is just to deliver a friendlier error message */
        if (!directory_is_empty(subfile))
        {
            FreeDir(dirdesc);
            return false;
        }

        /* Do the real deed */
        if (rmdir(subfile) < 0)
            ereport(ERROR,
                    (errcode_for_file_access(),
                     errmsg("could not delete directory \"%s\": %m",
                            subfile)));

        pfree(subfile);
    }

    FreeDir(dirdesc);

    /*
     * Okay, try to unlink PG_VERSION (we allow it to not be there, even in
     * non-REDO case, for robustness).
     */
    subfile = palloc(strlen(location) + 11 + 1);
    sprintf(subfile, "%s/PG_VERSION", location);

    if (unlink(subfile) < 0)
    {
        if (errno != ENOENT)
            ereport(ERROR,
                    (errcode_for_file_access(),
                     errmsg("could not remove file \"%s\": %m",
                            subfile)));
    }

    pfree(subfile);

    /*
     * Okay, try to remove the symlink.  We must however deal with the
     * possibility that it's a directory instead of a symlink --- this could
     * happen during WAL replay (see TablespaceCreateDbspace), and it is also
     * the normal case on Windows.
     */
    if (lstat(location, &st) == 0 && S_ISDIR(st.st_mode))
    {
        if (rmdir(location) < 0)
            ereport(ERROR,
                    (errcode_for_file_access(),
                     errmsg("could not remove directory \"%s\": %m",
                            location)));
    }
    else
    {
        if (unlink(location) < 0)
            ereport(ERROR,
                    (errcode_for_file_access(),
                     errmsg("could not remove symbolic link \"%s\": %m",
                            location)));
    }

    pfree(location);

    return true;
}
Exemple #13
-1
char *
getwd(char *pathname)
{
    DIR    *dp;
    struct dirent *d;
    extern int errno;

    struct stat st_root, st_cur, st_next, st_dotdot;
    char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
    char   *pathptr, *nextpathptr, *cur_name_add;

    /* find the inode of root */
    if (stat("/", &st_root) == -1) {
        (void)sprintf(pathname,
                      "getwd: Cannot stat \"/\" (%s)", strerror(errno));
        return NULL;
    }
    pathbuf[MAXPATHLEN - 1] = '\0';
    pathptr = &pathbuf[MAXPATHLEN - 1];
    nextpathbuf[MAXPATHLEN - 1] = '\0';
    cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];

    /* find the inode of the current directory */
    if (lstat(".", &st_cur) == -1) {
        (void)sprintf(pathname,
                      "getwd: Cannot stat \".\" (%s)", strerror(errno));
        return NULL;
    }
    nextpathptr = strrcpy(nextpathptr, "../");

    /* Descend to root */
    for (;;) {

        /* look if we found root yet */
        if (st_cur.st_ino == st_root.st_ino &&
                DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
            (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
            return (pathname);
        }

        /* open the parent directory */
        if (stat(nextpathptr, &st_dotdot) == -1) {
            (void)sprintf(pathname,
                          "getwd: Cannot stat directory \"%s\" (%s)",
                          nextpathptr, strerror(errno));
            return NULL;
        }
        if ((dp = opendir(nextpathptr)) == NULL) {
            (void)sprintf(pathname,
                          "getwd: Cannot open directory \"%s\" (%s)",
                          nextpathptr, strerror(errno));
            return NULL;
        }

        /* look in the parent for the entry with the same inode */
        if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
            /* Parent has same device. No need to stat every member */
            for (d = readdir(dp); d != NULL; d = readdir(dp))
                if (d->d_fileno == st_cur.st_ino)
                    break;
        }
        else {
            /*
             * Parent has a different device. This is a mount point so we
             * need to stat every member
             */
            for (d = readdir(dp); d != NULL; d = readdir(dp)) {
                if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
                    continue;
                (void)strcpy(cur_name_add, d->d_name);
                if (lstat(nextpathptr, &st_next) == -1) {
                    (void)sprintf(pathname,
                                  "getwd: Cannot stat \"%s\" (%s)",
                                  d->d_name, strerror(errno));
                    (void)closedir(dp);
                    return NULL;
                }
                /* check if we found it yet */
                if (st_next.st_ino == st_cur.st_ino &&
                        DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
                    break;
            }
        }
        if (d == NULL) {
            (void)sprintf(pathname,
                          "getwd: Cannot find \".\" in \"..\"");
            (void)closedir(dp);
            return NULL;
        }
        st_cur = st_dotdot;
        pathptr = strrcpy(pathptr, d->d_name);
        pathptr = strrcpy(pathptr, "/");
        nextpathptr = strrcpy(nextpathptr, "../");
        (void)closedir(dp);
        *cur_name_add = '\0';
    }
} /* end getwd */