added qse_fs_setattr() and related functions
This commit is contained in:
		| @ -27,7 +27,164 @@ | ||||
| #include "fs-prv.h" | ||||
| #include "../cmn/mem-prv.h" | ||||
|  | ||||
| int qse_fs_sysgetattr (qse_fs_t* fs, const qse_fs_char_t* fspath, qse_fs_attr_t* attr) | ||||
|  | ||||
| static void stat_to_attr (const qse_stat_t* st, qse_fs_attr_t* attr) | ||||
| { | ||||
| 	QSE_MEMSET (attr, 0, QSE_SIZEOF(*attr)); | ||||
|  | ||||
| 	if (S_ISDIR(st->st_mode)) attr->isdir = 1; | ||||
| 	if (S_ISLNK(st->st_mode)) attr->islnk = 1; | ||||
| 	if (S_ISREG(st->st_mode)) attr->isreg = 1; | ||||
| 	if (S_ISBLK(st->st_mode)) attr->isblk = 1; | ||||
| 	if (S_ISCHR(st->st_mode)) attr->ischr = 1; | ||||
|  | ||||
| 	attr->mode = st->st_mode; | ||||
| 	attr->size = st->st_size; | ||||
| 	attr->ino = st->st_ino; | ||||
| 	attr->dev = st->st_dev; | ||||
| 	attr->uid = st->st_uid; | ||||
| 	attr->gid = st->st_gid; | ||||
|  | ||||
| #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) | ||||
| 	attr->atime.sec = st->st_atim.tv_sec; | ||||
| 	attr->atime.nsec = st->st_atim.tv_nsec; | ||||
| 	attr->mtime.sec = st->st_mtim.tv_sec; | ||||
| 	attr->mtime.nsec = st->st_mtim.tv_nsec; | ||||
| 	attr->ctime.sec = st->st_ctim.tv_sec; | ||||
| 	attr->ctime.nsec = st->st_ctim.tv_nsec; | ||||
| #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) | ||||
| 	attr->atime.sec = st->st_atimespec.tv_sec; | ||||
| 	attr->atime.nsec = st->st_atimespec.tv_nsec; | ||||
| 	attr->mtime.sec = st->st_mtimespec.tv_sec; | ||||
| 	attr->mtime.nsec = st->st_mtimespec.tv_nsec; | ||||
| 	attr->ctime.sec = st->st_ctimespec.tv_sec; | ||||
| 	attr->ctime.nsec = st->st_ctimespec.tv_nsec; | ||||
| #else | ||||
| 	attr->atime.sec = st->st_atime; | ||||
| 	attr->mtime.sec = st->st_mtime; | ||||
| 	attr->ctime.sec = st->st_ctime; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| int qse_fs_getattronfd (qse_fs_t* fs, qse_fs_handle_t fd, qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|  | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(__OS2__) | ||||
|  | ||||
| 	/* TODO */ | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(__DOS__) | ||||
|  | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(HAVE_FSTAT) | ||||
| 	qse_fstat_t st; | ||||
|  | ||||
| 	if (QSE_FSTAT (fd, &st) <= -1) | ||||
| 	{ | ||||
| 		fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	stat_to_attr (&st, attr); | ||||
| 	return 0; | ||||
| #else | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| int qse_fs_getattrsys (qse_fs_t* fs, const qse_fs_char_t* fspath, qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|  | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(__OS2__) | ||||
|  | ||||
| 	/* TODO */ | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(__DOS__) | ||||
|  | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(HAVE_FSTATAT) | ||||
|  | ||||
| 	qse_fstatat_t st; | ||||
| 	int sysflags = 0; | ||||
|  | ||||
| 	if (flags & QSE_FS_GETATTR_SYMLINK) sysflags |= AT_SYMLINK_NOFOLLOW; | ||||
| 	if (QSE_FSTATAT(AT_FDCWD, fspath, &st, sysflags) <= -1) | ||||
| 	{ | ||||
| 		fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	stat_to_attr (&st, attr); | ||||
| 	return 0; | ||||
|  | ||||
| #else | ||||
| 	qse_stat_t st; | ||||
| 	int x; | ||||
|  | ||||
| 	if (flags & QSE_FS_GETATTR_SYMLINK) | ||||
| 		x = QSE_LSTAT (fspath, &st); | ||||
| 	else | ||||
| 		x = QSE_STAT (fspath, &st); | ||||
|  | ||||
| 	if (x <= -1) | ||||
| 	{ | ||||
| 		fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	stat_to_attr (&st, attr); | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| int qse_fs_getattrmbs (qse_fs_t* fs, const qse_mchar_t* path, qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| 	qse_fs_char_t* fspath; | ||||
| 	int ret; | ||||
|  | ||||
| 	fspath = qse_fs_makefspathformbs (fs, path); | ||||
| 	if (!fspath) return -1; | ||||
|  | ||||
| 	ret = qse_fs_getattrsys (fs, fspath, attr, flags); | ||||
|  | ||||
| 	qse_fs_freefspathformbs (fs, path, fspath); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int qse_fs_getattrwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| 	qse_fs_char_t* fspath; | ||||
| 	int ret; | ||||
|  | ||||
| 	fspath = qse_fs_makefspathforwcs (fs, path); | ||||
| 	if (!fspath) return -1; | ||||
|  | ||||
| 	ret = qse_fs_getattrsys (fs, fspath, attr, flags); | ||||
|  | ||||
| 	qse_fs_freefspathforwcs (fs, path, fspath); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| /* -------------------------------------------------------------------------- */ | ||||
|  | ||||
| int qse_fs_setattronfd (qse_fs_t* fs, qse_fs_handle_t fd, const qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|  | ||||
| @ -46,66 +203,235 @@ int qse_fs_sysgetattr (qse_fs_t* fs, const qse_fs_char_t* fspath, qse_fs_attr_t* | ||||
| 	return -1; | ||||
|  | ||||
| #else | ||||
| 	#if defined(HAVE_LSTAT) | ||||
| 	qse_lstat_t st; | ||||
| 	#else | ||||
| 	qse_stat_t st; | ||||
| 	#endif | ||||
|  | ||||
| 	#if defined(HAVE_LSTAT) | ||||
| 	if (QSE_LSTAT (fspath, &st) == -1)  | ||||
| 	if (flags & QSE_FS_SETATTR_TIME) | ||||
| 	{ | ||||
| 		fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	#if defined(HAVE_FUTIMENS) && defined(HAVE_STRUCT_TIMESPEC) | ||||
| 		struct timespec ts[2]; | ||||
|  | ||||
| 		QSE_MEMSET (&ts, 0, QSE_SIZEOF(ts)); | ||||
| 		ts[0].tv_sec = attr->atime.sec; | ||||
| 		ts[0].tv_nsec = attr->atime.nsec; | ||||
| 		ts[1].tv_sec = attr->mtime.sec; | ||||
| 		ts[1].tv_nsec = attr->mtime.nsec; | ||||
| 		if (QSE_FUTIMENS (fd, ts) <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 	#elif defined(HAVE_FUTIMES) | ||||
| 		struct timeval tv[2]; | ||||
|  | ||||
| 		QSE_MEMSET (&tv, 0, QSE_SIZEOF(tv)); | ||||
| 		tv[0].tv_sec = attr->atime.sec; | ||||
| 		tv[0].tv_usec = QSE_NSEC_TO_USEC(attr->atime.nsec); | ||||
| 		tv[1].tv_sec = attr->mtime.sec; | ||||
| 		tv[1].tv_usec = QSE_NSEC_TO_USEC(attr->mtime.nsec); | ||||
| 		if (QSE_FUTIMES (fspath, tv) <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	#else | ||||
| 	/* is this ok to use stat? */ | ||||
| 	if (QSE_STAT (fspath, &st) == -1)  | ||||
| 		fs->errnum = QSE_FS_ENOIMPL; | ||||
| 		return -1; | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	if (flags & QSE_FS_SETATTR_OWNER) | ||||
| 	{ | ||||
| 		fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	QSE_MEMSET (attr, 0, QSE_SIZEOF(*attr)); | ||||
|  | ||||
| 	if (S_ISDIR(st.st_mode)) attr->isdir = 1; | ||||
| 	if (S_ISLNK(st.st_mode)) attr->islnk = 1; | ||||
| 	if (S_ISREG(st.st_mode)) attr->isreg = 1; | ||||
| 	if (S_ISBLK(st.st_mode)) attr->isblk = 1; | ||||
| 	if (S_ISCHR(st.st_mode)) attr->ischr = 1; | ||||
|  | ||||
| 	attr->mode = st.st_mode; | ||||
| 	attr->size = st.st_size; | ||||
| 	attr->ino = st.st_ino; | ||||
| 	attr->dev = st.st_dev; | ||||
| 	attr->uid = st.st_uid; | ||||
| 	attr->gid = st.st_gid; | ||||
| 	 | ||||
| 	#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) | ||||
| 		attr->atime.sec = st.st_atim.tv_sec; | ||||
| 		attr->atime.nsec = st.st_atim.tv_nsec; | ||||
| 		attr->mtime.sec = st.st_mtim.tv_sec; | ||||
| 		attr->mtime.nsec = st.st_mtim.tv_nsec; | ||||
| 		attr->ctime.sec = st.st_ctim.tv_sec; | ||||
| 		attr->ctime.nsec = st.st_ctim.tv_nsec; | ||||
| 	#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) | ||||
| 		attr->atime.sec = st.st_atimespec.tv_sec; | ||||
| 		attr->atime.nsec = st.st_atimespec.tv_nsec; | ||||
| 		attr->mtime.sec = st.st_mtimespec.tv_sec; | ||||
| 		attr->mtime.nsec = st.st_mtimespec.tv_nsec; | ||||
| 		attr->ctime.sec = st.st_ctimespec.tv_sec; | ||||
| 		attr->ctime.nsec = st.st_ctimespec.tv_nsec; | ||||
| 	#if defined(HAVE_FCHOWN) | ||||
| 		if (QSE_FCHOWN (fd, attr->uid, attr->gid) <= -1)  | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	#else | ||||
| 		attr->atime.sec = st.st_atime; | ||||
| 		attr->mtime.sec = st.st_mtime; | ||||
| 		attr->ctime.sec = st.st_ctime; | ||||
| 		fs->errnum = QSE_FS_ENOIMPL; | ||||
| 		return -1; | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	if (flags & QSE_FS_SETATTR_MODE) | ||||
| 	{ | ||||
| 	#if defined(HAVE_FCHMOD) | ||||
| 		if (QSE_FCHMOD(fd, attr->mode) <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	#else | ||||
| 		fs->errnum = QSE_FS_ENOIMPL; | ||||
| 		return -1; | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| int qse_fs_getattrmbs (qse_fs_t* fs, const qse_mchar_t* path, qse_fs_attr_t* attr) | ||||
| int qse_fs_setattrsys (qse_fs_t* fs, qse_fs_char_t* path, const qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|  | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(__OS2__) | ||||
|  | ||||
| 	/* TODO */ | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #elif defined(__DOS__) | ||||
|  | ||||
| 	fs->errnum = QSE_FS_ENOIMPL; | ||||
| 	return -1; | ||||
|  | ||||
| #else | ||||
| 	if (flags & QSE_FS_SETATTR_TIME) | ||||
| 	{ | ||||
| 	#if defined(HAVE_UTIMENSAT) | ||||
| 		struct timespec ts[2]; | ||||
| 		int sysflags = 0; | ||||
|  | ||||
| 		if (flags & QSE_FS_SETATTR_SYMLINK) sysflags |= AT_SYMLINK_NOFOLLOW; | ||||
|  | ||||
| 		QSE_MEMSET (&ts, 0, QSE_SIZEOF(ts)); | ||||
| 		ts[0].tv_sec = attr->atime.sec; | ||||
| 		ts[0].tv_nsec = attr->atime.nsec; | ||||
| 		ts[1].tv_sec = attr->mtime.sec; | ||||
| 		ts[1].tv_nsec = attr->mtime.nsec; | ||||
|  | ||||
| 		if (QSE_UTIMENSAT(AT_FDCWD, path, NULL, sysflags) <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 	#else | ||||
| 		if (flags & QSE_FS_SETATTR_SYMLINK) | ||||
| 		{ | ||||
| 		#if defined(HAVE_LUTIMES) | ||||
| 			struct timeval tv[2]; | ||||
|  | ||||
| 			QSE_MEMSET (&tv, 0, QSE_SIZEOF(tv)); | ||||
| 			tv[0].tv_sec = attr->atime.sec; | ||||
| 			tv[0].tv_usec = QSE_NSEC_TO_USEC(attr->atime.nsec); | ||||
| 			tv[1].tv_sec = attr->mtime.sec; | ||||
| 			tv[1].tv_usec = QSE_NSEC_TO_USEC(attr->mtime.nsec); | ||||
|  | ||||
| 			if (QSE_LUTIMES (path, tv) <= -1) | ||||
| 			{ | ||||
| 				fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		#else | ||||
| 			fs->errnum = QSE_FS_ENOIMPL; | ||||
| 			return -1; | ||||
| 		#endif | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 		#if defined(HAVE_UTIMES) | ||||
| 			struct timeval tv[2]; | ||||
|  | ||||
| 			QSE_MEMSET (&tv, 0, QSE_SIZEOF(tv)); | ||||
| 			tv[0].tv_sec = attr->atime.sec; | ||||
| 			tv[0].tv_usec = QSE_NSEC_TO_USEC(attr->atime.nsec); | ||||
| 			tv[1].tv_sec = attr->mtime.sec; | ||||
| 			tv[1].tv_usec = QSE_NSEC_TO_USEC(attr->mtime.nsec); | ||||
|  | ||||
| 			if (QSE_UTIMES (path, tv) <= -1) | ||||
| 			{ | ||||
| 				fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 		#elif defined(HAVE_UTIME) | ||||
| 			struct utimbuf ub; | ||||
|  | ||||
| 			QSE_MEMSET (&ub, 0, QSE_SIZEOF(ub)); | ||||
| 			ub.actime = attr->atime.sec; | ||||
| 			ub.modtime = attr->mtime.sec; | ||||
| 			if (QSE_UTIME (path, &ub) <= -1) | ||||
| 			{ | ||||
| 				fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 		#else | ||||
| 			fs->errnum = QSE_FS_ENOIMPL; | ||||
| 			return -1; | ||||
| 		#endif | ||||
| 		} | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	if (flags & QSE_FS_SETATTR_OWNER) | ||||
| 	{ | ||||
| 	#if defined(QSE_FCHOWNAT) | ||||
| 		int sysflags = 0; | ||||
|  | ||||
| 		if (flags & QSE_FS_SETATTR_SYMLINK) sysflags |= AT_SYMLINK_NOFOLLOW; | ||||
|  | ||||
| 		if (QSE_FCHOWNAT(AT_FDCWD, path, attr->uid, attr->gid, sysflags) <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	#else | ||||
| 		int x; | ||||
|  | ||||
| 		if (flags & QSE_FS_SETATTR_SYMLINK) | ||||
| 			x = QSE_LCHOWN (path, attr->uid, attr->gid); | ||||
| 		else | ||||
| 			x = QSE_CHOWN (path, attr->uid, attr->gid); | ||||
|  | ||||
| 		if (x <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	if (flags & QSE_FS_SETATTR_MODE) | ||||
| 	{ | ||||
| 	#if defined(QSE_FCHMODAT) | ||||
| 		int sysflags = 0; | ||||
|  | ||||
| 		if (flags & QSE_FS_SETATTR_SYMLINK) sysflags |= AT_SYMLINK_NOFOLLOW; | ||||
|  | ||||
| 		if (QSE_FCHMODAT(AT_FDCWD, path, attr->mode, sysflags) <= -1) | ||||
| 		{ | ||||
| 			fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	#else | ||||
| 		if (flags & QSE_FS_SETATTR_SYMLINK) | ||||
| 		{ | ||||
| 			/* not supported. symlink permission is kind of fixed. | ||||
| 			 * do nothing */ | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (QSE_CHMOD(path, attr->mode) <= -1) | ||||
| 			{ | ||||
| 				fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| int qse_fs_setattrmbs (qse_fs_t* fs, qse_mchar_t* path, const qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| 	qse_fs_char_t* fspath; | ||||
| 	int ret; | ||||
| @ -113,13 +439,14 @@ int qse_fs_getattrmbs (qse_fs_t* fs, const qse_mchar_t* path, qse_fs_attr_t* att | ||||
| 	fspath = qse_fs_makefspathformbs (fs, path); | ||||
| 	if (!fspath) return -1; | ||||
|  | ||||
| 	ret = qse_fs_sysgetattr (fs, fspath, attr); | ||||
| 	ret = qse_fs_setattrsys (fs, fspath, attr, flags); | ||||
|  | ||||
| 	qse_fs_freefspathformbs (fs, path, fspath); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int qse_fs_getattrwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_attr_t* attr) | ||||
|  | ||||
| int qse_fs_setattrwcs (qse_fs_t* fs, qse_wchar_t* path, const qse_fs_attr_t* attr, int flags) | ||||
| { | ||||
| 	qse_fs_char_t* fspath; | ||||
| 	int ret; | ||||
| @ -127,7 +454,7 @@ int qse_fs_getattrwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_attr_t* att | ||||
| 	fspath = qse_fs_makefspathforwcs (fs, path); | ||||
| 	if (!fspath) return -1; | ||||
|  | ||||
| 	ret = qse_fs_sysgetattr (fs, fspath, attr); | ||||
| 	ret = qse_fs_setattrsys (fs, fspath, attr, flags); | ||||
|  | ||||
| 	qse_fs_freefspathforwcs (fs, path, fspath); | ||||
| 	return ret; | ||||
|  | ||||
| @ -38,10 +38,8 @@ | ||||
| struct cpfile_t | ||||
| { | ||||
| 	int flags; | ||||
|  | ||||
| 	qse_fs_char_t* src_fspath; | ||||
| 	qse_fs_char_t* dst_fspath; | ||||
|  | ||||
| 	qse_fs_attr_t src_attr; | ||||
| 	qse_fs_attr_t dst_attr; | ||||
| }; | ||||
| @ -67,7 +65,8 @@ static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 	qse_fs_freefspath (fs, QSE_NULL, cpfile->dst_fspath); | ||||
| 	cpfile->dst_fspath = fstmp; | ||||
|  | ||||
| 	if (qse_fs_sysgetattr (fs, cpfile->dst_fspath, &cpfile->dst_attr) <= -1)  | ||||
| /* TODO: check on the flags to getattrsys()... */ | ||||
| 	if (qse_fs_getattrsys (fs, cpfile->dst_fspath, &cpfile->dst_attr, 0) <= -1)  | ||||
| 	{ | ||||
| 		/* attribute on the new destination is not available */ | ||||
| 		cpfile->flags &= ~CPFILE_DST_ATTR; | ||||
| @ -280,17 +279,6 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 				goto oops; | ||||
| 			} | ||||
|  | ||||
| 		#elif defined(HAVE_UTIME) | ||||
|  | ||||
| 			QSE_MEMSET (&ub, 0, QSE_SIZEOF(ub)); | ||||
| 			ub.actime = cpfile->src_attr.atime.sec; | ||||
| 			ub.modtime = cpfile->src_attr.mtime.sec; | ||||
| 			if (QSE_UTIME (cpfile->dst_fspath, &ub) <= -1) | ||||
| 			{ | ||||
| 				fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 				goto oops; | ||||
| 			} | ||||
|  | ||||
| 		#elif defined(HAVE_UTIMES) | ||||
|  | ||||
| 			QSE_MEMSET (&tv, 0, QSE_SIZEOF(tv)); | ||||
| @ -305,6 +293,17 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 				goto oops; | ||||
| 			} | ||||
|  | ||||
| 		#elif defined(HAVE_UTIME) | ||||
|  | ||||
| 			QSE_MEMSET (&ub, 0, QSE_SIZEOF(ub)); | ||||
| 			ub.actime = cpfile->src_attr.atime.sec; | ||||
| 			ub.modtime = cpfile->src_attr.mtime.sec; | ||||
| 			if (QSE_UTIME (cpfile->dst_fspath, &ub) <= -1) | ||||
| 			{ | ||||
| 				fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||
| 				goto oops; | ||||
| 			} | ||||
|  | ||||
| 		#else | ||||
| 		#	error none of futimens, futimes, utime, utimes exist | ||||
| 		#endif | ||||
| @ -327,8 +326,9 @@ static int prepare_cpfile (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| { | ||||
| 	/* error if the source file can't be stat'ed. | ||||
| 	 * ok if the destination file can't be stat'ed */ | ||||
| 	if (qse_fs_sysgetattr (fs, cpfile->src_fspath, &cpfile->src_attr) <= -1) return -1; | ||||
| 	if (qse_fs_sysgetattr (fs, cpfile->dst_fspath, &cpfile->dst_attr) >= 0) cpfile->flags |= CPFILE_DST_ATTR; | ||||
| /* TODO: check on flags to getattrsys() */ | ||||
| 	if (qse_fs_getattrsys (fs, cpfile->src_fspath, &cpfile->src_attr, 0) <= -1) return -1; | ||||
| 	if (qse_fs_getattrsys (fs, cpfile->dst_fspath, &cpfile->dst_attr, 0) >= 0) cpfile->flags |= CPFILE_DST_ATTR; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -634,3 +634,198 @@ oops: | ||||
| 	clear_cpfile (fs, &cpfile); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
| /* --------------------------------------------------------------------- */ | ||||
| /* | ||||
|  * Copyright (c) 1983 Regents of the University of California. | ||||
|  * All rights reserved.  The Berkeley software License Agreement | ||||
|  * specifies the terms and conditions for redistribution. | ||||
|  */ | ||||
|  | ||||
| static int copy (const char* from, const char* to) | ||||
| { | ||||
| 	int fold, fnew, n, exists; | ||||
| 	char *last, destname[MAXPATHLEN + 1], buf[MAXBSIZE]; | ||||
| 	struct stat stfrom, stto; | ||||
|  | ||||
| 	fold = open (from, O_RDONLY); | ||||
| 	if (fold < 0)  | ||||
| 	{ | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (fstat(fold, &stfrom) < 0) | ||||
| 	{ | ||||
| 		close(fold); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (stat(to, &stto) >= 0 && (stto.st_mode&S_IFMT) == S_IFDIR)  | ||||
| 	{ | ||||
| 		last = rindex(from, '/'); | ||||
| 		if (last) last++; else last = from; | ||||
|  | ||||
| 		if (strlen(to) + strlen(last) >= sizeof(destname) - 1)  | ||||
| 		{ | ||||
| 			/* name too long */ | ||||
| 			close(fold); | ||||
| 			return(1); | ||||
| 		} | ||||
|  | ||||
| 		(void) sprintf(destname, "%s/%s", to, last); | ||||
| 		to = destname; | ||||
| 	} | ||||
|  | ||||
| 	if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR)  | ||||
| 	{ | ||||
| 		int fixmode = 0;    /* cleanup mode after rcopy */ | ||||
|  | ||||
| 		close(fold); | ||||
| 		if (stat(to, &stto) < 0) | ||||
| 		{ | ||||
| 			if (mkdir(to, (stfrom.st_mode & 07777) | 0700) < 0) | ||||
| 			{ | ||||
| 				Perror(to); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			fixmode = 1; | ||||
| 		} | ||||
| 		else if ((stto.st_mode&S_IFMT) != S_IFDIR) | ||||
| 		{ | ||||
| 		  fprintf(stderr, "cp: %s: Not a directory.\n", to); | ||||
| 		  return (1); | ||||
| 		} | ||||
| 		else if (pflag) | ||||
| 		{ | ||||
| 		  fixmode = 1; | ||||
| 		} | ||||
|  | ||||
| 		n = rcopy(from, to); | ||||
| 		if (fixmode) chmod(to, stfrom.st_mode & 07777); | ||||
| 		return (n); | ||||
| 	} | ||||
|  | ||||
| 	if ((stfrom.st_mode&S_IFMT) == S_IFDIR) | ||||
| 	   fprintf(stderr, | ||||
| 		  "cp: %s: Is a directory (copying as plain file).\n", | ||||
| 			 from); | ||||
|  | ||||
| 	exists = stat(to, &stto) == 0; | ||||
| 	if (exists)  | ||||
| 	{ | ||||
| 		if (stfrom.st_dev == stto.st_dev && stfrom.st_ino == stto.st_ino) | ||||
| 		{ | ||||
| 			fprintf(stderr, | ||||
| 			 "cp: %s and %s are identical (not copied).\n", from, to); | ||||
| 			close(fold); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		if (iflag && isatty(fileno(stdin))) | ||||
| 		{ | ||||
| 			int i, c; | ||||
|  | ||||
| 			fprintf (stderr, "overwrite %s? ", to); | ||||
| 			i = c = getchar(); | ||||
|  | ||||
| 			while (c != '\n' && c != EOF) | ||||
| 			c = getchar(); | ||||
| 			if (i != 'y') | ||||
| 			{ | ||||
| 				close(fold); | ||||
| 				return(1); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	fnew = creat(to, stfrom.st_mode & 07777); | ||||
| 	if (fnew < 0) | ||||
| 	{ | ||||
| 		Perror(to); | ||||
| 		(void) close(fold); | ||||
| 		return(1); | ||||
| 	} | ||||
|  | ||||
| 	if (exists && pflag) | ||||
| 		fchmod(fnew, stfrom.st_mode & 07777); | ||||
|  | ||||
| 	for (;;) | ||||
| 	{ | ||||
| 		/* use vmsplice() to copy??? */ | ||||
| 		n = read(fold, buf, sizeof buf); | ||||
| 		if (n == 0) break; | ||||
|  | ||||
| 		if (n < 0)  | ||||
| 		{ | ||||
| 			Perror(from); | ||||
| 			close(fold); | ||||
| 			close(fnew); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		if (write(fnew, buf, n) != n) | ||||
| 		{ | ||||
| 			Perror(to); | ||||
| 			close(fold); | ||||
| 			close(fnew); | ||||
| 			return (1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	close(fold); | ||||
| 	close(fnew); | ||||
| 	if (pflag) return (setimes(to, &stfrom)); | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| int rcopy(const char* from, const char* to) | ||||
| { | ||||
| 	DIR *fold = opendir(from); | ||||
| 	struct direct *dp; | ||||
| 	struct stat statb; | ||||
| 	int errs = 0; | ||||
| 	char fromname[MAXPATHLEN + 1]; | ||||
|  | ||||
| 	if (fold == 0 || (pflag && fstat(fold->dd_fd, &statb) < 0)) { | ||||
| 		Perror(from); | ||||
| 		return (1); | ||||
| 	} | ||||
| 	for (;;)  | ||||
| 	{ | ||||
| 		dp = readdir(fold); | ||||
| 		if (dp == 0)  | ||||
| 		{ | ||||
| 			closedir(fold); | ||||
| 			if (pflag) return (setimes(to, &statb) + errs); | ||||
| 			return (errs); | ||||
| 		} | ||||
| 		if (dp->d_ino == 0) continue; | ||||
| 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; | ||||
| 		if (strlen(from)+1+strlen(dp->d_name) >= sizeof fromname - 1) | ||||
| 		{ | ||||
| 			fprintf(stderr, "cp: %s/%s: Name too long.\n", from, dp->d_name); | ||||
| 			errs++; | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		sprintf(fromname, "%s/%s", from, dp->d_name); | ||||
| 		errs += copy(fromname, to); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int setimes(const char* path, const struct stat* statp) | ||||
| { | ||||
| 	struct timeval tv[2]; | ||||
|  | ||||
| 	tv[0].tv_sec = statp->st_atime; | ||||
| 	tv[1].tv_sec = statp->st_mtime; | ||||
| 	tv[0].tv_usec = tv[1].tv_usec = 0; | ||||
| 	if (utimes(path, tv) < 0)  | ||||
| 	{ | ||||
| 		Perror(path); | ||||
| 		return (1); | ||||
| 	} | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -143,10 +143,18 @@ void qse_fs_freefspathforwcs ( | ||||
| #	define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathforwcs(fs,path,fspath); | ||||
| #endif | ||||
|  | ||||
| int qse_fs_sysgetattr ( | ||||
| int qse_fs_getattrsys ( | ||||
| 	qse_fs_t*            fs, | ||||
| 	const qse_fs_char_t* fspath, | ||||
| 	qse_fs_attr_t* attr | ||||
| 	qse_fs_attr_t*       attr, | ||||
| 	int                  flags | ||||
| ); | ||||
|  | ||||
| int qse_fs_setattrsys ( | ||||
| 	qse_fs_t*            fs, | ||||
| 	qse_fs_char_t*       path, | ||||
| 	const qse_fs_attr_t* attr, | ||||
| 	int                  flags /** bitwise-ORed #qse_fs_setattr_flag_t enumerators */ | ||||
| ); | ||||
|  | ||||
| int qse_fs_syscpfile ( | ||||
|  | ||||
		Reference in New Issue
	
	Block a user