Exemplo n.º 1
0
Arquivo: string.c Projeto: Lyude/linux
/**
 * strscpy - Copy a C-string into a sized buffer
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 * @count: Size of destination buffer
 *
 * Copy the string, or as much of it as fits, into the dest buffer.
 * The routine returns the number of characters copied (not including
 * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough.
 * The behavior is undefined if the string buffers overlap.
 * The destination buffer is always NUL terminated, unless it's zero-sized.
 *
 * Preferred to strlcpy() since the API doesn't require reading memory
 * from the src string beyond the specified "count" bytes, and since
 * the return value is easier to error-check than strlcpy()'s.
 * In addition, the implementation is robust to the string changing out
 * from underneath it, unlike the current strlcpy() implementation.
 *
 * Preferred to strncpy() since it always returns a valid string, and
 * doesn't unnecessarily force the tail of the destination buffer to be
 * zeroed.  If the zeroing is desired, it's likely cleaner to use strscpy()
 * with an overflow test, then just memset() the tail of the dest buffer.
 */
ssize_t strscpy(char *dest, const char *src, size_t count)
{
	const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
	size_t max = count;
	long res = 0;

	if (count == 0)
		return -E2BIG;

#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
	/*
	 * If src is unaligned, don't cross a page boundary,
	 * since we don't know if the next page is mapped.
	 */
	if ((long)src & (sizeof(long) - 1)) {
		size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
		if (limit < max)
			max = limit;
	}
#else
	/* If src or dest is unaligned, don't do word-at-a-time. */
	if (((long) dest | (long) src) & (sizeof(long) - 1))
		max = 0;
#endif

	while (max >= sizeof(unsigned long)) {
		unsigned long c, data;

		c = read_word_at_a_time(src+res);
		if (has_zero(c, &data, &constants)) {
			data = prep_zero_mask(c, data, &constants);
			data = create_zero_mask(data);
			*(unsigned long *)(dest+res) = c & zero_bytemask(data);
			return res + find_zero(data);
		}
		*(unsigned long *)(dest+res) = c;
		res += sizeof(unsigned long);
		count -= sizeof(unsigned long);
		max -= sizeof(unsigned long);
	}

	while (count) {
		char c;

		c = src[res];
		dest[res] = c;
		if (!c)
			return res;
		res++;
		count--;
	}

	/* Hit buffer length without finding a NUL; force NUL-termination. */
	if (res)
		dest[res-1] = '\0';

	return -E2BIG;
}
Exemplo n.º 2
0
/*
 * Do a strncpy, return length of string without final '\0'.
 * 'count' is the user-supplied count (return 'count' if we
 * hit it), 'max' is the address space maximum (and we return
 * -EFAULT if we hit it).
 */
static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
{
	static const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
	long res = 0;

	/*
	 * Truncate 'max' to the user-specified limit, so that
	 * we only have one limit we need to check in the loop
	 */
	if (max > count)
		max = count;

	if (IS_UNALIGNED(src, dst))
		goto byte_at_a_time;

	while (max >= sizeof(unsigned long)) {
		unsigned long c, data;

		/* Fall back to byte-at-a-time if we get a page fault */
		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
			break;
		*(unsigned long *)(dst+res) = c;
		if (has_zero(c, &data, &constants)) {
			data = prep_zero_mask(c, data, &constants);
			data = create_zero_mask(data);
			return res + find_zero(data);
		}
		res += sizeof(unsigned long);
		max -= sizeof(unsigned long);
	}

byte_at_a_time:
	while (max) {
		char c;

		if (unlikely(__get_user(c,src+res)))
			return -EFAULT;
		dst[res] = c;
		if (!c)
			return res;
		res++;
		max--;
	}

	/*
	 * Uhhuh. We hit 'max'. But was that the user-specified maximum
	 * too? If so, that's ok - we got as much as the user asked for.
	 */
	if (res >= count)
		return res;

	/*
	 * Nope: we hit the address space limit, and we still had more
	 * characters the caller would have wanted. That's an EFAULT.
	 */
	return -EFAULT;
}
Exemplo n.º 3
0
/*
 * Do a strnlen, return length of string *with* final '\0'.
 * 'count' is the user-supplied count, while 'max' is the
 * address space maximum.
 *
 * Return 0 for exceptions (which includes hitting the address
 * space maximum), or 'count+1' if hitting the user-supplied
 * maximum count.
 *
 * NOTE! We can sometimes overshoot the user-supplied maximum
 * if it fits in a aligned 'long'. The caller needs to check
 * the return value against "> max".
 */
static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max)
{
	const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
	long align, res = 0;
	unsigned long c;

	/*
	 * Truncate 'max' to the user-specified limit, so that
	 * we only have one limit we need to check in the loop
	 */
	if (max > count)
		max = count;

	/*
	 * Do everything aligned. But that means that we
	 * need to also expand the maximum..
	 */
	align = (sizeof(long) - 1) & (unsigned long)src;
	src -= align;
	max += align;

	if (unlikely(__get_user(c,(unsigned long __user *)src)))
		return 0;
	c |= aligned_byte_mask(align);

	for (;;) {
		unsigned long data;
		if (has_zero(c, &data, &constants)) {
			data = prep_zero_mask(c, data, &constants);
			data = create_zero_mask(data);
			return res + find_zero(data) + 1 - align;
		}
		res += sizeof(unsigned long);
		if (unlikely(max < sizeof(unsigned long)))
			break;
		max -= sizeof(unsigned long);
		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
			return 0;
	}
	res -= align;

	/*
	 * Uhhuh. We hit 'max'. But was that the user-specified maximum
	 * too? If so, return the marker for "too long".
	 */
	if (res >= count)
		return count+1;

	/*
	 * Nope: we hit the address space limit, and we still had more
	 * characters the caller would have wanted. That's 0.
	 */
	return 0;
}
Exemplo n.º 4
0
/*
 * Do a strncpy, return length of string without final '\0'.
 * 'count' is the user-supplied count (return 'count' if we
 * hit it), 'max' is the address space maximum (and we return
 * -EFAULT if we hit it).
 */
static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
{
	long res = 0;

	/*
	 * Truncate 'max' to the user-specified limit, so that
	 * we only have one limit we need to check in the loop
	 */
	if (max > count)
		max = count;

	while (max >= sizeof(unsigned long)) {
		unsigned long c;

		/* Fall back to byte-at-a-time if we get a page fault */
		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
			break;
		/* This can write a few bytes past the NUL character, but that's ok */
		*(unsigned long *)(dst+res) = c;
		c = has_zero(c);
		if (c)
			return res + count_bytes(c);
		res += sizeof(unsigned long);
		max -= sizeof(unsigned long);
	}

	while (max) {
		char c;

		if (unlikely(__get_user(c,src+res)))
			return -EFAULT;
		dst[res] = c;
		if (!c)
			return res;
		res++;
		max--;
	}

	/*
	 * Uhhuh. We hit 'max'. But was that the user-specified maximum
	 * too? If so, that's ok - we got as much as the user asked for.
	 */
	if (res >= count)
		return res;

	/*
	 * Nope: we hit the address space limit, and we still had more
	 * characters the caller would have wanted. That's an EFAULT.
	 */
	return -EFAULT;
}
Exemplo n.º 5
0
int main(void)
{
	int a[LEN] = {-1, 0, 1};
	int b[LEN] = {1, 2, 3};

	printf("a[] =");
	for (int i = 0; i < LEN; i++) {
		printf(" %d", a[i]);
	}
	printf("\n");

	printf("b[] =");
	for (int i = 0; i < LEN; i++) {
		printf(" %d", b[i]);
	}
	printf("\n");

	printf("has_zero(a, 3) => %s\n",
	       (has_zero(a, 3) == 1) ? "true" : "false");
	printf("has_zero(b, 3) => %s\n",
	       (has_zero(b, 3) == 1) ? "true" : "false");

	return 0;
}
Exemplo n.º 6
0
int main( ) 
{
    int n = 1000000;
    int num = 0;
    while( n-- ) {
        if( !is_prime( n ) ) continue;
        if( has_zero( n ) ) continue;
        int r = n;
        int circular = 1;
        while( (r = rotate(r)) != n ) {
            if( !is_prime( r ) ) {
                circular = 0;
                break;
            }
        }
        if( circular ) {
            num++;
        }
    }
    printf( "Answer: %d\n", num );
}
Exemplo n.º 7
0
int main(void)
{
	int offset = 0, pos = 0;
	u64 largest = 0;

	while(offset <= (1000 - 13)){
		if((pos = has_zero(offset))){
			offset += pos;
			continue;
		}

		u64 current = 1LL;
		for(int i = 0; i < 13; i++)
			current *= (u64) (number[offset + i] - '0');
		if(current > largest)
			largest = current;

		offset++;
	}

	printf("%llu\n", largest);
}
Exemplo n.º 8
0
const char *fgets2(FILE *stream)
{
	static char buffer[FGETS2_BUFSIZE + 5];
	static char *end = buffer;
	static char *line = buffer;

	char *next;
	int ret;

	next = line;

	while (1) {
		/* this is a speed-up, we read 32 bits at once and check for an
		 * LF character there. We stop if found then continue one at a
		 * time.
		 */
		while (next < end && (((unsigned long)next) & 3) && *next != '\n')
			next++;

		/* now next is multiple of 4 or equal to end */
		while (next <= (end-32)) {
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
			if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
				break;
			next += 4;
		}

		/* we finish if needed. Note that next might be slightly higher
		 * than end here because we might have gone past it above.
		 */
		while (next < end) {
			if (*next == '\n') {
				const char *start = line;

				*next = '\0';
				line = next + 1;
				return start;
			}
			next++;
		}

		/* we found an incomplete line. First, let's move the
		 * remaining part of the buffer to the beginning, then
		 * try to complete the buffer with a new read.
		 */
		if (line > buffer) {
			if (end != line)
				memmove(buffer, line, end - line);
			end = buffer + (end - line);
			next = end;
			line = buffer;
		} else {
			if (end == buffer + FGETS2_BUFSIZE)
				return NULL;
		}

		ret = read(fileno(stream), end, buffer + FGETS2_BUFSIZE - end);

		if (ret <= 0) {
			if (end == line)
				return NULL;

			*end = '\0';
			end = line; /* ensure we stop next time */
			return line;
		}

		end += ret;
		/* search for '\n' again */
	}
}
Exemplo n.º 9
0
const char *fgets2(FILE *stream)
{
	static char buffer[FGETS2_BUFSIZE + 68];
	static char *end = buffer;
	static char *line = buffer;

	char *next;
	int ret;

	next = line;

	while (1) {
		/* this is a speed-up, we read 64 bits at once and check for an
		 * LF character there. We stop if found then continue one at a
		 * time.
		 */

		if (next <= end) {
			/* max 3 bytes tested here */
			while ((((unsigned long)next) & 3) && *next != '\n')
				next++;

			/* maybe we have can skip 4 more bytes */
			if ((((unsigned long)next) & 4) && !has_zero(*(unsigned int *)next ^ 0x0A0A0A0AU))
				next += 4;
		}

		/* now next is multiple of 8 or equal to end */
		while (next <= (end-68)) {
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
			if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
				break;
			next += 8;
		}

		/* maybe we can skip 4 more bytes */
		if (!has_zero(*(unsigned int *)next ^ 0x0A0A0A0AU))
			next += 4;

		/* We finish if needed : if <next> is below <end>, it means we
		 * found an LF in one of the 4 following bytes.
		 */
		while (next < end) {
			if (*next == '\n') {
				const char *start = line;

				*next = '\0';
				line = next + 1;
				return start;
			}
			next++;
		}

		/* we found an incomplete line. First, let's move the
		 * remaining part of the buffer to the beginning, then
		 * try to complete the buffer with a new read. We can't
		 * rely on <next> anymore because it went past <end>.
		 */
		if (line > buffer) {
			if (end != line)
				memmove(buffer, line, end - line);
			end = buffer + (end - line);
			next = end;
			line = buffer;
		} else {
			if (end == buffer + FGETS2_BUFSIZE)
				return NULL;
		}

		ret = read(fileno(stream), end, buffer + FGETS2_BUFSIZE - end);

		if (ret <= 0) {
			if (end == line)
				return NULL;

			*end = '\0';
			end = line; /* ensure we stop next time */
			return line;
		}

		end += ret;
		*end = '\n'; /* make parser stop ASAP */
		/* search for '\n' again */
	}
}