162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * symlink.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1999 Al Smith 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/string.h> 1162306a36Sopenharmony_ci#include <linux/pagemap.h> 1262306a36Sopenharmony_ci#include <linux/buffer_head.h> 1362306a36Sopenharmony_ci#include "efs.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int efs_symlink_read_folio(struct file *file, struct folio *folio) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci struct page *page = &folio->page; 1862306a36Sopenharmony_ci char *link = page_address(page); 1962306a36Sopenharmony_ci struct buffer_head * bh; 2062306a36Sopenharmony_ci struct inode * inode = page->mapping->host; 2162306a36Sopenharmony_ci efs_block_t size = inode->i_size; 2262306a36Sopenharmony_ci int err; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci err = -ENAMETOOLONG; 2562306a36Sopenharmony_ci if (size > 2 * EFS_BLOCKSIZE) 2662306a36Sopenharmony_ci goto fail; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci /* read first 512 bytes of link target */ 2962306a36Sopenharmony_ci err = -EIO; 3062306a36Sopenharmony_ci bh = sb_bread(inode->i_sb, efs_bmap(inode, 0)); 3162306a36Sopenharmony_ci if (!bh) 3262306a36Sopenharmony_ci goto fail; 3362306a36Sopenharmony_ci memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size); 3462306a36Sopenharmony_ci brelse(bh); 3562306a36Sopenharmony_ci if (size > EFS_BLOCKSIZE) { 3662306a36Sopenharmony_ci bh = sb_bread(inode->i_sb, efs_bmap(inode, 1)); 3762306a36Sopenharmony_ci if (!bh) 3862306a36Sopenharmony_ci goto fail; 3962306a36Sopenharmony_ci memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE); 4062306a36Sopenharmony_ci brelse(bh); 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci link[size] = '\0'; 4362306a36Sopenharmony_ci SetPageUptodate(page); 4462306a36Sopenharmony_ci unlock_page(page); 4562306a36Sopenharmony_ci return 0; 4662306a36Sopenharmony_cifail: 4762306a36Sopenharmony_ci SetPageError(page); 4862306a36Sopenharmony_ci unlock_page(page); 4962306a36Sopenharmony_ci return err; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciconst struct address_space_operations efs_symlink_aops = { 5362306a36Sopenharmony_ci .read_folio = efs_symlink_read_folio 5462306a36Sopenharmony_ci}; 55