/*....................................................................... * Create a new PathName object. * * Output: * return PathName * The new object, or NULL on error. */ PathName *_new_PathName(void) { PathName *path; /* The object to be returned */ /* * Allocate the container. */ path = (PathName *) malloc(sizeof(PathName)); if(!path) { errno = ENOMEM; return NULL; }; /* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to _del_PathName(). */ path->name = NULL; path->dim = 0; /* * Figure out the maximum length of an expanded pathname. */ path->dim = _pu_pathname_dim(); if(path->dim == 0) return _del_PathName(path); /* * Allocate the pathname buffer. */ path->name = (char *)malloc(path->dim * sizeof(char)); if(!path->name) { errno = ENOMEM; return _del_PathName(path); }; return path; }
/*....................................................................... * Create the resources needed to expand filenames. * * Output: * return ExpandFile * The new object, or NULL on error. */ ExpandFile *new_ExpandFile(void) { ExpandFile *ef; /* The object to be returned */ /* * Allocate the container. */ ef = (ExpandFile *) malloc(sizeof(ExpandFile)); if(!ef) { fprintf(stderr, "new_ExpandFile: Insufficient memory.\n"); return NULL; }; /* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to del_ExpandFile(). */ ef->sg = NULL; ef->cache.mem = NULL; ef->cache.head = NULL; ef->cache.next = NULL; ef->cache.tail = NULL; ef->path = NULL; ef->home = NULL; ef->result.files = NULL; ef->result.nfile = 0; ef->usrnam[0] = '\0'; ef->envnam[0] = '\0'; ef->errmsg[0] = '\0'; /* * Allocate a list of string segments for storing filenames. */ ef->sg = _new_StringGroup(_pu_pathname_dim()); if(!ef->sg) return del_ExpandFile(ef); /* * Allocate a freelist for allocating directory cache nodes. */ ef->cache.mem = _new_FreeList("new_ExpandFile", sizeof(DirNode), DIR_CACHE_BLK); if(!ef->cache.mem) return del_ExpandFile(ef); /* * Allocate a pathname buffer. */ ef->path = _new_PathName(); if(!ef->path) return del_ExpandFile(ef); /* * Allocate an object for looking up home-directories. */ ef->home = _new_HomeDir(); if(!ef->home) return del_ExpandFile(ef); /* * Allocate an array for files. This will be extended later if needed. */ ef->files_dim = MATCH_BLK_FACT; ef->result.files = (char **) malloc(sizeof(ef->result.files[0]) * ef->files_dim); if(!ef->result.files) { fprintf(stderr, "new_ExpandFile: Insufficient memory to allocate array of files.\n"); return del_ExpandFile(ef); }; return ef; }
/*....................................................................... * Create a new HomeDir object. * * Output: * return HomeDir * The new object, or NULL on error. */ HomeDir *_new_HomeDir(void) { HomeDir *home; /* The object to be returned */ size_t pathlen; /* The estimated maximum size of a pathname */ /* * Allocate the container. */ home = (HomeDir *) malloc(sizeof(HomeDir)); if(!home) { errno = ENOMEM; return NULL; }; /* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to _del_HomeDir(). */ home->err = NULL; home->buffer = NULL; home->buflen = 0; /* * Allocate a place to record error messages. */ home->err = _new_ErrMsg(); if(!home->err) return _del_HomeDir(home); /* * Allocate the buffer that is used by the reentrant POSIX password-entry * lookup functions. */ #ifdef THREAD_COMPATIBLE /* * Get the length of the buffer needed by the reentrant version * of getpwnam(). */ #ifndef _SC_GETPW_R_SIZE_MAX home->buflen = DEF_GETPW_R_SIZE_MAX; #else errno = 0; home->buflen = sysconf(_SC_GETPW_R_SIZE_MAX); /* * If the limit isn't available, substitute a suitably large fallback value. */ if(home->buflen < 0 || errno) home->buflen = DEF_GETPW_R_SIZE_MAX; #endif #endif /* * If the existing buffer length requirement is too restrictive to record * a pathname, increase its length. */ pathlen = _pu_pathname_dim(); if(pathlen > home->buflen) home->buflen = pathlen; /* * Allocate a work buffer. */ home->buffer = (char *) malloc(home->buflen); if(!home->buffer) { errno = ENOMEM; return _del_HomeDir(home); }; return home; }