提交 ddbb8684 编写于 作者: L 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
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
------------
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
session setup to distinguish multiple mounts to same server from different
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).
Performance of file create to Samba improved (posix create on lookup
removes 1 of 2 network requests sent on file create)
Version 1.57
------------
......
......@@ -262,7 +262,8 @@ A partial list of the supported mount options follows:
mount.
domain Set the SMB/CIFS workgroup name prepended to the
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
properly configured Samba server, the server provides
the uid, gid and mode so this parameter should not be
......@@ -292,6 +293,12 @@ A partial list of the supported mount options follows:
the client. Note that the mount.cifs helper must be
at version 1.10 or higher to support specifying the uid
(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).
file_mode If CIFS Unix extensions are not supported by the server
this overrides the default mode for file inodes.
......@@ -388,8 +395,13 @@ A partial list of the supported mount options follows:
or the CIFS Unix Extensions equivalent and for those
this mount option will have no effect. Exporting cifs mounts
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
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
the client will attempt to set the effective uid and gid of
the local process on newly created files, directories, and
......
......@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <keys/user-type.h>
#include <linux/key-type.h>
#include <linux/inet.h>
#include "cifsglob.h"
#include "cifs_spnego.h"
#include "cifs_debug.h"
......@@ -73,9 +74,6 @@ struct key_type cifs_spnego_key_type = {
* strlen(";sec=ntlmsspi") */
#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=" */
#define HOST_KEY_LEN 5
......@@ -102,7 +100,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
host=hostname sec=mechanism uid=0xFF user=username */
desc_len = MAX_VER_STR_LEN +
HOST_KEY_LEN + strlen(hostname) +
IP_KEY_LEN + MAX_IPV6_ADDR_LEN +
IP_KEY_LEN + INET6_ADDRSTRLEN +
MAX_MECH_STR_LEN +
UID_KEY_LEN + (sizeof(uid_t) * 2) +
USER_KEY_LEN + strlen(sesInfo->userName) + 1;
......
......@@ -552,130 +552,138 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
return rc;
}
/* Retrieve an ACL from the server */
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
const char *path, const __u16 *pfid)
static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
__u16 fid, u32 *pacllen)
{
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;
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)
return NULL;
cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
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();
if (pfid == NULL)
open_file = find_readable_file(CIFS_I(inode));
else
fid = *pfid;
sb = inode->i_sb;
if (sb == NULL) {
FreeXid(xid);
return NULL;
}
cifs_sb = CIFS_SB(sb);
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 = 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) {
cERROR(1, ("Unable to open file to get ACL"));
goto out;
}
rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, 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);
return pntsd;
}
/* Set an ACL on the server */
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
struct inode *inode, const char *path)
/* Retrieve an ACL from the server */
static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct inode *inode, const char *path,
u32 *pacllen)
{
struct cifsFileInfo *open_file;
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 cifsFileInfo *open_file = NULL;
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)
return rc;
pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
atomic_dec(&open_file->wrtPending);
return pntsd;
}
sb = inode->i_sb;
if (sb == NULL)
return rc;
static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
struct cifs_ntsd *pnntsd, u32 acllen)
{
int xid, rc;
cifs_sb = CIFS_SB(sb);
xid = GetXid();
rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
FreeXid(xid);
open_file = find_readable_file(CIFS_I(inode));
if (open_file) {
unlock_file = true;
fid = open_file->netfid;
} else {
int oplock = 0;
/* open file */
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
WRITE_DAC, 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 set ACL"));
FreeXid(xid);
return rc;
}
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
return rc;
}
static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
struct cifs_ntsd *pnntsd, u32 acllen)
{
int oplock = 0;
int xid, rc;
__u16 fid;
xid = GetXid();
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
&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);
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);
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;
}
/* 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;
u32 acllen = 0;
int rc = 0;
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 (pntsd)
......@@ -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));
/* 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
other ACEs as chmod disables ACEs and set the security descriptor */
......
......@@ -146,7 +146,7 @@ cifs_read_super(struct super_block *sb, void *data,
#endif
sb->s_blocksize = 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)) {
rc = PTR_ERR(inode);
......
......@@ -36,7 +36,7 @@ extern void cifs_read_inode(struct inode *);
/* Functions related to inodes */
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,
struct nameidata *);
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);
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
#define CIFS_VERSION "1.58"
#define CIFS_VERSION "1.59"
#endif /* _CIFSFS_H */
......@@ -90,10 +90,10 @@ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *);
extern void DeleteOplockQEntry(struct oplock_q_entry *);
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 __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
int offset);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct super_block *sb, int mode, int oflags,
......@@ -108,8 +108,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, int xid);
extern void acl_to_uid_mode(struct inode *inode, const char *path,
const __u16 *pfid);
extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
const char *path, const __u16 *pfid);
extern int mode_to_acl(struct inode *inode, const char *path, __u64);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
......
......@@ -524,8 +524,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
int val, seconds, remain, result;
struct timespec ts, utc;
utc = CURRENT_TIME;
ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
le16_to_cpu(rsp->SrvTime.Time));
ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
rsp->SrvTime.Time, 0);
cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
(int)ts.tv_sec, (int)utc.tv_sec,
(int)(utc.tv_sec - ts.tv_sec)));
......@@ -2427,8 +2427,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
/* BB find exact max data count below from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......
......@@ -35,6 +35,7 @@
#include <linux/namei.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <linux/inet.h>
#include <net/ipv6.h>
#include "cifspdu.h"
#include "cifsglob.h"
......@@ -61,7 +62,6 @@ struct smb_vol {
char *domainname;
char *UNC;
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 source_rfc1001_name[16]; /* netbios name of client */
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,
vol->target_rfc1001_name[0] = 0;
vol->linux_uid = current_uid(); /* use current_euid() instead? */
vol->linux_gid = current_gid();
vol->dir_mode = S_IRWXUGO;
/* 2767 perms indicate mandatory locking support */
vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
/* default to only allowing write access to owner of the mount */
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->rw = true;
/* default is always to request posix paths. */
vol->posix_paths = 1;
/* default to using server inode numbers where available */
vol->server_ino = 1;
if (!options)
return 1;
......@@ -955,10 +957,12 @@ cifs_parse_mount_options(char *options, const char *devname,
}
strcpy(vol->password, value);
}
} else if (strnicmp(data, "ip", 2) == 0) {
} else if (!strnicmp(data, "ip", 2) ||
!strnicmp(data, "addr", 4)) {
if (!value || !*value) {
vol->UNCip = NULL;
} else if (strnlen(value, 35) < 35) {
} else if (strnlen(value, INET6_ADDRSTRLEN) <
INET6_ADDRSTRLEN) {
vol->UNCip = value;
} else {
printk(KERN_WARNING "CIFS: ip address "
......@@ -1092,17 +1096,17 @@ cifs_parse_mount_options(char *options, const char *devname,
return 1;
}
} else if (strnicmp(data, "uid", 3) == 0) {
if (value && *value) {
if (value && *value)
vol->linux_uid =
simple_strtoul(value, &value, 0);
} else if (strnicmp(data, "forceuid", 8) == 0) {
vol->override_uid = 1;
}
} else if (strnicmp(data, "gid", 3) == 0) {
if (value && *value) {
if (value && *value)
vol->linux_gid =
simple_strtoul(value, &value, 0);
} else if (strnicmp(data, "forcegid", 8) == 0) {
vol->override_gid = 1;
}
} else if (strnicmp(data, "file_mode", 4) == 0) {
if (value && *value) {
vol->file_mode =
......@@ -1315,16 +1319,6 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->direct_io = 1;
} else if (strnicmp(data, "forcedirectio", 13) == 0) {
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) {
printk(KERN_WARNING "CIFS: Mount option noac not "
"supported. Instead set "
......
......@@ -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? */
/* if not oplocked, invalidate inode pages if mtime or file
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) &&
(file->f_path.dentry->d_inode->i_size ==
(loff_t)le64_to_cpu(buf->EndOfFile))) {
......
......@@ -85,10 +85,10 @@ static void cifs_unix_info_to_inode(struct inode *inode,
__u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
__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 =
cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime));
inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange));
cifs_NTtimeToUnix(info->LastModificationTime);
inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
inode->i_mode = le64_to_cpu(info->Permissions);
/*
......@@ -554,14 +554,11 @@ int cifs_get_inode_info(struct inode **pinode,
/* Linux can not store file creation time so ignore it */
if (pfindData->LastAccessTime)
inode->i_atime = cifs_NTtimeToUnix
(le64_to_cpu(pfindData->LastAccessTime));
inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
else /* do not need to use current_fs_time - time not stored */
inode->i_atime = CURRENT_TIME;
inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
cFYI(DBG2, ("Attributes came in as 0x%x", attr));
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
......@@ -629,7 +626,7 @@ int cifs_get_inode_info(struct inode **pinode,
/* fill in 0777 bits from ACL */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_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
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)
}
/* 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;
struct cifs_sb_info *cifs_sb;
......
......@@ -853,12 +853,12 @@ smbCalcSize_LE(struct smb_hdr *ptr)
#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
/*
* Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
* into Unix UTC (based 1970-01-01, in seconds).
*/
/*
* Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
* into Unix UTC (based 1970-01-01, in seconds).
*/
struct timespec
cifs_NTtimeToUnix(u64 ntutc)
cifs_NTtimeToUnix(__le64 ntutc)
{
struct timespec ts;
/* BB what about the timezone? BB */
......@@ -866,7 +866,7 @@ cifs_NTtimeToUnix(u64 ntutc)
/* Subtract the NTFS time offset, then convert to 1s intervals. */
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_sec = t;
return ts;
......@@ -883,16 +883,12 @@ cifs_UnixTimeToNT(struct timespec t)
static int total_days_of_prev_months[] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
{
return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
}
struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
{
struct timespec ts;
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_DATE *sd = (SMB_DATE *)&date;
......@@ -933,7 +929,7 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
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)); */
......
......@@ -115,17 +115,6 @@ construct_dentry(struct qstr *qstring, struct file *file,
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,
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,
allocation_size = le64_to_cpu(pfindData->AllocationSize);
end_of_file = le64_to_cpu(pfindData->EndOfFile);
tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
cifs_NTtimeToUnix(pfindData->LastAccessTime);
tmp_inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
cifs_NTtimeToUnix(pfindData->LastWriteTime);
tmp_inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
cifs_NTtimeToUnix(pfindData->ChangeTime);
} 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 *)buf;
tmp_inode->i_mtime = cnvrtDosUnixTm(
le16_to_cpu(pfindData->LastWriteDate),
le16_to_cpu(pfindData->LastWriteTime));
tmp_inode->i_atime = cnvrtDosUnixTm(
le16_to_cpu(pfindData->LastAccessDate),
le16_to_cpu(pfindData->LastAccessTime));
tmp_inode->i_ctime = cnvrtDosUnixTm(
le16_to_cpu(pfindData->LastWriteDate),
le16_to_cpu(pfindData->LastWriteTime));
AdjustForTZ(cifs_sb->tcon, tmp_inode);
tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
pfindData->LastWriteTime,
offset);
tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
pfindData->LastAccessTime,
offset);
tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
pfindData->LastWriteTime,
offset);
attr = le16_to_cpu(pfindData->Attributes);
allocation_size = le32_to_cpu(pfindData->AllocationSize);
end_of_file = le32_to_cpu(pfindData->DataSize);
......@@ -331,11 +319,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
local_size = tmp_inode->i_size;
tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
cifs_NTtimeToUnix(pfindData->LastAccessTime);
tmp_inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
cifs_NTtimeToUnix(pfindData->LastModificationTime);
tmp_inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
cifs_NTtimeToUnix(pfindData->LastStatusChange);
tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
/* since we set the inode type below we need to mask off type
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册