cleanup wrappers for file operations

Previously wrapper functions for open(), opendir(), and stat(), etc,
are implemneted in path.h, and now they are in fileops.h and fileops.c.
This commit is a reparation for remote glob.
This commit is contained in:
Ryo Nakamura
2023-08-03 17:07:39 +09:00
parent 8ab06c9531
commit 9f7c135b15
7 changed files with 420 additions and 314 deletions

View File

@@ -98,253 +98,4 @@ int copy_chunk(FILE *msg_fp, struct chunk *c,
/* just print contents. just for debugging */
void path_dump(struct list_head *path_list);
/* wrap DIR/dirent and sftp_dir/sftp_attribute. not thread safe */
struct mscp_dir {
DIR *l;
sftp_dir r;
sftp_session sftp;
};
typedef struct mscp_dir mdir;
struct mscp_dirent {
struct dirent *l;
sftp_attributes r;
};
typedef struct mscp_dirent mdirent;
#define mdirent_name(e) ((e->l) ? e->l->d_name : e->r->name)
#define mdirent_is_dir(e) ((e->l) ? \
(e->l->d_type == DT_DIR) : \
(e->r->type == SSH_FILEXFER_TYPE_DIRECTORY))
#define mdirent_is_null(e) (e->l == NULL && e->r == NULL)
static mdir *mscp_opendir(const char *path, sftp_session sftp)
{
mdir *d;
if (!(d = malloc(sizeof(*d))))
return NULL;
memset(d, 0, sizeof(*d));
d->sftp = sftp;
if (sftp) {
d->r = sftp_opendir(sftp, path);
if (!d->r) {
mscp_set_error("sftp_opendir '%s': %s",
path, sftp_get_ssh_error(sftp));
free(d);
return NULL;
}
} else {
d->l = opendir(path);
if (!d->l) {
mscp_set_error("opendir '%s': %s", path, strerrno());
free(d);
return NULL;
}
}
return d;
}
static int mscp_closedir(mdir *d)
{
int ret;
if (d->r)
ret = sftp_closedir(d->r);
else
ret = closedir(d->l);
free(d);
return ret;
}
static mdirent *mscp_readdir(mdir *d)
{
static mdirent e;
memset(&e, 0, sizeof(e));
if (d->r)
e.r = sftp_readdir(d->sftp, d->r);
else
e.l = readdir(d->l);
return &e;
}
static void mscp_dirent_free(mdirent *e)
{
if (e->r) {
sftp_attributes_free(e->r);
e->r = NULL;
}
}
/* wrap retriving error */
static const char *mscp_strerror(sftp_session sftp)
{
if (sftp)
return sftp_get_ssh_error(sftp);
return strerrno();
}
/* warp stat/sftp_stat */
struct mscp_stat {
struct stat l;
sftp_attributes r;
};
typedef struct mscp_stat mstat;
static int mscp_stat(const char *path, mstat *s, sftp_session sftp)
{
memset(s, 0, sizeof(*s));
if (sftp) {
s->r = sftp_stat(sftp, path);
if (!s->r) {
mscp_set_error("sftp_stat: %s %s",
sftp_get_ssh_error(sftp), path);
return -1;
}
} else {
if (stat(path, &s->l) < 0) {
mscp_set_error("stat: %s %s", strerrno(), path);
return -1;
}
}
return 0;
}
static int mscp_stat_check_err_noent(sftp_session sftp)
{
if (sftp) {
if (sftp_get_error(sftp) == SSH_FX_NO_SUCH_PATH ||
sftp_get_error(sftp) == SSH_FX_NO_SUCH_FILE)
return 0;
} else {
if (errno == ENOENT)
return 0;
}
return -1;
}
static void mscp_stat_free(mstat s) {
if (s.r)
sftp_attributes_free(s.r);
}
#define mstat_size(s) ((s.r) ? s.r->size : s.l.st_size)
#define mstat_mode(s) ((s.r) ? \
s.r->permissions : \
s.l.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))
#define mstat_is_regular(s) ((s.r) ? \
(s.r->type == SSH_FILEXFER_TYPE_REGULAR) : \
S_ISREG(s.l.st_mode))
#define mstat_is_dir(s) ((s.r) ? \
(s.r->type == SSH_FILEXFER_TYPE_DIRECTORY) : \
S_ISDIR(s.l.st_mode))
/* wrap mkdir */
static int mscp_mkdir(const char *path, mode_t mode, sftp_session sftp)
{
int ret;
if (sftp) {
ret = sftp_mkdir(sftp, path, mode);
if (ret < 0 &&
sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS) {
mscp_set_error("sftp_mkdir '%s': %s",
path, sftp_get_ssh_error(sftp));
return -1;
}
} else {
if (mkdir(path, mode) == -1 && errno != EEXIST) {
mscp_set_error("mkdir '%s': %s", path, strerrno());
return -1;
}
}
return 0;
}
/* wrap open/sftp_open */
struct mscp_file_handle {
int fd;
sftp_file sf;
};
typedef struct mscp_file_handle mfh;
static mfh mscp_open(const char *path, int flags, mode_t mode, size_t off,
sftp_session sftp)
{
mfh h;
h.fd = -1;
h.sf = NULL;
if (sftp) {
h.sf = sftp_open(sftp, path, flags, mode);
if (!h.sf) {
mscp_set_error("sftp_open '%s': %s",
path, sftp_get_ssh_error(sftp));
return h;
}
if (sftp_seek64(h.sf, off) < 0) {
mscp_set_error("sftp_seek64 '%s': %s",
path, sftp_get_ssh_error(sftp));
sftp_close(h.sf);
h.sf = NULL;
return h;
}
} else {
h.fd = open(path, flags, mode);
if (h.fd < 0) {
mscp_set_error("open '%s': %s", path, strerrno());
return h;
}
if (lseek(h.fd, off, SEEK_SET) < 0) {
mscp_set_error("lseek '%s': %s", path, strerrno());
close(h.fd);
h.fd = -1;
return h;
}
}
return h;
}
#define mscp_open_is_failed(h) (h.fd < 0 && h.sf == NULL)
static void mscp_close(mfh h)
{
if (h.sf)
sftp_close(h.sf);
if (h.fd > 0)
close(h.fd);
h.sf = NULL;
h.fd = -1;
}
/* wrap chmod/sftp_chmod */
static int mscp_chmod(const char *path, mode_t mode, sftp_session sftp)
{
if (sftp) {
if (sftp_chmod(sftp, path, mode) < 0) {
mscp_set_error("sftp_chmod '%s': %s",
path, sftp_get_ssh_error(sftp));
return -1;
}
} else {
if (chmod(path, mode) < 0) {
mscp_set_error("chmod '%s': %s", path, strerrno());
return -1;
}
}
return 0;
}
#endif /* _PATH_H_ */