static void cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, struct cifs_sb_info *cifs_sb) { int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj; memset(fattr, 0, sizeof(*fattr)); fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, info->LastAccessTime, offset); fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, info->LastWriteTime, offset); fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, info->LastWriteTime, offset); fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); fattr->cf_bytes = le32_to_cpu(info->AllocationSize); fattr->cf_eof = le32_to_cpu(info->DataSize); cifs_fill_common_info(fattr, cifs_sb); }
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, char *buf, unsigned int *pobject_type, int isNewInode) { loff_t local_size; struct timespec local_mtime; struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); __u32 attr; __u64 allocation_size; __u64 end_of_file; umode_t default_mode; /* save mtime and size */ local_mtime = tmp_inode->i_mtime; local_size = tmp_inode->i_size; if (new_buf_type) { FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf; attr = le32_to_cpu(pfindData->ExtFileAttributes); 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)); tmp_inode->i_mtime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); tmp_inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); } else { /* legacy, OS2 and DOS style */ /* struct timespec ts;*/ 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); attr = le16_to_cpu(pfindData->Attributes); allocation_size = le32_to_cpu(pfindData->AllocationSize); end_of_file = le32_to_cpu(pfindData->DataSize); } /* Linux can not store file creation time unfortunately so ignore it */ cifsInfo->cifsAttrs = attr; #ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { /* get more accurate mode via ACL - so force inode refresh */ cifsInfo->time = 0; } else #endif /* CONFIG_CIFS_EXPERIMENTAL */ cifsInfo->time = jiffies; /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ /* 2767 perms - indicate mandatory locking */ /* BB fill in uid and gid here? with help from winbind? or retrieve from NTFS stream extended attribute */ if (atomic_read(&cifsInfo->inUse) == 0) { tmp_inode->i_uid = cifs_sb->mnt_uid; tmp_inode->i_gid = cifs_sb->mnt_gid; } if (attr & ATTR_DIRECTORY) default_mode = cifs_sb->mnt_dir_mode; else default_mode = cifs_sb->mnt_file_mode; /* set initial permissions */ if ((atomic_read(&cifsInfo->inUse) == 0) || (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) tmp_inode->i_mode = default_mode; else { /* just reenable write bits if !ATTR_READONLY */ if ((tmp_inode->i_mode & S_IWUGO) == 0 && (attr & ATTR_READONLY) == 0) tmp_inode->i_mode |= (S_IWUGO & default_mode); tmp_inode->i_mode &= ~S_IFMT; } /* clear write bits if ATTR_READONLY is set */ if (attr & ATTR_READONLY) tmp_inode->i_mode &= ~S_IWUGO; /* set inode type */ if ((attr & ATTR_SYSTEM) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { if (end_of_file == 0) { tmp_inode->i_mode |= S_IFIFO; *pobject_type = DT_FIFO; } else { /* * trying to get the type can be slow, so just call * this a regular file for now, and mark for reval */ tmp_inode->i_mode |= S_IFREG; *pobject_type = DT_REG; cifsInfo->time = 0; } } else { if (attr & ATTR_DIRECTORY) { tmp_inode->i_mode |= S_IFDIR; *pobject_type = DT_DIR; } else { tmp_inode->i_mode |= S_IFREG; *pobject_type = DT_REG; } } /* can not fill in nlink here as in qpathinfo version and Unx search */ if (atomic_read(&cifsInfo->inUse) == 0) atomic_set(&cifsInfo->inUse, 1); spin_lock(&tmp_inode->i_lock); if (is_size_safe_to_change(cifsInfo, end_of_file)) { /* can not safely change the file size here if the client is writing to it due to potential races */ i_size_write(tmp_inode, end_of_file); /* 512 bytes (2**9) is the fake blocksize that must be used */ /* for this calculation, even though the reported blocksize is larger */ tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; } spin_unlock(&tmp_inode->i_lock); if (allocation_size < end_of_file) cFYI(1, ("May be sparse file, allocation less than file size")); cFYI(1, ("File Size %ld and blocks %llu", (unsigned long)tmp_inode->i_size, (unsigned long long)tmp_inode->i_blocks)); if (S_ISREG(tmp_inode->i_mode)) { cFYI(1, ("File inode")); tmp_inode->i_op = &cifs_file_inode_ops; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; else tmp_inode->i_fop = &cifs_file_direct_ops; } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) tmp_inode->i_fop = &cifs_file_nobrl_ops; else tmp_inode->i_fop = &cifs_file_ops; if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server->maxBuf < PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; else tmp_inode->i_data.a_ops = &cifs_addr_ops; if (isNewInode) return; /* No sense invalidating pages for new inode since have not started caching readahead file data yet */ if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && (local_size == tmp_inode->i_size)) { cFYI(1, ("inode exists but unchanged")); } else { /* file may have changed on server */ cFYI(1, ("invalidate inode, readdir detected change")); invalidate_remote_inode(tmp_inode); } } else if (S_ISDIR(tmp_inode->i_mode)) { cFYI(1, ("Directory inode")); tmp_inode->i_op = &cifs_dir_inode_ops; tmp_inode->i_fop = &cifs_dir_ops; } else if (S_ISLNK(tmp_inode->i_mode)) { cFYI(1, ("Symbolic Link inode")); tmp_inode->i_op = &cifs_symlink_inode_ops; } else { cFYI(1, ("Init special inode")); init_special_inode(tmp_inode, tmp_inode->i_mode, tmp_inode->i_rdev); } }
__le64 cnvrtDosCifsTm(__u16 date, __u16 time) { return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time))); }