Mercurial > dwindows
view os2/dirent.c @ 2819:a2fc275fa9bb
iOS: Fix major memory leaks when destroying widgets and windows.
More surely needs to be done regardig this, iOS doesn't destroy subviews as
expected when the parent is removed. I was expecting it to bring the
reference counts to 0 and starts destroying subviews... so I had to do this
manually. Boxes, ScrollBoxes, Spinbuttons and Comboboxes all now destroy
their subviews. Probably will need to do the same for splitbar, notebooks
and possibly others. However this stops the memory leak in Interface
Builder when recreating the interface. Also need to figure out why the
reference count is lower for DWButtons.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Tue, 02 Aug 2022 06:17:09 +0000 |
parents | 6baf177f335c |
children |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define INCL_DOSFILEMGR #define INCL_DOSERRORS #include "dwcompat.h" #include <errno.h> #ifdef __WATCOMC__ #include "platform\dirent.h" typedef struct _dirdescr DIRW; #define DIR DIRW #endif # define FFBUF FILEFINDBUF3 # define Word ULONG /* * LS20 recommends a request count of 100, but according to the * APAR text it does not lead to missing files, just to funny * numbers of returned entries. * * LS30 HPFS386 requires a count greater than 2, or some files * are missing (those starting with a character less that '.'). * * Novell looses entries which overflow the buffer. In previous * versions of dirent2, this could have lead to missing files * when the average length of 100 directory entries was 40 bytes * or more (quite unlikely for files on a Novell server). * * Conclusion: Make sure that the entries all fit into the buffer * and that the buffer is large enough for more than 2 entries * (each entry is at most 300 bytes long). And ignore the LS20 * effect. */ # define Count 25 # define BufSz (25 * (sizeof(FILEFINDBUF3)+1)) #if defined(__IBMC__) || defined(__IBMCPP__) #define error(rc) _doserrno = rc, errno = EOS2ERR #else #define error(rc) errno = 255 #endif struct _dirdescr { HDIR handle; /* DosFindFirst handle */ char fstype; /* filesystem type */ Word count; /* valid entries in <ffbuf> */ long number; /* absolute number of next entry */ int index; /* relative number of next entry */ FFBUF * next; /* pointer to next entry */ char name[MAXPATHLEN+3]; /* directory name */ unsigned attrmask; /* attribute mask for seekdir */ struct dirent entry; /* buffer for directory entry */ BYTE ffbuf[BufSz]; }; /* * Return first char of filesystem type, or 0 if unknown. */ static char API getFSType(const char *path) { static char cache[1+26]; char drive[3], info[512]; Word unit, infolen; char r; if (isalpha((int)path[0]) && path[1] == ':') { unit = toupper(path[0]) - '@'; path += 2; } else { ULONG driveMap; if (DosQueryCurrentDisk(&unit, &driveMap)) return 0; } if ((path[0] == '\\' || path[0] == '/') && (path[1] == '\\' || path[1] == '/')) return 0; if (cache [unit]) return cache [unit]; drive[0] = '@' + unit; drive[1] = ':'; drive[2] = '\0'; infolen = sizeof info; if (DosQueryFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen)) return 0; if (infolen >= sizeof(FSQBUFFER2)) { FSQBUFFER2 *p = (FSQBUFFER2 *)info; r = p->szFSDName[p->cbName]; } else r = 0; return cache [unit] = r; } char * API _abs_path(const char *name, char *buffer, int len) { char buf[4]; if (isalpha((int)name[0]) && name[1] == ':' && name[2] == '\0') { buf[0] = name[0]; buf[1] = name[1]; buf[2] = '.'; buf[3] = '\0'; name = buf; } if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len)) return NULL; return buffer; } DIR * API _openxdir(const char *path, unsigned att_mask) { DIR *dir; char name[MAXPATHLEN+3]; Word rc; if(!path) return NULL; dir = malloc(sizeof(DIR)); if (dir == NULL) { errno = ENOMEM; return NULL; } strncpy(name, path, MAXPATHLEN); name[MAXPATHLEN] = '\0'; switch (name[strlen(name)-1]) { default: strcat(name, "\\"); case '\\': case '/': case ':': ; } strcat(name, "."); if (!abs_path(name, dir->name, MAXPATHLEN+1)) strcpy(dir->name, name); if (dir->name[strlen(dir->name)-1] == '\\') strcat(dir->name, "*"); else strcat(dir->name, "\\*"); dir->fstype = getFSType(dir->name); dir->attrmask = att_mask | A_DIR; dir->handle = HDIR_CREATE; dir->count = 100; rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask, dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); switch (rc) { default: free(dir); error(rc); return NULL; case NO_ERROR: case ERROR_NO_MORE_FILES: ; } dir->number = 0; dir->index = 0; dir->next = (FFBUF *)dir->ffbuf; return (DIR *)dir; } DIR * API _opendir(const char *pathname) { return openxdir(pathname, 0); } struct dirent * API _readdir(DIR *dir) { static int dummy_ino = 2; if (dir->index == dir->count) { Word rc; dir->count = 100; rc = DosFindNext(dir->handle, dir->ffbuf, sizeof dir->ffbuf, &dir->count); if (rc) { error(rc); return NULL; } dir->index = 0; dir->next = (FFBUF *)dir->ffbuf; } if (dir->index == dir->count) return NULL; memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName); dir->entry.d_name[dir->next->cchName] = '\0'; dir->entry.d_ino = dummy_ino++; dir->entry.d_reclen = dir->next->cchName; dir->entry.d_namlen = dir->next->cchName; dir->entry.d_size = dir->next->cbFile; dir->entry.d_attribute = dir->next->attrFile; dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite; dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite; switch (dir->fstype) { case 'F': /* FAT */ case 'C': /* CDFS */ if (dir->next->attrFile & FILE_DIRECTORY) strupr(dir->entry.d_name); else strlwr(dir->entry.d_name); } dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset); ++dir->number; ++dir->index; return &dir->entry; } long API _telldir(DIR *dir) { return dir->number; } void API _seekdir(DIR *dir, long off) { if (dir->number > off) { char name[MAXPATHLEN+2]; Word rc; DosFindClose(dir->handle); strcpy(name, dir->name); strcat(name, "*"); dir->handle = HDIR_CREATE; dir->count = 32767; rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask, dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); switch (rc) { default: error(rc); return; case NO_ERROR: case ERROR_NO_MORE_FILES: ; } dir->number = 0; dir->index = 0; dir->next = (FFBUF *)dir->ffbuf; } while (dir->number < off && readdir(dir)) ; } void API _closedir(DIR *dir) { DosFindClose(dir->handle); free(dir); } /*****************************************************************************/ #ifdef TEST main(int argc, char **argv) { int i; DIR *dir; struct dirent *ep; for (i = 1; i < argc; ++i) { dir = opendir(argv[i]); if (!dir) continue; while (ep = readdir(dir)) if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1])) printf("%s%s\n", argv[i], ep->d_name); else printf("%s/%s\n", argv[i], ep->d_name); closedir(dir); } return 0; } #endif