diff --git a/.downloads/ncpfs-0.3.tgz b/.downloads/ncpfs-0.3.tgz new file mode 100644 index 0000000..df7691e Binary files /dev/null and b/.downloads/ncpfs-0.3.tgz differ diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..cea62ba --- /dev/null +++ b/BUGS @@ -0,0 +1,17 @@ +Maybe you want to look at LIMITATIONS in README. Some might consider +them to be bugs. + +But there are really problems that might be fixed in the future. + +Invalid directory timestamps: +I did not yet find out how to get valid timestamps for directories +from a NetWare server. So I simply return 0, which means 01.01.70. If +anybody knows how to get these values, please mail +lendecke@namu01.gwdg.de. + +'df' returns 0: +Free disk space is distributed among the volumes in NetWare. df is +only able to report one number per mounted filesystem. As connections +are quite expensive for NetWare (with lwared that might change ...), I +rejected the alternative to mount only a single volume for a unix +mount point. So I simply return 0. diff --git a/Changes b/Changes index c9af799..9c6a84c 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,10 @@ +ncpfs-0.2 -> ncpfs-0.3 + +- removed bug in get_pname_static +- removed bug in 'ncpmount -n' +- fake '.' and '..' +- return 0 for df and directory timestamps. See file BUGS + ncpfs-0.1 -> ncpfs-0.2 - should be compileable with gcc other than 2.7.0 diff --git a/Makefile b/Makefile index f41c49e..81f1dfc 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ INCLUDES = -I/usr/src/linux/include CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \ $(INCLUDES) \ - -DDEBUG_NCP_MALLOC # -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC +# -DDEBUG_NCP_MALLOC CC = gcc -D__KERNEL__ -I. AS = as @@ -52,7 +52,7 @@ clean: rm -f *.o *~ realclean: clean - rm -fr ncpmount ncptest .depend $(DISTFILE) mnt + rm -fr ncpmount ncptest .depend $(DISTFILE) mnt *.out modules: ncpfs.o diff --git a/README b/README index ffdb0cb..e57e845 100644 --- a/README +++ b/README @@ -17,13 +17,46 @@ I use tools written by Greg Page, Caldera. I hope I did not do too much harm to their business. For your convenience I included the file ipx.tar made available by Caldera. -For the curious: the file ncplib.c is usable from user space as well! -Look at the file ncptest.c for a possible use. I use ncptest to check -my assumptions about the widely undocumented NetWare Core -Protocol. Maybe this is the beginning of a free NetWare API for Linux! -I would be happy to receive your comments on this. +My main source of information is a book written in german by Manfred +Hill and Ralf Zessin, "Netzwerkprogrammierung in C", IWT Verlag GmbH, +1995, ISBN 3-88322-491-X. It contains quite a lot of typographical and +other errors, but I find it very valuable as an introduction to NCP +programming. If you know about the concepts and possibilities of NCP, +Ralph Brown's interrupt list becomes much more readable. It's much +easier to find undocumented information if you know what to look for! -LIMITATIONS (compare these with smbfs :-)) + +MAILING LIST + +There is a mailing list for discussing lwared and ncpfs. Here's the +message I received after subscribing: + +--- +Thank you for your subscription to the list "linware". + +Topics for the list: +- discussing LinWare server, its features, installation problems and bugs +- using IPX protocol under Linux +- IPX routing and router daemons under Linux + +Send your list postings to address: "linware@sh.cvut.cz" +Send your list control commands to address: "listserv@sh.cvut.cz" +--- + +You can subscribe to this list by sending a message with a line +'add your_name@your_host linware' to listserv@sh.cvut.cz . + + +NCPLIB + +For the curious: the file ncplib.c is usable from user space as well. +Look at the file ncptest.c for a possible use. I use ncptest to check +my assumptions about the widely undocumented NetWare Core Protocol. +Maybe this is the beginning of a free NetWare API for Linux! I would +be happy to receive your comments on this. + + +LIMITATIONS (compare these with smbfs :-) The limitations ncpfs has are the natural limitations of the NCP protocol, which was designed with MS-DOS based PCs in mind. The first @@ -44,4 +77,3 @@ different. You can never know when the client will access the file-id you offered, so you would have to cache the inode numbers indefinitely long. I think this should not be done in kernel mode, as it would require an unlimited amount of RAM. - diff --git a/dir.c b/dir.c index 6b9ee20..4d96f5d 100644 --- a/dir.c +++ b/dir.c @@ -303,13 +303,34 @@ ncp_readdir(struct inode *inode, struct file *filp, } static int -ncp_read_volume_list(struct ncp_server *server, int start_with, int cache_size) +ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size) { struct ncp_dirent *entry = c_entry; int total_count = 0; int i; + void fill_one(char *name) + { + if (total_count < fpos) { + DPRINTK("ncp_do_readdir: skipped file: %s\n", name); + } else if (total_count >= fpos + cache_size) { + return; + } else { + DPRINTK("ncp_do_readdir: found file: %s\n", name); + + entry->attr = aDIR; + entry->mtime = 0; + entry->ctime = 0; + entry->atime = 0; + entry->size = 1024; + entry->f_pos = total_count; + strcpy(entry->path, name); + entry += 1; + } + total_count += 1; + } + for (i=0; i 0) { - - if (total_count < start_with) { - DPRINTK("ncp_read_volumes: skipped vol: %s\n", - info.volume_name); - } else if (total_count >= start_with + cache_size) { - return (total_count - start_with); - } else { - DPRINTK("ncp_read_volumes: found vol %s\n", - info.volume_name); - entry->attr = aDIR; - entry->mtime = 0; - entry->ctime = 0; - entry->atime = 0; - entry->size = 1024; - entry->f_pos = total_count; - strcpy(entry->path, info.volume_name); - entry += 1; - } - - total_count += 1; + fill_one(info.volume_name); } } - return (total_count - start_with); + fill_one("."); + fill_one(".."); + return (total_count - fpos); } static int @@ -353,6 +357,41 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, int total_count = 0; + void fill_one(int attr, char *name, + int upd_time, int upd_date, + int cr_date, int ac_date, int length) + { + if (total_count < fpos) { + DPRINTK("ncp_do_readdir: skipped file: %s\n", name); + } else if (total_count >= fpos + cache_size) { + return; + } else { + DPRINTK("ncp_do_readdir: found file: %s\n", name); + + entry->attr = attr; + if ((attr & aDIR) == 0) { + entry->mtime = date_dos2unix(upd_time, + upd_date); + entry->ctime = date_dos2unix(0, cr_date); + entry->atime = date_dos2unix(0, ac_date); + entry->size = length; + } else { + /* Sorry, I do not know how to get the + * values for directories :-(. Mail + * lendecke@namu01.gwdg.de if you + * know more. */ + entry->mtime = 0; + entry->ctime = 0; + entry->atime = 0; + entry->size = 1024; + } + entry->f_pos = total_count; + strcpy(entry->path, name); + entry += 1; + } + total_count += 1; + } + void doit(int attr) { if (ncp_file_search_init(server, 0, NCP_FINFO(dir)->path, @@ -363,35 +402,20 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, while (ncp_file_search_continue(server, &fsinfo, attr, "*", &finfo) == 0) { + + fill_one(attr, finfo.file_name, + finfo.update_time, finfo.update_date, + finfo.creation_date, finfo.access_date, + finfo.file_length); - if (total_count < fpos) { - DPRINTK("ncp_do_readdir: skipped file: %s\n", - finfo.file_name); - } else if (total_count >= fpos + cache_size) { - return; - } else { - DPRINTK("ncp_do_readdir: found file: %s\n", - finfo.file_name); - - entry->attr = attr; - entry->mtime = - date_dos2unix(finfo.update_time, - finfo.update_date); - entry->ctime = - date_dos2unix(0, finfo.creation_date); - entry->atime = - date_dos2unix(0, finfo.access_date); - entry->size = (attr & aDIR) != 0 ? - 1024 : finfo.file_length; - entry->f_pos = total_count; - strcpy(entry->path, finfo.file_name); - entry += 1; - } - total_count += 1; + } return; } + fill_one(aDIR, ".", 0, 0, 0, 0, 0); + fill_one(aDIR, "..", 0, 0, 0, 0, 0); + doit(0); doit(aDIR); @@ -480,7 +504,7 @@ get_pname_static(struct inode *dir, const char *name, int len, /* We're at the top */ path[0] = '\0'; - *res_len = 1; + *res_len = 0; return 0; } @@ -497,7 +521,6 @@ get_pname_static(struct inode *dir, const char *name, int len, path[len] = '\0'; } else if (parentlen == 0) { - memcpy(path, name, len); path[len] = ':'; path[len+1] = '\0'; @@ -787,10 +810,10 @@ ncp_lookup(struct inode *dir, const char *__name, int len, i, c_entry[i].path); if (strcmp(c_entry[i].path, __name) == 0) { DPRINTK("ncp_lookup: found in cache!\n"); - finfo = c_entry[i]; - finfo.path = NULL; /* It's not ours! */ - found_in_cache = 1; - break; + finfo = c_entry[i]; + finfo.path = NULL; /* It's not ours! */ + found_in_cache = 1; + break; } i = (i + 1) % c_size; DDPRINTK("ncp_lookup: index %d, name %s failed\n", diff --git a/inode.c b/inode.c index 742158d..05f9e77 100644 --- a/inode.c +++ b/inode.c @@ -34,6 +34,7 @@ extern int close_fp(struct file *filp); static void ncp_put_inode(struct inode *); static void ncp_read_inode(struct inode *); static void ncp_put_super(struct super_block *); +static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); static int ncp_notify_change(struct inode *inode, struct iattr *attr); static struct super_operations ncp_sops = { @@ -43,7 +44,7 @@ static struct super_operations ncp_sops = { ncp_put_inode, /* put inode */ ncp_put_super, /* put superblock */ NULL, /* write superblock */ - NULL, /* stat filesystem */ + ncp_statfs, /* stat filesystem */ NULL }; @@ -329,6 +330,27 @@ ncp_put_super(struct super_block *sb) MOD_DEC_USE_COUNT; } +static void +ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +{ + struct statfs tmp; + + /* We cannot say how much disk space is left on a mounted + NetWare Server, because free space is distributed over + volumes, and the current user might have disk quotas. So + free space is not that simple to determine. Our decision + here is to err conservatively. */ + + tmp.f_type = NCP_SUPER_MAGIC; + tmp.f_bsize = 512; + tmp.f_blocks = 0; + tmp.f_bfree = 0; + tmp.f_bavail = 0; + tmp.f_files = -1; + tmp.f_ffree = -1; + tmp.f_namelen = 12; + memcpy_tofs(buf, &tmp, bufsiz); +} /* DO MORE */ static int diff --git a/ncpfs-0.2.lsm b/ncpfs-0.3.lsm similarity index 73% rename from ncpfs-0.2.lsm rename to ncpfs-0.3.lsm index e2559f8..be0973a 100644 --- a/ncpfs-0.2.lsm +++ b/ncpfs-0.3.lsm @@ -1,14 +1,14 @@ Begin3 Title: ncpfs -Version: 0.2 -Entered-date: 19. October 1995 +Version: 0.3 +Entered-date: 01. November 1995 Description: With ncpfs you can mount volumes of your novell server under Linux. Keywords: filesystem kernel ncp novell netware Author: lendecke@namu01.gwdg.de (Volker Lendecke) Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke) Primary-site: linux01.gwdg.de:/pub/ncpfs - ~44k ncpfs-0.2.tgz - ~ 1k ncpfs-0.2.lsm + ~45k ncpfs-0.3.tgz + ~ 1k ncpfs-0.3.lsm Copying-policy: GPL End diff --git a/ncpmount.c b/ncpmount.c index 7922945..af49a92 100644 --- a/ncpmount.c +++ b/ncpmount.c @@ -334,7 +334,7 @@ parse_args(int argc, char *argv[], struct ncp_mount_data *data, *got_password = 1; break; case 'n': - data->password[0] = '0'; + data->password[0] = '\0'; *got_password = 1; break; default: @@ -629,7 +629,7 @@ main(int argc, char *argv[]) ment.mnt_fsname = server_name; ment.mnt_dir = fullpath(mount_point); ment.mnt_type = "ncpfs"; - ment.mnt_opts = ""; + ment.mnt_opts = "rw"; ment.mnt_freq = 0; ment.mnt_passno= 0; diff --git a/sock.c b/sock.c index ff79887..11e6bbd 100644 --- a/sock.c +++ b/sock.c @@ -84,7 +84,7 @@ ncp_wdog_data_ready(struct sock *sk, int len) sendto(sock, (void *)packet_buf, 2, 1, 0, (struct sockaddr *)&sender, sizeof(sender)); - printk("send result: %d\n", result); + DPRINTK("send result: %d\n", result); } set_fs(fs); }