diff --git a/.downloads/ncpfs-2.0.2.tgz b/.downloads/ncpfs-2.0.2.tgz new file mode 100644 index 0000000..f758119 Binary files /dev/null and b/.downloads/ncpfs-2.0.2.tgz differ diff --git a/Changes b/Changes index 52f7ee7..682e687 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,13 @@ I only began this file with ncpfs-0.12. If you're interested in older versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old. +ncpfs-2.0.1 -> ncpfs-2.0.2 +- Added some values to ipxparse. +- Added a patch against 2.0.7 for long file names support. I did not + apply this change to the 1.2-module. Please upgrade to 2.0.7 if you + want to use long file names. +- nwbpvalues can print ITEM properties + ncpfs-2.0.0 -> ncpfs-2.0.1 - Added some values to ipxparse. - Added the little bindery utilities. Maybe someone has the time to diff --git a/FAQ b/FAQ index 04f7776..cdaf2a1 100644 --- a/FAQ +++ b/FAQ @@ -39,8 +39,8 @@ packet signatures on the 4.1 server, as ncpfs does not support them. Q: Does ncpfs support long file names, using the OS/2 namespace? -No. Not yet. I still have to sort out how that really works. But it should -certainly be possible. +Yes. But you will have to patch your kernel. Look at the file +kernel-2.0/README for more information. ------------------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 3080993..bec5406 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux ncp-filesystem routines. # -VERSION = 2.0.1 +VERSION = 2.0.2 # If you are using kerneld to autoload ncp support, # uncomment this (kerneld is in linux since about 1.3.57): @@ -42,7 +42,7 @@ clean: mrproper: clean rm -fr $(INTERM_BINDIR)/* ncpfs.tgz make -C util mrproper - (cd daemon; make clean) + make -C ipxdump mrproper modules: ncpfs.o @@ -51,12 +51,10 @@ SRCDIR=$(shell basename $(SRCPATH)) DISTFILE=$(SRCDIR).tgz dist: mrproper - mv daemon .. (cd ..; \ tar cvf - $(SRCDIR) | \ gzip -9 > $(DISTFILE); \ mv $(DISTFILE) $(SRCDIR)) - mv ../daemon . make dep make all diff --git a/TODO b/TODO index c58ea44..d3663bf 100644 --- a/TODO +++ b/TODO @@ -12,6 +12,4 @@ or even help me ;-). a single NCP connection. This should make the trade-off mentioned in ncpmount.8 unnecessary. -- long file names - - Do some kind of mapping of NCP uid's to unix uid's diff --git a/ipxdump/ipxparse.c b/ipxdump/ipxparse.c index 8ac94cf..8e3e890 100644 --- a/ipxdump/ipxparse.c +++ b/ipxdump/ipxparse.c @@ -89,10 +89,31 @@ struct ncp_reply_header { __u8 data[0] __attribute__ ((packed)); }; +#define NCP_BURST_PACKET (0x7777) + +struct ncp_burst_header { + __u16 type __attribute__ ((packed)); + __u8 system_flags __attribute__ ((packed)); + __u8 stream_type __attribute__ ((packed)); + __u32 source_conn __attribute__ ((packed)); + __u32 dest_conn __attribute__ ((packed)); + __u32 packet_sequence __attribute__ ((packed)); + __u32 send_delay __attribute__ ((packed)); + __u16 burst_sequence __attribute__ ((packed)); + __u16 ack_sequence __attribute__ ((packed)); + __u32 burst_length __attribute__ ((packed)); + __u32 data_offset __attribute__ ((packed)); + __u16 data_bytes __attribute__ ((packed)); + __u16 missing_frags __attribute__ ((packed)); +}; + void handle_ipx (unsigned char *buf, int length, char *frame, int no); void handle_ncp (struct sockaddr_ipx *source, struct sockaddr_ipx *target, unsigned char *buf, int length, int no); +int handle_burst(struct sockaddr_ipx *source, + struct sockaddr_ipx *target, + unsigned char *buf, int length, int no); #define SAP_MAX_SERVER_NAME_LENGTH 48 /* in network packets */ #define SAP_MAX_SAPS_PER_PACKET 7 @@ -165,6 +186,12 @@ handle_ipx (unsigned char *buf, int length, char *frame, int no) ipx_print_saddr(&d_addr); printf("\n"); + if (handle_burst(&s_addr, &d_addr, buf + sizeof(struct ipx_packet), + length - sizeof(struct ipx_packet), no) != 0) + { + return; + } + if ( (ntohs(s_addr.sipx_port) == 0x451) || (ntohs(d_addr.sipx_port) == 0x451)) { @@ -253,6 +280,55 @@ handle_ipx (unsigned char *buf, int length, char *frame, int no) } +int handle_burst(struct sockaddr_ipx *source, + struct sockaddr_ipx *target, + unsigned char *buf, int length, int no) +{ + struct ncp_burst_header *rq = (struct ncp_burst_header *)buf; + + if (rq->type != NCP_BURST_PACKET) + { + return 0; + } + + printf("Burst Packet\n"); + printf("Stream Type: %02X, System Flags: %02X\n", + rq->stream_type, rq->system_flags); + printf("Source Conn: %08X, Dest Conn: %08X, Packet Seq: %08X\n", + rq->source_conn, rq->dest_conn, + (unsigned int)ntohl(rq->packet_sequence)); + printf("Send Delay: %08X, Burst Seq: %04X, Ack Seq: %04X\n", + (unsigned int)ntohl(rq->send_delay), ntohs(rq->burst_sequence), + ntohs(rq->ack_sequence)); + printf("Burst Length: %08X\n", (unsigned int)ntohl(rq->burst_length)); + printf("Data Offset: %08X, Data Bytes: %04X, Missing Frags: %04X\n", + (unsigned int)ntohl(rq->data_offset), ntohs(rq->data_bytes), + ntohs(rq->missing_frags)); + + if (ntohs(rq->data_bytes) == 24) + { + struct ncp_burst_request + { + struct ncp_burst_header h __attribute__ ((packed)); + __u32 function __attribute__ ((packed)); + __u32 file_handle __attribute__ ((packed)); + __u8 reserved[8] __attribute__ ((packed)); + __u32 file_offset __attribute__ ((packed)); + __u32 number_of_bytes __attribute__ ((packed)); + } *brq = (struct ncp_burst_request *)rq; + + printf("Assuming Burst Request:\n"); + printf("%s: Handle %08X, Offset %08X, Bytes %08X\n", + brq->function == 1 ? "Read " : "Write", + brq->file_handle, + (unsigned int)ntohl(brq->file_offset), + (unsigned int)ntohl(brq->number_of_bytes)); + } + + printf("\n"); + return 1; +} + void handle_ncp (struct sockaddr_ipx *source, struct sockaddr_ipx *target, unsigned char *buf, int length, int no) @@ -305,6 +381,9 @@ void handle_ncp (struct sockaddr_ipx *source, case 01: printf("Get Directory Path\n"); break; + case 03: + printf("Get Effective Directory Rights\n"); + break; case 05: printf("Get Volume Number\n"); break; diff --git a/kernel-2.0/README b/kernel-2.0/README new file mode 100644 index 0000000..ec19f0c --- /dev/null +++ b/kernel-2.0/README @@ -0,0 +1,18 @@ +This directory contains the patch you have to apply to the Linux +kernel if you want to use the support for long file names using the +OS/2 namespace on the NetWare server. It did not make it into 2.0, but +patching your kernel is really no problem. + +To apply this patch, please take a clean Linux kernel. This patch is +against Linux 2.0.7, but any later kernel version in the 2.0.x series +should also work fine. Please perform the following two steps: + +cd /usr/src/linux +patch -p1 name_space[info->volNumber]; ++} ++ ++static inline int ++ncp_preserve_case(struct inode *i) ++{ ++ return (ncp_namespace(i) == NW_NS_OS2); ++} ++ + static struct file_operations ncp_dir_operations = { + NULL, /* lseek - default */ + ncp_dir_read, /* read - bad */ +@@ -128,7 +142,7 @@ + /* Here we encapsulate the inode number handling that depends upon the + * mount mode: When we mount a complete server, the memory address of + * the ncp_inode_info is used as the inode number. When only a single +- * volume is mounted, then the DosDirNum is used as the inode ++ * volume is mounted, then the dirEntNum is used as the inode + * number. As this is unique for the complete volume, this should + * enable the NFS exportability of a ncpfs-mounted volume. + */ +@@ -143,7 +157,7 @@ + ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info) + { + return ncp_single_volume(server) +- ? info->finfo.i.DosDirNum : (ino_t)info; ++ ? info->finfo.i.dirEntNum : (ino_t)info; + } + + static inline int +@@ -177,8 +191,6 @@ + return NULL; + } + +- +- + static int + ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count) + { +@@ -326,9 +338,12 @@ + c_last_returned_index = 0; + index = 0; + +- for (i = 0; i < c_size; i++) ++ if (!ncp_preserve_case(inode)) + { +- str_lower(c_entry[i].i.entryName); ++ for (i = 0; i < c_size; i++) ++ { ++ str_lower(c_entry[i].i.entryName); ++ } + } + } + } +@@ -345,7 +360,7 @@ + + if (ncp_single_volume(server)) + { +- ino = (ino_t)(entry->i.DosDirNum); ++ ino = (ino_t)(entry->i.dirEntNum); + } + else + { +@@ -652,7 +667,7 @@ + root->finfo.opened = 0; + i->attributes = aDIR; + i->dataStreamSize = 1024; +- i->DosDirNum = 0; ++ i->dirEntNum = i->DosDirNum = 0; + i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */ + ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); + ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate)); +@@ -729,7 +744,7 @@ + + do + { +- if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum) ++ if ( (result->dir->finfo.i.dirEntNum == dir_info->dirEntNum) + && (result->dir->finfo.i.volNumber == dir_info->volNumber) + && (strcmp(result->finfo.i.entryName, name) == 0) + /* The root dir is never looked up using this +@@ -757,6 +772,7 @@ + struct ncp_server *server; + struct ncp_inode_info *result_info; + int found_in_cache; ++ int down_case = 0; + char name[len+1]; + + *result = NULL; +@@ -867,20 +883,26 @@ + if (found_in_cache == 0) + { + int res; +- str_upper(name); + + DDPRINTK("ncp_lookup: do_lookup on %s/%s\n", + NCP_ISTRUCT(dir)->entryName, name); + + if (ncp_is_server_root(dir)) + { ++ str_upper(name); ++ down_case = 1; + res = ncp_lookup_volume(server, name, &(finfo.i)); + } + else + { ++ if (!ncp_preserve_case(dir)) ++ { ++ str_upper(name); ++ down_case = 1; ++ } + res = ncp_obtain_info(server, + NCP_ISTRUCT(dir)->volNumber, +- NCP_ISTRUCT(dir)->DosDirNum, ++ NCP_ISTRUCT(dir)->dirEntNum, + name, &(finfo.i)); + } + if (res != 0) +@@ -892,7 +914,11 @@ + } + + finfo.opened = 0; +- str_lower(finfo.i.entryName); ++ ++ if (down_case != 0) ++ { ++ str_lower(finfo.i.entryName); ++ } + + if (!(*result = ncp_iget(dir, &finfo))) + { +@@ -929,7 +955,11 @@ + + strncpy(_name, name, len); + _name[len] = '\0'; +- str_upper(_name); ++ ++ if (!ncp_preserve_case(dir)) ++ { ++ str_upper(_name); ++ } + + lock_super(dir->i_sb); + if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), +@@ -946,7 +976,11 @@ + + ncp_invalid_dir_cache(dir); + +- str_lower(finfo.i.entryName); ++ if (!ncp_preserve_case(dir)) ++ { ++ str_lower(finfo.i.entryName); ++ } ++ + finfo.access = O_RDWR; + + if (!(*result = ncp_iget(dir, &finfo)) < 0) +@@ -980,7 +1014,11 @@ + + strncpy(_name, name, len); + _name[len] = '\0'; +- str_upper(_name); ++ ++ if (!ncp_preserve_case(dir)) ++ { ++ str_upper(_name); ++ } + + if (!dir || !S_ISDIR(dir->i_mode)) + { +@@ -1038,7 +1076,11 @@ + + strncpy(_name, name, len); + _name[len] = '\0'; +- str_upper(_name); ++ ++ if (!ncp_preserve_case(dir)) ++ { ++ str_upper(_name); ++ } + + if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), +@@ -1081,7 +1123,11 @@ + { + strncpy(_name, name, len); + _name[len] = '\0'; +- str_upper(_name); ++ ++ if (!ncp_preserve_case(dir)) ++ { ++ str_upper(_name); ++ } + + if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), +@@ -1136,11 +1182,19 @@ + + strncpy(_old_name, old_name, old_len); + _old_name[old_len] = '\0'; +- str_upper(_old_name); ++ ++ if (!ncp_preserve_case(old_dir)) ++ { ++ str_upper(_old_name); ++ } + + strncpy(_new_name, new_name, new_len); + _new_name[new_len] = '\0'; +- str_upper(_new_name); ++ ++ if (!ncp_preserve_case(new_dir)) ++ { ++ str_upper(_new_name); ++ } + + res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), + NCP_ISTRUCT(old_dir), _old_name, +diff -urN 2.0.7/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c +--- 2.0.7/fs/ncpfs/ncplib_kernel.c Thu Apr 18 08:40:28 1996 ++++ linux/fs/ncpfs/ncplib_kernel.c Tue Jul 16 10:52:33 1996 +@@ -190,25 +190,6 @@ + } + + 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_close_file(struct ncp_server *server, const char *file_id) + { + int result; +@@ -278,8 +259,8 @@ + + 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_byte(server, server->name_space[vol_num]); ++ ncp_add_byte(server, server->name_space[vol_num]); + ncp_add_word(server, 0xff); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, vol_num, dir_base, 1, path); +@@ -295,20 +276,57 @@ + return 0; + } + ++static inline int ++ncp_has_os2_namespace(struct ncp_server *server, __u8 volume) ++{ ++ int result; ++ __u8 *namespace; ++ __u16 no_namespaces; ++ ++ ncp_init_request(server); ++ ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */ ++ ncp_add_word(server, 0); ++ ncp_add_byte(server, volume); ++ ++ if ((result = ncp_request(server, 87)) != 0) ++ { ++ ncp_unlock_server(server); ++ return 0; ++ } ++ ++ no_namespaces = ncp_reply_word(server, 0); ++ namespace = ncp_reply_data(server, 2); ++ ++ while (no_namespaces > 0) ++ { ++ DPRINTK("get_namespaces: found %d on %d\n", *namespace,volume); ++ ++ if (*namespace == 4) ++ { ++ DPRINTK("get_namespaces: found OS2\n"); ++ ncp_unlock_server(server); ++ return 1; ++ } ++ namespace += 1; ++ no_namespaces -= 1; ++ } ++ ncp_unlock_server(server); ++ return 0; ++} ++ + int + ncp_lookup_volume(struct ncp_server *server, + char *volname, + struct nw_info_struct *target) + { + int result; +- __u8 vol_num; +- __u32 dir_base; ++ int volnum; + + DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname); + + ncp_init_request(server); + ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */ +- ncp_add_byte(server, 0); /* DOS name space */ ++ ncp_add_byte(server, 0); /* DOS namespace */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ +@@ -325,20 +343,19 @@ + return result; + } + +- dir_base = ncp_reply_dword(server, 4); +- vol_num = ncp_reply_byte(server, 8); ++ memset(target, 0, sizeof(*target)); ++ target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4); ++ target->volNumber = volnum = ncp_reply_byte(server, 8); + ncp_unlock_server(server); + +- if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL, +- target)) != 0) +- { +- return result; +- } ++ server->name_space[volnum] = ncp_has_os2_namespace(server,volnum)?4:0; + +- DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes); ++ DPRINTK("lookup_vol: namespace[%d] = %d\n", ++ volnum, server->name_space[volnum]); + + target->nameLen = strlen(volname); + strcpy(target->entryName, volname); ++ target->attributes = aDIR; + return 0; + } + +@@ -352,14 +369,14 @@ + + ncp_init_request(server); + ncp_add_byte(server, 7); /* subfunction */ +- ncp_add_byte(server, 0); /* dos name space */ ++ ncp_add_byte(server, server->name_space[file->volNumber]); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, 0x8006); /* search attribs: all */ + + ncp_add_dword(server, info_mask); + ncp_add_mem(server, info, sizeof(*info)); + ncp_add_handle_path(server, file->volNumber, +- file->DosDirNum, 1, NULL); ++ file->dirEntNum, 1, NULL); + + result = ncp_request(server, 87); + ncp_unlock_server(server); +@@ -374,11 +391,11 @@ + + ncp_init_request(server); + ncp_add_byte(server, 8); /* subfunction */ +- ncp_add_byte(server, 0); /* dos name space */ ++ ncp_add_byte(server, server->name_space[dir->volNumber]); + 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); ++ dir->dirEntNum, 1, name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); +@@ -406,15 +423,16 @@ + { + int result; + __u16 search_attribs = 0x0006; ++ __u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber; + + if ((create_attributes & aDIR) != 0) + { +- search_attribs |= 0x8000; +- } ++ search_attribs |= 0x8000; ++} + + ncp_init_request(server); + ncp_add_byte(server, 1); /* subfunction */ +- ncp_add_byte(server, 0); /* dos name space */ ++ ncp_add_byte(server, server->name_space[volume]); + ncp_add_byte(server, open_create_mode); + ncp_add_word(server, search_attribs); + ncp_add_dword(server, RIM_ALL); +@@ -425,13 +443,11 @@ + + if (dir != NULL) + { +- ncp_add_handle_path(server, dir->volNumber, +- dir->DosDirNum, 1, name); ++ ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name); + } + else + { +- ncp_add_handle_path(server, +- target->i.volNumber, target->i.DosDirNum, ++ ncp_add_handle_path(server, volume, target->i.dirEntNum, + 1, NULL); + } + +@@ -467,9 +483,9 @@ + + ncp_init_request(server); + ncp_add_byte(server, 2); /* subfunction */ +- ncp_add_byte(server, 0); /* dos name space */ ++ ncp_add_byte(server, server->name_space[dir->volNumber]); + ncp_add_byte(server, 0); /* reserved */ +- ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL); ++ ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL); + + if ((result = ncp_request(server, 87)) != 0) + { +@@ -493,7 +509,7 @@ + + ncp_init_request(server); + ncp_add_byte(server, 3); /* subfunction */ +- ncp_add_byte(server, 0); /* dos name space */ ++ ncp_add_byte(server, server->name_space[seq->volNumber]); + ncp_add_byte(server, 0); /* data stream (???) */ + ncp_add_word(server, 0xffff); /* Search attribs */ + ncp_add_dword(server, RIM_ALL); /* return info mask */ +@@ -528,19 +544,19 @@ + + ncp_init_request(server); + ncp_add_byte(server, 4); /* subfunction */ +- ncp_add_byte(server, 0); /* dos name space */ ++ ncp_add_byte(server, server->name_space[old_dir->volNumber]); + 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_dword(server, old_dir->dirEntNum); + 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_dword(server, new_dir->dirEntNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 destination component */ + +diff -urN 2.0.7/include/linux/ncp.h linux/include/linux/ncp.h +--- 2.0.7/include/linux/ncp.h Thu Apr 18 08:40:36 1996 ++++ linux/include/linux/ncp.h Tue Jul 16 17:27:45 1996 +@@ -116,6 +116,12 @@ + __u16 update_time; + }; + ++/* Defines for Name Spaces */ ++#define NW_NS_DOS 0 ++#define NW_NS_MAC 1 ++#define NW_NS_NFS 2 ++#define NW_NS_FTAM 3 ++#define NW_NS_OS2 4 + + /* Defines for ReturnInformationMask */ + #define RIM_NAME (0x0001L) +diff -urN 2.0.7/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h +--- 2.0.7/include/linux/ncp_fs_sb.h Thu Apr 18 08:40:36 1996 ++++ linux/include/linux/ncp_fs_sb.h Tue Jul 16 17:35:17 1996 +@@ -21,6 +21,8 @@ + interest for us later, so we store + it completely. */ + ++ __u8 name_space[NCP_NUMBER_OF_VOLUMES]; ++ + struct file *ncp_filp; /* File pointer to ncp socket */ + struct file *wdog_filp; /* File pointer to wdog socket */ + struct file *msg_filp; /* File pointer to message socket */ diff --git a/man/nwbpvalues.1 b/man/nwbpvalues.1 index e1daab5..96f8afe 100644 --- a/man/nwbpvalues.1 +++ b/man/nwbpvalues.1 @@ -122,10 +122,6 @@ the object flags, its security byte and the properties flag is also listed. .RE -.SH BUGS -Only SET properties can be printed. This will hopefully be fixed in -the future. (Feel free to fix this and send me a patch ;-)). - .SH AUTHORS nwbpvalues was written by Volker Lendecke with the corresponding Caldera utility in mind. See the Changes file of ncpfs for other diff --git a/ncpfs-2.0.1.lsm b/ncpfs-2.0.2.lsm similarity index 84% rename from ncpfs-2.0.1.lsm rename to ncpfs-2.0.2.lsm index 34d98ae..e52a046 100644 --- a/ncpfs-2.0.1.lsm +++ b/ncpfs-2.0.2.lsm @@ -1,7 +1,7 @@ Begin3 Title: ncpfs -Version: 2.0.1 -Entered-date: 10. July 1996 +Version: 2.0.2 +Entered-date: 18. July 1996 Description: With ncpfs you can mount volumes of your netware server under Linux. You can also print to netware print queues and spool netware print queues to the @@ -13,7 +13,7 @@ Author: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke) Maintained-by: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke) Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/ncpfs - ~124k ncpfs-2.0.1.tgz - ~ 1k ncpfs-2.0.1.lsm + ~124k ncpfs-2.0.2.tgz + ~ 1k ncpfs-2.0.2.lsm Copying-policy: GPL End diff --git a/util/nprint.c b/util/nprint.c index b9c54c5..8c6a806 100644 --- a/util/nprint.c +++ b/util/nprint.c @@ -306,8 +306,6 @@ main(int argc, char *argv[]) if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) { printf("close error\n"); - ncp_close(conn); - return; } ncp_close(conn); diff --git a/util/nwbpvalues.c b/util/nwbpvalues.c index 2e171b4..4911ad7 100644 --- a/util/nwbpvalues.c +++ b/util/nwbpvalues.c @@ -10,9 +10,13 @@ #include "ncplib.h" #include #include +#include static char *progname; +static void +print_property(char *prop_name, __u8 *val, int segments); + static void usage(void) { @@ -46,6 +50,7 @@ main(int argc, char *argv[]) char *object_name = NULL; int object_type = -1; char *property_name = NULL; + __u8 property_value[255*128]; int segno; int verbose = 0; struct nw_property segment; @@ -124,21 +129,29 @@ main(int argc, char *argv[]) goto finished; } - if ((info.property_flags & 2) == 0) - { - fprintf(stderr, "%s: Property %s is not of type SET\n", - argv[0], property_name); - goto finished; - } - segno = 1; while (ncp_read_property_value(conn, object_type, object_name, segno, property_name, &segment) == 0) { - __u32 *value = (__u32 *)(segment.value); + memcpy(&(property_value[(segno-1)*128]), segment.value, 128); + if ((segment.more_flag == 0) || (segno == 255)) + { + break; + } + } + + + if ((info.property_flags & 2) == 0) + { + print_property(property_name, property_value, segno); + } + else + { + int objects = 32 * segno; + __u32 *value = (__u32 *)property_value; int i; - for (i = 0; i < 32; i++) + for (i = 0; i < objects; i++) { struct ncp_bindery_object o; @@ -153,8 +166,8 @@ main(int argc, char *argv[]) { printf("%s %08X %04X\n", o.object_name, - (unsigned int)o.object_id, - (unsigned int)o.object_type); + (unsigned int) o.object_id, + (unsigned int) o.object_type); } else { @@ -163,12 +176,6 @@ main(int argc, char *argv[]) } value += 1; } - - if (segment.more_flag == 0) - { - break; - } - segno += 1; } result = 0; @@ -176,3 +183,79 @@ main(int argc, char *argv[]) ncp_close(conn); return result; } + +static void +print_unknown(__u8 *val) +{ + int j = (128/16); + while (1) + { + int i; + for ( i = 0 ; i < 16 ; i++ ) + { + printf ( "%02X " , val[i] ); + } + printf ( " [" ); + for ( i = 0 ; i < 16 ; i++ ) + { + printf ( "%c" , isprint(val[i]) ? val[i] : '.'); + } + j -= 1; + if ( j == 0 ) + { + printf ( "]\n" ); + return; + } + printf ( "]+\n" ) ; + val += 16; + } +} + +static void +print_string(__u8 *val) +{ + puts(val); +} + +static struct { + char *pname ; + void (*func)(__u8 *) ; +} formats[] = { + { "DESCRIPTION" , print_string } , + { "SURNAME" , print_string } , + { "OBJECT_CLASS" , print_string } , + { "DESCRIPTION" , print_string } , + { "IDENTIFICATION" , print_string } , + { "Q_DIRECTORY" , print_string } , + { NULL , NULL } +}; + +static void +print_property(char *prop_name, __u8 *val, int segments) +{ + int i; + void (*f)(__u8 *); + + for (i = 0; formats[i].pname != NULL; i++) + { + if (strcasecmp(prop_name, formats[i].pname) == 0) + { + break; + } + } + f = formats[i].func; + + if (f != NULL) + { + f(val); + return; + } + + for (i = 0; i < segments; i++) + { + printf("Segment: %03d\n", i+1); + print_unknown(&(val[i*128])); + printf("\n"); + } +} +