Annotation of mstools/samples/sdktools/windiff/scandir.c, revision 1.1

1.1     ! root        1: 
        !             2: /******************************************************************************\
        !             3: *       This is a part of the Microsoft Source Code Samples. 
        !             4: *       Copyright (C) 1993 Microsoft Corporation.
        !             5: *       All rights reserved. 
        !             6: *       This source code is only intended as a supplement to 
        !             7: *       Microsoft Development Tools and/or WinHelp documentation.
        !             8: *       See these sources for detailed information regarding the 
        !             9: *       Microsoft samples programs.
        !            10: \******************************************************************************/
        !            11: 
        !            12: /****************************** Module Header *******************************
        !            13: * Module Name: SCANDIR.C
        !            14: *
        !            15: * Scan a directory tree and build a sorted list of filenames within that
        !            16: * tree.
        !            17: *
        !            18: * Functions:
        !            19: *
        !            20: * dir_buildlist()
        !            21: * dir_delete()
        !            22: * dir_isfile()
        !            23: * dir_firstitem()
        !            24: * dir_nextitem()
        !            25: * dir_findnextfile()
        !            26: * dir_getrelname()
        !            27: * dir_getfullname()
        !            28: * dir_getroot_list()
        !            29: * dir_getroot_item()
        !            30: * dir_freerelname()
        !            31: * dir_freefullname()
        !            32: * dir_freeroot_list()
        !            33: * dir_freerootitem()
        !            34: * dir_getopenname()
        !            35: * dir_freeopenname()
        !            36: * dir_openfile()
        !            37: * dir_closefile()
        !            38: * dir_filesize()
        !            39: * dir_startcopy()
        !            40: * dir_endcopy()
        !            41: * dir_copy()
        !            42: * dir_finalelem()
        !            43: * dir_cleardirect()
        !            44: * dir_adddirect()
        !            45: * dir_addfile()
        !            46: * dir_scan()
        !            47: * dir_isvaliddir()
        !            48: * dir_isvalidfile()
        !            49: * dir_fileinit()
        !            50: * dir_dirinit()
        !            51: * dir_getpathsize()
        !            52: * dir_findnextfile()
        !            53: *
        !            54: * Comments:
        !            55: *
        !            56: * The call dir_buildlist takes a pathname and returns a handle. Subsequent
        !            57: * calls to dir_firstitem and dir_nextitem return handles to
        !            58: * items within the list, from which you can get the name of the
        !            59: * file (relative to the original pathname, or complete), and filesize.
        !            60: *
        !            61: * The list can be either built entirely during the build call, or
        !            62: * built one directory at a time as required by dir_nextitem calls. This
        !            63: * option affects only relative performance, and is taken as a
        !            64: * recommendation only (ie some of the time we will ignore the flag).
        !            65: *
        !            66: * The list is ordered alphabetically (case-insensitive using lstrcmpi).
        !            67: * within any one directory, we list filenames before going on
        !            68: * to subdirectory contents.
        !            69: *
        !            70: * All memory is allocated from a gmem_* heap hHeap declared
        !            71: * and initialised elsewhere.
        !            72: *
        !            73: * The caller gets handles to two things: a DIRLIST, representing the
        !            74: * entire list of filenames, and a DIRITEM: one item within the list.
        !            75: *
        !            76: * From the DIRITEM he can get the filename (including or excluding the
        !            77: * tree root passed to dir_build*) - and also he can get to the next
        !            78: * DIRITEM.
        !            79: *
        !            80: * We permit lazy building of the tree (usually so the caller can keep
        !            81: * the user-interface up-to-date as we go along). In this case,
        !            82: * we need to store information about how far we have scanned and
        !            83: * what is next to do. We need to scan an entire directory at a time and then
        !            84: * sort it so we can return files in the correct order.
        !            85: *
        !            86: * We scan an entire directory and store it in a DIRECT struct. This contains
        !            87: * a list of DIRITEMs for the files in the current directory, and a list of
        !            88: * DIRECTs for the subdirectories (possible un-scanned).
        !            89: *
        !            90: * dir_nextitem will use the list functions to get the next DIRITEM on the list.
        !            91: * When the end of the list is reached, it will use the backpointer back to the
        !            92: * DIRECT struct to find the next directory to scan.
        !            93: *
        !            94: ****************************************************************************/
        !            95: 
        !            96: #include <windows.h>
        !            97: #include <stdlib.h>
        !            98: #include <string.h>
        !            99: #include <dos.h>
        !           100: #include <direct.h>
        !           101: 
        !           102: #include "gutils.h"
        !           103: #include "list.h"
        !           104: #include "scandir.h"
        !           105: #include "windiff.h"
        !           106: #include "wdiffrc.h"
        !           107: 
        !           108: /*
        !           109:  * Hold name and information about a given file (one ITEM in a DIRectory)
        !           110:  * caller's DIRITEM handle is a pointer to one of these structures
        !           111:  */
        !           112: struct diritem {
        !           113:         LPSTR name;             /* ptr to filename (final element only) */
        !           114:         long size;              /* filesize */
        !           115:         struct direct FAR * direct; /* containing directory */
        !           116:         LPSTR localname;        /* name of temp copy of file */
        !           117:         BOOL bLocalIsTemp;      /* true if localname is tempfile.
        !           118:                                  */
        !           119: };
        !           120: 
        !           121: 
        !           122: /* DIRECT: Hold state about directory and current position in list of filenames.
        !           123:  */
        !           124: typedef struct direct {
        !           125:         LPSTR relname;          /* name of dir relative to DIRLIST root */
        !           126:         DIRLIST head;           /* back ptr (to get fullname) */
        !           127:         struct direct FAR * parent; /* parent directory (NULL if above tree root)*/
        !           128: 
        !           129:         BOOL bScanned;          /* TRUE if scanned */
        !           130:         LIST diritems;          /* list of DIRITEMs for files in cur. dir */
        !           131:         LIST directs;           /* list of DIRECTs for child dirs */
        !           132: 
        !           133:         int pos;                /* where are we begin, files, dirs */
        !           134:         struct direct FAR * curdir; /* subdir being scanned (ptr to list element)*/
        !           135: } FAR * DIRECT;
        !           136: 
        !           137: /* Values for direct.pos */
        !           138: #define DL_FILES        1       /* reading files from the diritems */
        !           139: #define DL_DIRS         2       /* in the dirs: List_Next on curdir */
        !           140: 
        !           141: 
        !           142: /*
        !           143:  * The DIRLIST handle returned from a build function is in fact
        !           144:  * a pointer to one of these
        !           145:  */
        !           146: struct dirlist {
        !           147: 
        !           148:         char rootname[256];        /* name of root of tree */
        !           149:         BOOL bFile;             /* TRUE if root of tree is file, not dir */
        !           150:         DIRECT dot;             /* dir  for '.' - for tree root dir */
        !           151: };
        !           152: 
        !           153: extern BOOL bAbort;             /* from windiff.c (read only here). */
        !           154: 
        !           155: 
        !           156: /* ------ memory allocation ---------------------------------------------*/
        !           157: 
        !           158: /* All memory is allocated from a heap created by the application */
        !           159: extern HANDLE hHeap;
        !           160: 
        !           161: /*-- forward declaration of internal functions ---------------------------*/
        !           162: 
        !           163: LPSTR dir_finalelem(LPSTR path);
        !           164: void dir_cleardirect(DIRECT dir);
        !           165: void dir_adddirect(DIRECT dir, LPSTR path);
        !           166: void dir_addfile(DIRECT dir, LPSTR path, DWORD size);
        !           167: void dir_scan(DIRECT dir, BOOL bRecurse);
        !           168: BOOL dir_isvaliddir(LPSTR path);
        !           169: BOOL dir_isvalidfile(LPSTR path);
        !           170: void dir_fileinit(DIRITEM pfile, DIRECT dir, LPSTR path, long size);
        !           171: void dir_dirinit(DIRECT dir, DIRLIST head, DIRECT parent, LPSTR name);
        !           172: long dir_getpathsize(LPSTR path);
        !           173: DIRITEM dir_findnextfile(DIRLIST dl, DIRECT curdir);
        !           174: 
        !           175: 
        !           176: 
        !           177: /***************************************************************************
        !           178:  * Function: dir_buildlist
        !           179:  *
        !           180:  * Purpose:
        !           181:  *
        !           182:  * Build a list of filenames
        !           183:  *
        !           184:  * Optionally build the list on demand, in which case we scan the
        !           185:  * entire directory but don't recurse into subdirs until needed
        !           186:  *
        !           187:  */
        !           188: 
        !           189: DIRLIST
        !           190: dir_buildlist(LPSTR path, BOOL bOnDemand)
        !           191: {
        !           192:         DIRLIST dl;
        !           193:         BOOL bFile;
        !           194:         
        !           195:         /* first check if the path is valid */
        !           196:         if (dir_isvaliddir(path)) {
        !           197:                 bFile = FALSE;
        !           198:         } else if (dir_isvalidfile(path)) {
        !           199:                 bFile = TRUE;
        !           200:         } else {
        !           201:                 /* not valid */
        !           202:                 return(NULL);
        !           203:         }
        !           204: 
        !           205: 
        !           206:         /* alloc and init the DIRLIST head */
        !           207: 
        !           208:         dl = (DIRLIST) gmem_get(hHeap, sizeof(struct dirlist));
        !           209:         memset(dl, 0, sizeof(struct dirlist));
        !           210: 
        !           211:         /* convert the pathname to an absolute path */
        !           212: 
        !           213:         _fullpath(dl->rootname, path, sizeof(dl->rootname));
        !           214: 
        !           215:         dl->bFile = bFile;
        !           216:         /* make a '.' directory for the current directory -
        !           217:          * all files and subdirs will be listed from here
        !           218:          */
        !           219:         dl->dot = (DIRECT) gmem_get(hHeap, sizeof(struct direct));
        !           220:         dir_dirinit(dl->dot, dl, NULL, ".");
        !           221: 
        !           222:         /* were we given a file or a directory ? */
        !           223:         if (bFile) {
        !           224:                 /* its a file. create a single file entry
        !           225:                  * and set the state accordingly
        !           226:                  */
        !           227:                 dl->dot->bScanned = TRUE;
        !           228: 
        !           229:                 dir_addfile(dl->dot, dir_finalelem(path),
        !           230:                                 dir_getpathsize(path));
        !           231: 
        !           232:                 return(dl);
        !           233:         }
        !           234: 
        !           235:         /* scan the root directory and return. if we are asked
        !           236:          * to scan the whole thing, this will cause a recursive
        !           237:          * scan all the way down the tree
        !           238:          */
        !           239:         dir_scan(dl->dot, (!bOnDemand) );
        !           240: 
        !           241:         return(dl);
        !           242: } /* dir_buildlist */
        !           243: 
        !           244: /***************************************************************************
        !           245:  * Function: dir_delete
        !           246:  *
        !           247:  * Purpose:
        !           248:  *
        !           249:  * Free up the DIRLIST and all associated memory 
        !           250:  */
        !           251: void
        !           252: dir_delete(DIRLIST dl)
        !           253: {
        !           254:         if (dl == NULL) {
        !           255:                 return;
        !           256:         }
        !           257:         dir_cleardirect(dl->dot);
        !           258:         gmem_free(hHeap, (LPSTR) dl->dot, sizeof(struct direct));
        !           259: 
        !           260: 
        !           261:         gmem_free(hHeap, (LPSTR) dl, sizeof(struct dirlist));
        !           262: }
        !           263: 
        !           264: 
        !           265: 
        !           266: /***************************************************************************
        !           267:  * Function: dir_isfile
        !           268:  *
        !           269:  * Purpose:
        !           270:  *
        !           271:  * Was the original build request a file or a directory ? 
        !           272:  */
        !           273: BOOL
        !           274: dir_isfile(DIRLIST dl)
        !           275: {
        !           276:         if (dl == NULL) {
        !           277:                 return(FALSE);
        !           278:         }
        !           279: 
        !           280:         return(dl->bFile);
        !           281: }
        !           282: 
        !           283: /***************************************************************************
        !           284:  * Function: dir_firstitem
        !           285:  *
        !           286:  * Purpose:
        !           287:  *
        !           288:  * Return the first file in the list, or NULL if no files found.
        !           289:  * Returns a DIRITEM. This can be used to get filename, size and chcksum.
        !           290:  * If there are no files in the root, we recurse down until we find a file.
        !           291:  */
        !           292: DIRITEM
        !           293: dir_firstitem(DIRLIST dl)
        !           294: {
        !           295:         if (dl == NULL) {
        !           296:                 return(NULL);
        !           297:         }
        !           298:         /*
        !           299:          * reset the state to indicate that no files have been read yet
        !           300:          */
        !           301:         dl->dot->pos = DL_FILES;
        !           302:         dl->dot->curdir = NULL;
        !           303: 
        !           304:         /* now get the next filename */
        !           305:         return(dir_findnextfile(dl, dl->dot));
        !           306: } /* dir_firstitem */
        !           307: 
        !           308: 
        !           309: /***************************************************************************
        !           310:  * Function:dir_nextitem
        !           311:  *
        !           312:  * Purpose:
        !           313:  *
        !           314:  * Get the next filename after the one given.
        !           315:  *
        !           316:  * The List_Next function can give us the next element on the list of files.
        !           317:  * If this is null, we need to go back to the DIRECT and find the
        !           318:  * next list of files to traverse (in the next subdir).
        !           319:  *
        !           320:  * After scanning all the subdirs, return to the parent to scan further
        !           321:  * dirs that are peers of this, if there are any. If we have reached the end of
        !           322:  * the tree (no more dirs in dl->dot to scan), return NULL.
        !           323:  *
        !           324:  * Don't recurse to lower levels unless fDeep is TRUE
        !           325:  */
        !           326: DIRITEM
        !           327: dir_nextitem(DIRLIST dl, DIRITEM cur, BOOL fDeep)
        !           328: {
        !           329:         DIRITEM next;
        !           330: 
        !           331:         if ((dl == NULL) || (cur == NULL)) {
        !           332:                 return(NULL);
        !           333:         }
        !           334:         if (bAbort) return NULL;  /* user requested abort */
        !           335: 
        !           336:         if ( (next = List_Next(cur)) != NULL) {
        !           337:                 /* there was another file on this list */
        !           338:                 return(next);
        !           339:         }
        !           340:         if (!fDeep) return NULL;
        !           341: 
        !           342:         /* get the head of the next list of filenames from the directory */
        !           343:         cur->direct->pos = DL_DIRS;
        !           344:         cur->direct->curdir = NULL;
        !           345:         return(dir_findnextfile(dl, cur->direct));
        !           346: } /* dir_nextitem */
        !           347: 
        !           348: /***************************************************************************
        !           349:  * Function: dir_findnextfile
        !           350:  *
        !           351:  * Purpose:
        !           352:  *
        !           353:  * Gets the next file in the directory
        !           354:  */
        !           355: DIRITEM
        !           356: dir_findnextfile(DIRLIST dl, DIRECT curdir)
        !           357: {
        !           358:         DIRITEM curfile;
        !           359: 
        !           360:         if ((dl == NULL) || (curdir == NULL)) {
        !           361:                 return(NULL);
        !           362:         }
        !           363: 
        !           364:         /* scan the subdir if necessary */
        !           365:         if (!curdir->bScanned) {
        !           366:                 dir_scan(curdir, FALSE);
        !           367:         }
        !           368: 
        !           369:         /* have we already read the files in this directory ? */
        !           370:         if (curdir->pos == DL_FILES) {
        !           371:                 /* no - return head of file list */
        !           372:                 curfile = (DIRITEM) List_First(curdir->diritems);
        !           373:                 if (curfile != NULL) {
        !           374:                         return(curfile);
        !           375:                 }
        !           376: 
        !           377:                 /* no more files - try the subdirs */
        !           378:                 curdir->pos = DL_DIRS;
        !           379:         }
        !           380: 
        !           381:         /* try the next subdir on the list, if any */
        !           382:         /* is this the first or the next */
        !           383:         if (curdir->curdir == NULL) {
        !           384:                 curdir->curdir = (DIRECT) List_First(curdir->directs);
        !           385:         } else {
        !           386:                 curdir->curdir = (DIRECT) List_Next(curdir->curdir);
        !           387:         }
        !           388:         /* did we find a subdir ? */
        !           389:         if (curdir->curdir == NULL) {
        !           390: 
        !           391:                 /* no more dirs - go back to parent if there is one */
        !           392:                 if (curdir->parent == NULL) {
        !           393:                         /* no parent - we have exhausted the tree */
        !           394:                         return(NULL);
        !           395:                 }
        !           396: 
        !           397:                 /* reset parent state to indicate this is the current
        !           398:                  * directory - so that next gets the next after this.
        !           399:                  * this ensures that multiple callers of dir_nextitem()
        !           400:                  * to the same tree work.
        !           401:                  */
        !           402:                 curdir->parent->pos = DL_DIRS;
        !           403:                 curdir->parent->curdir = curdir;
        !           404: 
        !           405:                 return(dir_findnextfile(dl, curdir->parent));
        !           406:         }
        !           407: 
        !           408:         /* there is a next directory - set it to the
        !           409:          * beginning and get the first file from it
        !           410:          */
        !           411:         curdir->curdir->pos = DL_FILES;
        !           412:         curdir->curdir->curdir = NULL;
        !           413:         return(dir_findnextfile(dl, curdir->curdir));
        !           414: 
        !           415: } /* dir_findnextfile */
        !           416: 
        !           417: 
        !           418: /*-- pathnames ----
        !           419:  *
        !           420:  * This module supports two types of pathnames, called relative and full.
        !           421:  * Relative names are relative to the root passed in the initial call
        !           422:  * to dir_build*, and full names include the tree root.
        !           423:  *
        !           424:  * Note that this is a different distinction to relative vs absolute
        !           425:  * pathnames, since the tree root may still be either relative or absolute.
        !           426:  *
        !           427:  * Examples:
        !           428:  *
        !           429:  *  - if you called dir_buildlist("c:\")
        !           430:  *              getrelname gives:               ".\config.sys"
        !           431:  *              getfullname gives:              "c:\config.sys"
        !           432:  *
        !           433:  * - if you called dir_buildlist(".\geraintd")
        !           434:  *              getrelname gives:               ".\source\scandir.h"
        !           435:  *              getfullname gives either
        !           436:  *                      ".\geraintd\source\scandir.h"
        !           437:  *                    or "c:\geraintd\source\scandir.h"
        !           438:  *                   (depending on the implementation).
        !           439:  *
        !           440:  * To support this, we maintain the tree root name in the DIRLIST head, and
        !           441:  * in each directory, the name of that directory relative to tree root.
        !           442:  * Files just have the filename, so we need to prepend the directory name,
        !           443:  * and (for getfullname) the tree root name as well
        !           444:  *
        !           445:  * We store the directory name with a trailing
        !           446:  * slash to make concatenation easier
        !           447:  *
        !           448:  * -----
        !           449:  */
        !           450: 
        !           451: /***************************************************************************
        !           452:  * Function: dir_getrelname
        !           453:  *
        !           454:  * Purpose:
        !           455:  *
        !           456:  * Return the name of the current file relative to tree root
        !           457:  */
        !           458: LPSTR
        !           459: dir_getrelname(DIRITEM cur)
        !           460: {
        !           461:         LPSTR name;
        !           462:         int size;
        !           463: 
        !           464:         /* check this is a valid item */
        !           465:         if (cur == NULL) {
        !           466:                 return(NULL);
        !           467:         }
        !           468:         /* remember to include the NULL when sizing */
        !           469:         size = lstrlen(cur->direct->relname) + lstrlen(cur->name) + 1;
        !           470:         name = gmem_get(hHeap, size);
        !           471:         lstrcpy(name, cur->direct->relname);
        !           472:         lstrcat(name, cur->name);
        !           473: 
        !           474:         return(name);
        !           475: } /* dir_getrelname */
        !           476: 
        !           477: /***************************************************************************
        !           478:  * Function: dir_getfullname
        !           479:  *
        !           480:  * Purpose:
        !           481:  *
        !           482:  * Return the fullname of the file (including the tree root passed in) 
        !           483:  */
        !           484: LPSTR
        !           485: dir_getfullname(DIRITEM cur)
        !           486: {
        !           487:         LPSTR name;
        !           488:         int size;
        !           489:         LPSTR head;
        !           490: 
        !           491:         /* check this is a valid item */
        !           492:         if (cur == NULL)  {
        !           493:                 return(NULL);
        !           494:         }
        !           495: 
        !           496:         if (cur->direct->head->bFile) {
        !           497:                 return(cur->direct->head->rootname);
        !           498:         }
        !           499: 
        !           500:         /* remember to include the NULL when sizing */
        !           501:         size = lstrlen(cur->name) + 1;
        !           502: 
        !           503:         size += lstrlen(cur->direct->relname);
        !           504: 
        !           505:         /* add on root name */
        !           506:         head = cur->direct->head->rootname;
        !           507:         size += lstrlen(head);
        !           508: 
        !           509:         /* root names may not end in a slash. we need to
        !           510:          * insert one in this case. Also, relnames always begin .\, so
        !           511:          * we skip the . always, and the .\ if we don't need to
        !           512:          * append a slash
        !           513:          *
        !           514:          */
        !           515:         size--;         /* omit the '.' */
        !           516:         if (head[lstrlen(head) -1] == '\\') {
        !           517:                 size--;                         /* omit the .\ */
        !           518:         }
        !           519: 
        !           520:         name = gmem_get(hHeap, size);
        !           521: 
        !           522:         lstrcpy(name, cur->direct->head->rootname);
        !           523: 
        !           524:         /* add relname and then name, omiting the .\ */
        !           525: 
        !           526:                 /* skip . or .\ before relname */
        !           527:                 if (head[lstrlen(head) -1] == '\\') {
        !           528:                         lstrcat(name, &cur->direct->relname[2]);
        !           529:                 } else {
        !           530:                         lstrcat(name, &cur->direct->relname[1]);
        !           531:                 }
        !           532:                 lstrcat(name, cur->name);
        !           533:         return(name);
        !           534: } /* dir_getfullname */
        !           535: 
        !           536: 
        !           537: /***************************************************************************
        !           538:  * Function: dir_getroot_list
        !           539:  *
        !           540:  * Purpose:
        !           541:  *
        !           542:  * Return the name of the tree root given a handle to the DIRLIST.
        !           543:  */
        !           544: LPSTR
        !           545: dir_getroot_list(DIRLIST dl)
        !           546: {
        !           547:         if (dl == NULL) 
        !           548:                 return(NULL);
        !           549:         return(dl->rootname);
        !           550: } /* dir_getroot_list */
        !           551: 
        !           552: /***************************************************************************
        !           553:  * Function: dir_getroot_item
        !           554:  *
        !           555:  * Purpose:
        !           556:  *
        !           557:  * Return the root name of this tree given a handle to a DIRITEM in the
        !           558:  * list.
        !           559:  */
        !           560: LPSTR dir_getroot_item(DIRITEM item)
        !           561: {
        !           562:         if (item == NULL) 
        !           563:                 return(NULL);
        !           564: 
        !           565:         return(dir_getroot_list(item->direct->head));
        !           566: }
        !           567: 
        !           568: 
        !           569: /***************************************************************************
        !           570:  * Function: dir_freerelname
        !           571:  *
        !           572:  * Purpose:
        !           573:  *
        !           574:  * Free up a relname that we allocated. This interface allows us
        !           575:  * some flexibility in how we store relative and complete names
        !           576:  *
        !           577:  */
        !           578: void
        !           579: dir_freerelname(DIRITEM cur, LPSTR name)
        !           580: {
        !           581:         if((cur != NULL) && (name != NULL))
        !           582:                         gmem_free(hHeap, name, lstrlen(name) +1);
        !           583: } /* dir_freerelname */
        !           584: 
        !           585: /***************************************************************************
        !           586:  * Function: dir_freefullname
        !           587:  *
        !           588:  * Purpose:
        !           589:  *
        !           590:  */
        !           591: void
        !           592: dir_freefullname(DIRITEM cur, LPSTR name)
        !           593: {
        !           594:         if (cur->direct->head->bFile)
        !           595:                 return;
        !           596: 
        !           597:         if (name != NULL) 
        !           598:                 gmem_free(hHeap, name, lstrlen(name) + 1);
        !           599: } /* dir_freefullname            */
        !           600: 
        !           601: /***************************************************************************
        !           602:  * Function: dir_freeroot_list
        !           603:  *
        !           604:  * Purpose:
        !           605:  *
        !           606:  * Free up rootname allocated by dir_getroot_list.
        !           607:  * We just gave a pointer to the rootname, so do nothing.
        !           608:  */
        !           609: void
        !           610: dir_freeroot_list(DIRLIST dl, LPSTR name)
        !           611: {
        !           612:         if ((dl == NULL) || (name == NULL)) {
        !           613:                 return;
        !           614:         }
        !           615:         return;
        !           616: } /* dir_freeroot_list */
        !           617: 
        !           618: /***************************************************************************
        !           619:  * Function: dir_freeroot_item
        !           620:  *
        !           621:  * Purpose:
        !           622:  *
        !           623:  * Free up memory alloc-ed by a call to dir_getroot_item. 
        !           624:  */
        !           625: void
        !           626: dir_freeroot_item(DIRITEM item, LPSTR name)
        !           627: {
        !           628:         if ((item == NULL) || (name == NULL)) 
        !           629:                 return;
        !           630:         dir_freeroot_list(item->direct->head, name);
        !           631: }
        !           632: 
        !           633: /***************************************************************************
        !           634:  * Function: dir_getopenname
        !           635:  *
        !           636:  * Purpose:
        !           637:  *
        !           638:  * Get an open-able name for the file. This will be the same as the fullname.
        !           639:  */
        !           640: LPSTR
        !           641: dir_getopenname(DIRITEM item)
        !           642: {
        !           643:         LPSTR fname;
        !           644: 
        !           645:         if (item == NULL) 
        !           646:                 return(NULL);
        !           647: 
        !           648:         fname = dir_getfullname(item);
        !           649: 
        !           650:                 return(fname);
        !           651: } /* dir_getopenname */
        !           652: 
        !           653: 
        !           654: /***************************************************************************
        !           655:  * Function: dir_freeopenname
        !           656:  *
        !           657:  * Purpose:
        !           658:  *
        !           659:  * Free up memory created by a call to dir_getopenname(). This *may*
        !           660:  * cause the file to be deleted if it was a temporary copy.
        !           661:  */
        !           662: void
        !           663: dir_freeopenname(DIRITEM item, LPSTR openname)
        !           664: {
        !           665:         if ((item == NULL) || (openname == NULL)) 
        !           666:                 return;
        !           667: 
        !           668:         dir_freefullname(item, openname);
        !           669: } /* dir_freeopenname */
        !           670: 
        !           671: /***************************************************************************
        !           672:  * Function: dir_openfile
        !           673:  *
        !           674:  * Purpose:
        !           675:  *
        !           676:  * Return an open file handle to the file. 
        !           677:  */
        !           678: int
        !           679: dir_openfile(DIRITEM item)
        !           680: {
        !           681:         LPSTR fname;
        !           682:         int fh;
        !           683:         OFSTRUCT os;
        !           684: 
        !           685:         fname = dir_getfullname(item);
        !           686:         fh = OpenFile(fname, &os, OF_READ|OF_SHARE_DENY_NONE);
        !           687:         dir_freefullname(item, fname);
        !           688:         return(fh);
        !           689: } /* dir_openfile */
        !           690: 
        !           691: /***************************************************************************
        !           692:  * Function: dir_closefile
        !           693:  *
        !           694:  * Purpose:
        !           695:  *
        !           696:  * Close a file opened with dir_openfile.
        !           697:  */
        !           698: void
        !           699: dir_closefile(DIRITEM item, int fh)
        !           700: {
        !           701:         _lclose(fh);
        !           702: 
        !           703: } /* dir_closefile */
        !           704: 
        !           705: 
        !           706: /***************************************************************************
        !           707:  * Function: dir_getfilesize
        !           708:  *
        !           709:  * Purpose:
        !           710:  *
        !           711:  * Return the file size (set during scanning) 
        !           712:  */
        !           713: long
        !           714: dir_getfilesize(DIRITEM cur)
        !           715: {
        !           716:         /* check this is a valid item */
        !           717:         if (cur == NULL)
        !           718:                 return(0);
        !           719: 
        !           720:         return(cur->size);
        !           721: } /* dir_getfilesize */
        !           722: 
        !           723: 
        !           724: 
        !           725: /* ss_endcopy returns a number indicating the number of files copied,
        !           726:    but we may have some local copies too.  We need to count these
        !           727:    ourselves and add them in
        !           728: */
        !           729: 
        !           730: int nLocalCopies;        /* cleared in startcopy, ++d in copy
        !           731:                                 ** inspected in endcopy
        !           732:                                 */
        !           733: 
        !           734: /***************************************************************************
        !           735:  * Function: dir_startcopy
        !           736:  *
        !           737:  * Purpose:
        !           738:  *
        !           739:  * Start a bulk copy 
        !           740:  */
        !           741: BOOL dir_startcopy(DIRLIST dl)
        !           742: {
        !           743:         nLocalCopies = 0;
        !           744:         return(TRUE);
        !           745: 
        !           746: } /* dir_startcopy */
        !           747: /***************************************************************************
        !           748:  * Function: dir_endcopy
        !           749:  *
        !           750:  */
        !           751:  
        !           752: int dir_endcopy(DIRLIST dl)
        !           753: {
        !           754:         return(nLocalCopies);
        !           755: 
        !           756: } /* dir_endcopy */
        !           757: 
        !           758: /***************************************************************************
        !           759:  * Function: dir_copy
        !           760:  *
        !           761:  * Purpose:
        !           762:  *
        !           763:  * Create a copy of the file, in the new root directory. Creates sub-dirs as
        !           764:  * necessary. 
        !           765:  *
        !           766:  * Returns TRUE for success and FALSE for failure.
        !           767:  */
        !           768: BOOL dir_copy(DIRITEM item, LPSTR newroot)
        !           769: {
        !           770:         static char newpath[256];
        !           771:         LPSTR relname, fullname;
        !           772:         LPSTR pstart, pdest, pel;
        !           773:         BOOL bOK;
        !           774: 
        !           775:         BY_HANDLE_FILE_INFORMATION bhfi;
        !           776:         HANDLE hfile;
        !           777: 
        !           778:         /*
        !           779:          * check that the newroot directory itself exists
        !           780:          */
        !           781:         if ((item == NULL) || !dir_isvaliddir(newroot)) {
        !           782:                 return(FALSE);
        !           783:         }
        !           784: 
        !           785:         /*
        !           786:          * name of file relative to the tree root
        !           787:          */
        !           788:         relname = dir_getrelname(item);
        !           789: 
        !           790:         /*
        !           791:          * build the new pathname by concatenating the new root and
        !           792:          * the old relative name. add one path element at a time and
        !           793:          * ensure that the directory exists, creating it if necessary.
        !           794:          */
        !           795:         lstrcpy(newpath, newroot);
        !           796: 
        !           797:         /* add separating slash if not already there */
        !           798:         if (newpath[lstrlen(newpath) -1] != '\\') {
        !           799:                 lstrcat(newpath, "\\");
        !           800:         }
        !           801: 
        !           802:         pstart = relname;
        !           803:         while ( (pel = strchr(pstart, '\\')) != NULL) {
        !           804: 
        !           805:                 /* found another element ending in slash. incr past the \\ */
        !           806:                 pel++;
        !           807: 
        !           808:                 /*
        !           809:                  * ignore .
        !           810:                  */
        !           811:                 if (strncmp(pstart, ".\\", 2) != 0) {
        !           812: 
        !           813:                         pdest = &newpath[lstrlen(newpath)];
        !           814:                         strncpy(pdest, pstart, pel - pstart);
        !           815:                         pdest[pel - pstart] = '\0';
        !           816: 
        !           817:                         /* create subdir if necessary */
        !           818:                         if (!dir_isvaliddir(newpath)) {
        !           819:                                 if (_mkdir(newpath) != 0) {
        !           820:                                         return(FALSE);
        !           821:                                 }
        !           822:                         }
        !           823:                 }
        !           824: 
        !           825:                 pstart = pel;
        !           826:         }
        !           827: 
        !           828:         /*
        !           829:          * there are no more slashes, so pstart points at the final
        !           830:          * element
        !           831:          */
        !           832:         lstrcat(newpath, pstart);
        !           833: 
        !           834:         fullname = dir_getfullname(item);
        !           835: 
        !           836:                 bOK = CopyFile(fullname, newpath, FALSE);
        !           837: 
        !           838:                 /* having copied the file, now copy the times, attributes */
        !           839:                 hfile = CreateFile(fullname, GENERIC_READ, 0, NULL,
        !           840:                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        !           841:                 bhfi.dwFileAttributes = GetFileAttributes(fullname);
        !           842:                 GetFileTime(hfile, &bhfi.ftCreationTime,
        !           843:                                 &bhfi.ftLastAccessTime, &bhfi.ftLastWriteTime);
        !           844:                 CloseHandle(hfile);
        !           845: 
        !           846:                 hfile = CreateFile(newpath, GENERIC_WRITE, 0, NULL,
        !           847:                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        !           848:                 SetFileTime(hfile, &bhfi.ftCreationTime,
        !           849:                                    &bhfi.ftLastAccessTime,
        !           850:                                    &bhfi.ftLastWriteTime);
        !           851:                 CloseHandle(hfile);
        !           852:                 SetFileAttributes(newpath, bhfi.dwFileAttributes);
        !           853: 
        !           854: 
        !           855:                 if (bOK) ++nLocalCopies;
        !           856: 
        !           857:         dir_freerelname(item, relname);
        !           858:         dir_freefullname(item, fullname);
        !           859: 
        !           860:         return(bOK);
        !           861: } /* dir_copy */
        !           862: 
        !           863: 
        !           864: /***************************************************************************
        !           865:  * Function: dir_dirinit
        !           866:  *
        !           867:  * Purpose:
        !           868:  *
        !           869:  * Fill out a new DIRECT for a subdirectory (pre-allocated).
        !           870:  * Init files and dirs lists to empty (List_Create). Set the relname
        !           871:  * of the directory by pre-pending the parent relname if there
        !           872:  * is a parent, and appending a trailing slash (if there isn't one).
        !           873:  */
        !           874: void
        !           875: dir_dirinit(DIRECT dir, DIRLIST head, DIRECT parent, LPSTR name)
        !           876: {
        !           877:         int size;
        !           878: 
        !           879:         dir->head = head;
        !           880:         dir->parent = parent;
        !           881: 
        !           882:         /* add on one for the null and one for the trailing slash */
        !           883:         size = lstrlen(name) + 2;
        !           884:         if (parent != NULL) {
        !           885:                 size += lstrlen(parent->relname);
        !           886:         }
        !           887: 
        !           888:         /* build the relname from the parent and the current name
        !           889:          * with a terminating slash
        !           890:          */
        !           891:         dir->relname = gmem_get(hHeap, size);
        !           892:         if (parent != NULL) {
        !           893:                 lstrcpy(dir->relname, parent->relname);
        !           894:         } else{
        !           895:                 dir->relname[0] = '\0';
        !           896:         }
        !           897: 
        !           898:         lstrcat(dir->relname, name);
        !           899: 
        !           900:         if (dir->relname[lstrlen(dir->relname) -1] != '\\') {
        !           901:                 lstrcat(dir->relname, "\\");
        !           902:         }
        !           903: 
        !           904:         /* force name to lowercase */
        !           905:         AnsiLowerBuff(dir->relname, lstrlen(dir->relname));
        !           906: 
        !           907:         dir->diritems = List_Create();
        !           908:         dir->directs = List_Create();
        !           909:         dir->bScanned = FALSE;
        !           910:         dir->pos = DL_FILES;
        !           911: 
        !           912: } /* dir_dirinit */
        !           913: 
        !           914: 
        !           915: /***************************************************************************
        !           916:  * Function: dir_fileinit
        !           917:  *
        !           918:  * Purpose:
        !           919:  *
        !           920:  * Initialise the contents of an (allocated) DIRITEM struct. 
        !           921:  */
        !           922: void
        !           923: dir_fileinit(DIRITEM pfile, DIRECT dir, LPSTR path, long size)
        !           924: {
        !           925: 
        !           926:         pfile->name = gmem_get(hHeap, lstrlen(path) + 1);
        !           927:         lstrcpy(pfile->name, path);
        !           928: 
        !           929:         /* force name to lower case */
        !           930:         AnsiLowerBuff(pfile->name, lstrlen(path));
        !           931: 
        !           932:         pfile->direct = dir;
        !           933:         pfile->size = size;
        !           934: 
        !           935:         pfile->localname = NULL;
        !           936: 
        !           937: } /* dir_fileinit */
        !           938: 
        !           939: /***************************************************************************
        !           940:  * Function: dir_isfilevalid
        !           941:  *
        !           942:  * Purpose:
        !           943:  *
        !           944:  * Is this a valid file or not 
        !           945:  */
        !           946: BOOL
        !           947: dir_isvalidfile(LPSTR path)
        !           948: {
        !           949:         DWORD dwAttrib;
        !           950: 
        !           951:         dwAttrib = GetFileAttributes(path);
        !           952:         if (dwAttrib == -1) {
        !           953:                 return(FALSE);
        !           954:         }
        !           955:         if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) {
        !           956:                 return(FALSE);
        !           957:         }
        !           958:         return(TRUE);
        !           959: } /* dir_isvalidfile */
        !           960: 
        !           961: /***************************************************************************
        !           962:  * Function: dir_isvaliddir
        !           963:  *
        !           964:  * Purpose:
        !           965:  *
        !           966:  * Is this a valid directory ? 
        !           967:  */
        !           968: BOOL
        !           969: dir_isvaliddir(LPSTR path)
        !           970: {
        !           971:         DWORD dwAttrib;
        !           972: 
        !           973:         dwAttrib = GetFileAttributes(path);
        !           974:         if (dwAttrib == -1) {
        !           975:                 return(FALSE);
        !           976:         }
        !           977:         if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) {
        !           978:                 return(TRUE);
        !           979:         }
        !           980:         return(FALSE);
        !           981: } /* dir_isvaliddir */
        !           982: 
        !           983: /***************************************************************************
        !           984:  * Function: dir_scan
        !           985:  *
        !           986:  * Purpose:
        !           987:  *
        !           988:  * Scan the directory given. Add all files to the list
        !           989:  * in alphabetic order, and add all directories in alphabetic
        !           990:  * order to the list of child DIRITEMs. If bRecurse is true, go on to
        !           991:  * recursive call dir_scan for each of the child DIRITEMs
        !           992:  */
        !           993: void
        !           994: dir_scan(DIRECT dir, BOOL bRecurse)
        !           995: {
        !           996:         PSTR path;
        !           997:         int size;
        !           998:         DIRECT child;
        !           999:         BOOL bMore;
        !          1000:         long filesize;
        !          1001:         BOOL bIsDir;
        !          1002:         LPSTR name;
        !          1003: 
        !          1004:         HANDLE hFind;
        !          1005:         WIN32_FIND_DATA finddata;
        !          1006: 
        !          1007:         char debugmsg[200];
        !          1008:         wsprintf(debugmsg, "scandir: %s %s\n",
        !          1009:                  dir->relname, bRecurse?"recursive":"non-recursive"
        !          1010:                 );
        !          1011: 
        !          1012:         /* make the complete search string including *.* */
        !          1013:         size = lstrlen(dir->head->rootname);
        !          1014:         size += lstrlen(dir->relname);
        !          1015: 
        !          1016:         /* add on one null and *.* */
        !          1017:         size += 4;
        !          1018: 
        !          1019:         path = LocalLock(LocalAlloc(LHND, size));
        !          1020: 
        !          1021:         lstrcpy(path, dir->head->rootname);
        !          1022: 
        !          1023:         /* omit the . at the beginning of the relname, and the
        !          1024:          * .\ if there is a trailing \ on the rootname
        !          1025:          */
        !          1026:         if (path[strlen(path)-1] == '\\') {
        !          1027:                 lstrcat(path, &dir->relname[2]);
        !          1028:         } else {
        !          1029:                 lstrcat(path, &dir->relname[1]);
        !          1030:         }
        !          1031:         lstrcat(path, "*.*");
        !          1032: 
        !          1033:         /* read all entries in the directory */
        !          1034:         hFind = FindFirstFile(path, &finddata);
        !          1035:         bMore = (hFind != (HANDLE) -1);
        !          1036:         LocalUnlock(LocalHandle ( (PSTR) path));
        !          1037:         LocalFree(LocalHandle ( (PSTR) path));
        !          1038: 
        !          1039:         while (bMore) {
        !          1040: 
        !          1041:                 bIsDir = (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
        !          1042:                 name = (LPSTR) &finddata.cFileName;
        !          1043:                 filesize = finddata.nFileSizeLow;
        !          1044:                 if (!bIsDir) {
        !          1045: 
        !          1046:                         dir_addfile(dir, name, filesize);
        !          1047: 
        !          1048:                 } else if ( (lstrcmp(name, ".") != 0) &&
        !          1049:                            ( lstrcmp(name, "..") != 0) ) {
        !          1050: 
        !          1051:                         dir_adddirect(dir, name);
        !          1052:                 }
        !          1053: 
        !          1054:                 bMore = FindNextFile(hFind, &finddata);
        !          1055:         }
        !          1056: 
        !          1057:         FindClose(hFind);
        !          1058: 
        !          1059:         dir->bScanned = TRUE;
        !          1060:         dir->pos = DL_FILES;
        !          1061: 
        !          1062:         if (bRecurse) {
        !          1063:                 List_TRAVERSE(dir->directs, child) {
        !          1064:                         dir_scan(child, TRUE);
        !          1065:                 }
        !          1066:         }
        !          1067: 
        !          1068: } /* dir_scan */
        !          1069: 
        !          1070: 
        !          1071: /***************************************************************************
        !          1072:  * Function: dir_addfile
        !          1073:  *
        !          1074:  * Purpose:
        !          1075:  *
        !          1076:  * Add the file 'path' to the list of files in dir, in order.
        !          1077:  */
        !          1078: void
        !          1079: dir_addfile(DIRECT dir, LPSTR path, DWORD size)
        !          1080: {
        !          1081:         DIRITEM pfile;
        !          1082: 
        !          1083:         AnsiLowerBuff(path, lstrlen(path));  // needless?
        !          1084: 
        !          1085:         List_TRAVERSE(dir->diritems, pfile) {
        !          1086:                 /////if (lstrcmpi(pfile->name, path) > 0) {
        !          1087:                 if (utils_CompPath(pfile->name, path) > 0) {
        !          1088: 
        !          1089:                         /* goes before this one */
        !          1090:                         pfile = List_NewBefore(dir->diritems, pfile, sizeof(struct diritem));
        !          1091:                         dir_fileinit(pfile, dir, path, size);
        !          1092:                         return;
        !          1093:                 }
        !          1094:         }
        !          1095:         /* goes at end */
        !          1096:         pfile = List_NewLast(dir->diritems, sizeof(struct diritem));
        !          1097:         dir_fileinit(pfile, dir, path, size);
        !          1098: } /* dir_addfile */
        !          1099: 
        !          1100: 
        !          1101: /***************************************************************************
        !          1102:  * Function: dir_addirect
        !          1103:  *
        !          1104:  * Purpose:
        !          1105:  *
        !          1106:  * Add a new directory in alphabetic order on
        !          1107:  * the list dir->directs
        !          1108:  *
        !          1109:  */
        !          1110: void
        !          1111: dir_adddirect(DIRECT dir, LPSTR path)
        !          1112: {
        !          1113:         DIRECT child;
        !          1114:         LPSTR finalel;
        !          1115:         char achTempName[256];
        !          1116: 
        !          1117:         AnsiLowerBuff(path, lstrlen(path));
        !          1118:         List_TRAVERSE(dir->directs, child) {
        !          1119: 
        !          1120:                 int cmpval;
        !          1121: 
        !          1122:                 /* we need to compare the child name with the new name.
        !          1123:                  * the child name is a relname with a trailing
        !          1124:                  * slash - so compare only the name up to but
        !          1125:                  * not including the final slash.
        !          1126:                  */
        !          1127:                 finalel = dir_finalelem(child->relname);
        !          1128: 
        !          1129:                 /*
        !          1130:                  * we cannot use strnicmp since this uses a different
        !          1131:                  * collating sequence to lstrcmpi. So copy the portion
        !          1132:                  * we are interested in to a null-term. buffer.
        !          1133:                  */
        !          1134:                 strncpy(achTempName, finalel, lstrlen(finalel)-1);
        !          1135:                 achTempName[lstrlen(finalel)-1] = '\0';
        !          1136: 
        !          1137:                 cmpval = utils_CompPath(achTempName, path);
        !          1138: 
        !          1139:                 if (cmpval > 0) {
        !          1140: 
        !          1141:                         /* goes before this one */
        !          1142:                         child = List_NewBefore(dir->directs, child, sizeof(struct direct));
        !          1143:                         dir_dirinit(child, dir->head, dir, path);
        !          1144:                         return;
        !          1145:                 }
        !          1146:         }
        !          1147:         /* goes at end */
        !          1148:         child = List_NewLast(dir->directs, sizeof(struct direct));
        !          1149:         dir_dirinit(child, dir->head, dir, path);
        !          1150: } /* dir_adddirect */
        !          1151: 
        !          1152: 
        !          1153: /***************************************************************************
        !          1154:  * Function: dir_cleardirect
        !          1155:  *
        !          1156:  * Purpose:
        !          1157:  *
        !          1158:  * Free all memory associated with a DIRECT (including freeing
        !          1159:  * child lists). Don't de-alloc the direct itself (allocated on a list)
        !          1160:  */
        !          1161: void
        !          1162: dir_cleardirect(DIRECT dir)
        !          1163: {
        !          1164:         DIRITEM pfile;
        !          1165:         DIRECT child;
        !          1166: 
        !          1167:         /* clear contents of files list */
        !          1168:         List_TRAVERSE(dir->diritems, pfile) {
        !          1169:                 gmem_free(hHeap, pfile->name, lstrlen(pfile->name));
        !          1170:                 if ((pfile->localname) && (pfile->bLocalIsTemp)) {
        !          1171: 
        !          1172:                         /*
        !          1173:                          * the copy will have copied the attributes,
        !          1174:                          * including read-only. We should unset this bit
        !          1175:                          * so we can delete the temp file.
        !          1176:                          */
        !          1177:                         SetFileAttributes(pfile->localname,
        !          1178:                                 GetFileAttributes(pfile->localname)
        !          1179:                                         & ~FILE_ATTRIBUTE_READONLY);
        !          1180:                         DeleteFile(pfile->localname);
        !          1181:                         gmem_free(hHeap, pfile->localname, 256);
        !          1182:                         pfile->localname = NULL;
        !          1183:                 }
        !          1184: 
        !          1185:         }
        !          1186:         List_Destroy(&dir->diritems);
        !          1187: 
        !          1188:         /* clear contents of dirs list (recursively) */
        !          1189:         List_TRAVERSE(dir->directs, child) {
        !          1190:                 dir_cleardirect(child);
        !          1191:         }
        !          1192:         List_Destroy(&dir->directs);
        !          1193: 
        !          1194:         gmem_free(hHeap, dir->relname, lstrlen(dir->relname) + 1);
        !          1195: 
        !          1196: } /* dir_cleardirect */
        !          1197: 
        !          1198: /***************************************************************************
        !          1199:  * Function: dir_finalelem
        !          1200:  *
        !          1201:  * Purpose:
        !          1202:  *
        !          1203:  * Return a pointer to the final element in a path. Note that
        !          1204:  * we may be passed relnames with a trailing final slash - ignore this
        !          1205:  * and return the element before that final slash.
        !          1206:  */
        !          1207: LPSTR
        !          1208: dir_finalelem(LPSTR path)
        !          1209: {
        !          1210:         LPSTR chp;
        !          1211:         int size;
        !          1212: 
        !          1213:         /* is the final character a slash ? */
        !          1214:         size = lstrlen(path) - 1;
        !          1215:         if (path[size] == '\\') {
        !          1216:                 /* find the slash before this */
        !          1217:                 for (size-- ; size > 0; size--) {
        !          1218:                         if (path[size] == '\\') {
        !          1219:                                 /* skip the slash itself */
        !          1220:                                 size++;
        !          1221:                                 break;
        !          1222:                         }
        !          1223:                 }
        !          1224:                 return(&path[size]);
        !          1225:         }
        !          1226:         /* look for final slash */
        !          1227:         chp = strrchr(path, '\\');
        !          1228:         if (chp != NULL) {
        !          1229:                 return(chp+1);
        !          1230:         }
        !          1231: 
        !          1232:         /* no slash - is there a drive letter ? */
        !          1233:         chp = strrchr(path, ':');
        !          1234:         if (chp != NULL) {
        !          1235:                 return(chp+1);
        !          1236:         }
        !          1237: 
        !          1238:         /* this is a final-element anyway */
        !          1239:         return(path);
        !          1240: 
        !          1241: } /* dir_finalelem */
        !          1242: 
        !          1243: /***************************************************************************
        !          1244:  * Function: dir_getpathsize
        !          1245:  *
        !          1246:  * Purpose:
        !          1247:  *
        !          1248:  * Find the size of a file given a pathname to it 
        !          1249:  */
        !          1250: long
        !          1251: dir_getpathsize(LPSTR path)
        !          1252: {
        !          1253:         int fh;
        !          1254:         OFSTRUCT os;
        !          1255:         long size;
        !          1256:         fh = OpenFile(path, &os, OF_READ|OF_SHARE_DENY_NONE);
        !          1257:         if (fh == -1) {
        !          1258:                 return(0);
        !          1259:         }
        !          1260: 
        !          1261:         size = GetFileSize( (HANDLE) fh, NULL);
        !          1262:         _lclose(fh);
        !          1263:         return(size);
        !          1264: } /* dir_getpathsize */
        !          1265: 
        !          1266: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.