diff --git a/lib/vfs/direntry.c b/lib/vfs/direntry.c index 46cbcb211..f4f281a82 100644 --- a/lib/vfs/direntry.c +++ b/lib/vfs/direntry.c @@ -496,31 +496,6 @@ vfs_s_internal_stat (const vfs_path_t * vpath, struct stat *buf, int flag) /* --------------------------------------------------------------------------------------------- */ -static int -vfs_s_stat (const vfs_path_t * vpath, struct stat *buf) -{ - return vfs_s_internal_stat (vpath, buf, FL_FOLLOW); -} - -/* --------------------------------------------------------------------------------------------- */ - -static int -vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf) -{ - return vfs_s_internal_stat (vpath, buf, FL_NONE); -} - -/* --------------------------------------------------------------------------------------------- */ - -static int -vfs_s_fstat (void *fh, struct stat *buf) -{ - *buf = FH->ino->st; - return 0; -} - -/* --------------------------------------------------------------------------------------------- */ - static int vfs_s_readlink (const vfs_path_t * vpath, char *buf, size_t size) { @@ -992,15 +967,56 @@ vfs_s_default_stat (struct vfs_class *me, mode_t mode) st.st_mode = mode; st.st_ino = 0; st.st_dev = 0; +#ifdef HAVE_STRUCT_STAT_ST_RDEV st.st_rdev = 0; +#endif st.st_uid = getuid (); st.st_gid = getgid (); +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + st.st_blksize = 512; +#endif st.st_size = 0; st.st_mtime = st.st_atime = st.st_ctime = time (NULL); + vfs_adjust_stat (&st); + return &st; } +/* --------------------------------------------------------------------------------------------- */ +/** + * Calculate number of st_blocks using st_size and st_blksize. + * In according to stat(2), st_blocks is the size in 512-byte units. + * + * @param s stat info + */ + +void +vfs_adjust_stat (struct stat *s) +{ +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + if (s->st_size == 0) + s->st_blocks = 0; + else + { +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + blkcnt_t ioblocks; + blksize_t ioblock_size; + + /* 1. Calculate how many IO blocks are occupied */ + ioblocks = 1 + (s->st_size - 1) / s->st_blksize; + /* 2. Calculate size of st_blksize in 512-byte units */ + ioblock_size = 1 + (s->st_blksize - 1) / 512; + /* 3. Calculate number of blocks */ + s->st_blocks = ioblocks * ioblock_size; +#else + /* Let IO block size is 512 bytes */ + s->st_blocks = 1 + (s->st_size - 1) / 512; +#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ + } +#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */ +} + /* --------------------------------------------------------------------------------------------- */ struct vfs_s_entry * @@ -1321,6 +1337,31 @@ vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode) /* --------------------------------------------------------------------------------------------- */ +int +vfs_s_stat (const vfs_path_t * vpath, struct stat *buf) +{ + return vfs_s_internal_stat (vpath, buf, FL_FOLLOW); +} + +/* --------------------------------------------------------------------------------------------- */ + +int +vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf) +{ + return vfs_s_internal_stat (vpath, buf, FL_NONE); +} + +/* --------------------------------------------------------------------------------------------- */ + +int +vfs_s_fstat (void *fh, struct stat *buf) +{ + *buf = FH->ino->st; + return 0; +} + +/* --------------------------------------------------------------------------------------------- */ + int vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino) { diff --git a/lib/vfs/parse_ls_vga.c b/lib/vfs/parse_ls_vga.c index 33c6d411d..2fda951ff 100644 --- a/lib/vfs/parse_ls_vga.c +++ b/lib/vfs/parse_ls_vga.c @@ -813,9 +813,7 @@ vfs_parse_ls_lga (const char *p, struct stat * s, char **filename, char **linkna #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE s->st_blksize = 512; #endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - s->st_blocks = (s->st_size + 511) / 512; -#endif + vfs_adjust_stat (s); if (num_spaces != NULL) { diff --git a/lib/vfs/vfs.h b/lib/vfs/vfs.h index a4d4c8dd1..2510195a6 100644 --- a/lib/vfs/vfs.h +++ b/lib/vfs/vfs.h @@ -226,6 +226,11 @@ extern int use_netrc; /* lib/vfs/direntry.c: */ void *vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode); +int vfs_s_stat (const vfs_path_t * vpath, struct stat *buf); +int vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf); +int vfs_s_fstat (void *fh, struct stat *buf); + +void vfs_adjust_stat (struct stat *s); vfsid vfs_getid (const vfs_path_t * vpath); diff --git a/src/consaver/cons.saver.c b/src/consaver/cons.saver.c index dd2b39056..58821f3af 100644 --- a/src/consaver/cons.saver.c +++ b/src/consaver/cons.saver.c @@ -186,9 +186,13 @@ main (int argc, char **argv) die (); if (fstat (console_fd, &st) < 0 || !S_ISCHR (st.st_mode)) die (); +#ifdef HAVE_STRUCT_STAT_ST_RDEV if ((st.st_rdev & 0xff00) != 0x0400) die (); console_minor = (int) (st.st_rdev & 0x00ff); +#else + console_minor = 1; /* FIXME */ +#endif if (console_minor < 1 || console_minor > 63) die (); if (st.st_uid != uid) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index e4e08bd46..d1c8d6567 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1602,7 +1602,13 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, if (S_ISCHR (src_stat.st_mode) || S_ISBLK (src_stat.st_mode) || S_ISFIFO (src_stat.st_mode) || S_ISNAM (src_stat.st_mode) || S_ISSOCK (src_stat.st_mode)) { - while (mc_mknod (dst_vpath, src_stat.st_mode & ctx->umask_kill, src_stat.st_rdev) < 0 + dev_t rdev = 0; + +#ifdef HAVE_STRUCT_STAT_ST_RDEV + rdev = src_stat.st_rdev; +#endif + + while (mc_mknod (dst_vpath, src_stat.st_mode & ctx->umask_kill, rdev) < 0 && !ctx->skip_all) { return_status = file_error (_("Cannot create special file \"%s\"\n%s"), dst_path); diff --git a/src/vfs/cpio/cpio.c b/src/vfs/cpio/cpio.c index f7da3185c..88068d2fd 100644 --- a/src/vfs/cpio/cpio.c +++ b/src/vfs/cpio/cpio.c @@ -388,6 +388,7 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat /* cppcheck-suppress syntaxError */ case S_IFNAM: #endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV if ((st->st_size != 0) && (st->st_rdev == 0x0001)) { /* FIXME: representation of major/minor differs between */ @@ -395,6 +396,7 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat st->st_rdev = (unsigned) st->st_size; st->st_size = 0; } +#endif break; default: break; @@ -583,7 +585,9 @@ cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super) st.st_nlink = u.buf.c_nlink; st.st_uid = u.buf.c_uid; st.st_gid = u.buf.c_gid; +#ifdef HAVE_STRUCT_STAT_ST_RDEV st.st_rdev = u.buf.c_rdev; +#endif st.st_size = (u.buf.c_filesizes[0] << 16) | u.buf.c_filesizes[1]; st.st_atime = st.st_mtime = st.st_ctime = (u.buf.c_mtimes[0] << 16) | u.buf.c_mtimes[1]; @@ -650,7 +654,9 @@ cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super) u.st.st_nlink = hd.c_nlink; u.st.st_uid = hd.c_uid; u.st.st_gid = hd.c_gid; +#ifdef HAVE_STRUCT_STAT_ST_RDEV u.st.st_rdev = hd.c_rdev; +#endif u.st.st_size = hd.c_filesize; u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime; @@ -726,7 +732,9 @@ cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super) u.st.st_nlink = hd.c_nlink; u.st.st_uid = hd.c_uid; u.st.st_gid = hd.c_gid; +#ifdef HAVE_STRUCT_STAT_ST_RDEV u.st.st_rdev = makedev (hd.c_rdev, hd.c_rdevmin); +#endif u.st.st_size = hd.c_filesize; u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime; diff --git a/src/vfs/extfs/extfs.c b/src/vfs/extfs/extfs.c index fb71cbe5d..dc739742a 100644 --- a/src/vfs/extfs/extfs.c +++ b/src/vfs/extfs/extfs.c @@ -1095,9 +1095,7 @@ extfs_stat_move (struct stat *buf, const struct inode *inode) #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE buf->st_blksize = RECORDSIZE; #endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - buf->st_blocks = (inode->size + RECORDSIZE - 1) / RECORDSIZE; -#endif + vfs_adjust_stat (buf); buf->st_atime = inode->atime; buf->st_mtime = inode->mtime; buf->st_ctime = inode->ctime; diff --git a/src/vfs/fish/fish.c b/src/vfs/fish/fish.c index 4125ab635..1ae9dba88 100644 --- a/src/vfs/fish/fish.c +++ b/src/vfs/fish/fish.c @@ -157,9 +157,35 @@ static char reply_str[80]; static struct vfs_class vfs_fish_ops; +/* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +static void +fish_set_blksize (struct stat *s) +{ +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + /* redefine block size */ + s->st_blksize = 64 * 1024; /* FIXME */ +#endif +} + +/* --------------------------------------------------------------------------------------------- */ + +static struct stat * +fish_default_stat (struct vfs_class *me) +{ + struct stat *s; + + s = vfs_s_default_stat (me, S_IFDIR | 0755); + fish_set_blksize (s); + vfs_adjust_stat (s); + + return s; +} + +/* --------------------------------------------------------------------------------------------- */ + static char * fish_load_script_from_file (const char *hostname, const char *script_name, const char *def_content) { @@ -551,7 +577,8 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super) super->name = g_strdup (PATH_SEP_STR); #endif - super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755)); + super->root = vfs_s_new_inode (me, super, fish_default_stat (me)); + return 0; } @@ -1248,6 +1275,42 @@ fish_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2) /* --------------------------------------------------------------------------------------------- */ +static int +fish_stat (const vfs_path_t * vpath, struct stat *buf) +{ + int ret; + + ret = vfs_s_stat (vpath, buf); + fish_set_blksize (buf); + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +fish_lstat (const vfs_path_t * vpath, struct stat *buf) +{ + int ret; + + ret = vfs_s_lstat (vpath, buf); + fish_set_blksize (buf); + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +fish_fstat (void *vfs_info, struct stat *buf) +{ + int ret; + + ret = vfs_s_fstat (vfs_info, buf); + fish_set_blksize (buf); + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ + static int fish_chmod (const vfs_path_t * vpath, mode_t mode) { @@ -1668,6 +1731,9 @@ init_fish (void) vfs_fish_ops.name = "fish"; vfs_fish_ops.prefix = "sh"; vfs_fish_ops.fill_names = fish_fill_names; + vfs_fish_ops.stat = fish_stat; + vfs_fish_ops.lstat = fish_lstat; + vfs_fish_ops.fstat = fish_fstat; vfs_fish_ops.chmod = fish_chmod; vfs_fish_ops.chown = fish_chown; vfs_fish_ops.utime = fish_utime; diff --git a/src/vfs/ftpfs/ftpfs.c b/src/vfs/ftpfs/ftpfs.c index d90b219e8..9a21a4041 100644 --- a/src/vfs/ftpfs/ftpfs.c +++ b/src/vfs/ftpfs/ftpfs.c @@ -244,6 +244,7 @@ static char buffer[BUF_MEDIUM]; static char *netrc; static const char *netrcp; +/* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -270,6 +271,31 @@ static int ftpfs_netrc_lookup (const char *host, char **login, char **pass); /* --------------------------------------------------------------------------------------------- */ +static void +ftpfs_set_blksize (struct stat *s) +{ +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + /* redefine block size */ + s->st_blksize = 64 * 1024; /* FIXME */ +#endif +} + +/* --------------------------------------------------------------------------------------------- */ + +static struct stat * +ftpfs_default_stat (struct vfs_class *me) +{ + struct stat *s; + + s = vfs_s_default_stat (me, S_IFDIR | 0755); + ftpfs_set_blksize (s); + vfs_adjust_stat (s); + + return s; +} + +/* --------------------------------------------------------------------------------------------- */ + static char * ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path) { @@ -991,8 +1017,7 @@ ftpfs_open_archive (struct vfs_s_super *super, SUP->ctl_connection_busy = 0; super->name = g_strdup (PATH_SEP_STR); super->root = - vfs_s_new_inode (vpath_element->class, super, - vfs_s_default_stat (vpath_element->class, S_IFDIR | 0755)); + vfs_s_new_inode (vpath_element->class, super, ftpfs_default_stat (vpath_element->class)); return ftpfs_open_archive_int (vpath_element->class, super); } @@ -2020,6 +2045,42 @@ ftpfs_send_command (const vfs_path_t * vpath, const char *cmd, int flags) /* --------------------------------------------------------------------------------------------- */ +static int +ftpfs_stat (const vfs_path_t * vpath, struct stat *buf) +{ + int ret; + + ret = vfs_s_stat (vpath, buf); + ftpfs_set_blksize (buf); + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +ftpfs_lstat (const vfs_path_t * vpath, struct stat *buf) +{ + int ret; + + ret = vfs_s_lstat (vpath, buf); + ftpfs_set_blksize (buf); + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +ftpfs_fstat (void *vfs_info, struct stat *buf) +{ + int ret; + + ret = vfs_s_fstat (vfs_info, buf); + ftpfs_set_blksize (buf); + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ + static int ftpfs_chmod (const vfs_path_t * vpath, mode_t mode) { @@ -2608,6 +2669,9 @@ init_ftpfs (void) vfs_ftpfs_ops.prefix = "ftp"; vfs_ftpfs_ops.done = &ftpfs_done; vfs_ftpfs_ops.fill_names = ftpfs_fill_names; + vfs_ftpfs_ops.stat = ftpfs_stat; + vfs_ftpfs_ops.lstat = ftpfs_lstat; + vfs_ftpfs_ops.fstat = ftpfs_fstat; vfs_ftpfs_ops.chmod = ftpfs_chmod; vfs_ftpfs_ops.chown = ftpfs_chown; vfs_ftpfs_ops.unlink = ftpfs_unlink; diff --git a/src/vfs/sftpfs/dir.c b/src/vfs/sftpfs/dir.c index 10a7aaf95..63fed6139 100644 --- a/src/vfs/sftpfs/dir.c +++ b/src/vfs/sftpfs/dir.c @@ -82,11 +82,15 @@ sftpfs_opendir (const vfs_path_t * vpath, GError ** mcerror) while (TRUE) { + const char *fixfname; + unsigned int fixfname_len = 0; int libssh_errno; + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); + handle = - libssh2_sftp_opendir (super_data->sftp_session, - sftpfs_fix_filename (path_element->path)); + libssh2_sftp_open_ex (super_data->sftp_session, fixfname, fixfname_len, 0, 0, + LIBSSH2_SFTP_OPENDIR); if (handle != NULL) break; @@ -209,12 +213,11 @@ sftpfs_mkdir (const vfs_path_t * vpath, mode_t mode, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = - libssh2_sftp_mkdir_ex (super_data->sftp_session, - fixfname, sftpfs_filename_buffer->len, mode); + res = libssh2_sftp_mkdir_ex (super_data->sftp_session, fixfname, fixfname_len, mode); if (res >= 0) break; @@ -266,11 +269,11 @@ sftpfs_rmdir (const vfs_path_t * vpath, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = - libssh2_sftp_rmdir_ex (super_data->sftp_session, fixfname, sftpfs_filename_buffer->len); + res = libssh2_sftp_rmdir_ex (super_data->sftp_session, fixfname, fixfname_len); if (res >= 0) break; diff --git a/src/vfs/sftpfs/file.c b/src/vfs/sftpfs/file.c index d95de9b74..bfdd4f369 100644 --- a/src/vfs/sftpfs/file.c +++ b/src/vfs/sftpfs/file.c @@ -126,12 +126,15 @@ sftpfs_open_file (vfs_file_handler_t * file_handler, int flags, mode_t mode, GEr while (TRUE) { + const char *fixfname; + unsigned int fixfname_len = 0; int libssh_errno; - file_handler_data->handle = - libssh2_sftp_open (super_data->sftp_session, sftpfs_fix_filename (name), - sftp_open_flags, sftp_open_mode); + fixfname = sftpfs_fix_filename (name, &fixfname_len); + file_handler_data->handle = + libssh2_sftp_open_ex (super_data->sftp_session, fixfname, fixfname_len, sftp_open_flags, + sftp_open_mode, LIBSSH2_SFTP_OPENFILE); if (file_handler_data->handle != NULL) break; @@ -217,7 +220,10 @@ sftpfs_fstat (void *data, struct stat *buf, GError ** mcerror) } if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0) + { buf->st_size = attrs.filesize; + sftpfs_blksize (buf); + } if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0) buf->st_mode = attrs.permissions; diff --git a/src/vfs/sftpfs/internal.c b/src/vfs/sftpfs/internal.c index 5377b66e5..392589596 100644 --- a/src/vfs/sftpfs/internal.c +++ b/src/vfs/sftpfs/internal.c @@ -74,13 +74,16 @@ sftpfs_ssherror_to_gliberror (sftpfs_super_data_t * super_data, int libssh_errno * Fix filename for SFTP operations: add leading slash to file name. * * @param file_name file name - * @return newly allocated string contains the file name with leading slash + * @param length length of returned string + * + * @return pointer to string that contains the file name with leading slash */ const char * -sftpfs_fix_filename (const char *file_name) +sftpfs_fix_filename (const char *file_name, unsigned int *length) { g_string_printf (sftpfs_filename_buffer, "%c%s", PATH_SEP, file_name); + *length = sftpfs_filename_buffer->len; return sftpfs_filename_buffer->str; } @@ -119,6 +122,19 @@ sftpfs_waitsocket (sftpfs_super_data_t * super_data, GError ** mcerror) return select (super_data->socket_handle + 1, readfd, writefd, NULL, &timeout); } +/* --------------------------------------------------------------------------------------------- */ + +/* Adjust block size and number of blocks */ + +void +sftpfs_blksize (struct stat *s) +{ +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + s->st_blksize = LIBSSH2_CHANNEL_WINDOW_DEFAULT; /* FIXME */ +#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ + vfs_adjust_stat (s); +} + /* --------------------------------------------------------------------------------------------- */ /** * Getting information about a symbolic link. @@ -155,11 +171,13 @@ sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, - sftpfs_filename_buffer->len, LIBSSH2_SFTP_LSTAT, &attrs); + res = + libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len, + LIBSSH2_SFTP_LSTAT, &attrs); if (res >= 0) break; @@ -188,7 +206,10 @@ sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) } if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0) + { buf->st_size = attrs.filesize; + sftpfs_blksize (buf); + } if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0) buf->st_mode = attrs.permissions; @@ -232,12 +253,13 @@ sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); res = - libssh2_sftp_stat_ex (super_data->sftp_session, - fixfname, sftpfs_filename_buffer->len, LIBSSH2_SFTP_STAT, &attrs); + libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len, + LIBSSH2_SFTP_STAT, &attrs); if (res >= 0) break; @@ -267,7 +289,10 @@ sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) } if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0) + { buf->st_size = attrs.filesize; + sftpfs_blksize (buf); + } if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0) buf->st_mode = attrs.permissions; @@ -311,10 +336,13 @@ sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mce do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = libssh2_sftp_readlink (super_data->sftp_session, fixfname, buf, size); + res = + libssh2_sftp_symlink_ex (super_data->sftp_session, fixfname, fixfname_len, buf, size, + LIBSSH2_SFTP_READLINK); if (res >= 0) break; @@ -350,6 +378,7 @@ sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** const vfs_path_element_t *path_element1; const vfs_path_element_t *path_element2; char *tmp_path; + unsigned int tmp_path_len; int res; mc_return_val_if_error (mcerror, -1); @@ -366,20 +395,21 @@ sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** if (super_data->sftp_session == NULL) return -1; - tmp_path = g_strdup_printf ("%c%s", PATH_SEP, path_element2->path); + tmp_path = (char *) sftpfs_fix_filename (path_element2->path, &tmp_path_len); + tmp_path = g_strndup (tmp_path, tmp_path_len); + path_element1 = vfs_path_get_by_index (vpath1, -1); do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element1->path); + fixfname = sftpfs_fix_filename (path_element1->path, &fixfname_len); res = - libssh2_sftp_symlink_ex (super_data->sftp_session, - fixfname, - sftpfs_filename_buffer->len, tmp_path, strlen (tmp_path), - LIBSSH2_SFTP_SYMLINK); + libssh2_sftp_symlink_ex (super_data->sftp_session, fixfname, fixfname_len, tmp_path, + tmp_path_len, LIBSSH2_SFTP_SYMLINK); if (res >= 0) break; @@ -439,11 +469,13 @@ sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, - sftpfs_filename_buffer->len, LIBSSH2_SFTP_LSTAT, &attrs); + res = + libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len, + LIBSSH2_SFTP_LSTAT, &attrs); if (res >= 0) break; @@ -463,14 +495,17 @@ sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, - sftpfs_filename_buffer->len, LIBSSH2_SFTP_SETSTAT, &attrs); + res = + libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len, + LIBSSH2_SFTP_SETSTAT, &attrs); if (res >= 0) break; - else if (res != LIBSSH2_ERROR_EAGAIN) + + if (res != LIBSSH2_ERROR_EAGAIN) { sftpfs_ssherror_to_gliberror (super_data, res, mcerror); return -1; @@ -517,12 +552,11 @@ sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror) do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element->path); + fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len); - res = - libssh2_sftp_unlink_ex (super_data->sftp_session, fixfname, - sftpfs_filename_buffer->len); + res = libssh2_sftp_unlink_ex (super_data->sftp_session, fixfname, fixfname_len); if (res >= 0) break; @@ -558,6 +592,7 @@ sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** m const vfs_path_element_t *path_element1; const vfs_path_element_t *path_element2; char *tmp_path; + unsigned int tmp_path_len; int res; mc_return_val_if_error (mcerror, -1); @@ -573,19 +608,21 @@ sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** m if (super_data->sftp_session == NULL) return -1; - tmp_path = g_strdup_printf ("%c%s", PATH_SEP, path_element2->path); + tmp_path = (char *) sftpfs_fix_filename (path_element2->path, &tmp_path_len); + tmp_path = g_strndup (tmp_path, tmp_path_len); + path_element1 = vfs_path_get_by_index (vpath1, -1); do { const char *fixfname; + unsigned int fixfname_len = 0; - fixfname = sftpfs_fix_filename (path_element1->path); + fixfname = sftpfs_fix_filename (path_element1->path, &fixfname_len); - res = libssh2_sftp_rename_ex - (super_data->sftp_session, - fixfname, - sftpfs_filename_buffer->len, tmp_path, strlen (tmp_path), LIBSSH2_SFTP_SYMLINK); + res = + libssh2_sftp_rename_ex (super_data->sftp_session, fixfname, fixfname_len, tmp_path, + tmp_path_len, LIBSSH2_SFTP_SYMLINK); if (res >= 0) break; diff --git a/src/vfs/sftpfs/internal.h b/src/vfs/sftpfs/internal.h index a6bb0db99..2c08e5f55 100644 --- a/src/vfs/sftpfs/internal.h +++ b/src/vfs/sftpfs/internal.h @@ -70,7 +70,8 @@ void sftpfs_ssherror_to_gliberror (sftpfs_super_data_t * super_data, int libssh_ GError ** mcerror); int sftpfs_waitsocket (sftpfs_super_data_t * super_data, GError ** mcerror); -const char *sftpfs_fix_filename (const char *file_name); +const char *sftpfs_fix_filename (const char *file_name, unsigned int *length); +void sftpfs_blksize (struct stat *s); int sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror); int sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror); int sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mcerror); diff --git a/src/vfs/tar/tar.c b/src/vfs/tar/tar.c index aee1174cb..04e393b5d 100644 --- a/src/vfs/tar/tar.c +++ b/src/vfs/tar/tar.c @@ -401,7 +401,10 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade st->st_mode |= S_IFREG; st->st_dev = 0; +#ifdef HAVE_STRUCT_STAT_ST_RDEV st->st_rdev = 0; +#endif + switch (arch->type) { case TAR_USTAR: @@ -420,9 +423,12 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade { case LF_BLK: case LF_CHR: +#ifdef HAVE_STRUCT_STAT_ST_RDEV st->st_rdev = - (tar_from_oct (8, header->header.devmajor) << 8) | - tar_from_oct (8, header->header.devminor); + makedev (tar_from_oct (8, header->header.devmajor), + tar_from_oct (8, header->header.devminor)); +#endif + break; default: break; } @@ -439,6 +445,11 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade st->st_atime = tar_from_oct (1 + 12, header->header.unused.oldgnu.atime); st->st_ctime = tar_from_oct (1 + 12, header->header.unused.oldgnu.ctime); } + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + st->st_blksize = 8 * 1024; /* FIXME */ +#endif + vfs_adjust_stat (st); } /* --------------------------------------------------------------------------------------------- */ diff --git a/tests/lib/vfs/Makefile.am b/tests/lib/vfs/Makefile.am index c6e133ce5..ebb531ac7 100644 --- a/tests/lib/vfs/Makefile.am +++ b/tests/lib/vfs/Makefile.am @@ -23,6 +23,7 @@ TESTS = \ path_serialize \ relative_cd \ tempdir \ + vfs_adjust_stat \ vfs_parse_ls_lga \ vfs_path_from_str_flags \ vfs_path_string_convert \ @@ -65,6 +66,9 @@ relative_cd_SOURCES = \ tempdir_SOURCES = \ tempdir.c +vfs_adjust_stat_SOURCES = \ + vfs_adjust_stat.c + vfs_get_encoding_SOURCES = \ vfs_get_encoding.c diff --git a/tests/lib/vfs/vfs_adjust_stat.c b/tests/lib/vfs/vfs_adjust_stat.c new file mode 100644 index 000000000..ea8fda69f --- /dev/null +++ b/tests/lib/vfs/vfs_adjust_stat.c @@ -0,0 +1,213 @@ +/* + lib/vfs - test vfs_adjust_stat() functionality + + Copyright (C) 2017 + Free Software Foundation, Inc. + + Written by: + Andrew Borodin , 2017 + + This file is part of the Midnight Commander. + + The Midnight Commander is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#define TEST_SUITE_NAME "/lib/vfs" + +#include "tests/mctest.h" + +#include + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("test_test_vfs_adjust_stat_ds") */ +/* *INDENT-OFF* */ +static const struct test_vfs_adjust_stat_ds +{ + struct stat etalon_stat; +} test_vfs_adjust_stat_ds[] = +{ + /* 0 */ + { + .etalon_stat = + { + .st_size = 0, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 512, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 0 +#endif + } + }, + /* 1 */ + { + .etalon_stat = + { + .st_size = 4096, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 512, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 8 +#endif + } + }, + /* 2 */ + { + .etalon_stat = + { + .st_size = 4096, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 1024, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 8 +#endif + } + }, + /* 3 */ + { + .etalon_stat = + { + .st_size = 4096, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 2048, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 8 +#endif + } + }, + /* 4 */ + { + .etalon_stat = + { + .st_size = 4096, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 4096, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 8 +#endif + } + }, + /* 5 */ + { + .etalon_stat = + { + .st_size = 5000, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 512, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 10 +#endif + } + }, + /* 6 */ + { + .etalon_stat = + { + .st_size = 5000, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 1024, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 10 +#endif + } + }, + /* 7 */ + { + .etalon_stat = + { + .st_size = 5000, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 2048, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 12 +#endif + } + }, + /* 8 */ + { + .etalon_stat = + { + .st_size = 5000, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + .st_blksize = 4096, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + .st_blocks = 16 +#endif + } + } +}; +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test(dataSource = "test_vfs_adjust_stat_ds") */ +/* *INDENT-OFF* */ +START_PARAMETRIZED_TEST (test_vfs_adjust_stat, test_vfs_adjust_stat_ds) +/* *INDENT-ON* */ +{ +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + /* given */ + struct stat expected_stat; + + expected_stat.st_size = data->etalon_stat.st_size; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + expected_stat.st_blksize = data->etalon_stat.st_blksize; +#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ + /* when */ + vfs_adjust_stat (&expected_stat); + + /* then */ + mctest_assert_int_eq (data->etalon_stat.st_blocks, expected_stat.st_blocks); +#else + mctest_assert_int_eq (0, 0); +#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */ +} +/* *INDENT-OFF* */ +END_PARAMETRIZED_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + /* Add new tests here: *************** */ + mctest_add_parameterized_test (tc_core, test_vfs_adjust_stat, test_vfs_adjust_stat_ds); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "vfs_adjust_stat.log"); + srunner_run_all (sr, CK_ENV); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/lib/vfs/vfs_parse_ls_lga.c b/tests/lib/vfs/vfs_parse_ls_lga.c index f18ac246e..77d2d2b44 100644 --- a/tests/lib/vfs/vfs_parse_ls_lga.c +++ b/tests/lib/vfs/vfs_parse_ls_lga.c @@ -119,10 +119,16 @@ fill_stat_struct (struct stat *etalon_stat, int iterator) etalon_stat->st_nlink = 10; etalon_stat->st_uid = 500; etalon_stat->st_gid = 500; +#ifdef HAVE_STRUCT_STAT_ST_RDEV etalon_stat->st_rdev = 0; +#endif etalon_stat->st_size = 4096; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE etalon_stat->st_blksize = 512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS etalon_stat->st_blocks = 8; +#endif etalon_stat->st_atime = 1308838140; etalon_stat->st_mtime = 1308838140; etalon_stat->st_ctime = 1308838140; @@ -134,10 +140,16 @@ fill_stat_struct (struct stat *etalon_stat, int iterator) etalon_stat->st_nlink = 10; etalon_stat->st_uid = 500; etalon_stat->st_gid = 500; +#ifdef HAVE_STRUCT_STAT_ST_RDEV etalon_stat->st_rdev = 0; +#endif etalon_stat->st_size = 11; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE etalon_stat->st_blksize = 512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS etalon_stat->st_blocks = 1; +#endif etalon_stat->st_atime = 1268431200; etalon_stat->st_mtime = 1268431200; etalon_stat->st_ctime = 1268431200; @@ -149,10 +161,16 @@ fill_stat_struct (struct stat *etalon_stat, int iterator) etalon_stat->st_nlink = 10; etalon_stat->st_uid = 500; etalon_stat->st_gid = 500; +#ifdef HAVE_STRUCT_STAT_ST_RDEV etalon_stat->st_rdev = 0; +#endif etalon_stat->st_size = 4096; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE etalon_stat->st_blksize = 512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS etalon_stat->st_blocks = 8; +#endif etalon_stat->st_atime = 1308838140; etalon_stat->st_mtime = 1308838140; etalon_stat->st_ctime = 1308838140; @@ -164,10 +182,16 @@ fill_stat_struct (struct stat *etalon_stat, int iterator) etalon_stat->st_nlink = 10; etalon_stat->st_uid = 500; etalon_stat->st_gid = 500; +#ifdef HAVE_STRUCT_STAT_ST_RDEV etalon_stat->st_rdev = 0; +#endif etalon_stat->st_size = 4096; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE etalon_stat->st_blksize = 512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS etalon_stat->st_blocks = 8; +#endif etalon_stat->st_atime = 1308838140; etalon_stat->st_mtime = 1308838140; etalon_stat->st_ctime = 1308838140; @@ -237,7 +261,9 @@ START_PARAMETRIZED_TEST (test_vfs_parse_ls_lga, test_vfs_parse_ls_lga_ds) vfs_parse_ls_lga_init (); +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS etalon_stat.st_blocks = 0; +#endif etalon_stat.st_size = 0; etalon_stat.st_mode = 0; fill_stat_struct (&etalon_stat, _i); @@ -257,10 +283,16 @@ START_PARAMETRIZED_TEST (test_vfs_parse_ls_lga, test_vfs_parse_ls_lga_ds) mctest_assert_int_eq (etalon_stat.st_mode, test_stat.st_mode); mctest_assert_int_eq (etalon_stat.st_uid, test_stat.st_uid); mctest_assert_int_eq (etalon_stat.st_gid, test_stat.st_gid); +#ifdef HAVE_STRUCT_STAT_ST_RDEV mctest_assert_int_eq (etalon_stat.st_rdev, test_stat.st_rdev); +#endif mctest_assert_int_eq (etalon_stat.st_size, test_stat.st_size); +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE mctest_assert_int_eq (etalon_stat.st_blksize, test_stat.st_blksize); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS mctest_assert_int_eq (etalon_stat.st_blocks, test_stat.st_blocks); +#endif /* FIXME: these commented checks are related to time zone! mctest_assert_int_eq (etalon_stat.st_atime, test_stat.st_atime);