cregit-Linux how code gets into the kernel

Release 4.18 fs/udf/symlink.c

Directory: fs/udf
/*
 * symlink.c
 *
 * PURPOSE
 *      Symlink handling routines for the OSTA-UDF(tm) filesystem.
 *
 * COPYRIGHT
 *      This file is distributed under the terms of the GNU General Public
 *      License (GPL). Copies of the GPL can be obtained from:
 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
 *      Each contributing author retains all rights to their own work.
 *
 *  (C) 1998-2001 Ben Fennema
 *  (C) 1999 Stelias Computing Inc
 *
 * HISTORY
 *
 *  04/16/99 blf  Created.
 *
 */

#include "udfdecl.h"
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/pagemap.h>
#include "udf_i.h"


static int udf_pc_to_char(struct super_block *sb, unsigned char *from, int fromlen, unsigned char *to, int tolen) { struct pathComponent *pc; int elen = 0; int comp_len; unsigned char *p = to; /* Reserve one byte for terminating \0 */ tolen--; while (elen < fromlen) { pc = (struct pathComponent *)(from + elen); elen += sizeof(struct pathComponent); switch (pc->componentType) { case 1: /* * Symlink points to some place which should be agreed * upon between originator and receiver of the media. Ignore. */ if (pc->lengthComponentIdent > 0) { elen += pc->lengthComponentIdent; break; } /* Fall through */ case 2: if (tolen == 0) return -ENAMETOOLONG; p = to; *p++ = '/'; tolen--; break; case 3: if (tolen < 3) return -ENAMETOOLONG; memcpy(p, "../", 3); p += 3; tolen -= 3; break; case 4: if (tolen < 2) return -ENAMETOOLONG; memcpy(p, "./", 2); p += 2; tolen -= 2; /* that would be . - just ignore */ break; case 5: elen += pc->lengthComponentIdent; if (elen > fromlen) return -EIO; comp_len = udf_get_filename(sb, pc->componentIdent, pc->lengthComponentIdent, p, tolen); if (comp_len < 0) return comp_len; p += comp_len; tolen -= comp_len; if (tolen == 0) return -ENAMETOOLONG; *p++ = '/'; tolen--; break; } } if (p > to + 1) p[-1] = '\0'; else p[0] = '\0'; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)15751.99%330.00%
Jan Kara12140.07%330.00%
Ben Fennema123.97%220.00%
Fabian Frederick92.98%110.00%
Al Viro30.99%110.00%
Total302100.00%10100.00%


static int udf_symlink_filler(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; struct buffer_head *bh = NULL; unsigned char *symlink; int err; unsigned char *p = page_address(page); struct udf_inode_info *iinfo; uint32_t pos; /* We don't support symlinks longer than one block */ if (inode->i_size > inode->i_sb->s_blocksize) { err = -ENAMETOOLONG; goto out_unmap; } iinfo = UDF_I(inode); pos = udf_block_map(inode, 0); down_read(&iinfo->i_data_sem); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr; } else { bh = sb_bread(inode->i_sb, pos); if (!bh) { err = -EIO; goto out_unlock_inode; } symlink = bh->b_data; } err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); brelse(bh); if (err) goto out_unlock_inode; up_read(&iinfo->i_data_sem); SetPageUptodate(page); unlock_page(page); return 0; out_unlock_inode: up_read(&iinfo->i_data_sem); SetPageError(page); out_unmap: unlock_page(page); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)12351.04%527.78%
Jan Kara4619.09%316.67%
Alessio Igor Bogani3514.52%15.56%
Marcin Ślusarz229.13%211.11%
Ben Fennema62.49%211.11%
Al Viro31.24%211.11%
Andrew Morton20.83%15.56%
Cyrill V. Gorcunov20.83%15.56%
Linus Torvalds20.83%15.56%
Total241100.00%18100.00%


static int udf_symlink_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) { struct dentry *dentry = path->dentry; struct inode *inode = d_backing_inode(dentry); struct page *page; generic_fillattr(inode, stat); page = read_mapping_page(inode->i_mapping, 0, NULL); if (IS_ERR(page)) return PTR_ERR(page); /* * UDF uses non-trivial encoding of symlinks so i_size does not match * number of characters reported by readlink(2) which apparently some * applications expect. Also POSIX says that "The value returned in the * st_size field shall be the length of the contents of the symbolic * link, and shall not count a trailing null if one is present." So * let's report the length of string returned by readlink(2) for * st_size. */ stat->size = strlen(page_address(page)); put_page(page); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara8381.37%150.00%
David Howells1918.63%150.00%
Total102100.00%2100.00%

/* * symlinks can't do much... */ const struct address_space_operations udf_symlink_aops = { .readpage = udf_symlink_filler, }; const struct inode_operations udf_symlink_inode_operations = { .get_link = page_get_link, .getattr = udf_symlink_getattr, };

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)31544.81%621.43%
Jan Kara26737.98%621.43%
Alessio Igor Bogani354.98%13.57%
Marcin Ślusarz223.13%27.14%
David Howells192.70%13.57%
Ben Fennema182.56%27.14%
Fabian Frederick101.42%27.14%
Al Viro60.85%27.14%
Cyrill V. Gorcunov30.43%13.57%
Andrew Morton20.28%13.57%
Linus Torvalds20.28%13.57%
Art Haas20.28%13.57%
Christoph Hellwig10.14%13.57%
Dave Jones10.14%13.57%
Total703100.00%28100.00%
Directory: fs/udf
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.