Commit ddbb8684 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: remove never-used in6_addr option
  cifs: add addr= mount option alias for ip=
  [CIFS] Add mention of new mount parm (forceuid) to cifs readme
  cifs: make overriding of ownership conditional on new mount options
  cifs: fix IPv6 address length check
  cifs: clean up set_cifs_acl interfaces
  cifs: reorganize get_cifs_acl
  [CIFS] Update readme to indicate change to default mount (serverino)
  cifs: make serverino the default when mounting
  cifs: rename cifs_iget to cifs_root_iget
  cifs: make cnvrtDosUnixTm take a little-endian args and an offset
  cifs: have cifs_NTtimeToUnix take a little-endian arg
  cifs: tighten up default file_mode/dir_mode
  cifs: fix artificial limit on reading symlinks
parents 3296ca27 61b6bc52
Version 1.59
------------
Client uses server inode numbers (which are persistent) rather than
client generated ones by default (mount option "serverino" turned
on by default if server supports it). Add forceuid and forcegid
mount options (so that when negotiating unix extensions specifying
which uid mounted does not immediately force the server's reported
uids to be overridden).
Version 1.58 Version 1.58
------------ ------------
Guard against buffer overruns in various UCS-2 to UTF-8 string conversions Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
...@@ -10,6 +19,8 @@ we converted from). Fix endianness of the vcnum field used during ...@@ -10,6 +19,8 @@ we converted from). Fix endianness of the vcnum field used during
session setup to distinguish multiple mounts to same server from different session setup to distinguish multiple mounts to same server from different
userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental
flag to be set to 2, and mount must enable krb5 to turn on extended security). flag to be set to 2, and mount must enable krb5 to turn on extended security).
Performance of file create to Samba improved (posix create on lookup
removes 1 of 2 network requests sent on file create)
Version 1.57 Version 1.57
------------ ------------
......
...@@ -262,7 +262,8 @@ A partial list of the supported mount options follows: ...@@ -262,7 +262,8 @@ A partial list of the supported mount options follows:
mount. mount.
domain Set the SMB/CIFS workgroup name prepended to the domain Set the SMB/CIFS workgroup name prepended to the
username during CIFS session establishment username during CIFS session establishment
uid Set the default uid for inodes. For mounts to servers forceuid Set the default uid for inodes based on the uid
passed in. For mounts to servers
which do support the CIFS Unix extensions, such as a which do support the CIFS Unix extensions, such as a
properly configured Samba server, the server provides properly configured Samba server, the server provides
the uid, gid and mode so this parameter should not be the uid, gid and mode so this parameter should not be
...@@ -292,6 +293,12 @@ A partial list of the supported mount options follows: ...@@ -292,6 +293,12 @@ A partial list of the supported mount options follows:
the client. Note that the mount.cifs helper must be the client. Note that the mount.cifs helper must be
at version 1.10 or higher to support specifying the uid at version 1.10 or higher to support specifying the uid
(or gid) in non-numeric form. (or gid) in non-numeric form.
forcegid (similar to above but for the groupid instead of uid)
uid Set the default uid for inodes, and indicate to the
cifs kernel driver which local user mounted . If the server
supports the unix extensions the default uid is
not used to fill in the owner fields of inodes (files)
unless the "forceuid" parameter is specified.
gid Set the default gid for inodes (similar to above). gid Set the default gid for inodes (similar to above).
file_mode If CIFS Unix extensions are not supported by the server file_mode If CIFS Unix extensions are not supported by the server
this overrides the default mode for file inodes. this overrides the default mode for file inodes.
...@@ -388,8 +395,13 @@ A partial list of the supported mount options follows: ...@@ -388,8 +395,13 @@ A partial list of the supported mount options follows:
or the CIFS Unix Extensions equivalent and for those or the CIFS Unix Extensions equivalent and for those
this mount option will have no effect. Exporting cifs mounts this mount option will have no effect. Exporting cifs mounts
under nfsd requires this mount option on the cifs mount. under nfsd requires this mount option on the cifs mount.
This is now the default if server supports the
required network operation.
noserverino Client generates inode numbers (rather than using the actual one noserverino Client generates inode numbers (rather than using the actual one
from the server) by default. from the server). These inode numbers will vary after
unmount or reboot which can confuse some applications,
but not all server filesystems support unique inode
numbers.
setuids If the CIFS Unix extensions are negotiated with the server setuids If the CIFS Unix extensions are negotiated with the server
the client will attempt to set the effective uid and gid of the client will attempt to set the effective uid and gid of
the local process on newly created files, directories, and the local process on newly created files, directories, and
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <keys/user-type.h> #include <keys/user-type.h>
#include <linux/key-type.h> #include <linux/key-type.h>
#include <linux/inet.h>
#include "cifsglob.h" #include "cifsglob.h"
#include "cifs_spnego.h" #include "cifs_spnego.h"
#include "cifs_debug.h" #include "cifs_debug.h"
...@@ -73,9 +74,6 @@ struct key_type cifs_spnego_key_type = { ...@@ -73,9 +74,6 @@ struct key_type cifs_spnego_key_type = {
* strlen(";sec=ntlmsspi") */ * strlen(";sec=ntlmsspi") */
#define MAX_MECH_STR_LEN 13 #define MAX_MECH_STR_LEN 13
/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
#define MAX_IPV6_ADDR_LEN 43
/* strlen of "host=" */ /* strlen of "host=" */
#define HOST_KEY_LEN 5 #define HOST_KEY_LEN 5
...@@ -102,7 +100,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) ...@@ -102,7 +100,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
host=hostname sec=mechanism uid=0xFF user=username */ host=hostname sec=mechanism uid=0xFF user=username */
desc_len = MAX_VER_STR_LEN + desc_len = MAX_VER_STR_LEN +
HOST_KEY_LEN + strlen(hostname) + HOST_KEY_LEN + strlen(hostname) +
IP_KEY_LEN + MAX_IPV6_ADDR_LEN + IP_KEY_LEN + INET6_ADDRSTRLEN +
MAX_MECH_STR_LEN + MAX_MECH_STR_LEN +
UID_KEY_LEN + (sizeof(uid_t) * 2) + UID_KEY_LEN + (sizeof(uid_t) * 2) +
USER_KEY_LEN + strlen(sesInfo->userName) + 1; USER_KEY_LEN + strlen(sesInfo->userName) + 1;
......
...@@ -552,130 +552,138 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, ...@@ -552,130 +552,138 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
return rc; return rc;
} }
static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
/* Retrieve an ACL from the server */ __u16 fid, u32 *pacllen)
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
const char *path, const __u16 *pfid)
{ {
struct cifsFileInfo *open_file = NULL;
bool unlock_file = false;
int xid;
int rc = -EIO;
__u16 fid;
struct super_block *sb;
struct cifs_sb_info *cifs_sb;
struct cifs_ntsd *pntsd = NULL; struct cifs_ntsd *pntsd = NULL;
int xid, rc;
xid = GetXid();
rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
FreeXid(xid);
cFYI(1, ("get mode from ACL for %s", path));
if (inode == NULL) cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
return NULL; return pntsd;
}
static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
const char *path, u32 *pacllen)
{
struct cifs_ntsd *pntsd = NULL;
int oplock = 0;
int xid, rc;
__u16 fid;
xid = GetXid(); xid = GetXid();
if (pfid == NULL)
open_file = find_readable_file(CIFS_I(inode));
else
fid = *pfid;
sb = inode->i_sb; rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
if (sb == NULL) { &fid, &oplock, NULL, cifs_sb->local_nls,
FreeXid(xid); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
return NULL; if (rc) {
} cERROR(1, ("Unable to open file to get ACL"));
cifs_sb = CIFS_SB(sb); goto out;
if (open_file) {
unlock_file = true;
fid = open_file->netfid;
} else if (pfid == NULL) {
int oplock = 0;
/* open file */
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
READ_CONTROL, 0, &fid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc != 0) {
cERROR(1, ("Unable to open file to get ACL"));
FreeXid(xid);
return NULL;
}
} }
rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
if (unlock_file == true) /* find_readable_file increments ref count */
atomic_dec(&open_file->wrtPending);
else if (pfid == NULL) /* if opened above we have to close the handle */
CIFSSMBClose(xid, cifs_sb->tcon, fid);
/* else handle was passed in by caller */
CIFSSMBClose(xid, cifs_sb->tcon, fid);
out:
FreeXid(xid); FreeXid(xid);
return pntsd; return pntsd;
} }
/* Set an ACL on the server */ /* Retrieve an ACL from the server */
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct inode *inode, const char *path) struct inode *inode, const char *path,
u32 *pacllen)
{ {
struct cifsFileInfo *open_file; struct cifs_ntsd *pntsd = NULL;
bool unlock_file = false; struct cifsFileInfo *open_file = NULL;
int xid;
int rc = -EIO;
__u16 fid;
struct super_block *sb;
struct cifs_sb_info *cifs_sb;
cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); if (inode)
open_file = find_readable_file(CIFS_I(inode));
if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
if (!inode) pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
return rc; atomic_dec(&open_file->wrtPending);
return pntsd;
}
sb = inode->i_sb; static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
if (sb == NULL) struct cifs_ntsd *pnntsd, u32 acllen)
return rc; {
int xid, rc;
cifs_sb = CIFS_SB(sb);
xid = GetXid(); xid = GetXid();
rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
FreeXid(xid);
open_file = find_readable_file(CIFS_I(inode)); cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
if (open_file) { return rc;
unlock_file = true; }
fid = open_file->netfid;
} else { static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
int oplock = 0; struct cifs_ntsd *pnntsd, u32 acllen)
/* open file */ {
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, int oplock = 0;
WRITE_DAC, 0, &fid, &oplock, NULL, int xid, rc;
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & __u16 fid;
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc != 0) { xid = GetXid();
cERROR(1, ("Unable to open file to set ACL"));
FreeXid(xid); rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
return rc; &fid, &oplock, NULL, cifs_sb->local_nls,
} cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
cERROR(1, ("Unable to open file to set ACL"));
goto out;
} }
rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
if (unlock_file)
atomic_dec(&open_file->wrtPending);
else
CIFSSMBClose(xid, cifs_sb->tcon, fid);
CIFSSMBClose(xid, cifs_sb->tcon, fid);
out:
FreeXid(xid); FreeXid(xid);
return rc;
}
/* Set an ACL on the server */
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
struct inode *inode, const char *path)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsFileInfo *open_file;
int rc;
cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
open_file = find_readable_file(CIFS_I(inode));
if (!open_file)
return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
atomic_dec(&open_file->wrtPending);
return rc; return rc;
} }
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid) void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
const char *path, const __u16 *pfid)
{ {
struct cifs_ntsd *pntsd = NULL; struct cifs_ntsd *pntsd = NULL;
u32 acllen = 0; u32 acllen = 0;
int rc = 0; int rc = 0;
cFYI(DBG2, ("converting ACL to mode for %s", path)); cFYI(DBG2, ("converting ACL to mode for %s", path));
pntsd = get_cifs_acl(&acllen, inode, path, pfid);
if (pfid)
pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
else
pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
if (pntsd) if (pntsd)
...@@ -698,7 +706,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) ...@@ -698,7 +706,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
cFYI(DBG2, ("set ACL from mode for %s", path)); cFYI(DBG2, ("set ACL from mode for %s", path));
/* Get the security descriptor */ /* Get the security descriptor */
pntsd = get_cifs_acl(&secdesclen, inode, path, NULL); pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
/* Add three ACEs for owner, group, everyone getting rid of /* Add three ACEs for owner, group, everyone getting rid of
other ACEs as chmod disables ACEs and set the security descriptor */ other ACEs as chmod disables ACEs and set the security descriptor */
......
...@@ -146,7 +146,7 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -146,7 +146,7 @@ cifs_read_super(struct super_block *sb, void *data,
#endif #endif
sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize = CIFS_MAX_MSGSIZE;
sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
inode = cifs_iget(sb, ROOT_I); inode = cifs_root_iget(sb, ROOT_I);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
rc = PTR_ERR(inode); rc = PTR_ERR(inode);
......
...@@ -36,7 +36,7 @@ extern void cifs_read_inode(struct inode *); ...@@ -36,7 +36,7 @@ extern void cifs_read_inode(struct inode *);
/* Functions related to inodes */ /* Functions related to inodes */
extern const struct inode_operations cifs_dir_inode_ops; extern const struct inode_operations cifs_dir_inode_ops;
extern struct inode *cifs_iget(struct super_block *, unsigned long); extern struct inode *cifs_root_iget(struct super_block *, unsigned long);
extern int cifs_create(struct inode *, struct dentry *, int, extern int cifs_create(struct inode *, struct dentry *, int,
struct nameidata *); struct nameidata *);
extern struct dentry *cifs_lookup(struct inode *, struct dentry *, extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
...@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ...@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */ #endif /* EXPERIMENTAL */
#define CIFS_VERSION "1.58" #define CIFS_VERSION "1.59"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -90,10 +90,10 @@ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16, ...@@ -90,10 +90,10 @@ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *); struct cifsTconInfo *);
extern void DeleteOplockQEntry(struct oplock_q_entry *); extern void DeleteOplockQEntry(struct oplock_q_entry *);
extern void DeleteTconOplockQEntries(struct cifsTconInfo *); extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601); extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
extern u64 cifs_UnixTimeToNT(struct timespec); extern u64 cifs_UnixTimeToNT(struct timespec);
extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); int offset);
extern int cifs_posix_open(char *full_path, struct inode **pinode, extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct super_block *sb, int mode, int oflags, struct super_block *sb, int mode, int oflags,
...@@ -108,8 +108,8 @@ extern int cifs_get_inode_info(struct inode **pinode, ...@@ -108,8 +108,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
extern int cifs_get_inode_info_unix(struct inode **pinode, extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path, const unsigned char *search_path,
struct super_block *sb, int xid); struct super_block *sb, int xid);
extern void acl_to_uid_mode(struct inode *inode, const char *path, extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
const __u16 *pfid); const char *path, const __u16 *pfid);
extern int mode_to_acl(struct inode *inode, const char *path, __u64); extern int mode_to_acl(struct inode *inode, const char *path, __u64);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
......
...@@ -524,8 +524,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -524,8 +524,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
int val, seconds, remain, result; int val, seconds, remain, result;
struct timespec ts, utc; struct timespec ts, utc;
utc = CURRENT_TIME; utc = CURRENT_TIME;
ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
le16_to_cpu(rsp->SrvTime.Time)); rsp->SrvTime.Time, 0);
cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d", cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
(int)ts.tv_sec, (int)utc.tv_sec, (int)ts.tv_sec, (int)utc.tv_sec,
(int)(utc.tv_sec - ts.tv_sec))); (int)(utc.tv_sec - ts.tv_sec)));
...@@ -2427,8 +2427,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, ...@@ -2427,8 +2427,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
pSMB->TotalDataCount = 0; pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max data count below from sess structure BB */ pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0; pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0; pSMB->Reserved = 0;
pSMB->Flags = 0; pSMB->Flags = 0;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <linux/inet.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
...@@ -61,7 +62,6 @@ struct smb_vol { ...@@ -61,7 +62,6 @@ struct smb_vol {
char *domainname; char *domainname;
char *UNC; char *UNC;
char *UNCip; char *UNCip;
char *in6_addr; /* ipv6 address as human readable form of in6_addr */
char *iocharset; /* local code page for mapping to and from Unicode */ char *iocharset; /* local code page for mapping to and from Unicode */
char source_rfc1001_name[16]; /* netbios name of client */ char source_rfc1001_name[16]; /* netbios name of client */
char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
...@@ -827,14 +827,16 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -827,14 +827,16 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->target_rfc1001_name[0] = 0; vol->target_rfc1001_name[0] = 0;
vol->linux_uid = current_uid(); /* use current_euid() instead? */ vol->linux_uid = current_uid(); /* use current_euid() instead? */
vol->linux_gid = current_gid(); vol->linux_gid = current_gid();
vol->dir_mode = S_IRWXUGO;
/* 2767 perms indicate mandatory locking support */ /* default to only allowing write access to owner of the mount */
vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = true; vol->rw = true;
/* default is always to request posix paths. */ /* default is always to request posix paths. */
vol->posix_paths = 1; vol->posix_paths = 1;
/* default to using server inode numbers where available */
vol->server_ino = 1;
if (!options) if (!options)
return 1; return 1;
...@@ -955,10 +957,12 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -955,10 +957,12 @@ cifs_parse_mount_options(char *options, const char *devname,
} }
strcpy(vol->password, value); strcpy(vol->password, value);
} }
} else if (strnicmp(data, "ip", 2) == 0) { } else if (!strnicmp(data, "ip", 2) ||
!strnicmp(data, "addr", 4)) {
if (!value || !*value) { if (!value || !*value) {
vol->UNCip = NULL; vol->UNCip = NULL;
} else if (strnlen(value, 35) < 35) { } else if (strnlen(value, INET6_ADDRSTRLEN) <
INET6_ADDRSTRLEN) {
vol->UNCip = value; vol->UNCip = value;
} else { } else {
printk(KERN_WARNING "CIFS: ip address " printk(KERN_WARNING "CIFS: ip address "
...@@ -1092,17 +1096,17 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -1092,17 +1096,17 @@ cifs_parse_mount_options(char *options, const char *devname,
return 1; return 1;
} }
} else if (strnicmp(data, "uid", 3) == 0) { } else if (strnicmp(data, "uid", 3) == 0) {
if (value && *value) { if (value && *value)
vol->linux_uid = vol->linux_uid =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
} else if (strnicmp(data, "forceuid", 8) == 0) {
vol->override_uid = 1; vol->override_uid = 1;
}
} else if (strnicmp(data, "gid", 3) == 0) { } else if (strnicmp(data, "gid", 3) == 0) {
if (value && *value) { if (value && *value)
vol->linux_gid = vol->linux_gid =
simple_strtoul(value, &value, 0); simple_strtoul(value, &value, 0);
} else if (strnicmp(data, "forcegid", 8) == 0) {
vol->override_gid = 1; vol->override_gid = 1;
}
} else if (strnicmp(data, "file_mode", 4) == 0) { } else if (strnicmp(data, "file_mode", 4) == 0) {
if (value && *value) { if (value && *value) {
vol->file_mode = vol->file_mode =
...@@ -1315,16 +1319,6 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -1315,16 +1319,6 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->direct_io = 1; vol->direct_io = 1;
} else if (strnicmp(data, "forcedirectio", 13) == 0) { } else if (strnicmp(data, "forcedirectio", 13) == 0) {
vol->direct_io = 1; vol->direct_io = 1;
} else if (strnicmp(data, "in6_addr", 8) == 0) {
if (!value || !*value) {
vol->in6_addr = NULL;
} else if (strnlen(value, 49) == 48) {
vol->in6_addr = value;
} else {
printk(KERN_WARNING "CIFS: ip v6 address not "
"48 characters long\n");
return 1;
}
} else if (strnicmp(data, "noac", 4) == 0) { } else if (strnicmp(data, "noac", 4) == 0) {
printk(KERN_WARNING "CIFS: Mount option noac not " printk(KERN_WARNING "CIFS: Mount option noac not "
"supported. Instead set " "supported. Instead set "
......
...@@ -241,7 +241,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, ...@@ -241,7 +241,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
/* BB need same check in cifs_create too? */ /* BB need same check in cifs_create too? */
/* if not oplocked, invalidate inode pages if mtime or file /* if not oplocked, invalidate inode pages if mtime or file
size changed */ size changed */
temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime)); temp = cifs_NTtimeToUnix(buf->LastWriteTime);
if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
(file->f_path.dentry->d_inode->i_size == (file->f_path.dentry->d_inode->i_size ==
(loff_t)le64_to_cpu(buf->EndOfFile))) { (loff_t)le64_to_cpu(buf->EndOfFile))) {
......
...@@ -85,10 +85,10 @@ static void cifs_unix_info_to_inode(struct inode *inode, ...@@ -85,10 +85,10 @@ static void cifs_unix_info_to_inode(struct inode *inode,
__u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
__u64 end_of_file = le64_to_cpu(info->EndOfFile); __u64 end_of_file = le64_to_cpu(info->EndOfFile);
inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime)); inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime);
inode->i_mtime = inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime)); cifs_NTtimeToUnix(info->LastModificationTime);
inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange)); inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
inode->i_mode = le64_to_cpu(info->Permissions); inode->i_mode = le64_to_cpu(info->Permissions);
/* /*
...@@ -554,14 +554,11 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -554,14 +554,11 @@ int cifs_get_inode_info(struct inode **pinode,
/* Linux can not store file creation time so ignore it */ /* Linux can not store file creation time so ignore it */
if (pfindData->LastAccessTime) if (pfindData->LastAccessTime)
inode->i_atime = cifs_NTtimeToUnix inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
(le64_to_cpu(pfindData->LastAccessTime));
else /* do not need to use current_fs_time - time not stored */ else /* do not need to use current_fs_time - time not stored */
inode->i_atime = CURRENT_TIME; inode->i_atime = CURRENT_TIME;
inode->i_mtime = inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
cFYI(DBG2, ("Attributes came in as 0x%x", attr)); cFYI(DBG2, ("Attributes came in as 0x%x", attr));
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
...@@ -629,7 +626,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -629,7 +626,7 @@ int cifs_get_inode_info(struct inode **pinode,
/* fill in 0777 bits from ACL */ /* fill in 0777 bits from ACL */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
cFYI(1, ("Getting mode bits from ACL")); cFYI(1, ("Getting mode bits from ACL"));
acl_to_uid_mode(inode, full_path, pfid); acl_to_uid_mode(cifs_sb, inode, full_path, pfid);
} }
#endif #endif
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
...@@ -699,7 +696,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) ...@@ -699,7 +696,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
} }
/* gets root inode */ /* gets root inode */
struct inode *cifs_iget(struct super_block *sb, unsigned long ino) struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
{ {
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
......
...@@ -853,12 +853,12 @@ smbCalcSize_LE(struct smb_hdr *ptr) ...@@ -853,12 +853,12 @@ smbCalcSize_LE(struct smb_hdr *ptr)
#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
/* /*
* Convert the NT UTC (based 1601-01-01, in hundred nanosecond units) * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
* into Unix UTC (based 1970-01-01, in seconds). * into Unix UTC (based 1970-01-01, in seconds).
*/ */
struct timespec struct timespec
cifs_NTtimeToUnix(u64 ntutc) cifs_NTtimeToUnix(__le64 ntutc)
{ {
struct timespec ts; struct timespec ts;
/* BB what about the timezone? BB */ /* BB what about the timezone? BB */
...@@ -866,7 +866,7 @@ cifs_NTtimeToUnix(u64 ntutc) ...@@ -866,7 +866,7 @@ cifs_NTtimeToUnix(u64 ntutc)
/* Subtract the NTFS time offset, then convert to 1s intervals. */ /* Subtract the NTFS time offset, then convert to 1s intervals. */
u64 t; u64 t;
t = ntutc - NTFS_TIME_OFFSET; t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
ts.tv_nsec = do_div(t, 10000000) * 100; ts.tv_nsec = do_div(t, 10000000) * 100;
ts.tv_sec = t; ts.tv_sec = t;
return ts; return ts;
...@@ -883,16 +883,12 @@ cifs_UnixTimeToNT(struct timespec t) ...@@ -883,16 +883,12 @@ cifs_UnixTimeToNT(struct timespec t)
static int total_days_of_prev_months[] = static int total_days_of_prev_months[] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
{
return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
}
struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
{ {
struct timespec ts; struct timespec ts;
int sec, min, days, month, year; int sec, min, days, month, year;
u16 date = le16_to_cpu(le_date);
u16 time = le16_to_cpu(le_time);
SMB_TIME *st = (SMB_TIME *)&time; SMB_TIME *st = (SMB_TIME *)&time;
SMB_DATE *sd = (SMB_DATE *)&date; SMB_DATE *sd = (SMB_DATE *)&date;
...@@ -933,7 +929,7 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) ...@@ -933,7 +929,7 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
sec += 24 * 60 * 60 * days; sec += 24 * 60 * 60 * days;
ts.tv_sec = sec; ts.tv_sec = sec + offset;
/* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */ /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
......
...@@ -115,17 +115,6 @@ construct_dentry(struct qstr *qstring, struct file *file, ...@@ -115,17 +115,6 @@ construct_dentry(struct qstr *qstring, struct file *file,
return rc; return rc;
} }
static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
{
if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
}
return;
}
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
char *buf, unsigned int *pobject_type, int isNewInode) char *buf, unsigned int *pobject_type, int isNewInode)
{ {
...@@ -150,26 +139,25 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -150,26 +139,25 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
allocation_size = le64_to_cpu(pfindData->AllocationSize); allocation_size = le64_to_cpu(pfindData->AllocationSize);
end_of_file = le64_to_cpu(pfindData->EndOfFile); end_of_file = le64_to_cpu(pfindData->EndOfFile);
tmp_inode->i_atime = tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); cifs_NTtimeToUnix(pfindData->LastAccessTime);
tmp_inode->i_mtime = tmp_inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); cifs_NTtimeToUnix(pfindData->LastWriteTime);
tmp_inode->i_ctime = tmp_inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); cifs_NTtimeToUnix(pfindData->ChangeTime);
} else { /* legacy, OS2 and DOS style */ } else { /* legacy, OS2 and DOS style */
/* struct timespec ts;*/ int offset = cifs_sb->tcon->ses->server->timeAdj;
FIND_FILE_STANDARD_INFO *pfindData = FIND_FILE_STANDARD_INFO *pfindData =
(FIND_FILE_STANDARD_INFO *)buf; (FIND_FILE_STANDARD_INFO *)buf;
tmp_inode->i_mtime = cnvrtDosUnixTm( tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
le16_to_cpu(pfindData->LastWriteDate), pfindData->LastWriteTime,
le16_to_cpu(pfindData->LastWriteTime)); offset);
tmp_inode->i_atime = cnvrtDosUnixTm( tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
le16_to_cpu(pfindData->LastAccessDate), pfindData->LastAccessTime,
le16_to_cpu(pfindData->LastAccessTime)); offset);
tmp_inode->i_ctime = cnvrtDosUnixTm( tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
le16_to_cpu(pfindData->LastWriteDate), pfindData->LastWriteTime,
le16_to_cpu(pfindData->LastWriteTime)); offset);
AdjustForTZ(cifs_sb->tcon, tmp_inode);
attr = le16_to_cpu(pfindData->Attributes); attr = le16_to_cpu(pfindData->Attributes);
allocation_size = le32_to_cpu(pfindData->AllocationSize); allocation_size = le32_to_cpu(pfindData->AllocationSize);
end_of_file = le32_to_cpu(pfindData->DataSize); end_of_file = le32_to_cpu(pfindData->DataSize);
...@@ -331,11 +319,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -331,11 +319,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
local_size = tmp_inode->i_size; local_size = tmp_inode->i_size;
tmp_inode->i_atime = tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); cifs_NTtimeToUnix(pfindData->LastAccessTime);
tmp_inode->i_mtime = tmp_inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime)); cifs_NTtimeToUnix(pfindData->LastModificationTime);
tmp_inode->i_ctime = tmp_inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange)); cifs_NTtimeToUnix(pfindData->LastStatusChange);
tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
/* since we set the inode type below we need to mask off type /* since we set the inode type below we need to mask off type
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment