#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
struct mntent {
  int /*<<< orphan*/ mnt_dir;
};
typedef int /*<<< orphan*/ FILE;

/* Variables and functions */
int /*<<< orphan*/ EINVAL;
int /*<<< orphan*/ endmntent(int /*<<< orphan*/ *);
int /*<<< orphan*/ errno;
int /*<<< orphan*/ free(char *);
struct mntent *getmntent(int /*<<< orphan*/ *);
char *malloc(scalar_t__);
char *realloc(char *, scalar_t__);
char *realpath(char const *, int /*<<< orphan*/ *);
int /*<<< orphan*/ *setmntent(char *, char *);
int /*<<< orphan*/ strcpy(char *, int /*<<< orphan*/);
scalar_t__ strlen(int /*<<< orphan*/);
int /*<<< orphan*/ strncmp(int /*<<< orphan*/, char *, scalar_t__);
char *get_mountpoint(const char *path) {
  char *mnt_dir = NULL;
  char *resolved_path = NULL;
  FILE *mtab_f;
  int done = 0;
  struct mntent *entry;
  if (path == NULL) {
    errno = EINVAL;
  } else if ((resolved_path = realpath(path, NULL)) != NULL &&
             (mtab_f = setmntent("/etc/mtab", "r")) != NULL) {
    do {
      entry = getmntent(mtab_f);
      if (entry != NULL) {
        if (!strncmp(entry->mnt_dir, resolved_path, strlen(entry->mnt_dir))) {
          char copy_string = 0;
          if (mnt_dir == NULL) {
            mnt_dir = malloc(strlen(entry->mnt_dir) + 1);
            copy_string = mnt_dir != NULL;
          } else {
            if (!strncmp(entry->mnt_dir, mnt_dir, strlen(entry->mnt_dir))) {
              mnt_dir = realloc(mnt_dir, strlen(entry->mnt_dir));
              copy_string = 1;
            }
          }
          if (copy_string != 0) {
            strcpy(mnt_dir, entry->mnt_dir);
          }
        }
      }
    } while (done == 0 && entry != NULL);
    endmntent(mtab_f);
  }
  if (resolved_path != NULL) {
    free(resolved_path);
  }
  return mnt_dir;
}


x86 assembly (clang, -O0):
<get_mountpoint>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %rdi,-0x8(%rbp)
movq   $0x0,-0x10(%rbp)
movq   $0x0,-0x18(%rbp)
movl   $0x0,-0x24(%rbp)
cmpq   $0x0,-0x8(%rbp)
jne    11e5 <get_mountpoint+0x45>
mov    0x2e03(%rip),%rax
mov    (%rax),%ecx
mov    0x2e02(%rip),%rax
mov    %ecx,(%rax)
jmp    136f <get_mountpoint+0x1cf>
mov    -0x8(%rbp),%rdi
xor    %eax,%eax
mov    %eax,%esi
call   1080 <realpath@plt>
mov    %rax,-0x18(%rbp)
cmp    $0x0,%rax
je     136a <get_mountpoint+0x1ca>
lea    0xdf9(%rip),%rdi
lea    0xdfc(%rip),%rsi
call   10b0 <setmntent@plt>
mov    %rax,-0x20(%rbp)
cmp    $0x0,%rax
je     136a <get_mountpoint+0x1ca>
jmp    1226 <get_mountpoint+0x86>
mov    -0x20(%rbp),%rdi
call   10a0 <getmntent@plt>
mov    %rax,-0x30(%rbp)
cmpq   $0x0,-0x30(%rbp)
je     1337 <get_mountpoint+0x197>
mov    -0x30(%rbp),%rax
mov    (%rax),%eax
mov    %eax,-0x44(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0x30(%rbp),%rax
mov    (%rax),%edi
call   1070 <strlen@plt>
mov    -0x44(%rbp),%edi
mov    -0x40(%rbp),%rsi
mov    %rax,%rdx
call   1050 <strncmp@plt>
cmp    $0x0,%eax
jne    1332 <get_mountpoint+0x192>
movb   $0x0,-0x31(%rbp)
cmpq   $0x0,-0x10(%rbp)
jne    12b1 <get_mountpoint+0x111>
mov    -0x30(%rbp),%rax
mov    (%rax),%edi
call   1070 <strlen@plt>
mov    %rax,%rdi
add    $0x1,%rdi
call   1090 <malloc@plt>
mov    %rax,-0x10(%rbp)
cmpq   $0x0,-0x10(%rbp)
setne  %al
and    $0x1,%al
movzbl %al,%eax
mov    %al,-0x31(%rbp)
jmp    1311 <get_mountpoint+0x171>
mov    -0x30(%rbp),%rax
mov    (%rax),%eax
mov    %eax,-0x54(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x50(%rbp)
mov    -0x30(%rbp),%rax
mov    (%rax),%edi
call   1070 <strlen@plt>
mov    -0x54(%rbp),%edi
mov    -0x50(%rbp),%rsi
mov    %rax,%rdx
call   1050 <strncmp@plt>
cmp    $0x0,%eax
jne    130c <get_mountpoint+0x16c>
mov    -0x10(%rbp),%rax
mov    %rax,-0x60(%rbp)
mov    -0x30(%rbp),%rax
mov    (%rax),%edi
call   1070 <strlen@plt>
mov    -0x60(%rbp),%rdi
mov    %rax,%rsi
call   10c0 <realloc@plt>
mov    %rax,-0x10(%rbp)
movb   $0x1,-0x31(%rbp)
jmp    1311 <get_mountpoint+0x171>
movsbl -0x31(%rbp),%eax
cmp    $0x0,%eax
je     132d <get_mountpoint+0x18d>
mov    -0x10(%rbp),%rdi
mov    -0x30(%rbp),%rax
mov    (%rax),%esi
call   1060 <strcpy@plt>
jmp    1332 <get_mountpoint+0x192>
jmp    1337 <get_mountpoint+0x197>
jmp    133c <get_mountpoint+0x19c>
xor    %eax,%eax
cmpl   $0x0,-0x24(%rbp)
mov    %al,-0x61(%rbp)
jne    1356 <get_mountpoint+0x1b6>
cmpq   $0x0,-0x30(%rbp)
setne  %al
mov    %al,-0x61(%rbp)
mov    -0x61(%rbp),%al
test   $0x1,%al
jne    1226 <get_mountpoint+0x86>
mov    -0x20(%rbp),%rdi
call   1040 <endmntent@plt>
jmp    136f <get_mountpoint+0x1cf>
cmpq   $0x0,-0x18(%rbp)
je     1383 <get_mountpoint+0x1e3>
mov    -0x18(%rbp),%rdi
call   1030 <free@plt>
mov    -0x10(%rbp),%rax
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<get_mountpoint>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
test   %rdi,%rdi
je     1285 <get_mountpoint+0xe5>
xor    %r12d,%r12d
xor    %esi,%esi
call   1080 <realpath@plt>
test   %rax,%rax
je     12b4 <get_mountpoint+0x114>
mov    %rax,%r14
lea    0xe32(%rip),%rdi
lea    0xe35(%rip),%rsi
call   10b0 <setmntent@plt>
test   %rax,%rax
je     129c <get_mountpoint+0xfc>
mov    %rax,%r15
mov    %rax,%rdi
call   10a0 <getmntent@plt>
test   %rax,%rax
je     12a1 <get_mountpoint+0x101>
mov    %rax,%rbx
xor    %r12d,%r12d
jmp    1230 <get_mountpoint+0x90>
add    $0x1,%rax
mov    %rax,%rdi
call   1090 <malloc@plt>
mov    %rax,%r12
test   %rax,%rax
je     1280 <get_mountpoint+0xe0>
mov    (%rbx),%esi
mov    %r12,%rdi
call   1060 <strcpy@plt>
nopl   (%rax)
mov    %r15,%rdi
call   10a0 <getmntent@plt>
mov    %rax,%rbx
test   %rax,%rax
je     12a4 <get_mountpoint+0x104>
mov    (%rbx),%ebp
mov    %ebp,%edi
call   1070 <strlen@plt>
mov    %ebp,%edi
mov    %r14,%rsi
mov    %rax,%rdx
call   1050 <strncmp@plt>
test   %eax,%eax
jne    1220 <get_mountpoint+0x80>
mov    (%rbx),%ebp
mov    %ebp,%edi
call   1070 <strlen@plt>
test   %r12,%r12
je     11ff <get_mountpoint+0x5f>
mov    %ebp,%edi
mov    %r12,%rsi
mov    %rax,%rdx
call   1050 <strncmp@plt>
test   %eax,%eax
jne    1220 <get_mountpoint+0x80>
mov    (%rbx),%edi
call   1070 <strlen@plt>
mov    %r12,%rdi
mov    %rax,%rsi
call   10c0 <realloc@plt>
mov    %rax,%r12
jmp    1213 <get_mountpoint+0x73>
xor    %r12d,%r12d
jmp    1220 <get_mountpoint+0x80>
mov    0x2d4c(%rip),%rax
mov    (%rax),%eax
mov    0x2d4b(%rip),%rcx
mov    %eax,(%rcx)
xor    %r12d,%r12d
jmp    12b4 <get_mountpoint+0x114>
xor    %r12d,%r12d
jmp    12ac <get_mountpoint+0x10c>
xor    %r12d,%r12d
mov    %r15,%rdi
call   1040 <endmntent@plt>
mov    %r14,%rdi
call   1030 <free@plt>
mov    %r12,%rax
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.mntent = type { i32 }
@EINVAL = global i32 0
@errno = global i32 0
@.str = [10 x i8] c"/etc/mtab\00"
@.str.1 = [2 x i8] c"r\00"
define i8* @get_mountpoint(i8* %0) {
%2 = alloca i8*
%3 = alloca i8*
%4 = alloca i8*
%5 = alloca i32*
%6 = alloca i32
%7 = alloca %struct.mntent*
%8 = alloca i8
store i8* %0, i8** %2
store i8* null, i8** %3
store i8* null, i8** %4
store i32 0, i32* %6
%9 = load i8*, i8** %2
%10 = icmp eq i8* %9, null
br i1 %10, label %11, label %13
11: ; preds = %1
%12 = load i32, i32* @EINVAL
store i32 %12, i32* @errno
br label %95
13: ; preds = %1
%14 = load i8*, i8** %2
%15 = call i8* @realpath(i8* %14, i32* null)
store i8* %15, i8** %4
%16 = icmp ne i8* %15, null
br i1 %16, label %17, label %94
17: ; preds = %13
%18 = call i32* @setmntent(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
store i32* %18, i32** %5
%19 = icmp ne i32* %18, null
br i1 %19, label %20, label %94
20: ; preds = %17
br label %21
21: ; preds = %89, %20
%22 = load i32*, i32** %5
%23 = call %struct.mntent* @getmntent(i32* %22)
store %struct.mntent* %23, %struct.mntent** %7
%24 = load %struct.mntent*, %struct.mntent** %7
%25 = icmp ne %struct.mntent* %24, null
br i1 %25, label %26, label %82
26: ; preds = %21
%27 = load %struct.mntent*, %struct.mntent** %7
%28 = getelementptr inbounds %struct.mntent, %struct.mntent* %27, i32 0, i32 0
%29 = load i32, i32* %28
%30 = load i8*, i8** %4
%31 = load %struct.mntent*, %struct.mntent** %7
%32 = getelementptr inbounds %struct.mntent, %struct.mntent* %31, i32 0, i32 0
%33 = load i32, i32* %32
%34 = call i64 @strlen(i32 %33)
%35 = call i32 @strncmp(i32 %29, i8* %30, i64 %34)
%36 = icmp ne i32 %35, 0
br i1 %36, label %81, label %37
37: ; preds = %26
store i8 0, i8* %8
%38 = load i8*, i8** %3
%39 = icmp eq i8* %38, null
br i1 %39, label %40, label %51
40: ; preds = %37
%41 = load %struct.mntent*, %struct.mntent** %7
%42 = getelementptr inbounds %struct.mntent, %struct.mntent* %41, i32 0, i32 0
%43 = load i32, i32* %42
%44 = call i64 @strlen(i32 %43)
%45 = add nsw i64 %44, 1
%46 = call i8* @malloc(i64 %45)
store i8* %46, i8** %3
%47 = load i8*, i8** %3
%48 = icmp ne i8* %47, null
%49 = zext i1 %48 to i32
%50 = trunc i32 %49 to i8
store i8 %50, i8* %8
br label %70
51: ; preds = %37
%52 = load %struct.mntent*, %struct.mntent** %7
%53 = getelementptr inbounds %struct.mntent, %struct.mntent* %52, i32 0, i32 0
%54 = load i32, i32* %53
%55 = load i8*, i8** %3
%56 = load %struct.mntent*, %struct.mntent** %7
%57 = getelementptr inbounds %struct.mntent, %struct.mntent* %56, i32 0, i32 0
%58 = load i32, i32* %57
%59 = call i64 @strlen(i32 %58)
%60 = call i32 @strncmp(i32 %54, i8* %55, i64 %59)
%61 = icmp ne i32 %60, 0
br i1 %61, label %69, label %62
62: ; preds = %51
%63 = load i8*, i8** %3
%64 = load %struct.mntent*, %struct.mntent** %7
%65 = getelementptr inbounds %struct.mntent, %struct.mntent* %64, i32 0, i32 0
%66 = load i32, i32* %65
%67 = call i64 @strlen(i32 %66)
%68 = call i8* @realloc(i8* %63, i64 %67)
store i8* %68, i8** %3
store i8 1, i8* %8
br label %69
69: ; preds = %62, %51
br label %70
70: ; preds = %69, %40
%71 = load i8, i8* %8
%72 = sext i8 %71 to i32
%73 = icmp ne i32 %72, 0
br i1 %73, label %74, label %80
74: ; preds = %70
%75 = load i8*, i8** %3
%76 = load %struct.mntent*, %struct.mntent** %7
%77 = getelementptr inbounds %struct.mntent, %struct.mntent* %76, i32 0, i32 0
%78 = load i32, i32* %77
%79 = call i32 @strcpy(i8* %75, i32 %78)
br label %80
80: ; preds = %74, %70
br label %81
81: ; preds = %80, %26
br label %82
82: ; preds = %81, %21
br label %83
83: ; preds = %82
%84 = load i32, i32* %6
%85 = icmp eq i32 %84, 0
br i1 %85, label %86, label %89
86: ; preds = %83
%87 = load %struct.mntent*, %struct.mntent** %7
%88 = icmp ne %struct.mntent* %87, null
br label %89
89: ; preds = %86, %83
%90 = phi i1 [ false, %83 ], [ %88, %86 ]
br i1 %90, label %21, label %91
91: ; preds = %89
%92 = load i32*, i32** %5
%93 = call i32 @endmntent(i32* %92)
br label %94
94: ; preds = %91, %17, %13
br label %95
95: ; preds = %94, %11
%96 = load i8*, i8** %4
%97 = icmp ne i8* %96, null
br i1 %97, label %98, label %101
98: ; preds = %95
%99 = load i8*, i8** %4
%100 = call i32 @free(i8* %99)
br label %101
101: ; preds = %98, %95
%102 = load i8*, i8** %3
ret i8* %102
}

LLVM IR (-O2):
%struct.mntent = type { i32 }
@EINVAL = global i32 0
@errno = global i32 0
@.str = [10 x i8] c"/etc/mtab\00"
@.str.1 = [2 x i8] c"r\00"
define i8* @get_mountpoint(i8* %0) {
%2 = icmp eq i8* %0, null
br i1 %2, label %3, label %5
3: ; preds = %1
%4 = load i32, i32* @EINVAL
store i32 %4, i32* @errno
br label %51
5: ; preds = %1
%6 = tail call i8* @realpath(i8* %0, i32* null)
%7 = icmp eq i8* %6, null
br i1 %7, label %51, label %8
8: ; preds = %5
%9 = tail call i32* @setmntent(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
%10 = icmp eq i32* %9, null
br i1 %10, label %48, label %11
11: ; preds = %8
%12 = tail call %struct.mntent* @getmntent(i32* %9)
%13 = icmp eq %struct.mntent* %12, null
br i1 %13, label %45, label %14
14: ; preds = %11, %41
%15 = phi %struct.mntent* [ %43, %41 ], [ %12, %11 ]
%16 = phi i8* [ %42, %41 ], [ null, %11 ]
%17 = getelementptr inbounds %struct.mntent, %struct.mntent* %15, i64 0, i32 0
%18 = load i32, i32* %17
%19 = tail call i64 @strlen(i32 %18)
%20 = tail call i32 @strncmp(i32 %18, i8* %6, i64 %19)
%21 = icmp eq i32 %20, 0
br i1 %21, label %22, label %41
22: ; preds = %14
%23 = icmp eq i8* %16, null
%24 = load i32, i32* %17
%25 = tail call i64 @strlen(i32 %24)
br i1 %23, label %33, label %26
26: ; preds = %22
%27 = tail call i32 @strncmp(i32 %24, i8* %16, i64 %25)
%28 = icmp eq i32 %27, 0
br i1 %28, label %29, label %41
29: ; preds = %26
%30 = load i32, i32* %17
%31 = tail call i64 @strlen(i32 %30)
%32 = tail call i8* @realloc(i8* %16, i64 %31)
br label %37
33: ; preds = %22
%34 = add nsw i64 %25, 1
%35 = tail call i8* @malloc(i64 %34)
%36 = icmp eq i8* %35, null
br i1 %36, label %41, label %37
37: ; preds = %29, %33
%38 = phi i8* [ %32, %29 ], [ %35, %33 ]
%39 = load i32, i32* %17
%40 = tail call i32 @strcpy(i8* %38, i32 %39)
br label %41
41: ; preds = %26, %33, %37, %14
%42 = phi i8* [ %16, %14 ], [ %38, %37 ], [ null, %33 ], [ %16, %26 ]
%43 = tail call %struct.mntent* @getmntent(i32* %9)
%44 = icmp eq %struct.mntent* %43, null
br i1 %44, label %45, label %14
45: ; preds = %41, %11
%46 = phi i8* [ null, %11 ], [ %42, %41 ]
%47 = tail call i32 @endmntent(i32* %9)
br label %48
48: ; preds = %45, %8
%49 = phi i8* [ %46, %45 ], [ null, %8 ]
%50 = tail call i32 @free(i8* %6)
br label %51
51: ; preds = %5, %3, %48
%52 = phi i8* [ %49, %48 ], [ null, %3 ], [ null, %5 ]
ret i8* %52
}