Guide to Doing File Search Software Development on NetWare 386 Table of Contents ------------------ 1.0 Introduction 2.0 File Searching on NetWare 2.1 File Searches on 286 2.2 File Searches on 386 3.0 Software Development Guidelines 3.1 General Information 3.2 Using Novel's API 3.2.1 Coding Examples 3.3 Using Turbo C 3.3.1 Coding Examples 3.4 Using DOS Function Calls 3.4.1 Coding Examples 4.0 NCPLIMIT patch for NetWare 386 version 3.10 1.0 Introduction The purpose of this guide is to provide additional information for software developers writing software that will operate on a NetWare environment. Specifically, this guide addresses problems and guidelines for doing file and directory searches on NetWare drives. CHAPTER 2: File searching on NetWare. This chapter describes NetWare file searching under 286 and 386. CHAPTER 3: Software Development Guidelines. This chapter gives specific examples of doing file searches using Novell's API, Borland C and DOS function calls. CHAPTER 4: NCPLIMIT patch for NetWare 386 version 3.10. This chapter describes the use of the patch written to fix a problem in NetWare. Additional References: Novell API: NetWare C Interface. BORLAND TURBO C: Library Reference Guide. DOS Technical Reference. 2.0 File Searching on NetWare File searching on NetWare, from a software developers view, is fundamentally the same as doing file searches on DOS. The real difference being that under DOS, the file searches are performed locally and under NetWare, a file search request command is sent to the File Server and a response is returned when the search is complete. The NetWare File Server maintains all the directory structures, file structures and tables that are needed to provide directory and file services to all attached workstations. A program that performs file searches is any program that does find first's, find next's, or scans directories for file information. File searches come in two forms: 1. when the complete filename or directory name is supplied by the program, such as "REPORTS.DOC" and 2. when a wildcard character ( "*" or "?" ) is supplied as a part of the filename, such as "MAY??.RPT" or "CLASS*.*". When a search is done and the complete filename is supplied to NetWare, the file server is able to perform the search to completion. When a search is done and a wildcard character is supplied, NetWare must retain information about the ongoing search until the searching has completed by reaching the end of the specified directory or volume. NetWare must store this information because the DOS DTA (Disk Transfer Area) does not have enough space to store a file server number, volume number, and a long (4 byte) search sequence number for over 2 million directory table entries per volume. 2.1 File Searches on 286 In order to appreciate how NetWare 386 works it helps to take a look back at NetWare 286 and see how things were. Two things to remember about NetWare 286 are first, each work- station is running under some version of DOS with the corresponding NetWare shell and second, there is a maximum of 32K directory table entries per volume. Under DOS, file commands (open, close, search, read, write, etc.) typically use a 16 bit file handle to address files and directorys. This 16 bit value worked nicely for addressing the NetWare 286 directory table. NetWare was able to use the information supplied by DOS to perform the file searches. 2.2 File Searches on 386 File operations on NetWare 386 are different for a number of reasons. One of particular interest to file searches exists because of a 386 enhancement allowing for a maximum number of directory table entries per volume of 2,097,152. With a work- station, running DOS, file handles are still 16 bit values. This 16 bit value is no longer adequate to address all possible entries in a NetWare 386 volume directory table. NetWare must now maintain a table of file and directory entries to map the DOS 16 bit handle to a NetWare 32 bit directory index. The number of entries in this table is limited by the SET parameter "Maximum Outstanding NCP Searches" (refer to the NetWare 386 System Administration guide for information on the "set" command). When the number of entries in the table exceeds the maximum, the oldest entry is removed. If the entry that is removed is still flagged as an "active" entry, the warning message "You exceeded your outstanding NCP directory search limit" is displayed on the workstation console. When this has happened, NetWare no longer has enough information to complete the file search command requested. A "file not found" status is returned to the calling program along with the console message. This will cause any number of undesirable side effects to the software involved. The goal of this document is to provide information so developers can write code that does not leave old search information in the NetWare search map table. 3.0 Software Development Guidelines 3.1 General Information This section will attempt to describe correct programming practices when doing file searches under NetWare. The problem we are going to try to avoid is starting a file search and leaving it uncompleted. This will fill up NetWare's mapping table with active entries and will eventually produce the warning message described in section 2.2. There are two specific cases where searches are started and not completed that will be discussed here. Case 1: A program does a "find first" search using a wildcard character in the file name followed by an "open" on the filename returned by the "find first". The "find first" search function call will leave an active entry in the NetWare mapping table. The correct way to program this example would be to eliminate the "find first" search function call. The "open" function automatically initiates a file search but does not leave an active entry in the NetWare search mapping table. NOTE: If the "find first" call did not use wild card characters, it does not cause this problem. Case 2: A program does a file search in a given directory using one of the wildcard characters "?" or "*" and does not complete the search. This happens when a program is searching for a file, finds it, and does not continue searching until the end of the directory or volume. This will leave an active entry in the NetWare mapping table and can eventually produce the warning message described in section 2.2. 3.2 Using Novel's API Novell's API programming library provides two functions that perform directory and file scans and return information about the respective directory or file. "ScanDirectoryInformation" allows a program to obtain information about the first (or next consecutive) subdirectory of a specified directory and "ScanFileInformation" will perform the same basic function for files. When using these two functions with a wildcard character as a part of the file or directory name search string, the program needs to finish the search by looping until the end of the directory. Failure to complete the search will leave an active entry in the NetWare mapping table and can eventually produce the warning message described in section 2.2. 3.2.1 Coding Examples /* Example 1 ScanDirectoryInformation */ #include main() { BYTE dir_handle; int sequence_number; char sub_dir_name[16]; BYTE date_time[4]; long owner; BYTE rights_mask; int done; /* . */ /* . */ /* . */ sequence_number = 0; /* find the first subdirectory */ done = ScanDirectoryInformation( dir_handle, "*.*", sequence_number, sub_dir_name, date_time, &owner, &rights_mask); while( !done ) /* loop through all subdirectories */ { /* process the subdirectory code */ /* . */ /* . */ /* . */ /* get the next subdirectory */ done = ScanDirectoryInformation( dir_handle, "*.*", sequence_number, sub_dir_name, date_time, &owner, &rights_mask); } } /* Example 2 ScanFileInformation */ #include main() { BYTE dir_handle; char path_name[255]; char file_name[15]; char creation_date[2]; char last_access_date[2]; char last_update_date_time[4]; char last_archive_date_time[4]; BYTE search_attributes; BYTE file_attributes; BYTE ext_file_attributes; long owner; long file_size; int done; /* . */ /* . */ /* . */ sequence_number = 0; /* find the first file */ done = ScanfileInformation( dir_handle, path_name, search_attributes, &sequence_number, file_name, &file_attributes, &ext_file_attributes, &file_size, creation_date, last_access_date, last_update_date_time, last_archive_date_time, &owner ); while( !done ) /* loop through all files */ { /* process the next file code */ /* . */ /* . */ /* . */ /* now get the next file */ done = ScanfileInformation( dir_handle, path_name, search_attributes, &sequence_number, file_name, &file_attributes, &ext_file_attributes, &file_size, creation_date, last_access_date, last_update_date_time, last_archive_date_time, &owner ); } } 3.3 Using Turbo C The Turbo C library contains two function calls that should be used with care when programming for NetWare, "findfirst" and "findnext". The call "findfirst" should not be used along with any of the Turbo C file open calls. Any time "findfirst" is used, "findnext" should always be used until searching is complete. 3.3.1 Coding Examples #include main() { struct ffblk file_find_blk; int done; done = findfirst( "*.*", /* get the first file */ &file_find_blk, 0); while( !done ) /* loop through all files */ { /* process the file code */ /* .. */ /* .. */ done = findnext(&file_find_blk); /* get next file */ } } 3.4 Using DOS Function Calls When using DOS function calls, there are two sets of calls that will perform file searches: Function 17 (11 Hex), Function 18 (12 Hex) and function 78 (4E Hex), function 79 (4F Hex). As with the previous examples, any time you make a call to function 17 or function 78 you must complete the searches by using functions 18 or 79. It should also be noted that functions 17 and 18 are old DOS functions (version 1.0) and use FCB's (File Control Blocks) instead of file handles. Functions 78 and 79 are the recommended functions to use. 3.4.1 Coding Examples file_name db "REPORT*.*" DTA_buffer db 43 dup (?) ;allocate space for the DTA . . . ;First we must set up the DTA. mov ah, 1AH ;DOS function 1AH mov dx, seg DTA_buffer ;ds:dx points to DTA buffer mov ds, dx mov dx, offset DTA_buffer int 21H ;hand it to DOS . . ;Now get ready to search for the ;first file... mov ah, 4EH ;DOS find first function mov cx, 0 ;normal search attribute mov dx, seg file_name ;ds:dx points to file name mov ds, dx mov dx, offset file_name int 21H ;Hand it to DOS jc no_more_files ;if carry is set, then no ;file was found. file_loop: . ;code for processing the . ;files as they are found. . ;Now setup to find the next ;file match mov ah, 4FH ;DOS find next file int 21H ;Hand it to DOS jc no_more_files ;if carry is set, then no ;more files to process jmp file_loop ;Always loop until there are ;no more files to process. no_more_files: 4.0 NCPLIMIT patch for NetWare 386 version 3.10 This patch is written for NetWare 386 version 3.10. It is to be used with the Novell patch manager NLM "PATCHMAN.NLM". The "NCPLIMIT.NLM" patch adds code that will provide better manage- ment of file searches done on the server. If you have applications that generate the warning message "You exceeded your outstanding NCP directory search limit." you should load this NLM on the server. To load NCPLIMIT.NLM from floppy disk enter the following commands at the server console: LOAD A:PATCHMAN ( This loads the patch manager NLM ) LOAD A:NCPLIMIT ( This loads the ncp limit NLM patch ) Using this patch will fix a problem with NetWare management of the search mapping table but is NOT a replacement for correct programming. If, after loading this patch, you still get the warning message on the workstation, you will need to follow the recommendations given in this guide to fix your software.