1*0Sstevel@tonic-gate/* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate/* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate.ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate .file "%M%" 30*0Sstevel@tonic-gate/* 31*0Sstevel@tonic-gate * The strlcpy() function copies at most dstsize-1 characters 32*0Sstevel@tonic-gate * (dstsize being the size of the string buffer dst) from src 33*0Sstevel@tonic-gate * to dst, truncating src if necessary. The result is always 34*0Sstevel@tonic-gate * null-terminated. The function returns strlen(src). Buffer 35*0Sstevel@tonic-gate * overflow can be checked as follows: 36*0Sstevel@tonic-gate * 37*0Sstevel@tonic-gate * if (strlcpy(dst, src, dstsize) >= dstsize) 38*0Sstevel@tonic-gate * return -1; 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate#include <sys/asm_linkage.h> 42*0Sstevel@tonic-gate#include "synonyms.h" 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate ! strlcpy implementation is similar to that of strcpy, except 45*0Sstevel@tonic-gate ! in this case, the maximum size of the detination must be 46*0Sstevel@tonic-gate ! tracked since it bounds our maximum copy size. However, 47*0Sstevel@tonic-gate ! we must still continue to check for zero since the routine 48*0Sstevel@tonic-gate ! is expected to null-terminate any string that is within 49*0Sstevel@tonic-gate ! the dest size bound. 50*0Sstevel@tonic-gate ! 51*0Sstevel@tonic-gate ! this method starts by checking for and arranging source alignment. 52*0Sstevel@tonic-gate ! Once this has occurred, we copy based upon destination alignment. 53*0Sstevel@tonic-gate ! This is either by word, halfword, or byte. As this occurs, we 54*0Sstevel@tonic-gate ! check for a zero-byte. If one is found, we branch to a method 55*0Sstevel@tonic-gate ! which checks for the exact location of a zero-byte within a 56*0Sstevel@tonic-gate ! larger word/half-word quantity. 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate ENTRY(strlcpy) 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate .align 32 61*0Sstevel@tonic-gate save %sp, -SA(WINDOWSIZE), %sp 62*0Sstevel@tonic-gate subcc %g0, %i2, %g4 ! n = -n or n == 0 ? 63*0Sstevel@tonic-gate bz,pn %icc, .getstrlen ! if 0 do nothing but strlen(src) 64*0Sstevel@tonic-gate add %i1, %i2, %i3 ! i3 = src + n 65*0Sstevel@tonic-gate andcc %i1, 3, %i4 ! word aligned? 66*0Sstevel@tonic-gate bz,pn %icc, .wordaligned 67*0Sstevel@tonic-gate add %i0, %i2, %i2 ! n = dst + n 68*0Sstevel@tonic-gate sub %i4, 4, %i4 ! bytes until src aligned 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate.alignsrc: 71*0Sstevel@tonic-gate ldub [%i3 + %g4], %l1 ! l1 = src[] 72*0Sstevel@tonic-gate andcc %l1, 0xff, %g0 ! null byte reached? 73*0Sstevel@tonic-gate stub %l1, [%i2 + %g4] ! dst[] = src[] 74*0Sstevel@tonic-gate bz,a %icc, .done 75*0Sstevel@tonic-gate add %i2, %g4, %i2 ! get single dest ptr for strlen 76*0Sstevel@tonic-gate addcc %g4, 1, %g4 ! src++ dest++ n-- 77*0Sstevel@tonic-gate bz,pn %icc, .forcenullunalign ! n == 0, append null byte 78*0Sstevel@tonic-gate addcc %i4, 1, %i4 ! incr, check align 79*0Sstevel@tonic-gate bnz,a %icc, .alignsrc 80*0Sstevel@tonic-gate nop 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate.wordaligned: 83*0Sstevel@tonic-gate sethi %hi(0x01010101), %i4 84*0Sstevel@tonic-gate add %i2, %g4, %l0 ! l0 = dest 85*0Sstevel@tonic-gate or %i4, %lo(0x01010101), %i4 86*0Sstevel@tonic-gate sub %i2, 4, %i2 ! pre-incr for in cpy loop 87*0Sstevel@tonic-gate andcc %l0, 3, %g1 ! word aligned? 88*0Sstevel@tonic-gate bnz %icc, .dstnotaligned 89*0Sstevel@tonic-gate sll %i4, 7, %i5 ! Mycroft part deux 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate.storeword: 92*0Sstevel@tonic-gate ld [%i3 + %g4], %l1 ! l1 = src[] 93*0Sstevel@tonic-gate addcc %g4, 4, %g4 ! n += 4, src += 4, dst +=4 94*0Sstevel@tonic-gate bcs,pn %icc, .lastword 95*0Sstevel@tonic-gate andn %i5, %l1, %g1 ! ~word & 0x80808080 96*0Sstevel@tonic-gate sub %l1, %i4, %l0 ! word - 0x01010101 97*0Sstevel@tonic-gate andcc %l0, %g1, %g0 ! doit 98*0Sstevel@tonic-gate bz,a,pt %icc, .storeword ! if expr == 0, no zero byte 99*0Sstevel@tonic-gate st %l1, [%i2 + %g4] ! dst[] = src[] 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate.zerobyte: 102*0Sstevel@tonic-gate add %i2, %g4, %i2 ! ptr to dest 103*0Sstevel@tonic-gate srl %l1, 24, %g1 ! 1st byte 104*0Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! test for end 105*0Sstevel@tonic-gate bz,pn %icc, .done 106*0Sstevel@tonic-gate stb %g1, [%i2] ! store byte 107*0Sstevel@tonic-gate add %i2, 1, %i2 ! dst ++ 108*0Sstevel@tonic-gate srl %l1, 16, %g1 ! 2nd byte 109*0Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! zero byte ? 110*0Sstevel@tonic-gate bz,pn %icc, .done 111*0Sstevel@tonic-gate stb %g1, [%i2] ! store byte 112*0Sstevel@tonic-gate add %i2, 1, %i2 ! dst ++ 113*0Sstevel@tonic-gate srl %l1, 8, %g1 ! 3rd byte 114*0Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! zero byte ? 115*0Sstevel@tonic-gate bz,pn %icc, .done 116*0Sstevel@tonic-gate stb %g1, [%i2] ! store byte 117*0Sstevel@tonic-gate stb %l1, [%i2 + 1] ! store last byte 118*0Sstevel@tonic-gate add %i2, 1, %i2 ! dst ++ 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate.done: 121*0Sstevel@tonic-gate sub %i2, %i0, %i0 ! len = dst - orig dst 122*0Sstevel@tonic-gate ret 123*0Sstevel@tonic-gate restore %i0, %g0, %o0 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate.lastword: 126*0Sstevel@tonic-gate add %i2, %g4, %i2 127*0Sstevel@tonic-gate sub %g4, 4, %g4 ! undo pre-incr 128*0Sstevel@tonic-gate add %i3, %g4, %i3 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate srl %l1, 24, %g1 ! 1st byte 131*0Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! zero byte? 132*0Sstevel@tonic-gate bz,pn %icc, .done 133*0Sstevel@tonic-gate stb %g1, [%i2] ! store byte 134*0Sstevel@tonic-gate inccc %g4 ! n-- 135*0Sstevel@tonic-gate bz .forcenull 136*0Sstevel@tonic-gate srl %l1, 16, %g1 ! 2nd byte 137*0Sstevel@tonic-gate add %i2, 1, %i2 ! dst++ 138*0Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! zero? 139*0Sstevel@tonic-gate bz,pn %icc, .done 140*0Sstevel@tonic-gate stb %g1, [%i2] ! store 141*0Sstevel@tonic-gate inccc %g4 142*0Sstevel@tonic-gate bz .forcenull 143*0Sstevel@tonic-gate srl %l1, 8, %g1 ! 3rd byte 144*0Sstevel@tonic-gate add %i2, 1, %i2 ! dst++ 145*0Sstevel@tonic-gate andcc %g1, 0xff, %g0 ! zero? 146*0Sstevel@tonic-gate bz,pn %icc, .done 147*0Sstevel@tonic-gate stb %g1, [%i2] ! store 148*0Sstevel@tonic-gate inccc %g4 ! n-- 149*0Sstevel@tonic-gate bz .forcenull 150*0Sstevel@tonic-gate andcc %l1, 0xff, %g0 ! zero? 151*0Sstevel@tonic-gate add %i2, 1, %i2 ! dst++ 152*0Sstevel@tonic-gate bz,pn %ncc, .done 153*0Sstevel@tonic-gate stb %l1, [%i2] 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate.forcenull: 156*0Sstevel@tonic-gate stb %g0, [%i2] 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate.searchword: 159*0Sstevel@tonic-gate ld [%i3], %l1 160*0Sstevel@tonic-gate.searchword2: 161*0Sstevel@tonic-gate andn %i5, %l1, %g1 ! word & 0x80808080 162*0Sstevel@tonic-gate sub %l1, %i4, %l0 ! word - 0x01010101 163*0Sstevel@tonic-gate andcc %l0, %g1, %g0 ! do it 164*0Sstevel@tonic-gate bz,a,pt %icc, .searchword 165*0Sstevel@tonic-gate add %i3, 4, %i3 ! src += 4 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate mov 0xff, %i5 168*0Sstevel@tonic-gate sll %i5, 24, %i5 ! mask 1st byte = 0xff000000 169*0Sstevel@tonic-gate.searchbyte: 170*0Sstevel@tonic-gate andcc %l1, %i5, %g0 ! cur byte 0? 171*0Sstevel@tonic-gate srl %i5, 8, %i5 ! mask next byte 172*0Sstevel@tonic-gate bnz,a %icc, .searchbyte ! cur !=0 continue 173*0Sstevel@tonic-gate add %i3, 1, %i3 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate.endfound: 176*0Sstevel@tonic-gate sub %i3, %i1, %i0 ! len = src - orig src 177*0Sstevel@tonic-gate ret 178*0Sstevel@tonic-gate restore %i0, %g0, %o0 179*0Sstevel@tonic-gate nop 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate.dstnotaligned: 182*0Sstevel@tonic-gate cmp %g1, 2 ! halfword aligned? 183*0Sstevel@tonic-gate be .storehalfword2 184*0Sstevel@tonic-gate .empty 185*0Sstevel@tonic-gate.storebyte: 186*0Sstevel@tonic-gate ld [%i3 + %g4], %l1 ! load src word 187*0Sstevel@tonic-gate addcc %g4, 4, %g4 ! src +=4 dst +=4 188*0Sstevel@tonic-gate bcs,pn %icc, .lastword 189*0Sstevel@tonic-gate andn %i5, %l1, %g1 ! ~x & 0x80808080 190*0Sstevel@tonic-gate sub %l1, %i4, %l0 ! x - 0x01010101 191*0Sstevel@tonic-gate andcc %l0, %g1, %g0 ! get your Mycroft on 192*0Sstevel@tonic-gate bnz,pn %icc, .zerobyte ! non-zero, we have zero byte 193*0Sstevel@tonic-gate add %i2, %g4, %l0 ! dst in ptr form 194*0Sstevel@tonic-gate srl %l1, 24, %g1 ! get 1st byte, then be hw aligned 195*0Sstevel@tonic-gate stb %g1, [%l0] 196*0Sstevel@tonic-gate srl %l1, 8, %g1 ! 2nd & 3rd bytes 197*0Sstevel@tonic-gate sth %g1, [%l0 + 1] 198*0Sstevel@tonic-gate ba .storebyte 199*0Sstevel@tonic-gate stb %l1, [%l0 + 3] ! store 4th byte 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate.storehalfword: 202*0Sstevel@tonic-gate ld [%i3 + %g4], %l1 ! src word 203*0Sstevel@tonic-gate.storehalfword2: 204*0Sstevel@tonic-gate addcc %g4, 4, %g4 ! src += 4 dst += 4 205*0Sstevel@tonic-gate bcs,pn %icc, .lastword 206*0Sstevel@tonic-gate andn %i5, %l1, %g1 ! ~x & 0x80808080 207*0Sstevel@tonic-gate sub %l1, %i4, %l0 ! x - 0x01010101 208*0Sstevel@tonic-gate andcc %l0, %g1, %g0 ! Mycroft again... 209*0Sstevel@tonic-gate bnz,pn %icc, .zerobyte ! non-zer, we have zero byte 210*0Sstevel@tonic-gate add %i2, %g4, %l0 ! dst in ptr form 211*0Sstevel@tonic-gate srl %l1, 16, %g1 ! first two bytes 212*0Sstevel@tonic-gate sth %g1, [%l0] 213*0Sstevel@tonic-gate ba .storehalfword 214*0Sstevel@tonic-gate sth %l1, [%l0 + 2] 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate.forcenullunalign: 217*0Sstevel@tonic-gate add %i2, %g4, %i2 ! single dst ptr 218*0Sstevel@tonic-gate stb %g0, [%i2 - 1] ! store terminating null byte 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate.getstrlen: 221*0Sstevel@tonic-gate sethi %hi(0x01010101), %i4 ! Mycroft... 222*0Sstevel@tonic-gate or %i4, %lo(0x01010101), %i4 223*0Sstevel@tonic-gate sll %i4, 7, %i5 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate.getstrlenloop: 226*0Sstevel@tonic-gate andcc %i3, 3, %g0 ! word aligned? 227*0Sstevel@tonic-gate bz,a,pn %icc, .searchword2 ! search word at a time 228*0Sstevel@tonic-gate ld [%i3], %l1 ! src word 229*0Sstevel@tonic-gate ldub [%i3], %l1 ! src byte 230*0Sstevel@tonic-gate andcc %l1, 0xff, %g0 ! end of src? 231*0Sstevel@tonic-gate bnz,a %icc, .getstrlenloop 232*0Sstevel@tonic-gate add %i3, 1, %i3 ! src ++ 233*0Sstevel@tonic-gate sub %i3, %i1, %i0 ! len = src - orig src 234*0Sstevel@tonic-gate ret 235*0Sstevel@tonic-gate restore %i0, %g0, %o0 236*0Sstevel@tonic-gate SET_SIZE(strlcpy) 237