diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/client/client.c | 153 | ||||
-rw-r--r-- | source3/lib/system.c | 26 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 131 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 26 |
4 files changed, 309 insertions, 27 deletions
diff --git a/source3/client/client.c b/source3/client/client.c index e14bcaa261..42db009c58 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -1705,6 +1705,158 @@ static int cmd_chmod(void) return 0; } +static const char *filetype_to_str(mode_t mode) +{ + if (S_ISREG(mode)) { + return "regular file"; + } else if (S_ISDIR(mode)) { + return "directory"; + } else +#ifdef S_ISCHR + if (S_ISCHR(mode)) { + return "character device"; + } else +#endif +#ifdef S_ISBLK + if (S_ISBLK(mode)) { + return "block device"; + } else +#endif +#ifdef S_ISFIFO + if (S_ISFIFO(mode)) { + return "fifo"; + } else +#endif +#ifdef S_ISLNK + if (S_ISLNK(mode)) { + return "symbolic link"; + } else +#endif +#ifdef S_ISSOCK + if (S_ISSOCK(mode)) { + return "socket"; + } else +#endif + return ""; +} + +static char rwx_to_str(mode_t m, mode_t bt, char ret) +{ + if (m & bt) { + return ret; + } else { + return '-'; + } +} + +static char *unix_mode_to_str(char *s, mode_t m) +{ + char *p = s; + const char *str = filetype_to_str(m); + + switch(str[0]) { + case 'd': + *p++ = 'd'; + break; + case 'c': + *p++ = 'c'; + break; + case 'b': + *p++ = 'b'; + break; + case 'f': + *p++ = 'p'; + break; + case 's': + *p++ = str[1] == 'y' ? 'l' : 's'; + break; + case 'r': + default: + *p++ = '-'; + break; + } + *p++ = rwx_to_str(m, S_IRUSR, 'r'); + *p++ = rwx_to_str(m, S_IWUSR, 'w'); + *p++ = rwx_to_str(m, S_IXUSR, 'x'); + *p++ = rwx_to_str(m, S_IRGRP, 'r'); + *p++ = rwx_to_str(m, S_IWGRP, 'w'); + *p++ = rwx_to_str(m, S_IXGRP, 'x'); + *p++ = rwx_to_str(m, S_IROTH, 'r'); + *p++ = rwx_to_str(m, S_IWOTH, 'w'); + *p++ = rwx_to_str(m, S_IXOTH, 'x'); + *p++ = '\0'; + return s; +} + +/**************************************************************************** + UNIX stat. +****************************************************************************/ + +static int cmd_stat(void) +{ + pstring src, name; + fstring mode_str; + SMB_STRUCT_STAT sbuf; + + if (!SERVER_HAS_UNIX_CIFS(cli)) { + d_printf("Server doesn't support UNIX CIFS calls.\n"); + return 1; + } + + pstrcpy(src,cur_dir); + + if (!next_token_nr(NULL,name,NULL,sizeof(name))) { + d_printf("stat file\n"); + return 1; + } + + pstrcat(src,name); + + if (!cli_unix_stat(cli, src, &sbuf)) { + d_printf("%s stat file %s\n", + cli_errstr(cli), src); + return 1; + } + + /* Print out the stat values. */ + d_printf("File: %s\n", src); + d_printf("Size: %-12.0f\tBlocks: %u\t%s\n", + (double)sbuf.st_size, + (unsigned int)sbuf.st_blocks, + filetype_to_str(sbuf.st_mode)); + +#if defined(S_ISCHR) && defined(S_ISBLK) + if (S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode)) { + d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n", + (double)sbuf.st_ino, + (unsigned int)sbuf.st_nlink, + unix_dev_major(sbuf.st_rdev), + unix_dev_minor(sbuf.st_rdev)); + } else +#endif + d_printf("Inode: %.0f\tLinks: %u\n", + (double)sbuf.st_ino, + (unsigned int)sbuf.st_nlink); + + d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n", + ((int)sbuf.st_mode & 0777), + unix_mode_to_str(mode_str, sbuf.st_mode), + (unsigned int)sbuf.st_uid, + (unsigned int)sbuf.st_gid); + + strftime(mode_str, sizeof(mode_str), "%F %T %z", localtime(&sbuf.st_atime)); + d_printf("Access: %s\n", mode_str); + + strftime(mode_str, sizeof(mode_str), "%F %T %z", localtime(&sbuf.st_mtime)); + d_printf("Modify: %s\n", mode_str); + + strftime(mode_str, sizeof(mode_str), "%F %T %z", localtime(&sbuf.st_ctime)); + d_printf("Change: %s\n", mode_str); + + return 0; +} + + /**************************************************************************** UNIX chown. ****************************************************************************/ @@ -2234,6 +2386,7 @@ static struct {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}}, {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}}, {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}}, + {"stat",cmd_stat,"filename Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_REMOTE}}, {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}}, {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}}, {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}}, diff --git a/source3/lib/system.c b/source3/lib/system.c index a0007ec83c..b27ac5c00a 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1580,3 +1580,29 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size return -1; #endif } + +/**************************************************************************** + Return the major devicenumber for UNIX extensions. +****************************************************************************/ + +uint32 unix_dev_major(SMB_DEV_T dev) +{ +#if defined(HAVE_DEVICE_MAJOR_FN) + return (uint32)major(dev); +#else + return (uint32)(dev >> 8); +#endif +} + +/**************************************************************************** + Return the minor devicenumber for UNIX extensions. +****************************************************************************/ + +uint32 unix_dev_minor(SMB_DEV_T dev) +{ +#if defined(HAVE_DEVICE_MINOR_FN) + return (uint32)minor(dev); +#else + return (uint32)(dev & 0xff); +#endif +} diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index ff0edc6bb4..d302206949 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -77,7 +77,7 @@ static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const Map standard UNIX permissions onto wire representations. ****************************************************************************/ -uint32 unix_perms_to_wire(mode_t perms) +uint32 unix_perms_to_wire(mode_t perms) { unsigned int ret = 0; @@ -103,6 +103,135 @@ uint32 unix_perms_to_wire(mode_t perms) } /**************************************************************************** + Map wire permissions to standard UNIX. +****************************************************************************/ + +mode_t wire_perms_to_unix(uint32 perms) +{ + mode_t ret = (mode_t)0; + + ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0); + ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0); + ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0); + ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0); + ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0); + ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0); + ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0); + ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0); + ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0); +#ifdef S_ISVTX + ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0); +#endif +#ifdef S_ISGID + ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0); +#endif +#ifdef S_ISUID + ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0); +#endif + return ret; +} + +/**************************************************************************** + Return the file type from the wire filetype for UNIX extensions. +****************************************************************************/ + +static mode_t unix_filetype_from_wire(uint32 wire_type) +{ + switch (wire_type) { + case UNIX_TYPE_FILE: + return S_IFREG; + case UNIX_TYPE_DIR: + return S_IFDIR; +#ifdef S_IFLNK + case UNIX_TYPE_SYMLINK: + return S_IFLNK; +#endif +#ifdef S_IFCHR + case UNIX_TYPE_CHARDEV: + return S_IFCHR; +#endif +#ifdef S_IFBLK + case UNIX_TYPE_BLKDEV: + return S_IFBLK; +#endif +#ifdef S_IFIFO + case UNIX_TYPE_FIFO: + return S_IFIFO; +#endif +#ifdef S_IFSOCK + case UNIX_TYPE_SOCKET: + return S_IFSOCK; +#endif + default: + return (mode_t)0; + } +} + +/**************************************************************************** + Stat a file (UNIX extensions). +****************************************************************************/ + +BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf) +{ + unsigned int param_len = 0; + unsigned int data_len = 0; + uint16 setup = TRANSACT2_QPATHINFO; + char param[sizeof(pstring)+6]; + char *rparam=NULL, *rdata=NULL; + char *p; + + ZERO_STRUCTP(sbuf); + + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC); + p += 6; + p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE); + param_len = PTR_DIFF(p, param); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + NULL, 0, cli->max_xmit /* data, length, max */ + )) { + return False; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return False; + } + + sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */ + sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */ + sbuf->st_blocks /= STAT_ST_BLOCKSIZE; + sbuf->st_ctime = interpret_long_date(rdata + 16); /* time of last change */ + sbuf->st_atime = interpret_long_date(rdata + 24); /* time of last access */ + sbuf->st_mtime = interpret_long_date(rdata + 32); /* time of last modification */ + sbuf->st_uid = IVAL(rdata,40); /* user ID of owner */ + sbuf->st_gid = IVAL(rdata,48); /* group ID of owner */ + sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56)); +#if defined(HAVE_MAKEDEV) + { + uint32 dev_major = IVAL(rdata,60); + uint32 dev_minor = IVAL(rdata,68); + sbuf->st_rdev = makedev(dev_major, dev_minor); + } +#endif + sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */ + sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */ + sbuf->st_nlink = IVAL(rdata,92); /* number of hard links */ + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + + return True; +} + +/**************************************************************************** Symlink a file (UNIX extensions). ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a7bc2efb4a..825481984d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -757,32 +757,6 @@ static uint32 unix_filetype(mode_t mode) } /**************************************************************************** - Return the major devicenumber for UNIX extensions. -****************************************************************************/ - -static uint32 unix_dev_major(SMB_DEV_T dev) -{ -#if defined(HAVE_DEVICE_MAJOR_FN) - return (uint32)major(dev); -#else - return (uint32)(dev >> 8); -#endif -} - -/**************************************************************************** - Return the minor devicenumber for UNIX extensions. -****************************************************************************/ - -static uint32 unix_dev_minor(SMB_DEV_T dev) -{ -#if defined(HAVE_DEVICE_MINOR_FN) - return (uint32)minor(dev); -#else - return (uint32)(dev & 0xff); -#endif -} - -/**************************************************************************** Map wire perms onto standard UNIX permissions. Obey share restrictions. ****************************************************************************/ |