void print_direntry( dtslot_t *slot, uint8 head_index) { ldtentry_t *entry; int32 len; UniChar *n; UniChar *name; int32 namlen; int32 next; dtslot_t *s; entry = (ldtentry_t *)&(slot[head_index]); namlen = entry->namlen; name = (UniChar *)malloc(sizeof(UniChar) * (namlen + 1)); if (name == 0) { fputs("dirname: malloc error!\n", stderr); return; } name[namlen] = 0; len = MIN(namlen, DTLHDRDATALEN); UniStrncpy(name, entry->name, len); next = entry -> next; n = name + len; while (next >= 0) { s = &(slot[next]); namlen -= len; len = MIN(namlen, DTSLOTDATALEN); UniStrncpy(n, s->name, len); next = s->next; n += len; } #ifdef _JFS_UNICODE printf("%d\t%ls\n", entry->inumber, name); #else printf("%d\t%s\n", entry->inumber, name); #endif free(name); }
/* ------------------------------------------------------------------------- */ void PrintUnicodeString( PCH pchBytes, ULONG length ) { PSZ pszOutput, psz; UniChar *puInput, *pu; size_t stIn, stOut, stSub; if (( puInput = (UniChar *) calloc( length+sizeof(UniChar), 1 )) == NULL ) return; UniStrncpy( puInput, (UniChar *) pchBytes, length / sizeof(UniChar) ); stIn = length / sizeof(UniChar); stOut = stIn * 4; stSub = 0; pszOutput = (PSZ) calloc( stOut+1, 1 ); pu = puInput; psz = pszOutput; if ( psz && ( UniUconvFromUcs( uconv, &pu, &stIn, (PPVOID) &psz, &stOut, &stSub ) == ULS_SUCCESS )) printf("%s", pszOutput ); if ( puInput ) free( puInput ); if ( pszOutput ) free( pszOutput ); }
/* * NAME: pathlookup_pc * * FUNCTION: Lookup path, preserving case. * Lookup path, copying each component into output string * preserving its case. * * PARAMETERS: vfsp - pointer to VFS * path - full path name * path_pc - output - full path name w/preserved case * * RETURN: errors from subroutines. * * NOTES: We assume path is in canonical form: "X:\<path>" where there * are no extraneous backslashes and . and .. have been removed. * * dtFind is not very efficient for finding a directory entry * without wildcards, but infolevel 7 does not seem to actually * be used anywhere, so it must not be too important. */ int32 pathlookup_pc( struct vfs *vfsp, UniChar *path, /* input - Path */ UniChar *path_pc) /* output - path w/preserved case */ { int32 comp_len; uint32 count; UniChar *component; struct dirent *dbuf; inode_t *ip; int32 offset; UniChar *outptr = path_pc; component_t pattern; int rc; UniChar *slash; int32 tbytes; struct vnode *vp; if (vfsp == NULL) { jERROR(2,("pathlookup_pc: invalid VPB!\n")); return ENOTDIR; } /* Copy "X:\" to output string */ UniStrncpy(outptr, path, 3); outptr += 3; path += 3; if (*path == 0) { /* Trivial case "X:\" */ *outptr = 0; return NO_ERROR; } component = (UniChar *)allocpool(unipool, 0); if (component == 0) return ENOSPC; pattern.name = component; dbuf = (struct dirent *)allocpool(dirent_pool, 0); if (dbuf == 0) { freepool(unipool, (caddr_t *)component); return ENOSPC; } vp = vfsp->vfs_mntd; /* vnode of root directory */ jfs_hold(vp); while (path) { slash = UniStrchr(path, '\\'); if (slash) { comp_len = slash - path; slash++; } else comp_len = UniStrlen(path); UniStrncpy(component, path, comp_len); component[comp_len] = 0; UniStrupr(component); /* Convert to upper case */ pattern.namlen = comp_len; path = slash; offset = 0; count = 1; tbytes = 0; rc = dtFind(VP2IP(vp), &pattern, 0, &offset, &count, PSIZE, &tbytes, dbuf); jfs_rele(vp); if (rc || (count == 0)) { freepool(dirent_pool, (caddr_t *)dbuf); freepool(unipool, (caddr_t *)component); return ENOENT; } UniStrncpy(outptr, dbuf->d_name, dbuf->d_namlen); outptr += dbuf->d_namlen; if (path) { ICACHE_LOCK(); rc = iget(vfsp, dbuf->d_ino, &ip, 0); ICACHE_UNLOCK(); if (rc) { freepool(dirent_pool, (caddr_t *)dbuf); freepool(unipool, (caddr_t *)component); return rc; } vp = IP2VP(ip); *(outptr++) = '\\'; } else *outptr = 0; } freepool(dirent_pool, (caddr_t *)dbuf); freepool(unipool, (caddr_t *)component); return NO_ERROR; }
/* * NAME: dirlookup * * FUNCTION: Resolve <path> to vnode <vpp> * with a reference acquired. * The last component of the path is not looked up. * * PARAMETERS: vfsp - file system anchor * path - full path name * last - last component of path name (out) * vpp - where to put the new vnode (out) * crp - credential * * RETURN: errors from subroutines. */ int32 dirlookup( struct vfs * vfsp, pathlook_t * plp, struct ucred * crp) { int32 rc = 0; struct vnode * dvp; struct vnode * vp; UniChar * compn; UniChar * compp = NULL; uint32 complen; UniChar *component; struct dasd_usage *du = &plp->dlim; // F226941 inode_t *ip; // F226941 /* * F226941 - Only accumulate dasd info if limits enabled & operation * may affect dasd usage */ if (((vfsp->vfs_flag & VFS_DASDLIM) == 0) || (du->flag & DLIM_READONLY)) du = 0; component = (UniChar *)allocpool(unipool, 0); /* get the root vnode as the starting directory. */ vp = vfsp->vfs_mntd; jfs_hold(vp); /* Address the beginning of the path, skipping over <d>:. * Note that the path has been put into canonical form * by the IFSM; that is, it has no extraneous backslashes, * and . and .. references have been removed. */ compn = UniStrchr(plp->path, '\\'); /* for each component of the path up to the last: * parse the component name out of the path string, * pass it to jfs_lookup to get a vnode for it. */ for(;;) { // BEGIN F226941 if (du) { DLIM_add(du, VP2IP(vp), rc) if (rc) { jfs_rele(vp); break; } } // END F226941 /* find end of component; if last component * then UniStrchr will return NULL. */ compp = compn + 1; compn = UniStrchr(compp, '\\'); /* end loop when we reach the last component */ if (compn == NULL) break; /* copy the string to the component buffer. */ complen = compn - compp; UniStrncpy(component, compp, complen); component[complen] = '\0'; /* promote current vnode to directory vnode. */ dvp = vp; /* call lookup to get a vnode for the component. */ rc = jfs_lookup(dvp, &vp, component, 0, NULL, crp); /* release hold on the directory */ if (du == 0) // F226941 jfs_rele(dvp); if (rc != 0) { if (rc == ENOENT) rc = ENOTDIR; break; } } /* set the output pointers and return */ plp->pathlast = compp; plp->dvp = vp; freepool (unipool, (caddr_t *)component); return rc; }
/* * NAME: readdir * * FUNCTION: read directory according to specifications * in directory search structure * * PARAMETER: * * RETURN: EINVAL - if not a directory * errors from subroutines * * note: * N.B. directory file offset encodes (directory page number, * entry index number), and shold NOT be interpreted/modified * by caller (lseek()) except that intial offset set to 0. * * no guarantees can be made that the exact offset * requested can be found if directory has been updated * by other threads between consecutive readdir()s. * transfer length of zero signals start offset beyond eof. * * unused space in the directory are not returned to the user, * i.e., more than requested size may have to be read * from directory to fill the user's buffer. */ readdir( struct vnode *dvp, /* inode of directory being read */ struct fsfd *fsfp, /* directory search information */ char *ubuf, /* user's data area */ uint32 ubytes, /* size of user's data area */ uint32 *matchcnt, /* count of entries returned */ uint32 level, /* level of output struct */ uint32 flags, /* offsets needed in output? */ EAOP *eaopp, /* pointer to EAOP */ struct ucred *crp) { int32 rc = 0; int32 ReturnCode = NO_ERROR; inode_t *dip; /* directory inode */ inode_t *ip; /* object inode */ uint32 matches; /* output matches found */ uint32 dtmatches; /* matches found per dtFind call */ uint32 position; /* offsets in output */ uint32 count; /* output buffer count */ int32 tbytes; /* byte count in dirent buffer */ struct dirent *dbuf; /* dirent buffer */ struct dirent *dbufp; /* dirent buffer */ uint32 ffhdsize; /* size of ffbuf header */ component_t lastmatch; /* pointer to last matching entry */ char *ffbuf; /* output buffer pointer */ char *nxbuf; /* output buffer pointer */ char *bufp; /* output buffer pointer */ MMPHPrereaddir(); /* MMPH Performance Hook */ /* set state from search structure */ dip = VP2IP(dvp); position = flags & FF_GETPOS; /* validate request */ if (ubytes == 0) { rc = EINVAL; goto readdir_Exit; } /* continuous read of empty directory ? */ if (fsfp->fsd_offset == -1) { rc = ERROR_NO_MORE_FILES; goto readdir_Exit; } dbuf = (struct dirent *)allocpool(dirent_pool, 0); // D228565 if (dbuf == 0) // D228565 { rc = ENOMEM; goto readdir_Exit; } /* set up variable to manipulate output buffer pointers * based on level. */ if (level == 1) ffhdsize = FFBUFHD; else if (level == 11) ffhdsize = FFBUFHD3L; else if (level < 11) ffhdsize = FFBUFHD2; else ffhdsize = FFBUFHD4L; if (position) ffhdsize += sizeof(uint32); ffbuf = ubuf; count = 0; matches = *matchcnt; *matchcnt = 0; while ((*matchcnt < matches) && (rc == 0)) { IREAD_LOCK(dip); /* directory became void when last link was removed */ if ((dip->i_nlink == 0) || ((dip->i_mode & IFMT) != IFDIR)) { IREAD_UNLOCK(dip); freepool(dirent_pool, (caddr_t *)dbuf); rc = ENOTDIR; goto readdir_Exit; } /* fill a directory buffer. * read on-disk structure (struct ldtentry_t) and * translate into readdir() structure (struct dirent). */ tbytes = 0; dtmatches = matches - *matchcnt; dbufp = dbuf; // D228565 rc = dtFind(dip, &fsfp->fsd_pattern, fsfp->fsd_lastmatch, &fsfp->fsd_offset, &dtmatches, PSIZE, &tbytes, dbufp); IREAD_UNLOCK(dip); if (rc) { freepool(dirent_pool, (caddr_t *)dbuf); goto readdir_Exit; } /* copy translate buffer to user FileFindBuf buffer */ while ((*matchcnt < matches) && (ReturnCode == NO_ERROR)) { uint32 namlen; /* translation buffer empty? */ if (tbytes == 0) break; /* get size of next name */ namlen = dbufp->d_namlen; /* user buffer full? * the +1 here is to allow for the null character * terminating the name string. */ if ((count + ffhdsize + namlen + 1) > ubytes) { rc = ERROR_BUFFER_OVERFLOW; break; } /* get the inode for the file */ ICACHE_LOCK(); rc = iget(dvp->v_vfsp, dbufp->d_ino, &ip, 0); ICACHE_UNLOCK(); if (rc) goto try_next; nxbuf = ffbuf; /* fill in file search info for files that have * the proper attributes; ignore others. */ rc = get_fileinfo(ip, &nxbuf, ubytes, dbufp->d_name, namlen, fsfp->fsd_havattr, level, eaopp, flags); if ((rc == ERROR_BUFFER_OVERFLOW) && (*matchcnt == 0) && ((level == FIL_QUERYEASFROMLIST) || (level == FIL_QUERYEASFROMLISTL))) { /* Can't fit EA in buffer, try without * getting EA */ if (level == FIL_QUERYEASFROMLIST) level = FIL_QUERYEASIZE; else level = FIL_QUERYEASIZEL; ReturnCode = ERROR_EAS_DIDNT_FIT; rc = get_fileinfo(ip, &nxbuf, ubytes, dbufp->d_name, namlen, fsfp->fsd_havattr, level, eaopp, flags); } /* release the inode */ jfs_rele(IP2VP(ip)); if (rc == 0) { /* set offset if requested */ if (position) { rc = KernCopyOut(ffbuf, &dbufp->d_offset, sizeof(int32)); if (rc) { /* This is very unlikely to * happen! */ ASSERT(0); break; } } /* update output buffer count */ count += nxbuf - ffbuf; /* move to next entry in output buffer */ ffbuf = nxbuf; /* update match count */ *matchcnt += 1; } else if (rc != -1) break; try_next: /* rc == -1 indicates no attribute match, * just keep going. */ rc = 0; /* save name for next call setup */ lastmatch.name = dbufp->d_name; lastmatch.namlen = namlen; /* update dirent buffer count */ tbytes -= dbufp->d_reclen; /* move to next entry in dirent buffer */ dbufp = (struct dirent *) ((caddr_t)dbufp + dbufp->d_reclen); } /* We don't want to continue if ReturnCode = ERROR_EAS_DIDNT_FIT */ if (rc == 0) rc = ReturnCode; /* set return code for end of directory with no matches */ if (fsfp->fsd_offset == -1) rc = ERROR_NO_MORE_FILES; else if ((rc == 0) || (rc == ERROR_EAS_DIDNT_FIT)) { /* save last matching name for next call */ UniStrncpy(fsfp->fsd_lastmatch,lastmatch.name, lastmatch.namlen); fsfp->fsd_lastmatch[lastmatch.namlen] = '\0'; } } /* claim success if we return any entries */ if (*matchcnt != 0) rc = ReturnCode; freepool(dirent_pool, (caddr_t *)dbuf); readdir_Exit: MMPHPostreaddir(); /* MMPH Performance Hook */ return rc; }