diff --git a/.downloads/ncpfs-0.5.tgz b/.downloads/ncpfs-0.5.tgz new file mode 100644 index 0000000..186e89e Binary files /dev/null and b/.downloads/ncpfs-0.5.tgz differ diff --git a/Changes b/Changes deleted file mode 100644 index 19fc7f6..0000000 --- a/Changes +++ /dev/null @@ -1,19 +0,0 @@ -ncpfs-0.3 -> ncpfs-0.4 - -- removed bug causing kernel to crash on filenames too long - This was a typical C bug! Thanks to Uwe Bonnes, - bon@elektron.ikp.physik.th-darmstadt.de for his patience with this one. - -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 -- first attempt at read/write access -- more complete ncpmount.c -- included file ipx.tar \ No newline at end of file diff --git a/Makefile b/Makefile index 6471cad..6f31368 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ ARCH = i386 .s.o: $(AS) -o $*.o $< -OBJS= inode.o dir.o file.o sock.o ioctl.o ncplib.o nwcrypt.o +OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o all: ncpfs.o ncpmount ncptest @@ -30,8 +30,8 @@ ncpfs.o: $(OBJS) ncplib.o: ncplib.c ncplib.h $(CC) $(CFLAGS) -finline-functions -c $< -ncpmount: ncpmount.o - gcc -o ncpmount ncpmount.o +ncpmount: ncpmount.o ncplib_user.o nwcrypt.o + gcc -o ncpmount ncpmount.o ncplib_user.o nwcrypt.o ncpmount.o: ncpmount.c gcc -c ncpmount.c -Wall -I. -g @@ -42,8 +42,8 @@ ncptest: ncptest.o ncplib_user.o nwcrypt.o ncptest.o: ncptest.c gcc -c ncptest.c -Wall -I. -g -ncplib_user.o: ncplib.o - gcc -c ncplib.c -O3 -Wall -I. -g -o ncplib_user.o +ncplib_user.o: ncplib_user.c ncplib_user.h + gcc -c ncplib_user.c -Wall -I. -g nwcrypt.o: nwcrypt.c gcc -c -O2 -Wall nwcrypt.c @@ -55,7 +55,7 @@ clean: rm -f *.o *~ realclean: clean - rm -fr ncpmount ncptest .depend $(DISTFILE) mnt *.out + rm -f ncpmount ncptest .depend $(DISTFILE) *.out modules: ncpfs.o @@ -71,6 +71,7 @@ backup: (cd $(HOME)/tarz/backup; ls -l $(BACKUPFILE); mcopy $(BACKUPFILE) a:) dist: realclean + rm -fr mnt (cd ..; \ tar cvf - $(SRCDIR) | \ gzip -9 > $(DISTFILE); \ diff --git a/README b/README index 74c1f00..9704108 100644 --- a/README +++ b/README @@ -1,5 +1,8 @@ -This is version 0.2 of ncpfs, a free NetWare client for Linux. For me -it works with 1.3.32 +This is version 0.5 of ncpfs, a free NetWare client for Linux. For me +it works with 1.3.39, although this version has severe problems with +the socket layer. Your connection will block after you have sent 64k +of requests to the server. Alan Cox told me he would like to have that +fixed in 1.3.42 or so. I know that this piece of software is VERY incomplete, I have to apologize for that. But I thought I should make it publically @@ -9,9 +12,11 @@ ncpfs to open it for criticism. If nobody complains, I will go on working. To install ncpfs, just type 'make', 'insmod ncpfs.o' and then -'ncpmount server mount-point'. Please note that your IPX system has to -be configured correctly. There has to be a route to the internal -network of your server. Please see the file start_ipx for an example. +'ncpmount server mount-point'. + +Please note that your IPX system has to be configured correctly. There +has to be a route to the internal network of your server. Please see +the file start_ipx for an example. 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 @@ -25,11 +30,14 @@ 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! -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. +For the curious: the file ncplib_user.[ch] is a library that makes it +possible to send NCP requests to the server over a mounted +directory. I use it to keep the encryption stuff out of the kernel by +logging in from user space. Look at the file ncptest.c for other +possible uses. 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 :-) diff --git a/dir.c b/dir.c index e810aa6..22408a5 100644 --- a/dir.c +++ b/dir.c @@ -5,11 +5,7 @@ * */ -#include -#ifdef MODULE -#include -#include -#endif +/* #include */ #include #include @@ -22,8 +18,11 @@ #include #include "ncplib.h" -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -#define ROUND_UP(x) (((x)+3) & ~3) +struct ncp_dirent { + struct nw_info_struct i; + struct nw_search_sequence s; /* given back for i */ + unsigned long f_pos; +}; static int ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count); @@ -39,22 +38,11 @@ static int ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, int cache_size, struct ncp_dirent *entry); -static int -get_pname(struct inode *dir, const char *name, int len, - char **res_path, int *res_len); - -static int -get_pname_static(struct inode *dir, const char *name, int len, - char *path, int *res_len); - static struct inode * -ncp_iget(struct inode *dir, char *path, struct ncp_dirent *finfo); - -static void -put_pname(char *path); +ncp_iget(struct inode *dir, struct nw_file_info *finfo); static struct ncp_inode_info * -ncp_find_inode(struct ncp_server *server, const char *path); +ncp_find_inode(struct inode *dir, const char *name); static int ncp_lookup(struct inode *dir, const char *__name, @@ -77,14 +65,6 @@ static int ncp_rename(struct inode *old_dir, const char *old_name, int old_len, struct inode *new_dir, const char *new_name, int new_len); -static int -date_dos2unix(unsigned short time,unsigned short date); - -/* -static void -date_unix2dos(int unix_date,unsigned short *time, unsigned short *date); -*/ - static inline void str_upper(char *name) { @@ -162,6 +142,7 @@ ncp_readdir(struct inode *inode, struct file *filp, int index = 0; struct ncp_dirent *entry = NULL; struct ncp_server *server = NCP_SERVER(inode); + struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino); DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos); DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n", @@ -180,25 +161,25 @@ ncp_readdir(struct inode *inode, struct file *filp, printk("ncp_readdir: no MEMORY for cache\n"); return -ENOMEM; } - for (i = 0; i < NCP_READDIR_CACHE_SIZE; i++) { - c_entry[i].path = - (char *) ncp_kmalloc(NCP_MAXNAMELEN + 1, - GFP_KERNEL); - if (c_entry[i].path == NULL) { - DPRINTK("ncp_readdir: could not alloc path\n"); - while (--i>=0) - kfree(c_entry[i].path); - kfree(c_entry); - c_entry = NULL; - return -ENOMEM; - } - } } if (filp->f_pos == 0) { ncp_invalid_dir_cache(inode->i_ino); + if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0) { + return 0; + } + filp->f_pos += 1; } + if (filp->f_pos == 1) { + if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0) { + return 0; + } + filp->f_pos += 1; + } + + + if (inode->i_ino == c_ino) { for (i = 0; i < c_size; i++) { if (filp->f_pos == c_entry[i].f_pos) { @@ -244,7 +225,7 @@ ncp_readdir(struct inode *inode, struct file *filp, index = 0; for (i = 0; i < c_size; i++) { - str_lower(c_entry[i].path); + str_lower(c_entry[i].i.entryName); } } } @@ -261,18 +242,9 @@ ncp_readdir(struct inode *inode, struct file *filp, use. Otherwise the inode number does not matter. (You can argue a lot about this..) */ - int path_len; - int len; struct ncp_inode_info *ino_info; - char complete_path[NCP_MAXPATHLEN]; - - len = strlen(entry->path); - if ((result = get_pname_static(inode, entry->path, len, - complete_path, - &path_len)) < 0) - return result; - - ino_info = ncp_find_inode(server, complete_path); + ino_info = ncp_find_inode(inode, entry->i.entryName); + /* Some programs seem to be confused about a zero inode number, so we set it to one. Thanks to @@ -281,10 +253,10 @@ ncp_readdir(struct inode *inode, struct file *filp, ino_info = (struct ncp_inode_info *) 1; } - DDPRINTK("ncp_readdir: entry->path = %s\n", entry->path); + DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName); DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos); - if (filldir(dirent, entry->path, len, + if (filldir(dirent, entry->i.entryName, entry->i.nameLen, entry->f_pos, (ino_t)ino_info) < 0) { break; } @@ -307,29 +279,15 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size) { struct ncp_dirent *entry = c_entry; - int total_count = 0; + int total_count = 2; 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; +#if 1 + if (fpos < 2) { + printk("OOPS, we expect fpos >= 2"); } + fpos = 2; +#endif for (i=0; i 0) { - fill_one(info.volume_name); + if (total_count < fpos) { + DPRINTK("ncp_read_volumes: skipped vol: %s\n", + info.volume_name); + } else if (total_count >= fpos + cache_size) { + return (total_count - fpos); + } else { + DPRINTK("ncp_read_volumes: found vol: %s\n", + info.volume_name); + + if (ncp_do_lookup(server, NULL, + info.volume_name, + &(entry->i)) != 0) { + printk("ncpfs: could not lookup vol " + "%s\n", info.volume_name); + continue; + } + + entry->f_pos = total_count; + entry += 1; + } + total_count += 1; } } - fill_one("."); - fill_one(".."); + return (total_count - fpos); } @@ -352,73 +329,41 @@ static int ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, int cache_size, struct ncp_dirent *entry) { - struct ncp_filesearch_info fsinfo; - struct ncp_file_info finfo; + struct nw_search_sequence seq; + int total_count = 2; - int total_count = 0; +#if 1 + if (fpos < 2) { + printk("OOPS, we expect fpos >= 2"); + } + fpos = 2; +#endif + + if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq) != 0) { + DPRINTK("ncp_init_search failed\n"); + return total_count - fpos; + } + + while (total_count < fpos + cache_size) { + + if (ncp_search_for_file_or_subdir(server, &seq, + &(entry->i)) != 0) { + return total_count - fpos; + } - 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; + DPRINTK("ncp_do_readdir: skipped file: %s\n", + entry->i.entryName); } 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; - } + DPRINTK("ncp_do_readdir: found file: %s\n", + entry->i.entryName); + entry->s = seq; 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, - &fsinfo) != 0) { - DPRINTK("could not fs init\n"); - return; - } - - 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); - - - } - return; - } - - fill_one(aDIR, ".", 0, 0, 0, 0, 0); - fill_one(aDIR, "..", 0, 0, 0, 0, 0); - - doit(0); - doit(aDIR); - return (total_count - fpos); } @@ -441,17 +386,11 @@ ncp_invalid_dir_cache(unsigned long ino) void ncp_free_dir_cache(void) { - int i; - DPRINTK("ncp_free_dir_cache: enter\n"); if (c_entry == NULL) return; - for (i = 0; i < NCP_READDIR_CACHE_SIZE; i++) { - ncp_kfree_s(c_entry[i].path, NAME_MAX + 1); - } - ncp_kfree_s(c_entry, sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE); c_entry = NULL; @@ -460,127 +399,8 @@ ncp_free_dir_cache(void) } -/* get_pname_static: it expects the res_path to be a preallocated - string of len NCP_MAXPATHLEN. */ -static int -get_pname_static(struct inode *dir, const char *name, int len, - char *path, int *res_len) -{ - char *parentname = NCP_INOP(dir)->finfo.path; - int parentlen = NCP_INOP(dir)->finfo.len; - -#if 1 - if (parentlen != strlen(parentname)) { - printk("get_pname: parent->finfo.len = %d instead of %d\n", - parentlen, strlen(parentname)); - parentlen = strlen(parentname); - } - -#endif - DDPRINTK("get_pname_static: parentname = %s, parlen = %d\n", - parentname, parentlen); - DDPRINTK("get_pname_static: name = %s, len = %d\n", - name, len); - - if (len > NCP_MAXNAMELEN) { - return -ENAMETOOLONG; - } - - /* Fast cheat for . */ - if (len == 0 || (len == 1 && name[0] == '.')) { - - memcpy(path, parentname, parentlen + 1); - *res_len = parentlen; - return 0; - } - - /* Hmm, what about .. ? */ - if (len == 2 && name[0] == '.' && name[1] == '.') { - - char *pos = strrchr(parentname, '\\'); - - if ( (pos == NULL) - && ( (parentname[parentlen-1] == ':') - || (parentlen == 0))) { - - /* We're at the top */ - - path[0] = '\0'; - *res_len = 0; - return 0; - } - - - if (pos == NULL) { - printk("ncp_make_name: Bad parent NCP-name: %s", - parentname); - return -ENODATA; - } - - len = pos - parentname; - - memcpy(path, parentname, len); - path[len] = '\0'; - } - else if (parentlen == 0) { - memcpy(path, name, len); - path[len] = ':'; - path[len+1] = '\0'; - len = len+1; - } - else - { - if (len + parentlen + 2 > NCP_MAXPATHLEN) - return -ENAMETOOLONG; - - memcpy(path, parentname, parentlen); - path[parentlen] = '\\'; - memcpy(path + parentlen + 1, name, len); - path[parentlen + 1 + len] = '\0'; - len = parentlen + len + 1; - } - - *res_len = len; - - DDPRINTK("get_pname: path = %s, *pathlen = %d\n", - path, *res_len); - return 0; -} - -static int -get_pname(struct inode *dir, const char *name, int len, - char **res_path, int *res_len) -{ - char result[NCP_MAXPATHLEN]; - int result_len; - int res; - - if ((res = get_pname_static(dir,name,len,result,&result_len)) != 0) { - return res; - } - - if ((*res_path = ncp_kmalloc(result_len+1, GFP_KERNEL)) == NULL) { - printk("get_pname: Out of memory while allocating name."); - return -ENOMEM; - } - - strcpy(*res_path, result); - *res_len = result_len; - return 0; -} - -static void -put_pname(char *path) -{ - ncp_kfree_s(path, 0); -} - -/* Insert a NEW ncp_inode_info into the inode tree of our filesystem, - under dir. The caller must assure that it's not already there. We - assume that path is allocated for us. */ - static struct inode * -ncp_iget(struct inode *dir, char *path, struct ncp_dirent *finfo) +ncp_iget(struct inode *dir, struct nw_file_info *finfo) { struct inode *inode; struct ncp_inode_info *new_inode_info; @@ -591,11 +411,6 @@ ncp_iget(struct inode *dir, char *path, struct ncp_dirent *finfo) return NULL; } - if (!path) { - printk("ncp_iget: path is NULL\n"); - return NULL; - } - if (!finfo) { printk("ncp_iget: finfo is NULL\n"); return NULL; @@ -605,18 +420,15 @@ ncp_iget(struct inode *dir, char *path, struct ncp_dirent *finfo) GFP_KERNEL); if (new_inode_info == NULL) { - printk("ncp_iget: could not alloc mem for %s\n", path); + printk("ncp_iget: could not alloc mem for %s\n", + finfo->i.entryName); return NULL; } new_inode_info->state = INODE_LOOKED_UP; new_inode_info->nused = 0; new_inode_info->dir = NCP_INOP(dir); - - new_inode_info->finfo = *finfo; - new_inode_info->finfo.opened = 0; - new_inode_info->finfo.path = path; - new_inode_info->finfo.len = strlen(path); + new_inode_info->finfo = *finfo; NCP_INOP(dir)->nused += 1; @@ -654,10 +466,12 @@ ncp_free_inode_info(struct ncp_inode_info *i) i->next->prev = i->prev; i->prev->next = i->next; - ncp_kfree_s(i->finfo.path, i->finfo.len+1); + DDPRINTK("ncp_free_inode_info: freeing %s\n", + i->finfo.i.entryName); + ncp_kfree_s(i, sizeof(struct ncp_inode_info)); - if (dir == NULL) return; + if (dir == i) return; (dir->nused)--; i = dir; @@ -668,23 +482,24 @@ void ncp_init_root(struct ncp_server *server) { struct ncp_inode_info *root = &(server->root); + struct nw_info_struct *i = &(root->finfo.i); + unsigned short dummy; DPRINTK("ncp_init_root: server %s\n", server->m.server_name); + DPRINTK("ncp_init_root: i = %x\n", (int)i); root->finfo.opened = 0; - root->finfo.attr = aDIR; - root->finfo.size = 1024; - root->finfo.mtime = 0; - root->finfo.ctime = 0; - root->finfo.atime = 0; - - server->root_path = '\0'; - root->finfo.path = &(server->root_path); - root->finfo.len = 0; + i->attributes = aDIR; + i->dataStreamSize = 1024; + ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); + ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate)); + ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate)); + i->nameLen = 0; + i->entryName[0] = '\0'; root->state = INODE_LOOKED_UP; root->nused = 1; - root->dir = NULL; + root->dir = root; root->next = root->prev = root; return; } @@ -716,17 +531,20 @@ ncp_free_all_inodes(struct ncp_server *server) /* We will search the inode that belongs to this name, currently by a complete linear search through the inodes belonging to this filesystem. This has to be fixed. */ - static struct ncp_inode_info * -ncp_find_inode(struct ncp_server *server, const char *path) +ncp_find_inode(struct inode *dir, const char *name) { + struct ncp_server *server = NCP_SERVER(dir); + struct nw_info_struct *dir_info = NCP_ISTRUCT(dir); struct ncp_inode_info *result = &(server->root); - if (path == NULL) + if (name == NULL) { return NULL; + } do { - if (strcmp(result->finfo.path, path) == 0) + if ( (result->finfo.i.DosDirNum == dir_info->DosDirNum) + && (strcmp(result->finfo.i.entryName, name) == 0)) return result; result = result->next; @@ -739,13 +557,10 @@ static int ncp_lookup(struct inode *dir, const char *__name, int len, struct inode **result) { - char *name = NULL; - struct ncp_dirent finfo; + struct nw_file_info finfo; struct ncp_server *server; struct ncp_inode_info *result_info; - int error; int found_in_cache; - int path_len; *result = NULL; @@ -765,24 +580,23 @@ ncp_lookup(struct inode *dir, const char *__name, int len, return 0; } - /* Now we will have to build up an NCP filename. */ - if ((error = get_pname(dir, __name, len, &name, &path_len)) < 0) { + /* ..and for .. */ + if (len == 2 && __name[0] == '.' && __name[1] == '.') { + *result = iget(dir->i_sb, (int)(NCP_INOP(dir)->dir)); iput(dir); - return error; + if (*result == 0) + return -EACCES; + else + return 0; } - DDPRINTK("ncp_lookup: get_pname for %s returned %d\n", - __name, error); - - result_info = ncp_find_inode(NCP_SERVER(dir), name); + result_info = ncp_find_inode(dir, __name); if (result_info != 0) { if (result_info->state == INODE_CACHED) result_info->state = INODE_LOOKED_UP; - put_pname(name); - /* Here we convert the inode_info address into an inode number */ @@ -796,10 +610,6 @@ ncp_lookup(struct inode *dir, const char *__name, int len, return 0; } - /* Ok, now we have made our name. We have to build a new - ncp_inode_info struct and insert it into the tree, if it is - a name that exists on the server */ - /* If the file is in the dir cache, we do not have to ask the server. */ @@ -812,17 +622,14 @@ ncp_lookup(struct inode *dir, const char *__name, int len, i = first; do { DDPRINTK("ncp_lookup: trying index: %d, name: %s\n", - i, c_entry[i].path); - if (strcmp(c_entry[i].path, __name) == 0) { + i, c_entry[i].i.entryName); + if (strcmp(c_entry[i].i.entryName, __name) == 0) { DPRINTK("ncp_lookup: found in cache!\n"); - finfo = c_entry[i]; - finfo.path = NULL; /* It's not ours! */ + finfo.i = c_entry[i].i; found_in_cache = 1; break; } i = (i + 1) % c_size; - DDPRINTK("ncp_lookup: index %d, name %s failed\n", - i, c_entry[i].path); } while (i != first); } @@ -832,59 +639,29 @@ ncp_lookup(struct inode *dir, const char *__name, int len, memcpy(this_name, __name, len); this_name[len] = 0; + str_upper(this_name); - if (dir->i_ino == (int)&(server->root)) { + DDPRINTK("ncp_lookup: do_lookup on %s/%s\n", + NCP_ISTRUCT(dir)->entryName, this_name); - /* We want to look up a volume. We only want - to know whether it exists, nothing more. */ - int vol_no; - - DPRINTK("ncp_lookup: looking up volume %s\n", - this_name); - - if (ncp_get_volume_number(server,this_name, - &vol_no)!=0) { - put_pname(name); - iput(dir); - return -ENOENT; - } - - finfo.attr = aDIR; - finfo.mtime = 0; - finfo.ctime = 0; - finfo.atime = 0; - finfo.size = 1024; - - } else { - struct ncp_file_info ninfo; - if (ncp_get_finfo(server, 0, NCP_FINFO(dir)->path, - this_name, &ninfo) != 0) { - error = -ENOENT; - } - - finfo.attr = ninfo.file_attributes; - finfo.mtime = date_dos2unix(ninfo.update_time, - ninfo.update_date); - finfo.ctime = date_dos2unix(0, ninfo.creation_date); - finfo.atime = date_dos2unix(0, ninfo.access_date); - finfo.size = (ninfo.file_attributes & aDIR) != 0 - ? 1024 : ninfo.file_length; - } - - if (error < 0) { - put_pname(name); + if (ncp_do_lookup(server, + dir->i_ino == (int)&(NCP_SERVER(dir)->root) + ? NULL : NCP_ISTRUCT(dir), + this_name, + &(finfo.i)) != 0) { iput(dir); - return error; + return -ENOENT; } } - if (!(*result = ncp_iget(dir, name, &finfo))) { - put_pname(name); + finfo.opened = 0; + str_lower(finfo.i.entryName); + + if (!(*result = ncp_iget(dir, &finfo))) { iput(dir); return -EACCES; } - DDPRINTK("ncp_lookup: %s => %lu\n", name, (unsigned long)result_info); iput(dir); return 0; } @@ -893,11 +670,8 @@ static int ncp_create(struct inode *dir, const char *name, int len, int mode, struct inode **result) { - int error; - char *path = NULL; - struct ncp_dirent entry; - struct ncp_file_info finfo; - struct ncp_dirent *ino_finfo; + struct nw_file_info finfo; + __u8 _name[len+1]; *result = NULL; @@ -907,39 +681,30 @@ ncp_create(struct inode *dir, const char *name, int len, int mode, return -ENOENT; } - /* Now we will have to build up an NCP filename. */ - if ((error = get_pname(dir, name, len, &path, &len)) < 0) { - iput(dir); - return error; - } + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); - if (ncp_create_newfile(NCP_SERVER(dir), 0, path, 0, &finfo) != 0) { - put_pname(path); + if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), _name, + OC_MODE_CREATE|OC_MODE_OPEN, + 0, AR_READ|AR_WRITE, + &finfo) != 0) { iput(dir); return -EACCES; } - entry.attr = finfo.file_attributes; - 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 = 0; - ncp_invalid_dir_cache(dir->i_ino); - if (!(*result = ncp_iget(dir, path, &entry)) < 0) { - ncp_close_file(NCP_SERVER(dir), finfo.file_id); - put_pname(path); + str_lower(finfo.i.entryName); + finfo.access = O_RDWR; + + if (!(*result = ncp_iget(dir, &finfo)) < 0) { + ncp_close_file(NCP_SERVER(dir), finfo.file_handle); iput(dir); - return error; + return -EINVAL; } - ino_finfo = &(NCP_INOP(*result)->finfo); - ino_finfo->opened = 1; - ino_finfo->access = O_RDWR; - memcpy(&(ino_finfo->file_id), finfo.file_id, NCP_FILE_ID_LEN); - iput(dir); return 0; } @@ -948,7 +713,12 @@ static int ncp_mkdir(struct inode *dir, const char *name, int len, int mode) { int error; - char path[NCP_MAXPATHLEN]; + struct nw_file_info new_dir; + __u8 _name[len+1]; + + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_mkdir: inode is NULL or not a directory\n"); @@ -956,14 +726,13 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode) return -ENOENT; } - /* Now we will have to build up an NCP filename. */ - if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { - iput(dir); - return error; - } - - if ((error = ncp_create_directory(NCP_SERVER(dir), 0, path, - 0xff)) == 0) { + if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), _name, + OC_MODE_CREATE, aDIR, 0xffff, + &new_dir) != 0) { + error = -EACCES; + } else { + error = 0; ncp_invalid_dir_cache(dir->i_ino); } @@ -975,24 +744,32 @@ static int ncp_rmdir(struct inode *dir, const char *name, int len) { int error; - char path[NCP_MAXPATHLEN]; + __u8 _name[len+1]; if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_rmdir: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } - if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { - iput(dir); - return error; - } - if (ncp_find_inode(NCP_SERVER(dir), path) != NULL) { + if (ncp_find_inode(dir, name) != NULL) { error = -EBUSY; - } else { - if ((error = ncp_delete_directory(NCP_SERVER(dir), - 0, path)) == 0) { + } + else + { + + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); + + if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), + _name)) == 0) { ncp_invalid_dir_cache(dir->i_ino); } + else + { + error = -EINVAL; + } } iput(dir); return error; @@ -1002,25 +779,33 @@ static int ncp_unlink(struct inode *dir, const char *name, int len) { int error; - char path[NCP_MAXPATHLEN]; + __u8 _name[len+1]; if (!dir || !S_ISDIR(dir->i_mode)) { printk("ncp_unlink: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } - if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { - iput(dir); - return error; - } - if (ncp_find_inode(NCP_SERVER(dir), path) != NULL) { + if (ncp_find_inode(dir, name) != NULL) { error = -EBUSY; - } else { - if ((error = ncp_erase_file(NCP_SERVER(dir), 0, path, - 0)) == 0) - ncp_invalid_dir_cache(dir->i_ino); } + else + { + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); + + if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), + _name)) == 0) { + ncp_invalid_dir_cache(dir->i_ino); + } + else + { + error = -EINVAL; + } + } iput(dir); return error; } @@ -1030,7 +815,8 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len, struct inode *new_dir, const char *new_name, int new_len) { int res; - char old_path[NCP_MAXPATHLEN], new_path[NCP_MAXPATHLEN]; + char _old_name[old_len+1]; + char _new_name[new_len+1]; if (!old_dir || !S_ISDIR(old_dir->i_mode)) { printk("ncp_rename: old inode is NULL or not a directory\n"); @@ -1044,28 +830,32 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len, goto finished; } - res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len); - if (res < 0) { - goto finished; - } - - res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len); - if (res < 0) { - goto finished; - } - - if ( (ncp_find_inode(NCP_SERVER(old_dir), old_path) != NULL) - || (ncp_find_inode(NCP_SERVER(new_dir), new_path) != NULL)) { + if ( (ncp_find_inode(old_dir, old_name) != NULL) + || (ncp_find_inode(new_dir, new_name) != NULL)) { res = -EBUSY; goto finished; } - res = ncp_rename_file(NCP_SERVER(old_dir), 0, old_path, 0,0, new_path); + strncpy(_old_name, old_name, old_len); + _old_name[old_len] = '\0'; + str_upper(_old_name); + + strncpy(_new_name, new_name, new_len); + _new_name[old_len] = '\0'; + str_upper(_new_name); + + res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), + NCP_ISTRUCT(old_dir), _old_name, + NCP_ISTRUCT(new_dir), _new_name); if (res == 0) { ncp_invalid_dir_cache(old_dir->i_ino); ncp_invalid_dir_cache(new_dir->i_ino); - } + } + else + { + res = -EACCES; + } finished: iput(old_dir); @@ -1083,13 +873,11 @@ static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; extern struct timezone sys_tz; -/* static int utc2local(int time) { return time - sys_tz.tz_minuteswest*60; } -*/ static int local2utc(int time) @@ -1099,8 +887,8 @@ local2utc(int time) /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ -static int -date_dos2unix(unsigned short time,unsigned short date) +int +ncp_date_dos2unix(unsigned short time,unsigned short date) { int month,year,secs; @@ -1115,9 +903,8 @@ date_dos2unix(unsigned short time,unsigned short date) /* Convert linear UNIX date to a MS-DOS time/date pair. */ -#if 0 -static void -date_unix2dos(int unix_date,unsigned short *time, unsigned short *date) +void +ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date) { int day,year,nl_day,month; @@ -1139,4 +926,3 @@ date_unix2dos(int unix_date,unsigned short *time, unsigned short *date) } *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9); } -#endif diff --git a/file.c b/file.c index e582a2d..40064e5 100644 --- a/file.c +++ b/file.c @@ -5,11 +5,7 @@ * */ -#include -#ifdef MODULE -#include -#include -#endif +/* #include */ #include #include @@ -33,41 +29,43 @@ ncp_fsync(struct inode *inode, struct file *file) int ncp_make_open(struct inode *i, int right) { - struct ncp_dirent *dirent; + struct nw_file_info *finfo; if (i == NULL) { printk("ncp_make_open: got NULL inode\n"); return -EINVAL; } - dirent = &(NCP_INOP(i)->finfo); + finfo = NCP_FINFO(i); - DPRINTK("ncp_make_open: dirent->opened = %d\n", dirent->opened); + DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened); - if ((dirent->opened) == 0) { - struct ncp_file_info finfo; + if (finfo->opened == 0) { /* tries max. rights */ - if (ncp_open_file(NCP_SERVER(i), 0, dirent->path, 0, - AR_READ | AR_WRITE, &finfo) == 0) { - dirent->access = O_RDWR; + if (ncp_open_create_file_or_subdir(NCP_SERVER(i), + NULL, NULL, + OC_MODE_OPEN, 0, + AR_READ | AR_WRITE, + finfo) == 0) { + finfo->access = O_RDWR; } - else if (ncp_open_file(NCP_SERVER(i), 0, dirent->path, 0, - AR_READ, &finfo) == 0) { - dirent->access = O_RDONLY; + else if (ncp_open_create_file_or_subdir(NCP_SERVER(i), + NULL, NULL, + OC_MODE_OPEN, 0, + AR_READ, + finfo) == 0) { + finfo->access = O_RDONLY; } else { return -EACCES; } - - dirent->opened = 1; - memcpy(&(dirent->file_id), finfo.file_id, NCP_FILE_ID_LEN); } - if ( ((right == O_RDONLY) && ( (dirent->access == O_RDONLY) - || (dirent->access == O_RDWR))) - || ((right == O_WRONLY) && ( (dirent->access == O_WRONLY) - || (dirent->access == O_RDWR))) - || ((right == O_RDWR) && (dirent->access == O_RDWR))) + if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY) + || (finfo->access == O_RDWR))) + || ((right == O_WRONLY) && ( (finfo->access == O_WRONLY) + || (finfo->access == O_RDWR))) + || ((right == O_RDWR) && (finfo->access == O_RDWR))) return 0; return -EACCES; @@ -80,7 +78,7 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) off_t pos; int errno; - DPRINTK("ncp_file_read: enter %s\n", NCP_FINFO(inode)->path); + DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName); if (!inode) { DPRINTK("ncp_file_read: inode = NULL\n"); @@ -121,7 +119,7 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) to_read = min(to_read, count - already_read); - if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_id, + if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, pos, to_read, buf, &read_this_time) != 0) { return -EIO; /* This is not exact, i know.. */ } @@ -140,7 +138,7 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; - DPRINTK("ncp_file_read: exit %s\n", NCP_FINFO(inode)->path); + DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName); return already_read; } @@ -164,7 +162,7 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf, return -EINVAL; } - DPRINTK("ncp_file_write: enter %s\n", NCP_FINFO(inode)->path); + DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName); if (count <= 0) return 0; @@ -192,7 +190,7 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf, } to_write = min(to_write, count - already_written); - if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_id, + if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, pos, to_write, buf, &written_this_time) != 0) { return -EIO; } @@ -215,7 +213,7 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf, inode->i_size = pos; } - DPRINTK("ncp_file_write: exit %s\n", NCP_FINFO(inode)->path); + DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName); return already_written; } diff --git a/inode.c b/inode.c index 05f9e77..b34f9f5 100644 --- a/inode.c +++ b/inode.c @@ -5,14 +5,7 @@ * */ -#include -#ifdef MODULE #include -#include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif #include #include @@ -77,7 +70,7 @@ ncp_read_inode(struct inode *inode) else { printk("ncp_read_inode: " "state != INODE_LOOKED_UP\n"); - return; + goto good; } } check_info = check_info->next; @@ -89,22 +82,30 @@ ncp_read_inode(struct inode *inode) return; good: + DDPRINTK("ncp_read_inode: read entry %s\n", + inode_info->finfo.i.entryName); #endif inode_info->state = INODE_VALID; NCP_INOP(inode) = inode_info; - if (NCP_INOP(inode)->finfo.attr & aDIR) + if (NCP_ISTRUCT(inode)->attributes & aDIR) { inode->i_mode = NCP_SERVER(inode)->m.dir_mode; + /* for directories in dataStreamSize seems to be some + Object ID ??? */ + inode->i_size = 0; + } else + { inode->i_mode = NCP_SERVER(inode)->m.file_mode; + inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize; + } DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); inode->i_nlink = 1; inode->i_uid = NCP_SERVER(inode)->m.uid; inode->i_gid = NCP_SERVER(inode)->m.gid; - inode->i_size = NCP_INOP(inode)->finfo.size; inode->i_blksize = 1024; inode->i_rdev = 0; if ((inode->i_blksize != 0) && (inode->i_size != 0)) @@ -113,9 +114,12 @@ ncp_read_inode(struct inode *inode) else inode->i_blocks = 0; - inode->i_mtime = NCP_INOP(inode)->finfo.mtime; - inode->i_ctime = NCP_INOP(inode)->finfo.ctime; - inode->i_atime = NCP_INOP(inode)->finfo.atime; + inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime, + NCP_ISTRUCT(inode)->modifyDate); + inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime, + NCP_ISTRUCT(inode)->creationDate); + inode->i_atime = ncp_date_dos2unix(0, + NCP_ISTRUCT(inode)->lastAccessDate); if (S_ISREG(inode->i_mode)) inode->i_op = &ncp_file_inode_operations; @@ -129,11 +133,11 @@ ncp_read_inode(struct inode *inode) static void ncp_put_inode(struct inode *inode) { - struct ncp_dirent *finfo = NCP_FINFO(inode); + struct nw_file_info *finfo = NCP_FINFO(inode); if (finfo->opened != 0) { - if (ncp_close_file(NCP_SERVER(inode), finfo->file_id) != 0) { + if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) { /* We can't do anything but complain. */ printk("ncp_put_inode: could not close\n"); } @@ -278,12 +282,13 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent) DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); - if (ncp_login_user(server, server->m.username, +/* if (ncp_login_user(server, server->m.username, server->m.password) != 0) { sb->s_dev = 0; printk("ncp_read_super: login failed\n"); goto disconnect; } +*/ MOD_INC_USE_COUNT; return sb; @@ -356,10 +361,10 @@ ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) static int ncp_notify_change(struct inode *inode, struct iattr *attr) { - int error = 0; + int result = 0; - if ((error = inode_change_ok(inode, attr)) < 0) - return error; + if ((result = inode_change_ok(inode, attr)) < 0) + return result; if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != NCP_SERVER(inode)->m.uid))) @@ -376,32 +381,30 @@ ncp_notify_change(struct inode *inode, struct iattr *attr) if ((attr->ia_valid & ATTR_SIZE) != 0) { - struct ncp_file_info finfo; - struct ncp_dirent *dirent = NCP_FINFO(inode); + int written; DPRINTK("ncpfs: trying to change size of %s to %ld\n", - dirent->path, attr->ia_size); + NCP_ISTRUCT(inode)->entryName, attr->ia_size); - if (attr->ia_size != 0) { - return -EPERM; + if ((result = ncp_make_open(inode, O_RDWR)) < 0) { + return -EACCES; } - if (NCP_FINFO(inode)->opened != 0) { - ncp_close_file(NCP_SERVER(inode), dirent->file_id); - dirent->opened = 0; - } + ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + attr->ia_size, 0, "", &written); - if (ncp_create_file(NCP_SERVER(inode), 0, - dirent->path, 0, &finfo) == 0) { - ncp_close_file(NCP_SERVER(inode), finfo.file_id); - dirent->opened = 0; - } - error = 0; + /* According to ndir, the changes only take effect after + closing the file */ + ncp_close_file(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle); + NCP_FINFO(inode)->opened = 0; + + result = 0; } ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir)); - return error; + return result; } #ifdef DEBUG_NCP_MALLOC @@ -411,11 +414,6 @@ int ncp_current_malloced; #ifdef MODULE -char kernel_version[] = UTS_RELEASE; - -/* looks ugly, taken from gcc-info */ -/* static void *shut_up_gcc = (&shut_up_gcc, kernel_version);*/ - static struct file_system_type ncp_fs_type = { ncp_read_super, "ncpfs", 0, NULL }; diff --git a/ioctl.c b/ioctl.c index 0bf7a2e..a1c71cb 100644 --- a/ioctl.c +++ b/ioctl.c @@ -4,14 +4,7 @@ * Copyright (C) 1995 by Volker Lendecke * */ -#include -#ifdef MODULE -#include -#include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif +/* #include */ #include #include diff --git a/ncp.h b/ncp.h index 862d6af..36eb85b 100644 --- a/ncp.h +++ b/ncp.h @@ -10,7 +10,7 @@ #include -#define NCP_PTYPE (0x17) +#define NCP_PTYPE (0x11) #define NCP_PORT (0x0451) #define NCP_ALLOC_SLOT_REQUEST (0x1111) @@ -43,6 +43,8 @@ struct ncp_reply_header { #define NCP_BINDERY_USER (0x0001) +#define NCP_BINDERY_UGROUP (0x0002) +#define NCP_BINDERY_PQUEUE (0x0003) #define NCP_BINDERY_NAME_LEN (48) struct ncp_bindery_object { __u32 object_id; @@ -50,6 +52,12 @@ struct ncp_bindery_object { __u8 object_name[NCP_BINDERY_NAME_LEN]; }; +struct nw_property { + __u8 value[128]; + __u8 more_flag; + __u8 property_flag; +}; + #define NCP_VOLNAME_LEN (16) #define NCP_NUMBER_OF_VOLUMES (64) @@ -98,4 +106,143 @@ struct ncp_file_info { __u16 update_time; }; + +/* Defines for ReturnInformationMask */ +#define RIM_NAME (0x0001L) +#define RIM_SPACE_ALLOCATED (0x0002L) +#define RIM_ATTRIBUTES (0x0004L) +#define RIM_DATA_SIZE (0x0008L) +#define RIM_TOTAL_SIZE (0x0010L) +#define RIM_EXT_ATTR_INFO (0x0020L) +#define RIM_ARCHIVE (0x0040L) +#define RIM_MODIFY (0x0080L) +#define RIM_CREATION (0x0100L) +#define RIM_OWNING_NAMESPACE (0x0200L) +#define RIM_DIRECTORY (0x0400L) +#define RIM_RIGHTS (0x0800L) +#define RIM_ALL (0x0FFFL) +#define RIM_COMPRESSED_INFO (0x80000000L) + +/* open/create modes */ +#define OC_MODE_OPEN 0x01 +#define OC_MODE_TRUNCATE 0x02 +#define OC_MODE_REPLACE 0x02 +#define OC_MODE_CREATE 0x08 + +/* open/create results */ +#define OC_ACTION_NONE 0x00 +#define OC_ACTION_OPEN 0x01 +#define OC_ACTION_CREATE 0x02 +#define OC_ACTION_TRUNCATE 0x04 +#define OC_ACTION_REPLACE 0x04 + +/* access rights attributes */ +#ifndef AR_READ_ONLY +#define AR_READ_ONLY 0x0001 +#define AR_WRITE_ONLY 0x0002 +#define AR_DENY_READ 0x0004 +#define AR_DENY_WRITE 0x0008 +#define AR_COMPATIBILITY 0x0010 +#define AR_WRITE_THROUGH 0x0040 +#define AR_OPEN_COMPRESSED 0x0100 +#endif + +struct nw_info_struct +{ + __u32 spaceAlloc __attribute__ ((packed)); + __u32 attributes __attribute__ ((packed)); + __u16 flags __attribute__ ((packed)); + __u32 dataStreamSize __attribute__ ((packed)); + __u32 totalStreamSize __attribute__ ((packed)); + __u16 numberOfStreams __attribute__ ((packed)); + __u16 creationTime __attribute__ ((packed)); + __u16 creationDate __attribute__ ((packed)); + __u32 creatorID __attribute__ ((packed)); + __u16 modifyTime __attribute__ ((packed)); + __u16 modifyDate __attribute__ ((packed)); + __u32 modifierID __attribute__ ((packed)); + __u16 lastAccessDate __attribute__ ((packed)); + __u16 archiveTime __attribute__ ((packed)); + __u16 archiveDate __attribute__ ((packed)); + __u32 archiverID __attribute__ ((packed)); + __u16 inheritedRightsMask __attribute__ ((packed)); + __u32 dirEntNum __attribute__ ((packed)); + __u32 DosDirNum __attribute__ ((packed)); + __u32 volNumber __attribute__ ((packed)); + __u32 EADataSize __attribute__ ((packed)); + __u32 EAKeyCount __attribute__ ((packed)); + __u32 EAKeySize __attribute__ ((packed)); + __u32 NSCreator __attribute__ ((packed)); + __u8 nameLen __attribute__ ((packed)); + __u8 entryName[256] __attribute__ ((packed)); +}; + +struct nw_file_info { + struct nw_info_struct i; + int opened; + int access; + __u32 server_file_handle __attribute__ ((packed)); + __u8 open_create_action __attribute__ ((packed)); + __u8 file_handle[6] __attribute__ ((packed)); +}; + +struct nw_search_sequence { + __u8 volNumber __attribute__ ((packed)); + __u32 dirBase __attribute__ ((packed)); + __u32 sequence __attribute__ ((packed)); +}; + +struct nw_queue_job_entry { + __u16 InUse __attribute__ ((packed)); + __u32 prev __attribute__ ((packed)); + __u32 next __attribute__ ((packed)); + __u32 ClientStation __attribute__ ((packed)); + __u32 ClientTask __attribute__ ((packed)); + __u32 ClientObjectID __attribute__ ((packed)); + __u32 TargetServerID __attribute__ ((packed)); + __u8 TargetExecTime[6] __attribute__ ((packed)); + __u8 JobEntryTime[6] __attribute__ ((packed)); + __u32 JobNumber __attribute__ ((packed)); + __u16 JobType __attribute__ ((packed)); + __u16 JobPosition __attribute__ ((packed)); + __u16 JobControlFlags __attribute__ ((packed)); + __u8 FileNameLen __attribute__ ((packed)); + char JobFileName[13] __attribute__ ((packed)); + __u32 JobFileHandle __attribute__ ((packed)); + __u32 ServerStation __attribute__ ((packed)); + __u32 ServerTaskNumber __attribute__ ((packed)); + __u32 ServerObjectID __attribute__ ((packed)); + char JobTextDescription[50] __attribute__ ((packed)); + char ClientRecordArea[152] __attribute__ ((packed)); +}; + +struct queue_job { + struct nw_queue_job_entry j; + __u8 file_handle[6]; +}; + +#define QJE_OPER_HOLD 0x80 +#define QJE_USER_HOLD 0x40 +#define QJE_ENTRYOPEN 0x20 +#define QJE_SERV_RESTART 0x10 +#define QJE_SERV_AUTO 0x08 + +/* ClientRecordArea for print jobs */ + +struct print_job_record { + __u8 Version __attribute__ ((packed)); + __u16 TabSize __attribute__ ((packed)); + __u16 Copies __attribute__ ((packed)); + __u8 CtrlFlags __attribute__ ((packed)); + __u16 Lines __attribute__ ((packed)); + __u16 Rows __attribute__ ((packed)); + char FormName[16] __attribute__ ((packed)); + __u8 Reserved[6] __attribute__ ((packed)); + char Banner[13] __attribute__ ((packed)); + char FnameBanner[13] __attribute__ ((packed)); + char FnameHeader[14] __attribute__ ((packed)); + char Path[80] __attribute__ ((packed)); +}; + + #endif /* _LINUX_NCP_H */ diff --git a/ncp_fs.h b/ncp_fs.h index a8d4fdd..6b903d1 100644 --- a/ncp_fs.h +++ b/ncp_fs.h @@ -55,6 +55,7 @@ struct ncp_ioctl_request { #define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) #define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo)) +#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i)) static inline int min(int a, int b) { return a -#include -#include -#include - -#define ncp_printf printf - -static void -assert_server_locked(struct ncp_server *server); - -static void -assert_server_not_locked(struct ncp_server *server) -{ - if (server->lock != 0) { - ncp_printf("ncpfs: server already locked!\n"); - } -} - -static void -ncp_lock_server(struct ncp_server *server) -{ - assert_server_not_locked(server); - server->lock = 1; -} - -static void -ncp_unlock_server(struct ncp_server *server) -{ - assert_server_locked(server); - server->lock = 0; -} - -static int -ncp_request(struct ncp_server *server, int function) { - - struct ncp_reply_header *reply - = (struct ncp_reply_header *)(server->packet); - struct ncp_ioctl_request request; - int result; - - assert_server_locked(server); - - if (server->has_subfunction != 0) { - *(word *)(server->packet) = server->current_size - 2; - } - - request.function = function; - request.size = server->current_size; - request.data = server->packet; - - if ((result = ioctl(server->mount_fid, NCP_IOC_NCPREQUEST, - &request)) < 0) { - return result; - } - - server->ncp_reply_size = result - sizeof(struct ncp_reply_header); - - return reply->completion_code; -} - -static inline int -min(int a, int b) { - if (alock == 0) { - ncp_printf("ncpfs: server not locked!\n"); + DPRINTK("ncpfs: server not locked!\n"); } } @@ -126,8 +49,6 @@ ncp_add_mem(struct ncp_server *server, const char *source, int size) return; } -#ifdef __KERNEL__ - static void ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size) { @@ -137,15 +58,13 @@ ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size) return; } -#endif - static void ncp_add_pstring(struct ncp_server *server, const char *s) { int len = strlen(s); assert_server_locked(server); if (len > 255) { - ncp_printf("ncpfs: string too long: %s\n", s); + DPRINTK("ncpfs: string too long: %s\n", s); len = 255; } ncp_add_byte(server, len); @@ -158,12 +77,7 @@ ncp_init_request(struct ncp_server *server) { ncp_lock_server(server); -#ifdef __KERNEL__ server->current_size = sizeof(struct ncp_request_header); -#else - server->current_size = 0; - server->packet = server->ncp_data; -#endif server->has_subfunction = 0; } @@ -211,8 +125,7 @@ ncp_negotiate_buffersize(struct ncp_server *server, ncp_init_request(server); ncp_add_word(server, htons(size)); - if ((result = ncp_request(server, 33)) < 0) { - ncp_printf("ncp_request_error: %d\n", result); + if ((result = ncp_request(server, 33)) != 0) { ncp_unlock_server(server); return result; } @@ -223,122 +136,6 @@ ncp_negotiate_buffersize(struct ncp_server *server, return 0; } - -/* - * result is a 8-byte buffer - */ -int -ncp_get_encryption_key(struct ncp_server *server, - char *target) -{ - int result; - - ncp_init_request_s(server, 23); - - if ((result = ncp_request(server, 23)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - if (server->ncp_reply_size < 8) { - ncp_printf("ncp_reply_size %d < 8\n", - server->ncp_reply_size); - ncp_unlock_server(server); - return result; - } - - memcpy(target, ncp_reply_data(server, 0), 8); - ncp_unlock_server(server); - return 0; -} - -int -ncp_get_bindery_object_id(struct ncp_server *server, - int object_type, char *object_name, - struct ncp_bindery_object *target) -{ - int result; - ncp_init_request_s(server, 53); - ncp_add_word(server, ntohs(object_type)); - ncp_add_pstring(server, object_name); - - if ((result = ncp_request(server, 23)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - if (server->ncp_reply_size < 54) { - ncp_printf("ncp_reply_size %d < 54\n", - server->ncp_reply_size); - ncp_unlock_server(server); - return result; - } - - target->object_id = ntohl(ncp_reply_dword(server, 0)); - target->object_type = ntohs(ncp_reply_word (server, 4)); - memcpy(target->object_name, ncp_reply_data(server, 6), 48); - ncp_unlock_server(server); - return 0; -} - -int -ncp_login_encrypted(struct ncp_server *server, - struct ncp_bindery_object *object, - unsigned char *key, - unsigned char *passwd) -{ - dword tmpID = htonl(object->object_id); - unsigned char buf[128]; - unsigned char encrypted[8]; - int result; - - shuffle((byte *)&tmpID, passwd, strlen(passwd), buf); - nw_encrypt(key, buf, encrypted); - - ncp_init_request_s(server, 24); - ncp_add_mem(server, encrypted, 8); - ncp_add_word(server, htons(object->object_type)); - ncp_add_pstring(server, object->object_name); - - if ((result = ncp_request(server, 23)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - ncp_unlock_server(server); - return 0; -} - -int -ncp_login_user(struct ncp_server *server, - unsigned char *username, - unsigned char *password) -{ - int result; - unsigned char ncp_key[8]; - struct ncp_bindery_object user; - - if ((result = ncp_get_encryption_key(server, ncp_key)) != 0) { - return result; - } - - if ((result = ncp_get_bindery_object_id(server, NCP_BINDERY_USER, - username, &user)) != 0) { - return result; - } - - if ((result = ncp_login_encrypted(server, &user, - ncp_key, password)) != 0) { - return result; - } - return 0; -} - - - int ncp_get_volume_info_with_number(struct ncp_server *server, int n, struct ncp_volume_info *target) @@ -350,7 +147,6 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n, ncp_add_byte(server, n); if ((result = ncp_request(server, 22)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); ncp_unlock_server(server); return result; } @@ -367,7 +163,7 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n, len = ncp_reply_byte(server, 29); if (len > NCP_VOLNAME_LEN) { - ncp_printf("ncpfs: volume name too long: %d\n", len); + DPRINTK("ncpfs: volume name too long: %d\n", len); ncp_unlock_server(server); return -EIO; } @@ -386,7 +182,6 @@ ncp_get_volume_number(struct ncp_server *server, const char *name, int *target) ncp_add_pstring(server, name); if ((result = ncp_request(server, 22)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); ncp_unlock_server(server); return result; } @@ -396,140 +191,6 @@ ncp_get_volume_number(struct ncp_server *server, const char *name, int *target) return 0; } - -int -ncp_file_search_init(struct ncp_server *server, - int dir_handle, const char *path, - struct ncp_filesearch_info *target) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, dir_handle); - ncp_add_pstring(server, path); - - if ((result = ncp_request(server, 62)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - target->volume_number = ncp_reply_byte(server, 0); - target->directory_id = ntohs(ncp_reply_word(server, 1)); - target->sequence_no = ntohs(ncp_reply_word(server, 3)); - target->access_rights = ncp_reply_byte(server, 5); - ncp_unlock_server(server); - return 0; -} - - -int -ncp_file_search_continue(struct ncp_server *server, - struct ncp_filesearch_info *fsinfo, - int attributes, const char *name, - struct ncp_file_info *target) -{ - int result; - - ncp_init_request(server); - - ncp_add_byte(server, fsinfo->volume_number); - ncp_add_word(server, htons(fsinfo->directory_id)); - ncp_add_word(server, htons(fsinfo->sequence_no)); - - ncp_add_byte(server, attributes); - ncp_add_pstring(server, name); - - if ((result = ncp_request(server, 63)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - fsinfo->sequence_no = ntohs(ncp_reply_word(server, 0)); - - memset(&(target->file_name), 0, sizeof(target->file_name)); - memcpy(&(target->file_name), ncp_reply_data(server, 4), - NCP_MAX_FILENAME); - - target->file_attributes = ncp_reply_byte(server, 18); - target->file_mode = ncp_reply_byte(server, 19); - target->file_length = ntohl(ncp_reply_dword(server, 20)); - target->creation_date = ntohs(ncp_reply_word(server, 24)); - target->access_date = ntohs(ncp_reply_word(server, 26)); - target->update_date = ntohs(ncp_reply_word(server, 28)); - target->update_time = ntohs(ncp_reply_word(server, 30)); - - ncp_unlock_server(server); - return 0; -} - -int -ncp_get_finfo(struct ncp_server *server, - int dir_handle, const char *path, const char *name, - struct ncp_file_info *target) -{ - int result; - - struct ncp_filesearch_info fsinfo; - - if ((result = ncp_file_search_init(server, dir_handle, path, - &fsinfo)) != 0) { - return result; - } - - if ((result = ncp_file_search_continue(server, &fsinfo, 0, name, - target)) == 0) { - return result; - } - - if ((result = ncp_file_search_init(server, dir_handle, path, - &fsinfo)) != 0) { - return result; - } - - return ncp_file_search_continue(server, &fsinfo, aDIR, name, target); -} - -int -ncp_open_file(struct ncp_server *server, - int dir_handle, const char *path, - int attr, int access, - struct ncp_file_info *target) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, dir_handle); - ncp_add_byte(server, attr); - ncp_add_byte(server, access); - ncp_add_pstring(server, path); - - if ((result = ncp_request(server, 76)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - memcpy(&(target->file_id), ncp_reply_data(server, 0), - NCP_FILE_ID_LEN); - - memset(&(target->file_name), 0, sizeof(target->file_name)); - memcpy(&(target->file_name), ncp_reply_data(server, 8), - NCP_MAX_FILENAME); - - target->file_attributes = ncp_reply_byte(server, 22); - target->file_mode = ncp_reply_byte(server, 23); - target->file_length = ntohl(ncp_reply_dword(server, 24)); - target->creation_date = ntohs(ncp_reply_word(server, 28)); - target->access_date = ntohs(ncp_reply_word(server, 30)); - target->update_date = ntohs(ncp_reply_word(server, 32)); - target->update_time = ntohs(ncp_reply_word(server, 34)); - - ncp_unlock_server(server); - return 0; -} - int ncp_close_file(struct ncp_server *server, const char *file_id) { @@ -540,7 +201,6 @@ ncp_close_file(struct ncp_server *server, const char *file_id) ncp_add_mem(server, file_id, 6); if ((result = ncp_request(server, 66)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); ncp_unlock_server(server); return result; } @@ -549,167 +209,130 @@ ncp_close_file(struct ncp_server *server, const char *file_id) return 0; } -static int -ncp_do_create(struct ncp_server *server, - int dir_handle, const char *path, - int attr, - struct ncp_file_info *target, - int function) +static void +ncp_add_handle_path(struct ncp_server *server, + __u8 vol_num, + __u32 dir_base, int have_dir_base, + char *path) { + ncp_add_byte(server, vol_num); + ncp_add_dword(server, dir_base); + if (have_dir_base != 0) { + ncp_add_byte(server, 1); /* dir_base */ + } else { + ncp_add_byte(server, 0xff); /* no handle */ + } + if (path != NULL) { + ncp_add_byte(server, 1); /* 1 component */ + ncp_add_pstring(server, path); + } + else + { + ncp_add_byte(server, 0); + } +} + +static void +ncp_extract_file_info(void *structure, struct nw_info_struct *target) +{ + __u8 *name_len; + const int info_struct_size = sizeof(struct nw_info_struct) - 257; + + memcpy(target, structure, info_struct_size); + name_len = structure + info_struct_size; + target->nameLen = *name_len; + strncpy(target->entryName, name_len+1, *name_len); + target->entryName[*name_len] = '\0'; + return; +} + + +int +ncp_do_lookup(struct ncp_server *server, + struct nw_info_struct *dir, + char *path, /* may only be one component */ + struct nw_info_struct *target) +{ + __u8 vol_num; + __u32 dir_base; int result; - - ncp_init_request(server); - ncp_add_byte(server, dir_handle); - ncp_add_byte(server, attr); - ncp_add_pstring(server, path); + char *volname = NULL; - if ((result = ncp_request(server, function)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); + if (target == NULL) { + return -EINVAL; + } + + if (dir == NULL) { + + DDPRINTK("ncp_do_lookup: looking up vol %s\n", path); + + /* Access a volume's root directory */ + ncp_init_request(server); + ncp_add_byte(server, 22); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, 0, 0, 0, /* no handle */ + path); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + dir_base = ncp_reply_dword(server, 4); + vol_num = ncp_reply_byte (server, 8); + ncp_unlock_server(server); + volname = path; + path = NULL; + } + else + { + vol_num = dir->volNumber; + dir_base = dir->DosDirNum; + } + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* dos name space as dest */ + ncp_add_word(server, 0xff); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, vol_num, dir_base, 1, + path); + + if ((result = ncp_request(server, 87)) != 0) { ncp_unlock_server(server); return result; } - memcpy(&(target->file_id), ncp_reply_data(server, 0), - NCP_FILE_ID_LEN); - - memset(&(target->file_name), 0, sizeof(target->file_name)); - memcpy(&(target->file_name), ncp_reply_data(server, 8), - NCP_MAX_FILENAME); + ncp_extract_file_info(ncp_reply_data(server, 0), target); - target->file_attributes = ncp_reply_byte(server, 22); - target->file_mode = ncp_reply_byte(server, 23); - target->file_length = ntohl(ncp_reply_dword(server, 24)); - target->creation_date = ntohs(ncp_reply_word(server, 28)); - target->access_date = ntohs(ncp_reply_word(server, 30)); - target->update_date = ntohs(ncp_reply_word(server, 32)); - target->update_time = ntohs(ncp_reply_word(server, 34)); + if (volname != NULL) { + target->nameLen = strlen(volname); + strcpy(target->entryName, volname); + } ncp_unlock_server(server); return 0; -} - -int -ncp_create_newfile(struct ncp_server *server, - int dir_handle, const char *path, - int attr, - struct ncp_file_info *target) -{ - return ncp_do_create(server, dir_handle, path, attr, target, 77); } int -ncp_create_file(struct ncp_server *server, - int dir_handle, const char *path, - int attr, - struct ncp_file_info *target) -{ - return ncp_do_create(server, dir_handle, path, attr, target, 67); -} - -int -ncp_erase_file(struct ncp_server *server, - int dir_handle, const char *path, - int attr) +ncp_del_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name) { int result; ncp_init_request(server); - ncp_add_byte(server, dir_handle); - ncp_add_byte(server, attr); - ncp_add_pstring(server, path); - - if ((result = ncp_request(server, 68)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - ncp_unlock_server(server); - return 0; -} - -int -ncp_rename_file(struct ncp_server *server, - int old_handle, const char *old_path, - int attr, - int new_handle, const char *new_path) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, old_handle); - ncp_add_byte(server, attr); - ncp_add_pstring(server, old_path); - ncp_add_byte(server, new_handle); - ncp_add_pstring(server, new_path); - - if ((result = ncp_request(server, 69)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - ncp_unlock_server(server); - return 0; -} - -int -ncp_create_directory(struct ncp_server *server, - int dir_handle, const char *path, - int inherit_mask) -{ - int result; - - ncp_init_request_s(server, 10); - ncp_add_byte(server, dir_handle); - ncp_add_byte(server, inherit_mask); - ncp_add_pstring(server, path); - - if ((result = ncp_request(server, 22)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - ncp_unlock_server(server); - return 0; -} - -int -ncp_delete_directory(struct ncp_server *server, - int dir_handle, const char *path) -{ - int result; - - ncp_init_request_s(server, 11); - ncp_add_byte(server, dir_handle); + ncp_add_byte(server, 8); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ ncp_add_byte(server, 0); /* reserved */ - ncp_add_pstring(server, path); - - if ((result = ncp_request(server, 22)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); - ncp_unlock_server(server); - return result; - } - - ncp_unlock_server(server); - return 0; -} + ncp_add_word(server, 0x8006); /* search attribs: all */ + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, name); -int -ncp_rename_directory(struct ncp_server *server, - int dir_handle, - const char *old_path, const char *new_path) -{ - int result; - - ncp_init_request_s(server, 15); - ncp_add_byte(server, dir_handle); - ncp_add_pstring(server, old_path); - ncp_add_pstring(server, new_path); - - if ((result = ncp_request(server, 22)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); + if ((result = ncp_request(server, 87)) != 0) { ncp_unlock_server(server); return result; } @@ -718,63 +341,162 @@ ncp_rename_directory(struct ncp_server *server, return 0; } +static inline void +ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] ) +{ + __u16 *dest = (__u16 *) ret; + memcpy(&(dest[1]), &sfd, 4); + dest[0] = dest[1] + 1; + return; +} -#ifndef __KERNEL__ - +/* If both dir and name are NULL, then in target there's already a + looked-up entry that wants to be opened. */ int -ncp_read(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_read, - char *target, int *bytes_read) +ncp_open_create_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name, + int open_create_mode, + __u32 create_attributes, + int desired_acc_rights, + struct nw_file_info *target) { int result; ncp_init_request(server); - ncp_add_byte(server, 0); - ncp_add_mem(server, file_id, 6); - ncp_add_dword(server, htonl(offset)); - ncp_add_word(server, htons(to_read)); + ncp_add_byte(server, 1); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, open_create_mode); + ncp_add_word(server, 0x8006); + ncp_add_dword(server, RIM_ALL); + ncp_add_dword(server, create_attributes); + /* The desired acc rights seem to be the inherited rights mask + for directories */ + ncp_add_word(server, desired_acc_rights); - if ((result = ncp_request(server, 72)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); + if (dir != NULL) { + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, name); + } else { + ncp_add_handle_path(server, + target->i.volNumber, target->i.DosDirNum, + 1, NULL); + } + + if ((result = ncp_request(server, 87)) != 0) { ncp_unlock_server(server); return result; } - *bytes_read = ntohs(ncp_reply_word(server, 0)); + target->opened = 1; + target->server_file_handle = ncp_reply_dword(server, 0); + target->open_create_action = ncp_reply_byte(server, 4); - memcpy(target, ncp_reply_data(server, 2), *bytes_read); + if (dir != NULL) { + /* in target there's a new finfo to fill */ + ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i)); + } + + ConvertToNWfromDWORD(target->server_file_handle, target->file_handle); ncp_unlock_server(server); return 0; } + int -ncp_write(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_write, - const char *source, int *bytes_written) +ncp_initialize_search(struct ncp_server *server, + struct nw_info_struct *dir, + struct nw_search_sequence *target) { int result; ncp_init_request(server); - ncp_add_byte(server, 0); - ncp_add_mem(server, file_id, 6); - ncp_add_dword(server, htonl(offset)); - ncp_add_word(server, htons(to_write)); - ncp_add_mem(server, source, to_write); - - if ((result = ncp_request(server, 73)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); + ncp_add_byte(server, 2); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL); + + if ((result = ncp_request(server, 87)) != 0) { ncp_unlock_server(server); return result; } - *bytes_written = to_write; + memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); ncp_unlock_server(server); return 0; } -#else +/* Search for everything */ +int +ncp_search_for_file_or_subdir(struct ncp_server *server, + struct nw_search_sequence *seq, + struct nw_info_struct *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 3); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* data stream (???) */ + ncp_add_word(server, 0xffff); /* Search attribs */ + ncp_add_dword(server, RIM_ALL); /* return info mask */ + ncp_add_mem(server, (unsigned char *)seq, 9); + ncp_add_byte(server, 2); /* 2 byte pattern */ + ncp_add_byte(server, 0xff); /* following is a wildcard */ + ncp_add_byte(server, '*'); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq)); + ncp_extract_file_info(ncp_reply_data(server, 10), target); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *old_dir, char *old_name, + struct nw_info_struct *new_dir, char *new_name) +{ + int result; + + if ( (old_dir == NULL) || (old_name == NULL) + || (new_dir == NULL) || (new_name == NULL)) + return -EINVAL; + + ncp_init_request(server); + ncp_add_byte(server, 4); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 1); /* rename flag */ + ncp_add_word(server, 0x8006); /* search attributes */ + + /* source Handle Path */ + ncp_add_byte(server, old_dir->volNumber); + ncp_add_dword(server, old_dir->DosDirNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 source component */ + + /* dest Handle Path */ + ncp_add_byte(server, new_dir->volNumber); + ncp_add_dword(server, new_dir->DosDirNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 destination component */ + + /* source path string */ + ncp_add_pstring(server, old_name); + /* dest path string */ + ncp_add_pstring(server, new_name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + /* We have to transfer to/from user space */ int @@ -791,7 +513,6 @@ ncp_read(struct ncp_server *server, const char *file_id, ncp_add_word(server, htons(to_read)); if ((result = ncp_request(server, 72)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); ncp_unlock_server(server); return result; } @@ -819,7 +540,6 @@ ncp_write(struct ncp_server *server, const char *file_id, ncp_add_mem_fromfs(server, source, to_write); if ((result = ncp_request(server, 73)) != 0) { - ncp_printf("ncp_request_error: %d\n", result); ncp_unlock_server(server); return result; } @@ -829,5 +549,4 @@ ncp_write(struct ncp_server *server, const char *file_id, ncp_unlock_server(server); return 0; } - -#endif + diff --git a/ncplib.h b/ncplib.h index 65d954d..86e52c8 100644 --- a/ncplib.h +++ b/ncplib.h @@ -1,15 +1,6 @@ #ifndef _NCPLIB_H #define _NCPLIB_H -#ifdef __KERNEL__ - -#include -#ifdef MODULE -#include -#include -#endif - - #include #include #include @@ -22,25 +13,6 @@ #include #include -#else - -#include -#include -#include - -struct ncp_server { - int current_size; - int has_subfunction; - int mount_fid; - int ncp_reply_size; - char *packet; - int lock; - - char ncp_data[NCP_PACKET_SIZE]; -}; - -#endif __KERNEL__ - #include int @@ -141,4 +113,38 @@ ncp_write(struct ncp_server *server, const char *file_id, __u32 offset, __u16 to_write, const char *source, int *bytes_written); +int +ncp_do_lookup(struct ncp_server *server, + struct nw_info_struct *dir, + char *path, /* may only be one component */ + struct nw_info_struct *target); + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name); + +int +ncp_open_create_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name, + int open_create_mode, + __u32 create_attributes, + int desired_acc_rights, + struct nw_file_info *target); + +int +ncp_initialize_search(struct ncp_server *server, + struct nw_info_struct *dir, + struct nw_search_sequence *target); + +int +ncp_search_for_file_or_subdir(struct ncp_server *server, + struct nw_search_sequence *seq, + struct nw_info_struct *target); + +int +ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *old_dir, char *old_name, + struct nw_info_struct *new_dir, char *new_name); + + #endif /* _NCPLIB_H */ diff --git a/ncplib_user.c b/ncplib_user.c new file mode 100644 index 0000000..55f9f2c --- /dev/null +++ b/ncplib_user.c @@ -0,0 +1,1079 @@ +#include "ncplib_user.h" +#include "nwcrypt.h" + +typedef __u8 byte; +typedef __u16 word; +typedef __u32 dword; + +#include +#include +#include +#include + +#define ncp_printf printf + +static void +assert_server_locked(struct ncp_server *server); + +static void +assert_server_not_locked(struct ncp_server *server) +{ + if (server->lock != 0) { + ncp_printf("ncpfs: server already locked!\n"); + } +} + +static void +ncp_lock_server(struct ncp_server *server) +{ + assert_server_not_locked(server); + server->lock = 1; +} + +static void +ncp_unlock_server(struct ncp_server *server) +{ + assert_server_locked(server); + server->lock = 0; +} + +static int +ncp_request(struct ncp_server *server, int function) { + + struct ncp_reply_header *reply + = (struct ncp_reply_header *)(server->packet); + struct ncp_ioctl_request request; + int result; + + assert_server_locked(server); + + if (server->has_subfunction != 0) { + *(word *)(server->packet) = server->current_size - 2; + } + + request.function = function; + request.size = server->current_size; + request.data = server->packet; + + if ((result = ioctl(server->mount_fid, NCP_IOC_NCPREQUEST, + &request)) < 0) { + return result; + } + + server->ncp_reply_size = result - sizeof(struct ncp_reply_header); + + result = reply->completion_code; + + if ((result != 0)&&(server->silent==0)) { + ncp_printf("ncp_request_error: %d\n", result); + } + return result; +} + +static inline int +min(int a, int b) { + if (alock == 0) { + ncp_printf("ncpfs: server not locked!\n"); + } +} + +static void +ncp_add_byte(struct ncp_server *server, byte x) +{ + assert_server_locked(server); + *(byte *)(&(server->packet[server->current_size])) = x; + server->current_size += 1; + return; +} + +static void +ncp_add_word(struct ncp_server *server, word x) +{ + assert_server_locked(server); + *(word *)(&(server->packet[server->current_size])) = x; + server->current_size += 2; + return; +} + +static void +ncp_add_dword(struct ncp_server *server, dword x) +{ + assert_server_locked(server); + *(dword *)(&(server->packet[server->current_size])) = x; + server->current_size += 4; + return; +} + +static void +ncp_add_mem(struct ncp_server *server, const void *source, int size) +{ + assert_server_locked(server); + memcpy(&(server->packet[server->current_size]), source, size); + server->current_size += size; + return; +} + +static void +ncp_add_pstring(struct ncp_server *server, const char *s) +{ + int len = strlen(s); + assert_server_locked(server); + if (len > 255) { + ncp_printf("ncpfs: string too long: %s\n", s); + len = 255; + } + ncp_add_byte(server, len); + ncp_add_mem(server, s, len); + return; +} + +static void +ncp_init_request(struct ncp_server *server) +{ + ncp_lock_server(server); + + server->current_size = 0; + server->packet = server->ncp_data; + server->has_subfunction = 0; +} + +static void +ncp_init_request_s(struct ncp_server *server, int subfunction) +{ + ncp_init_request(server); + ncp_add_word(server, 0); /* preliminary size */ + + ncp_add_byte(server, subfunction); + + server->has_subfunction = 1; +} + +static char * +ncp_reply_data(struct ncp_server *server, int offset) +{ + return &(server->packet[sizeof(struct ncp_reply_header) + offset]); +} + +static byte +ncp_reply_byte(struct ncp_server *server, int offset) +{ + return *(byte *)(ncp_reply_data(server, offset)); +} + +static word +ncp_reply_word(struct ncp_server *server, int offset) +{ + return *(word *)(ncp_reply_data(server, offset)); +} + +static dword +ncp_reply_dword(struct ncp_server *server, int offset) +{ + return *(dword *)(ncp_reply_data(server, offset)); +} + +int +ncp_negotiate_buffersize(struct ncp_server *server, + int size, int *target) { + + int result; + + ncp_init_request(server); + ncp_add_word(server, htons(size)); + + if ((result = ncp_request(server, 33)) != 0) { + ncp_unlock_server(server); + return result; + } + + *target =min(ntohs(ncp_reply_word(server, 0)), size); + + ncp_unlock_server(server); + return 0; +} + + +/* + * result is a 8-byte buffer + */ +int +ncp_get_encryption_key(struct ncp_server *server, + char *target) +{ + int result; + + ncp_init_request_s(server, 23); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + if (server->ncp_reply_size < 8) { + ncp_printf("ncp_reply_size %d < 8\n", + server->ncp_reply_size); + ncp_unlock_server(server); + return result; + } + + memcpy(target, ncp_reply_data(server, 0), 8); + ncp_unlock_server(server); + return 0; +} + +int +ncp_get_bindery_object_id(struct ncp_server *server, + int object_type, char *object_name, + struct ncp_bindery_object *target) +{ + int result; + ncp_init_request_s(server, 53); + ncp_add_word(server, htons(object_type)); + ncp_add_pstring(server, object_name); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + if (server->ncp_reply_size < 54) { + ncp_printf("ncp_reply_size %d < 54\n", + server->ncp_reply_size); + ncp_unlock_server(server); + return result; + } + + target->object_id = ntohl(ncp_reply_dword(server, 0)); + target->object_type = ntohs(ncp_reply_word (server, 4)); + memcpy(target->object_name, ncp_reply_data(server, 6), 48); + ncp_unlock_server(server); + return 0; +} + +int +ncp_read_property_value(struct ncp_server *server, + int object_type, char *object_name, + int segment, char *prop_name, + struct nw_property *target) +{ + int result; + ncp_init_request_s(server, 61); + ncp_add_word(server, htons(object_type)); + ncp_add_pstring(server, object_name); + ncp_add_byte(server, segment); + ncp_add_pstring(server, prop_name); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(&(target->value), ncp_reply_data(server, 0), 128); + target->more_flag = ncp_reply_byte(server, 128); + target->property_flag = ncp_reply_byte(server, 129); + ncp_unlock_server(server); + return 0; +} + +int +ncp_login_encrypted(struct ncp_server *server, + struct ncp_bindery_object *object, + unsigned char *key, + unsigned char *passwd) +{ + dword tmpID = htonl(object->object_id); + unsigned char buf[128]; + unsigned char encrypted[8]; + int result; + + shuffle((byte *)&tmpID, passwd, strlen(passwd), buf); + nw_encrypt(key, buf, encrypted); + + ncp_init_request_s(server, 24); + ncp_add_mem(server, encrypted, 8); + ncp_add_word(server, htons(object->object_type)); + ncp_add_pstring(server, object->object_name); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_login_user(struct ncp_server *server, + unsigned char *username, + unsigned char *password) +{ + int result; + unsigned char ncp_key[8]; + struct ncp_bindery_object user; + + if ((result = ncp_get_encryption_key(server, ncp_key)) != 0) { + return result; + } + + if ((result = ncp_get_bindery_object_id(server, NCP_BINDERY_USER, + username, &user)) != 0) { + return result; + } + + if ((result = ncp_login_encrypted(server, &user, + ncp_key, password)) != 0) { + return result; + } + return 0; +} + + + +int +ncp_get_volume_info_with_number(struct ncp_server *server, int n, + struct ncp_volume_info *target) +{ + int result; + int len; + + ncp_init_request_s(server, 44); + ncp_add_byte(server, n); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_unlock_server(server); + return result; + } + + target->total_blocks = ncp_reply_dword(server, 0); + target->free_blocks = ncp_reply_dword(server, 4); + target->purgeable_blocks = ncp_reply_dword(server, 8); + target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12); + target->total_dir_entries = ncp_reply_dword(server, 16); + target->available_dir_entries = ncp_reply_dword(server, 20); + target->sectors_per_block = ncp_reply_byte(server, 28); + + memset(&(target->volume_name), 0, sizeof(target->volume_name)); + + len = ncp_reply_byte(server, 29); + if (len > NCP_VOLNAME_LEN) { + ncp_printf("ncpfs: volume name too long: %d\n", len); + ncp_unlock_server(server); + return -EIO; + } + + memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); + ncp_unlock_server(server); + return 0; +} + +int +ncp_get_volume_number(struct ncp_server *server, const char *name, int *target) +{ + int result; + + ncp_init_request_s(server, 5); + ncp_add_pstring(server, name); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_unlock_server(server); + return result; + } + + *target = ncp_reply_byte(server, 0); + ncp_unlock_server(server); + return 0; +} + + +int +ncp_file_search_init(struct ncp_server *server, + int dir_handle, const char *path, + struct ncp_filesearch_info *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, dir_handle); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 62)) != 0) { + ncp_unlock_server(server); + return result; + } + + target->volume_number = ncp_reply_byte(server, 0); + target->directory_id = ntohs(ncp_reply_word(server, 1)); + target->sequence_no = ntohs(ncp_reply_word(server, 3)); + target->access_rights = ncp_reply_byte(server, 5); + ncp_unlock_server(server); + return 0; +} + + +int +ncp_file_search_continue(struct ncp_server *server, + struct ncp_filesearch_info *fsinfo, + int attributes, const char *name, + struct ncp_file_info *target) +{ + int result; + + ncp_init_request(server); + + ncp_add_byte(server, fsinfo->volume_number); + ncp_add_word(server, htons(fsinfo->directory_id)); + ncp_add_word(server, htons(fsinfo->sequence_no)); + + ncp_add_byte(server, attributes); + ncp_add_pstring(server, name); + + if ((result = ncp_request(server, 63)) != 0) { + ncp_unlock_server(server); + return result; + } + + fsinfo->sequence_no = ntohs(ncp_reply_word(server, 0)); + + memset(&(target->file_name), 0, sizeof(target->file_name)); + memcpy(&(target->file_name), ncp_reply_data(server, 4), + NCP_MAX_FILENAME); + + target->file_attributes = ncp_reply_byte(server, 18); + target->file_mode = ncp_reply_byte(server, 19); + target->file_length = ntohl(ncp_reply_dword(server, 20)); + target->creation_date = ntohs(ncp_reply_word(server, 24)); + target->access_date = ntohs(ncp_reply_word(server, 26)); + target->update_date = ntohs(ncp_reply_word(server, 28)); + target->update_time = ntohs(ncp_reply_word(server, 30)); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_get_finfo(struct ncp_server *server, + int dir_handle, const char *path, const char *name, + struct ncp_file_info *target) +{ + int result; + + struct ncp_filesearch_info fsinfo; + + if ((result = ncp_file_search_init(server, dir_handle, path, + &fsinfo)) != 0) { + return result; + } + + if ((result = ncp_file_search_continue(server, &fsinfo, 0, name, + target)) == 0) { + return result; + } + + if ((result = ncp_file_search_init(server, dir_handle, path, + &fsinfo)) != 0) { + return result; + } + + return ncp_file_search_continue(server, &fsinfo, aDIR, name, target); +} + +int +ncp_open_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, int access, + struct ncp_file_info *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, attr); + ncp_add_byte(server, access); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 76)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(&(target->file_id), ncp_reply_data(server, 0), + NCP_FILE_ID_LEN); + + memset(&(target->file_name), 0, sizeof(target->file_name)); + memcpy(&(target->file_name), ncp_reply_data(server, 8), + NCP_MAX_FILENAME); + + target->file_attributes = ncp_reply_byte(server, 22); + target->file_mode = ncp_reply_byte(server, 23); + target->file_length = ntohl(ncp_reply_dword(server, 24)); + target->creation_date = ntohs(ncp_reply_word(server, 28)); + target->access_date = ntohs(ncp_reply_word(server, 30)); + target->update_date = ntohs(ncp_reply_word(server, 32)); + target->update_time = ntohs(ncp_reply_word(server, 34)); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_close_file(struct ncp_server *server, const char *file_id) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + + if ((result = ncp_request(server, 66)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +static int +ncp_do_create(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target, + int function) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, attr); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, function)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(&(target->file_id), ncp_reply_data(server, 0), + NCP_FILE_ID_LEN); + + memset(&(target->file_name), 0, sizeof(target->file_name)); + memcpy(&(target->file_name), ncp_reply_data(server, 8), + NCP_MAX_FILENAME); + + target->file_attributes = ncp_reply_byte(server, 22); + target->file_mode = ncp_reply_byte(server, 23); + target->file_length = ntohl(ncp_reply_dword(server, 24)); + target->creation_date = ntohs(ncp_reply_word(server, 28)); + target->access_date = ntohs(ncp_reply_word(server, 30)); + target->update_date = ntohs(ncp_reply_word(server, 32)); + target->update_time = ntohs(ncp_reply_word(server, 34)); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_create_newfile(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target) +{ + return ncp_do_create(server, dir_handle, path, attr, target, 77); +} + +int +ncp_create_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target) +{ + return ncp_do_create(server, dir_handle, path, attr, target, 67); +} + +int +ncp_erase_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, attr); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 68)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_rename_file(struct ncp_server *server, + int old_handle, const char *old_path, + int attr, + int new_handle, const char *new_path) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, old_handle); + ncp_add_byte(server, attr); + ncp_add_pstring(server, old_path); + ncp_add_byte(server, new_handle); + ncp_add_pstring(server, new_path); + + if ((result = ncp_request(server, 69)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_create_directory(struct ncp_server *server, + int dir_handle, const char *path, + int inherit_mask) +{ + int result; + + ncp_init_request_s(server, 10); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, inherit_mask); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_delete_directory(struct ncp_server *server, + int dir_handle, const char *path) +{ + int result; + + ncp_init_request_s(server, 11); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_rename_directory(struct ncp_server *server, + int dir_handle, + const char *old_path, const char *new_path) +{ + int result; + + ncp_init_request_s(server, 15); + ncp_add_byte(server, dir_handle); + ncp_add_pstring(server, old_path); + ncp_add_pstring(server, new_path); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + + +static void +ncp_add_handle_path(struct ncp_server *server, + __u8 vol_num, + __u32 dir_base, int have_dir_base, + char *path) +{ + ncp_add_byte(server, vol_num); + ncp_add_dword(server, dir_base); + if (have_dir_base != 0) { + ncp_add_byte(server, 1); /* dir_base */ + } else { + ncp_add_byte(server, 0xff); /* no handle */ + } + if (path != NULL) { + ncp_add_byte(server, 1); /* 1 component */ + ncp_add_pstring(server, path); + } + else + { + ncp_add_byte(server, 0); + } +} + +static void +ncp_extract_file_info(void *structure, struct nw_info_struct *target) +{ + __u8 *name_len; + const int info_struct_size = sizeof(struct nw_info_struct) - 257; + + memcpy(target, structure, info_struct_size); + name_len = structure + info_struct_size; + target->nameLen = *name_len; + strncpy(target->entryName, name_len+1, *name_len); + target->entryName[*name_len] = '\0'; + return; +} + +int +ncp_do_lookup(struct ncp_server *server, + struct nw_info_struct *dir, + char *path, /* may only be one component */ + struct nw_info_struct *target) +{ + __u8 vol_num; + __u32 dir_base; + int result; + char *volname = NULL; + + if (target == NULL) { + return -EINVAL; + } + + if (dir == NULL) { + + /* Access a volume's root directory */ + ncp_init_request(server); + ncp_add_byte(server, 22); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, 0, 0, 0, /* no handle */ + path); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + dir_base = ncp_reply_dword(server, 4); + vol_num = ncp_reply_byte (server, 8); + ncp_unlock_server(server); + volname = path; + path = NULL; + } + else + { + vol_num = dir->volNumber; + dir_base = dir->DosDirNum; + } + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* dos name space as dest */ + ncp_add_word(server, 0xff); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, vol_num, dir_base, 1, + path); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_extract_file_info(ncp_reply_data(server, 0), target); + + if (volname != NULL) { + target->nameLen = strlen(volname); + strcpy(target->entryName, volname); + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 8); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, 0x8006); /* search attribs: all */ + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, name); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +static inline void +ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] ) +{ + __u16 *dest = (__u16 *) ret; + memcpy(&(dest[1]), &sfd, 4); + dest[0] = dest[1] + 1; + return; +} + +int +ncp_open_create_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name, + int open_create_mode, + __u32 create_attributes, + int desired_acc_rights, + struct nw_file_info *target) +{ + int result; + + target->opened = 0; + + ncp_init_request(server); + ncp_add_byte(server, 1); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, open_create_mode); + ncp_add_word(server, 0x8006); + ncp_add_dword(server, RIM_ALL); + ncp_add_dword(server, create_attributes); + /* The desired acc rights seem to be the inherited rights mask + for directories */ + ncp_add_word(server, desired_acc_rights); + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, name); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + target->opened = 1; + target->server_file_handle = ncp_reply_dword(server, 0); + target->open_create_action = ncp_reply_byte(server, 4); + ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i)); + ConvertToNWfromDWORD(target->server_file_handle, target->file_handle); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_initialize_search(struct ncp_server *server, + struct nw_info_struct *dir, + struct nw_search_sequence *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 2); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, NULL); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); + + ncp_unlock_server(server); + return 0; +} + +/* Search for everything */ +int +ncp_search_for_file_or_subdir(struct ncp_server *server, + struct nw_search_sequence *seq, + struct nw_info_struct *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 3); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* data stream (???) */ + ncp_add_word(server, 0xffff); /* Search attribs */ + ncp_add_dword(server, RIM_ALL); /* return info mask */ + ncp_add_mem(server, seq, 9); + ncp_add_byte(server, 2); /* 2 byte pattern */ + ncp_add_byte(server, 0xff); /* following is a wildcard */ + ncp_add_byte(server, '*'); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq)); + ncp_extract_file_info(ncp_reply_data(server, 10), target); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *old_dir, char *old_name, + struct nw_info_struct *new_dir, char *new_name) +{ + int result; + + if ( (old_dir == NULL) || (old_name == NULL) + || (new_dir == NULL) || (new_name == NULL)) + return -EINVAL; + + ncp_init_request(server); + ncp_add_byte(server, 4); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 1); /* rename flag */ + ncp_add_word(server, 0x8006); /* search attributes */ + + /* source Handle Path */ + ncp_add_byte(server, old_dir->volNumber); + ncp_add_dword(server, old_dir->DosDirNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 source component */ + + /* dest Handle Path */ + ncp_add_byte(server, new_dir->volNumber); + ncp_add_dword(server, new_dir->DosDirNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 destination component */ + + /* source path string */ + ncp_add_pstring(server, old_name); + /* dest path string */ + ncp_add_pstring(server, new_name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + + +/* Create a new job entry */ +int +ncp_create_queue_job_and_file(struct ncp_server *server, + __u32 queue_id, + struct queue_job *job) +{ + int result; + + ncp_init_request_s(server, 121); + ncp_add_dword(server, htonl(queue_id)); + ncp_add_mem(server, &(job->j), sizeof(job->j)); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + memcpy(&(job->j), ncp_reply_data(server, 0), 78); + + ConvertToNWfromDWORD(job->j.JobFileHandle, job->file_handle); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_close_file_and_start_job(struct ncp_server *server, + __u32 queue_id, + struct queue_job *job) +{ + int result; + + ncp_init_request_s(server, 127); + ncp_add_dword(server, htonl(queue_id)); + ncp_add_dword(server, job->j.JobNumber); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_read(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, + char *target, int *bytes_read) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_read)); + + if ((result = ncp_request(server, 72)) != 0) { + ncp_unlock_server(server); + return result; + } + + *bytes_read = ntohs(ncp_reply_word(server, 0)); + + memcpy(target, ncp_reply_data(server, 2), *bytes_read); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_write)); + ncp_add_mem(server, source, to_write); + + if ((result = ncp_request(server, 73)) != 0) { + ncp_unlock_server(server); + return result; + } + + *bytes_written = to_write; + + ncp_unlock_server(server); + return 0; +} + diff --git a/ncplib_user.h b/ncplib_user.h new file mode 100644 index 0000000..a26441c --- /dev/null +++ b/ncplib_user.h @@ -0,0 +1,168 @@ +#ifndef _NCPLIB_H +#define _NCPLIB_H + +#include +#include +#include + +struct ncp_server { + int current_size; + int has_subfunction; + int mount_fid; + int silent; + int ncp_reply_size; + char *packet; + int lock; + + char ncp_data[NCP_PACKET_SIZE]; +}; + +#include + +int +ncp_negotiate_buffersize(struct ncp_server *server, int size, + int *target); +int +ncp_get_encryption_key(struct ncp_server *server, + char *target); +int +ncp_get_bindery_object_id(struct ncp_server *server, + int object_type, char *object_name, + struct ncp_bindery_object *target); +int +ncp_read_property_value(struct ncp_server *server, + int object_type, char *object_name, + int segment, char *prop_name, + struct nw_property *target); +int +ncp_login_encrypted(struct ncp_server *server, + struct ncp_bindery_object *object, + unsigned char *key, + unsigned char *passwd); +int +ncp_login_user(struct ncp_server *server, + unsigned char *username, + unsigned char *password); +int +ncp_get_volume_info_with_number(struct ncp_server *server, int n, + struct ncp_volume_info *target); + +int +ncp_get_volume_number(struct ncp_server *server, const char *name, + int *target); + +int +ncp_file_search_init(struct ncp_server *server, + int dir_handle, const char *path, + struct ncp_filesearch_info *target); + +int +ncp_file_search_continue(struct ncp_server *server, + struct ncp_filesearch_info *fsinfo, + int attributes, const char *path, + struct ncp_file_info *target); + +int +ncp_get_finfo(struct ncp_server *server, + int dir_handle, const char *path, const char *name, + struct ncp_file_info *target); + +int +ncp_open_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, int access, + struct ncp_file_info *target); +int +ncp_close_file(struct ncp_server *server, const char *file_id); + +int +ncp_create_newfile(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target); + +int +ncp_create_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target); + +int +ncp_erase_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr); + +int +ncp_rename_file(struct ncp_server *server, + int old_handle, const char *old_path, + int attr, + int new_handle, const char *new_path); + +int +ncp_create_directory(struct ncp_server *server, + int dir_handle, const char *path, + int inherit_mask); + +int +ncp_delete_directory(struct ncp_server *server, + int dir_handle, const char *path); + +int +ncp_rename_directory(struct ncp_server *server, + int dir_handle, + const char *old_path, const char *new_path); + +int +ncp_read(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, + char *target, int *bytes_read); + +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written); + +int +ncp_do_lookup(struct ncp_server *server, + struct nw_info_struct *dir, + char *path, /* may only be one component */ + struct nw_info_struct *target); + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name); + +int +ncp_open_create_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name, + int open_create_mode, + __u32 create_attributes, + int desired_acc_rights, + struct nw_file_info *target); + +int +ncp_initialize_search(struct ncp_server *server, + struct nw_info_struct *dir, + struct nw_search_sequence *target); + +int +ncp_search_for_file_or_subdir(struct ncp_server *server, + struct nw_search_sequence *seq, + struct nw_info_struct *target); + +int +ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *old_dir, char *old_name, + struct nw_info_struct *new_dir, char *new_name); + +int +ncp_create_queue_job_and_file(struct ncp_server *server, + __u32 queue_id, + struct queue_job *job); + +int +ncp_close_file_and_start_job(struct ncp_server *server, + __u32 queue_id, + struct queue_job *job); + +#endif /* _NCPLIB_H */ diff --git a/ncpmount.c b/ncpmount.c index af49a92..d40ba91 100644 --- a/ncpmount.c +++ b/ncpmount.c @@ -34,6 +34,7 @@ extern pid_t waitpid(pid_t, int *, int); #include #include #include "ipxutil.h" +#include "ncplib_user.h" static char *progname; @@ -47,17 +48,6 @@ str_upper(char *name) } } -static char * -fullpath(const char *p) -{ - char path[MAXPATHLEN]; - - if (realpath(p, path) == NULL) - return strdup(p); - else - return strdup(path); -} - static void usage(void) { @@ -170,6 +160,7 @@ ipx_sap_find_server(char *name, int server_type, int timeout, int name_len = strlen(name); fd_set rd, wr, ex; struct timeval tv; + int packets; if (name_len > 48) { return -1; @@ -215,41 +206,54 @@ ipx_sap_find_server(char *name, int server_type, int timeout, perror("sendto"); goto finished; } - - FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); - FD_SET(sock, &rd); - - tv.tv_sec = timeout; - tv.tv_usec = 0; - - if (select(sock+1, &rd, &wr, &ex, &tv) == -1) { - perror("select"); - goto finished; - } - - if (FD_ISSET(sock, &rd)) { - int len = recv(sock, data, 1024, 0); - int i; - struct sap_server_ident *ident; + + packets = 10; + while (packets > 0) { + + packets -= 1; - for (i = 2; i < len; i += 64) { - ident = (struct sap_server_ident *)(data+i); - if ( (strncmp(name,ident->server_name,name_len)==0) - && (name_len < 48) - && (ident->server_name[name_len] == '\0')) - { - result->sipx_family = AF_IPX; - result->sipx_network = - ident->server_network; - result->sipx_port = ident->server_port; - ipx_assign_node(result->sipx_node, - ident->server_node); - res = 0; - goto finished; + FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); + FD_SET(sock, &rd); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + if (select(sock+1, &rd, &wr, &ex, &tv) == -1) { + perror("select"); + goto finished; + } + + if (FD_ISSET(sock, &rd)) { + int len = recv(sock, data, 1024, 0); + int i; + struct sap_server_ident *ident; + + for (i = 2; i < len; i += 64) { + ident = (struct sap_server_ident *)(data+i); + if ( (strncmp(name,ident->server_name, + name_len)==0) + && (name_len < 48) + && (ident->server_name[name_len] == '\0')) + { + result->sipx_family = AF_IPX; + result->sipx_network = + ident->server_network; + result->sipx_port = ident->server_port; + ipx_assign_node(result->sipx_node, + ident->server_node); + res = 0; + goto finished; + } } } + else + { + printf("nobody answered, server %s not found\n", + name); + exit(1); + } } - + finished: close(sock); return res; @@ -449,6 +453,8 @@ main(int argc, char *argv[]) struct ncp_mount_data data; struct sockaddr_ipx addr; struct stat st; + struct ncp_server serv; + struct ncp_server *server = &serv; int fd; int Got_Password; @@ -458,7 +464,7 @@ main(int argc, char *argv[]) char hostname[MAXHOSTNAMELEN + 1]; char *server_name; - char *mount_point; + char mount_point[MAXPATHLEN]; struct mntent ment; FILE *mtab; @@ -494,7 +500,9 @@ main(int argc, char *argv[]) } server_name = argv[1]; - mount_point = argv[2]; + str_upper(server_name); + + realpath(argv[2], mount_point); argv += 2; argc -= 2; @@ -615,26 +623,44 @@ main(int argc, char *argv[]) if (mount(NULL, mount_point, "ncpfs", flags, (char *)&data) < 0) { - perror("mount error"); + printf("mount failed\n"); close(wdog_sock); close(ncp_sock); - printf("Maybe you should try to type the username and\n" - "password in UPPERCASE.\n"); + printf("Maybe you have no route to the internal net " + "of your server.\n"); return -1; } close(ncp_sock); close(wdog_sock); + server->mount_fid = open(mount_point, O_RDONLY, 0); + server->silent = 1; + + if (server->mount_fid == -1) { + fprintf(stderr, "Could not open %s: %s\n", + mount_point, strerror(errno)); + umount(mount_point); + return -1; + } + + if (ncp_login_user(server, data.username, data.password) != 0) { + fprintf(stderr, "login failed\n"); + fprintf(stderr, + "should try to type the username and\n" + "password in UPPERCASE.\n"); + close(server->mount_fid); + umount(mount_point); + return -1; + } + ment.mnt_fsname = server_name; - ment.mnt_dir = fullpath(mount_point); + ment.mnt_dir = mount_point; ment.mnt_type = "ncpfs"; ment.mnt_opts = "rw"; ment.mnt_freq = 0; ment.mnt_passno= 0; - mount_point = ment.mnt_dir; - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { fprintf(stderr, "Can't get "MOUNTED"~ lock file"); diff --git a/ncptest.c b/ncptest.c index a914ac7..eb26532 100644 --- a/ncptest.c +++ b/ncptest.c @@ -1,5 +1,5 @@ /* - * ncpmount.c + * ncptest.c * * Copyright (C) 1995 by Volker Lendecke * @@ -35,7 +35,7 @@ extern pid_t waitpid(pid_t, int *, int); #include #include #include -#include "ncplib.h" +#include "ncplib_user.h" #include "ipxutil.h" static char *progname; @@ -112,10 +112,245 @@ testcreate(struct ncp_server *server) } +void +test_lookup(struct ncp_server *server) +{ + struct nw_info_struct sys; + struct nw_info_struct me; + struct nw_file_info blub; + + if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_do_lookup(server, &sys, "ME", &me) != 0) { + printf("lookup error\n"); + return; + } + + if (ncp_open_create_file_or_subdir(server, &me, "BLUB.TXT", + OC_MODE_CREATE, 0, 0xffff, + &blub) != 0) { + printf("open error\n"); + return; + } + return; +} + +void +test_trunc(struct ncp_server *server) +{ + struct nw_info_struct sys; + struct nw_info_struct me; + struct nw_file_info blub; + int written; + + if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_do_lookup(server, &sys, "ME", &me) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_do_lookup(server, &me, "BLUB.TXT", &(blub.i)) != 0) { + printf("lookup error\n"); + return; + } + + if (ncp_open_create_file_or_subdir(server, &(blub.i), NULL, + OC_MODE_OPEN, 0, AR_READ | AR_WRITE, + &blub) != 0) { + printf("open error\n"); + return; + } + + if (ncp_write(server, blub.file_handle, 4, 0, "", &written) != 0) { + printf("trunc error\n"); + return; + } + + if (ncp_close_file(server, blub.file_handle) != 0) { + printf("close error\n"); + return; + } + + return; +} + +void +test_ls(struct ncp_server *server) +{ + struct nw_info_struct sys; + struct nw_search_sequence seq; + struct nw_info_struct found; + int res; + + if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_initialize_search(server, &sys, &seq) != 0) { + printf("init error\n"); + return; + } + while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0) { + printf("found %s: %s\n", + (found.attributes & aDIR) ? "dir " : "file", + found.entryName); + } + + if (res == 0xfe) { + printf("result: no more files\n"); + } + else + { + printf("other error: %x\n", res); + } + return; +} + +void +test_ren(struct ncp_server *server) +{ + struct nw_info_struct sys; + struct nw_info_struct me; + + if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_do_lookup(server, &sys, "ME", &me) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_ren_or_mov_file_or_subdir(server, &me, "BLUB.TXT", + &me, "BLUB1.TXT") != 0) { + printf("ren error\n"); + return; + } + +} + +void +test_rm(struct ncp_server *server) +{ + struct nw_info_struct sys; + struct nw_info_struct me; + + if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_do_lookup(server, &sys, "ME", &me) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_del_file_or_subdir(server, &me, "BLUB1.TXT") != 0) { + printf("ren error\n"); + return; + } + +} + +void +test_mkdir(struct ncp_server *server) +{ + struct nw_info_struct sys; + struct nw_info_struct me; + struct nw_file_info dir1; + struct nw_file_info dir2; + + + if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_do_lookup(server, &sys, "ME", &me) != 0) { + printf("lookup error\n"); + return; + } + if (ncp_open_create_file_or_subdir(server, &me, "DIR1", + OC_MODE_CREATE, aDIR, 0xffff, &dir1) + != 0) { + printf("mkdir1 error\n"); + return; + } + if (ncp_open_create_file_or_subdir(server, &me, "DIR2", + OC_MODE_CREATE, aDIR, 0xffff, &dir2) + != 0) { + printf("mkdir2 error\n"); + return; + } + + if (ncp_del_file_or_subdir(server, &me, "DIR1") != 0) { + printf("rmdir error\n"); + return; + } +} + + +void +test_print(struct ncp_server *server) +{ + struct ncp_bindery_object q; + struct queue_job j; + struct print_job_record pj; + int written; + + if (ncp_get_bindery_object_id(server, NCP_BINDERY_PQUEUE, + "Q_DJ500", &q) != 0) { + printf("get oid error\n"); + return; + } + + memset(&j, 0, sizeof(j)); + + j.j.TargetServerID = 0xffffffff; /* any server */ + memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime)); /* at once */ + j.j.JobType = 0xffff; + strcpy(j.j.JobTextDescription, "Test Job"); + + memset(&pj, 0, sizeof(pj)); + + pj.Version = 0; + pj.TabSize = 0; + pj.Copies = 1; + pj.CtrlFlags = 0; + pj.Lines = 0; + pj.Rows = 0; + strcpy(pj.FormName, ""); + strcpy(pj.Banner, ""); + strcpy(pj.FnameBanner, ""); + strcpy(pj.FnameHeader, ""); + strcpy(pj.Path, ""); + + memcpy(j.j.ClientRecordArea, &pj, sizeof(pj)); + + if (ncp_create_queue_job_and_file(server, q.object_id, &j) != 0) { + printf("create error\n"); + return; + } + + if (ncp_write(server, j.file_handle, 0, 5, "hallo", &written) != 0) { + printf("write error\n"); + return; + } + + if (ncp_close_file_and_start_job(server, q.object_id, &j) != 0) { + printf("close error\n"); + return; + } + + return; +} + + + + int main(int argc, char **argv) { - struct ncp_mount_data data; struct stat st; struct ncp_server serv; struct ncp_server *server = &serv; @@ -128,8 +363,6 @@ main(int argc, char **argv) exit(1); } - memset(&data, 0, sizeof(struct ncp_mount_data)); - if (argc == 2) { mount_point = argv[1]; } else { @@ -146,6 +379,7 @@ main(int argc, char **argv) } server->mount_fid = open(mount_point, O_RDONLY, 0); + server->silent = 0; if (server->mount_fid == -1) { fprintf(stderr, "Could not open %s: %s\n", @@ -162,11 +396,11 @@ main(int argc, char **argv) test_filesearch(server); test_getfinfo(server); - + test_mkdir(server); + test_ls(server); #endif - - testcreate(server); + test_trunc(server); return 0; } diff --git a/sock.c b/sock.c index 11e6bbd..1c85702 100644 --- a/sock.c +++ b/sock.c @@ -7,11 +7,7 @@ * */ -#include -#ifdef MODULE -#include -#include -#endif +/* #include */ #include #include @@ -33,6 +29,47 @@ #define _S(nr) (1<<((nr)-1)) +static int _recvfrom(struct socket *sock, unsigned char *ubuf, + int size, int noblock, unsigned flags, + struct sockaddr_ipx *sa, int *addr_len) +{ + struct iovec iov; + struct msghdr msg; + + iov.iov_base = ubuf; + iov.iov_len = size; + + msg.msg_name = (void *)sa; + msg.msg_namelen = 0; + if (addr_len) + msg.msg_namelen = *addr_len; + msg.msg_accrights = NULL; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len); +} + +static int _sendto(struct socket *sock, const void *buff, + int len, int nonblock, unsigned flags, + struct sockaddr_ipx *sa, int addr_len) + +{ + struct iovec iov; + struct msghdr msg; + + iov.iov_base = (void *)buff; + iov.iov_len = len; + + msg.msg_name = (void *)sa; + msg.msg_namelen = addr_len; + msg.msg_accrights = NULL; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + return sock->ops->sendmsg(sock, &msg, len, nonblock, flags); +} + static void ncp_wdog_data_ready(struct sock *sk, int len) @@ -50,9 +87,8 @@ ncp_wdog_data_ready(struct sock *sk, int len) fs = get_fs(); set_fs(get_ds()); - result = sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0, - (struct sockaddr *)&sender, - &addr_len); + result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0, + &sender, &addr_len); if ( (result != 2) || (packet_buf[1] != '?') @@ -60,9 +96,8 @@ ncp_wdog_data_ready(struct sock *sk, int len) ) { /* Error, throw away the complete packet */ - sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0, - (struct sockaddr *)&sender, - &addr_len); + _recvfrom(sock, (void *)packet_buf, 2, 1, 0, + &sender, &addr_len); printk("ncpfs: got strange packet on watchdog " "socket\n"); @@ -80,10 +115,8 @@ ncp_wdog_data_ready(struct sock *sk, int len) packet_buf[0], packet_buf[1]); packet_buf[1] = 'Y'; - result = sock->ops-> - sendto(sock, (void *)packet_buf, 2, 1, 0, - (struct sockaddr *)&sender, - sizeof(sender)); + result = _sendto(sock, (void *)packet_buf, 2, 1, 0, + &sender, sizeof(sender)); DPRINTK("send result: %d\n", result); } set_fs(fs); @@ -253,7 +286,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size) fs = get_fs(); set_fs(get_ds()); for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) { - DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", +/* DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", htonl(server->m.serv_addr.sipx_network), server->m.serv_addr.sipx_node[0], server->m.serv_addr.sipx_node[1], @@ -261,20 +294,18 @@ do_ncp_rpc_call(struct ncp_server *server, int size) server->m.serv_addr.sipx_node[3], server->m.serv_addr.sipx_node[4], server->m.serv_addr.sipx_node[5], - ntohs(server->m.serv_addr.sipx_port)); - DDPRINTK("ncpfs: req.typ: %04X, con: %d, tsk: %d, " - "seq: %d\n", + ntohs(server->m.serv_addr.sipx_port));*/ + DDPRINTK("ncpfs: req.typ: %04X, con: %d, " + "seq: %d", request.type, (request.conn_high << 8) + request.conn_low, - request.task, request.sequence); - DDPRINTK("ncpfs: req.func: %d\n", + DDPRINTK(" func: %d\n", request.function); - result = sock->ops-> - sendto(sock, (void *) start, size, 0, 0, - (struct sockaddr *)&(server->m.serv_addr), - sizeof(server->m.serv_addr)); + result = _sendto(sock, (void *) start, size, 0, 0, + &(server->m.serv_addr), + sizeof(server->m.serv_addr)); if (result < 0) { printk("ncp_rpc_call: send error = %d\n", result); break; @@ -332,9 +363,9 @@ do_ncp_rpc_call(struct ncp_server *server, int size) /* Get the header from the next packet using a peek, so keep it * on the recv queue. If it is wrong, it will be some reply * we don't now need, so discard it */ - result = sock->ops->recvfrom(sock, (void *)&reply, - sizeof(reply), 1, MSG_PEEK, - NULL, &addrlen); + result = _recvfrom(sock, (void *)&reply, + sizeof(reply), 1, MSG_PEEK, + NULL, &addrlen); if (result < 0) { if (result == -EAGAIN) { DPRINTK("ncp_rpc_call: bad select ready\n"); @@ -354,9 +385,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size) && (reply.type == NCP_POSITIVE_ACK)) { /* Throw away the packet */ DPRINTK("ncp_rpc_call: got positive acknowledge\n"); - (void)sock->ops->recvfrom(sock, (void *)&reply, - sizeof(reply), 1, 0, NULL, - &addrlen); + _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, + NULL, &addrlen); goto re_select; } @@ -382,9 +412,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size) * we have xid mismatch, so discard the packet and start * again. What a hack! but I can't call recvfrom with * a null buffer yet. */ - (void)sock->ops->recvfrom(sock, (void *)&reply, - sizeof(reply), 1, 0, NULL, - &addrlen); + _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL, + &addrlen); #if 1 printk("ncp_rpc_call: reply mismatch\n"); #endif @@ -394,9 +423,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size) * we have the correct reply, so read into the correct place and * return it */ - result=sock->ops->recvfrom(sock, (void *)start, - server->packet_size, 1, 0, NULL, - &addrlen); + result = _recvfrom(sock, (void *)start, server->packet_size, 1, 0, + NULL, &addrlen); if (result < 0) { printk("NCP: notice message: result=%d\n", result); } else if (result < sizeof(struct ncp_reply_header)) { @@ -457,6 +485,7 @@ ncp_request(struct ncp_server *server, int function) h->function = function; if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0) { + DPRINTK("ncp_request_error: %d\n", result); return result; } @@ -465,8 +494,12 @@ ncp_request(struct ncp_server *server, int function) server->reply_size = result; server->ncp_reply_size = result - sizeof(struct ncp_reply_header); - return reply->completion_code; - + result = reply->completion_code; + + if (result != 0) { + DPRINTK("ncp_completion_code: %d\n", result); + } + return result; } int @@ -515,6 +548,12 @@ ncp_disconnect(struct ncp_server *server) void ncp_lock_server(struct ncp_server *server) { +#if 1 + /* For testing, only 1 process */ + if (server->lock != 0) { + DPRINTK("ncpfs: server locked!!!\n"); + } +#endif while (server->lock) sleep_on(&server->wait); server->lock = 1; diff --git a/start_ipx b/start_ipx index 624b58d..08a3faf 100755 --- a/start_ipx +++ b/start_ipx @@ -3,5 +3,6 @@ # abcd is my ipx network number and 1234 my server's internal network number. # 00001b038b11 is the server's node number. # -ipx_interface add -p eth0 EtherII abcd -ipx_route add 1234 abcd 00001b038b11 +ipx_interface add -p eth0 EtherII 10 +ipx_route add 1992 10 00001b3bc0c9 +ipx_route add 1234 10 00001b038b11