14 #include <linux/time.h>
15 #include <linux/errno.h>
16 #include <linux/stat.h>
17 #include <linux/kernel.h>
21 #include <asm/uaccess.h>
22 #include <asm/byteorder.h>
26 static void ncp_read_volume_list(
struct file *,
void *,
filldir_t,
35 static int ncp_unlink(
struct inode *,
struct dentry *);
37 static int ncp_rmdir(
struct inode *,
struct dentry *);
38 static int ncp_rename(
struct inode *,
struct dentry *,
42 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
45 #define ncp_symlink NULL
52 .readdir = ncp_readdir,
75 static int ncp_lookup_validate(
struct dentry *,
unsigned int);
76 static int ncp_hash_dentry(
const struct dentry *,
const struct inode *,
78 static int ncp_compare_dentry(
const struct dentry *,
const struct inode *,
80 unsigned int,
const char *,
const struct qstr *);
81 static int ncp_delete_dentry(
const struct dentry *);
85 .d_revalidate = ncp_lookup_validate,
86 .d_hash = ncp_hash_dentry,
87 .d_compare = ncp_compare_dentry,
88 .d_delete = ncp_delete_dentry,
91 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
93 static inline int ncp_preserve_entry_case(
struct inode *
i,
__u32 nscreator)
95 #ifdef CONFIG_NCPFS_SMALLDOS
99 #ifdef CONFIG_NCPFS_OS2_NS
108 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
110 static inline int ncp_case_sensitive(
const struct inode *
i)
112 #ifdef CONFIG_NCPFS_NFS_NS
127 if (!ncp_case_sensitive(inode)) {
135 for (i=0; i<this->
len ; i++)
138 this->hash = end_name_hash(hash);
144 ncp_compare_dentry(
const struct dentry *parent,
const struct inode *pinode,
145 const struct dentry *dentry,
const struct inode *inode,
146 unsigned int len,
const char *
str,
const struct qstr *
name)
148 if (len != name->len)
151 if (ncp_case_sensitive(pinode))
163 ncp_delete_dentry(
const struct dentry * dentry)
165 struct inode *inode = dentry->
d_inode;
180 return (server->
m.mounted_vol[0] !=
'\0');
183 static inline int ncp_is_server_root(
struct inode *inode)
185 return (!ncp_single_volume(
NCP_SERVER(inode)) &&
186 inode == inode->
i_sb->s_root->d_inode);
195 #ifdef CONFIG_NCPFS_STRONG
199 ncp_force_unlink(
struct inode *dir,
struct dentry* dentry)
211 old_nwattr = NCP_FINFO(inode)->nwattr;
222 info.attributes = old_nwattr;
232 #ifdef CONFIG_NCPFS_STRONG
234 ncp_force_rename(
struct inode *old_dir,
struct dentry* old_dentry,
char *_old_name,
235 struct inode *new_dir,
struct dentry* new_dentry,
char *_new_name)
239 struct inode *old_inode = old_dentry->
d_inode;
240 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
242 int old_nwattr_changed = 0;
243 int new_nwattr_changed = 0;
252 old_nwattr_changed = 1;
253 if (new_dentry && new_dentry->
d_inode) {
254 new_nwattr = NCP_FINFO(new_dentry->
d_inode)->nwattr;
258 new_nwattr_changed = 1;
262 if (new_nwattr_changed || old_nwattr_changed) {
272 new_nwattr_changed = old_nwattr_changed;
273 new_nwattr = old_nwattr;
274 old_nwattr_changed = 0;
277 if (old_nwattr_changed) {
278 info.attributes = old_nwattr;
282 if (new_nwattr_changed) {
283 info.attributes = new_nwattr;
293 ncp_lookup_validate(
struct dentry *dentry,
unsigned int flags)
296 struct dentry *parent;
302 if (dentry == dentry->
d_sb->s_root)
326 DDPRINTK(
"ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
330 len =
sizeof(__name);
331 if (ncp_is_server_root(dir)) {
345 finfo.volume = finfo.i.volNumber;
346 DDPRINTK(
"ncp_lookup_validate: looked for %s/%s, res=%d\n",
347 dentry->
d_parent->d_name.name, __name, res);
353 struct inode *inode = dentry->
d_inode;
356 if (finfo.i.dirEntNum == NCP_FINFO(inode)->
dirEntNum) {
357 ncp_new_dentry(dentry);
360 DDPRINTK(
"ncp_lookup_validate: found, but dirEntNum changed\n");
367 DDPRINTK(
"ncp_lookup_validate: result=%d\n", val);
372 static struct dentry *
373 ncp_dget_fpos(
struct dentry *dentry,
struct dentry *parent,
unsigned long fpos)
375 struct dentry *dent = dentry;
380 (
unsigned long)dent->
d_fsdata == fpos) {
391 spin_lock(&parent->
d_lock);
395 if ((
unsigned long)dent->
d_fsdata == fpos) {
400 spin_unlock(&parent->
d_lock);
405 spin_unlock(&parent->
d_lock);
412 static time_t ncp_obtain_mtime(
struct dentry *dentry)
414 struct inode *inode = dentry->
d_inode;
418 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
429 struct dentry *dentry = filp->
f_path.dentry;
430 struct inode *inode = dentry->
d_inode;
435 int result, mtime_valid = 0;
441 DDPRINTK(
"ncp_readdir: reading %s/%s, pos=%d\n",
447 if (!ncp_conn_valid(server))
451 if (filp->
f_pos == 0) {
452 if (filldir(dirent,
".", 1, 0, inode->
i_ino,
DT_DIR))
456 if (filp->
f_pos == 1) {
462 page = grab_cache_page(&inode->
i_data, 0);
466 ctl.cache = cache =
kmap(page);
469 if (!PageUptodate(page) || !
ctl.head.eof)
472 if (filp->
f_pos == 2) {
476 mtime = ncp_obtain_mtime(dentry);
478 if ((!mtime) || (mtime !=
ctl.head.mtime))
495 if (!PageUptodate(
ctl.page))
502 dent = ncp_dget_fpos(
ctl.cache->dentry[
ctl.idx],
503 dentry, filp->
f_pos);
506 res = filldir(dirent, dent->
d_name.name,
519 SetPageUptodate(
ctl.page);
536 ncp_invalidate_dircache_entries(dentry);
538 mtime = ncp_obtain_mtime(dentry);
550 if (ncp_is_server_root(inode)) {
551 ncp_read_volume_list(filp, dirent, filldir, &
ctl);
553 ncp_do_readdir(filp, dirent, filldir, &
ctl);
555 ctl.head.end =
ctl.fpos - 1;
560 SetPageUptodate(
ctl.page);
567 SetPageUptodate(page);
576 ncp_fill_cache(
struct file *filp,
void *dirent,
filldir_t filldir,
580 struct dentry *newdent, *dentry = filp->
f_path.dentry;
581 struct inode *dir = dentry->
d_inode;
589 qname.len =
sizeof(__name);
591 entry->
i.entryName, entry->
i.nameLen,
592 !ncp_preserve_entry_case(dir, entry->
i.NSCreator)))
598 if (dentry->
d_op && dentry->
d_op->d_hash)
599 if (dentry->
d_op->d_hash(dentry, dentry->
d_inode, &qname) != 0)
605 newdent =
d_alloc(dentry, &qname);
638 struct inode *inode = newdent->
d_inode;
648 ncp_new_dentry(newdent);
654 SetPageUptodate(ctl.
page);
678 ctl.
filled = filldir(dirent, qname.name, qname.len,
690 ncp_read_volume_list(
struct file *filp,
void *dirent,
filldir_t filldir,
693 struct dentry *dentry = filp->
f_path.dentry;
694 struct inode *inode = dentry->
d_inode;
700 DPRINTK(
"ncp_read_volume_list: pos=%ld\n",
701 (
unsigned long) filp->
f_pos);
711 DPRINTK(
"ncp_read_volume_list: found vol: %s\n",
716 DPRINTK(
"ncpfs: could not lookup vol %s\n",
721 entry.
volume = entry.
i.volNumber;
722 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
728 ncp_do_readdir(
struct file *filp,
void *dirent,
filldir_t filldir,
731 struct dentry *dentry = filp->
f_path.dentry;
732 struct inode *dir = dentry->
d_inode;
741 DPRINTK(
"ncp_do_readdir: %s/%s, fpos=%ld\n",
743 (
unsigned long) filp->
f_pos);
744 PPRINTK(
"ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
750 DPRINTK(
"ncp_do_readdir: init failed, err=%d\n", err);
784 entry.
volume = entry.
i.volNumber;
785 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
798 if (ncp_single_volume(server)) {
806 len =
sizeof(__name);
807 result =
ncp_io2vol(server, __name, &len, server->
m.mounted_vol,
808 strlen(server->
m.mounted_vol), 1);
813 PPRINTK(
"ncp_conn_logged_in: %s not found\n",
814 server->
m.mounted_vol);
819 struct inode* ino = dent->
d_inode;
827 DPRINTK(
"ncpfs: sb->s_root->d_inode == NULL!\n");
830 DPRINTK(
"ncpfs: sb->s_root == NULL!\n");
839 static struct dentry *ncp_lookup(
struct inode *dir,
struct dentry *dentry,
unsigned int flags)
842 struct inode *inode =
NULL;
848 if (!ncp_conn_valid(server))
851 PPRINTK(
"ncp_lookup: server lookup for %s/%s\n",
854 len =
sizeof(__name);
855 if (ncp_is_server_root(dir)) {
868 PPRINTK(
"ncp_lookup: looked for %s/%s, res=%d\n",
869 dentry->
d_parent->d_name.name, __name, res);
881 finfo.volume = finfo.i.volNumber;
886 ncp_new_dentry(dentry);
888 d_add(dentry, inode);
893 PPRINTK(
"ncp_lookup: result=%d\n", error);
894 return ERR_PTR(error);
900 static int ncp_instantiate(
struct inode *dir,
struct dentry *dentry,
916 PPRINTK(
"ncp_instantiate: %s/%s failed, closing file\n",
931 PPRINTK(
"ncp_create_new: creating %s/%s, mode=%hx\n",
934 ncp_age_dentry(server, dentry);
935 len =
sizeof(__name);
961 DPRINTK(
"ncp_create: %s/%s failed\n",
968 if (ncp_is_nfs_extras(server, finfo.
volume)) {
969 finfo.
i.nfs.mode =
mode;
970 finfo.
i.nfs.rdev = new_encode_dev(rdev);
973 mode, new_encode_dev(rdev)) != 0)
977 error = ncp_instantiate(dir, dentry, &finfo);
982 static int ncp_create(
struct inode *dir,
struct dentry *dentry,
umode_t mode,
988 static int ncp_mkdir(
struct inode *dir,
struct dentry *dentry,
umode_t mode)
995 DPRINTK(
"ncp_mkdir: making %s/%s\n",
998 ncp_age_dentry(server, dentry);
999 len =
sizeof(__name);
1010 if (ncp_is_nfs_extras(server, finfo.
volume)) {
1012 finfo.
i.nfs.mode =
mode;
1019 error = ncp_instantiate(dir, dentry, &finfo);
1020 }
else if (error > 0) {
1027 static int ncp_rmdir(
struct inode *dir,
struct dentry *dentry)
1033 DPRINTK(
"ncp_rmdir: removing %s/%s\n",
1042 if (!d_unhashed(dentry))
1045 len =
sizeof(__name);
1074 error = result < 0 ? result : -
EACCES;
1081 static int ncp_unlink(
struct inode *dir,
struct dentry *dentry)
1083 struct inode *inode = dentry->
d_inode;
1088 DPRINTK(
"ncp_unlink: unlinking %s/%s\n",
1095 PPRINTK(
"ncp_unlink: closing file\n");
1100 #ifdef CONFIG_NCPFS_STRONG
1104 error = ncp_force_unlink(dir, dentry);
1109 DPRINTK(
"ncp: removed %s/%s\n",
1129 error = error < 0 ? error : -
EACCES;
1135 static int ncp_rename(
struct inode *old_dir,
struct dentry *old_dentry,
1136 struct inode *new_dir,
struct dentry *new_dentry)
1140 int old_len, new_len;
1143 DPRINTK(
"ncp_rename: %s/%s to %s/%s\n",
1154 if (!d_unhashed(new_dentry))
1158 ncp_age_dentry(server, old_dentry);
1159 ncp_age_dentry(server, new_dentry);
1161 old_len =
sizeof(__old_name);
1162 error =
ncp_io2vol(server, __old_name, &old_len,
1168 new_len =
sizeof(__new_name);
1169 error =
ncp_io2vol(server, __new_name, &new_len,
1176 new_dir, __new_name);
1177 #ifdef CONFIG_NCPFS_STRONG
1178 if ((error == 0x90 || error == 0x8B || error == -
EACCES) &&
1180 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1181 new_dir, new_dentry, __new_name);
1186 DPRINTK(
"ncp renamed %s -> %s.\n",
1196 error = error < 0 ? error : -
EACCES;
1203 static int ncp_mknod(
struct inode * dir,
struct dentry *dentry,
1206 if (!new_valid_dev(rdev))
1219 static int day_n[] =
1220 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1226 static int utc2local(
int time)
1228 return time -
sys_tz.tz_minuteswest * 60;
1231 static int local2utc(
int time)
1233 return time +
sys_tz.tz_minuteswest * 60;
1245 month = ((
date >> 5) - 1) & 15;
1247 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1248 86400 * ((
date & 31) - 1 + day_n[month] + (year / 4) +
1249 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1251 return local2utc(secs);
1261 unix_date = utc2local(unix_date);
1263 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1264 (((unix_date / 3600) % 24) << 11));
1265 day = unix_date / 86400 - 3652;
1267 if ((year + 3) / 4 + 365 * year > day)
1269 day -= (year + 3) / 4 + 365 * year;
1270 if (day == 59 && !(year & 3)) {
1274 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1275 for (month = 1; month < 12; month++)
1276 if (day_n[month] > nl_day)
1279 *date =
cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));