Beispiel #1
0
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 );
}
Beispiel #3
0
/*
 * 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;
}
Beispiel #4
0
/*
 * 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;
}
Beispiel #5
0
/*
 * 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;
}